# Utilities

Utility classes and functions for error handling, configuration monitoring, and type conversion.

## Capabilities

### Configuration Monitoring

Utilities for monitoring VS Code settings and automatically managing client lifecycle.

```typescript { .api }
/**
 * Monitors VS Code configuration changes and manages language client lifecycle
 * Automatically starts/stops the client based on configuration changes
 */
class SettingMonitor {
  /** The language client being monitored */
  private readonly _client: LanguageClient;
  
  /** The configuration setting to monitor */
  private readonly _setting: string;
  
  /**
   * Create a setting monitor for a language client
   * @param client - The language client to manage
   * @param setting - The configuration setting key to monitor
   */
  constructor(client: LanguageClient, setting: string);
  
  /**
   * Start monitoring the configuration setting
   * @returns Disposable to stop monitoring
   */
  start(): Disposable;
}
```

**Usage Examples:**

Monitor a setting to control client lifecycle:

```typescript
import { SettingMonitor } from "vscode-languageclient/node";

const client = new LanguageClient(/* ... */);
const monitor = new SettingMonitor(client, 'myExtension.enable');

// Start monitoring - client will start/stop based on setting value
const disposable = monitor.start();

// Stop monitoring when extension is deactivated
context.subscriptions.push(disposable);
```

### Error Handling

Specialized error types for Language Server Protocol operations.

```typescript { .api }
/**
 * LSP-specific cancellation error with additional data
 */
class LSPCancellationError extends Error {
  /** Additional error data from LSP */
  readonly data: any;
  
  /**
   * Create an LSP cancellation error
   * @param data - Error data from the language server
   */
  constructor(data: any);
}

/**
 * Standard VS Code cancellation error
 */
class CancellationError extends Error {
  constructor();
}
```

**Usage Examples:**

Handle LSP-specific errors:

```typescript
try {
  const result = await client.sendRequest('custom/method', params);
} catch (error) {
  if (error instanceof LSPCancellationError) {
    console.log('Request was cancelled by LSP server:', error.data);
  } else if (error instanceof CancellationError) {
    console.log('Request was cancelled by VS Code');
  } else {
    console.error('Request failed:', error);
  }
}
```

### Type Conversion

Utility classes for converting between VS Code types and LSP protocol types.

```typescript { .api }
/**
 * Converter for transforming VS Code types to LSP protocol types
 */
class Code2ProtocolConverter {
  /** Convert VS Code URI to protocol string */
  asUri(uri: Uri): string;
  
  /** Convert VS Code document URI to protocol DocumentUri */
  asTextDocumentIdentifier(textDocument: TextDocument): TextDocumentIdentifier;
  
  /** Convert VS Code document to protocol VersionedTextDocumentIdentifier */
  asVersionedTextDocumentIdentifier(textDocument: TextDocument): VersionedTextDocumentIdentifier;
  
  /** Convert VS Code position to protocol Position */
  asPosition(position: Position): Position;
  
  /** Convert VS Code range to protocol Range */
  asRange(range: Range): Range;
  
  /** Convert VS Code location to protocol Location */
  asLocation(location: Location): Location;
  
  /** Convert VS Code diagnostic severity to protocol DiagnosticSeverity */
  asDiagnosticSeverity(severity: DiagnosticSeverity): lsp.DiagnosticSeverity;
  
  /** Convert VS Code diagnostic to protocol Diagnostic */
  asDiagnostic(diagnostic: Diagnostic): lsp.Diagnostic;
  
  /** Convert VS Code text edit to protocol TextEdit */
  asTextEdit(edit: TextEdit): lsp.TextEdit;
  
  /** Convert VS Code workspace edit to protocol WorkspaceEdit */
  asWorkspaceEdit(workspaceEdit: WorkspaceEdit): lsp.WorkspaceEdit;
  
  /** Convert VS Code completion item to protocol CompletionItem */
  asCompletionItem(item: CompletionItem): lsp.CompletionItem;
  
  /** Convert VS Code symbol information to protocol SymbolInformation */
  asSymbolInformation(symbol: SymbolInformation): lsp.SymbolInformation;
  
  /** Convert VS Code code action to protocol CodeAction */
  asCodeAction(action: CodeAction): lsp.CodeAction;
  
  /** Convert VS Code code lens to protocol CodeLens */
  asCodeLens(lens: CodeLens): lsp.CodeLens;
}

/**
 * Converter for transforming LSP protocol types to VS Code types
 */
class Protocol2CodeConverter {
  /** Convert protocol URI string to VS Code URI */
  asUri(uri: string): Uri;
  
  /** Convert protocol Position to VS Code Position */
  asPosition(position: lsp.Position): Position;
  
  /** Convert protocol Range to VS Code Range */
  asRange(range: lsp.Range): Range;
  
  /** Convert protocol Location to VS Code Location */
  asLocation(location: lsp.Location): Location;
  
  /** Convert protocol DiagnosticSeverity to VS Code DiagnosticSeverity */
  asDiagnosticSeverity(severity: lsp.DiagnosticSeverity | undefined): DiagnosticSeverity;
  
  /** Convert protocol DiagnosticTag to VS Code DiagnosticTag */
  asDiagnosticTag(tag: lsp.DiagnosticTag): DiagnosticTag;
  
  /** Convert protocol Diagnostic to VS Code Diagnostic */
  asDiagnostic(diagnostic: lsp.Diagnostic): Diagnostic;
  
  /** Convert protocol TextEdit to VS Code TextEdit */
  asTextEdit(edit: lsp.TextEdit): TextEdit;
  
  /** Convert protocol WorkspaceEdit to VS Code WorkspaceEdit */
  asWorkspaceEdit(workspaceEdit: lsp.WorkspaceEdit): WorkspaceEdit;
  
  /** Convert protocol CompletionItem to VS Code CompletionItem */
  asCompletionItem(item: lsp.CompletionItem): CompletionItem;
  
  /** Convert protocol Hover to VS Code Hover */
  asHover(hover: lsp.Hover): Hover;
  
  /** Convert protocol SignatureHelp to VS Code SignatureHelp */
  asSignatureHelp(signatureHelp: lsp.SignatureHelp): SignatureHelp;
  
  /** Convert protocol DocumentSymbol to VS Code DocumentSymbol */
  asDocumentSymbol(symbol: lsp.DocumentSymbol): DocumentSymbol;
  
  /** Convert protocol SymbolInformation to VS Code SymbolInformation */
  asSymbolInformation(symbol: lsp.SymbolInformation): SymbolInformation;
  
  /** Convert protocol CodeAction to VS Code CodeAction */
  asCodeAction(action: lsp.CodeAction): CodeAction;
  
  /** Convert protocol CodeLens to VS Code CodeLens */
  asCodeLens(lens: lsp.CodeLens): CodeLens;
  
  /** Convert protocol DocumentHighlight to VS Code DocumentHighlight */
  asDocumentHighlight(highlight: lsp.DocumentHighlight): DocumentHighlight;
  
  /** Convert protocol DocumentLink to VS Code DocumentLink */
  asDocumentLink(link: lsp.DocumentLink): DocumentLink;
  
  /** Convert protocol SelectionRange to VS Code SelectionRange */
  asSelectionRange(range: lsp.SelectionRange): SelectionRange;
  
  /** Convert protocol SemanticTokens to VS Code SemanticTokens */
  asSemanticTokens(tokens: lsp.SemanticTokens): SemanticTokens;
  
  /** Convert protocol InlayHint to VS Code InlayHint */
  asInlayHint(hint: lsp.InlayHint): InlayHint;
}
```

**Usage Examples:**

Using converters in middleware:

```typescript
const clientOptions: LanguageClientOptions = {
  middleware: {
    completion: {
      provideCompletionItem: (document, position, context, token, next) => {
        // Access converters from client
        const c2p = client.code2ProtocolConverter;
        const p2c = client.protocol2CodeConverter;
        
        // Convert position to protocol format
        const protocolPosition = c2p.asPosition(position);
        
        // Get completions and convert back
        return next(document, position, context, token).then(result => {
          if (Array.isArray(result)) {
            return result.map(item => {
              // Customize completion item
              return { ...item, sortText: '0' + item.label };
            });
          }
          return result;
        });
      }
    }
  }
};
```

### File Operations

Utilities for file system operations and path handling.

```typescript { .api }
/**
 * File formatting options interface
 */
interface FileFormattingOptions {
  /** Insert final newline */
  insertFinalNewline?: boolean;
  
  /** Trim final newlines */
  trimFinalNewlines?: boolean;
  
  /** Trim trailing whitespace */
  trimTrailingWhitespace?: boolean;
}
```

### Async Utilities

Helper classes for managing asynchronous operations.

```typescript { .api }
/**
 * Utility for delaying execution of operations
 */
class Delayer<T> {
  /** Default delay in milliseconds */
  readonly defaultDelay: number;
  
  /**
   * Create a delayer with default delay
   * @param defaultDelay - Default delay in milliseconds
   */
  constructor(defaultDelay: number);
  
  /**
   * Trigger execution after delay
   * @param task - Task to execute
   * @param delay - Custom delay (uses default if not provided)
   * @returns Promise that resolves with task result
   */
  trigger(task: () => T | Promise<T>, delay?: number): Promise<T>;
  
  /** Cancel pending execution */
  cancel(): void;
  
  /** Whether execution is pending */
  isTriggered(): boolean;
}

/**
 * Utility for controlling concurrent access to resources
 */
class Semaphore {
  /** Number of available permits */
  readonly size: number;
  
  /**
   * Create a semaphore with specified size
   * @param size - Number of concurrent operations allowed
   */
  constructor(size: number);
  
  /**
   * Acquire a permit and execute task
   * @param task - Task to execute with permit
   * @returns Promise that resolves with task result
   */
  lock<T>(task: () => Promise<T>): Promise<T>;
}
```

**Usage Examples:**

Using Delayer for batching operations:

```typescript
import { Delayer } from "vscode-languageclient/node";

class DiagnosticsManager {
  private _delayer = new Delayer<void>(500);
  private _pendingDiagnostics: Diagnostic[] = [];
  
  addDiagnostic(diagnostic: Diagnostic): void {
    this._pendingDiagnostics.push(diagnostic);
    
    // Batch diagnostics updates with 500ms delay
    this._delayer.trigger(() => {
      const diagnostics = [...this._pendingDiagnostics];
      this._pendingDiagnostics = [];
      return this.publishDiagnostics(diagnostics);
    });
  }
  
  private async publishDiagnostics(diagnostics: Diagnostic[]): Promise<void> {
    // Publish batched diagnostics
  }
}
```

Using Semaphore for resource control:

```typescript
import { Semaphore } from "vscode-languageclient/node";

class RequestManager {
  private _semaphore = new Semaphore(3); // Max 3 concurrent requests
  
  async sendRequest<T>(request: () => Promise<T>): Promise<T> {
    return this._semaphore.lock(request);
  }
}
```

### UUID Generation

Utility for generating unique identifiers.

```typescript { .api }
/**
 * Generate a UUID v4 string
 * @returns UUID v4 string
 */
function generateUuid(): string;

/**
 * Generate a short UUID (8 characters)
 * @returns Short UUID string
 */
function generateShortUuid(): string;
```

**Usage Examples:**

Generate request IDs:

```typescript
import * as UUID from "vscode-languageclient/lib/common/utils/uuid";

const requestId = UUID.generateUuid();
const shortId = UUID.generateShortUuid();

await client.sendRequest('custom/method', { 
  id: requestId,
  data: 'example' 
});
```

### Type Guards

Utility functions for runtime type checking.

```typescript { .api }
/**
 * Type guard utilities
 */
namespace Is {
  /** Check if value is a string */
  function string(value: any): value is string;
  
  /** Check if value is a number */
  function number(value: any): value is number;
  
  /** Check if value is a boolean */
  function boolean(value: any): value is boolean;
  
  /** Check if value is undefined */
  function undefined(value: any): value is undefined;
  
  /** Check if value is defined (not undefined) */
  function defined<T>(value: T | undefined): value is T;
  
  /** Check if value is a function */
  function func(value: any): value is Function;
  
  /** Check if value is an object */
  function objectLiteral(value: any): value is object;
}
```

**Usage Examples:**

Safe type checking:

```typescript
import * as Is from "vscode-languageclient/lib/common/utils/is";

function processConfig(config: any): void {
  if (Is.string(config.serverPath)) {
    // config.serverPath is guaranteed to be string
    const serverOptions = { command: config.serverPath };
  }
  
  if (Is.number(config.maxConcurrency) && config.maxConcurrency > 0) {
    // config.maxConcurrency is guaranteed to be positive number
    const semaphore = new Semaphore(config.maxConcurrency);
  }
}
```