or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration.mdcore-client.mdfeature-system.mdindex.mdlanguage-features.mdtransport.mdutilities.md

feature-system.mddocs/

0

# Feature System

1

2

Base interfaces and classes for implementing static and dynamic language server features.

3

4

## Capabilities

5

6

### Core Feature Interfaces

7

8

Base interfaces defining the feature system architecture.

9

10

```typescript { .api }

11

/**

12

* Base interface for all language client features

13

*/

14

interface Feature {

15

/** Get the current state of the feature */

16

getState(): FeatureState;

17

18

/** Clear the feature state and cleanup resources */

19

clear(): void;

20

}

21

22

/**

23

* Feature state enumeration

24

*/

25

enum FeatureState {

26

/** Feature is not initialized */

27

Initial,

28

/** Feature is starting */

29

Starting,

30

/** Feature is active and running */

31

Started,

32

/** Feature has been stopped */

33

Stopped,

34

/** Feature is disposing */

35

Disposing,

36

/** Feature has been disposed */

37

Disposed

38

}

39

```

40

41

### Static Features

42

43

Features that are registered once during client initialization.

44

45

```typescript { .api }

46

/**

47

* Interface for static language server features

48

* Static features are registered once during initialization and don't support dynamic registration

49

*/

50

interface StaticFeature extends Feature {

51

/**

52

* Fill initialization parameters sent to the server

53

* Called before client initialization

54

*/

55

fillInitializeParams?(params: InitializeParams): void;

56

57

/**

58

* Fill client capabilities advertised to the server

59

* Called during client initialization

60

*/

61

fillClientCapabilities(capabilities: ClientCapabilities): void;

62

63

/**

64

* Pre-initialization hook called before the feature is initialized

65

* Used for setup that requires server capabilities

66

*/

67

preInitialize?(capabilities: ServerCapabilities, documentSelector: DocumentSelector | undefined): void;

68

69

/**

70

* Initialize the feature with server capabilities

71

* Called after successful server initialization

72

*/

73

initialize(capabilities: ServerCapabilities, documentSelector: DocumentSelector | undefined): void;

74

}

75

```

76

77

**Usage Examples:**

78

79

Implementing a static feature:

80

81

```typescript

82

class CustomStaticFeature implements StaticFeature {

83

private _state: FeatureState = FeatureState.Initial;

84

85

fillClientCapabilities(capabilities: ClientCapabilities): void {

86

// Add custom capabilities

87

capabilities.experimental = {

88

...capabilities.experimental,

89

customFeature: true

90

};

91

}

92

93

initialize(capabilities: ServerCapabilities, documentSelector: DocumentSelector | undefined): void {

94

if (capabilities.experimental?.customFeature) {

95

this._state = FeatureState.Started;

96

// Initialize feature logic

97

}

98

}

99

100

getState(): FeatureState {

101

return this._state;

102

}

103

104

clear(): void {

105

this._state = FeatureState.Disposed;

106

// Cleanup resources

107

}

108

}

109

```

110

111

### Dynamic Features

112

113

Features that support dynamic registration and unregistration.

114

115

```typescript { .api }

116

/**

117

* Interface for dynamic language server features

118

* Dynamic features can be registered and unregistered at runtime

119

*/

120

interface DynamicFeature<RO> extends StaticFeature {

121

/** Registration type that identifies this feature */

122

readonly registrationType: RegistrationType<RO>;

123

124

/**

125

* Register the feature with specific options

126

* Called when server requests feature registration

127

*/

128

register(data: RegistrationData<RO>): void;

129

130

/**

131

* Unregister the feature by ID

132

* Called when server requests feature unregistration

133

*/

134

unregister(id: string): void;

135

}

136

137

/**

138

* Registration data for dynamic features

139

*/

140

interface RegistrationData<T> {

141

/** Unique registration identifier */

142

id: string;

143

/** Registration method name */

144

method: string;

145

/** Registration options specific to the feature */

146

registerOptions?: T;

147

}

148

149

/**

150

* Registration type interface

151

*/

152

interface RegistrationType<RO> {

153

/** LSP method name for this registration type */

154

readonly method: string;

155

}

156

```

157

158

**Usage Examples:**

159

160

Implementing a dynamic feature:

161

162

```typescript

163

class CustomDynamicFeature implements DynamicFeature<CustomRegistrationOptions> {

164

private _state: FeatureState = FeatureState.Initial;

165

private _registrations = new Map<string, CustomRegistration>();

166

167

readonly registrationType: RegistrationType<CustomRegistrationOptions> = {

168

method: 'textDocument/customFeature'

169

};

170

171

fillClientCapabilities(capabilities: ClientCapabilities): void {

172

capabilities.textDocument = capabilities.textDocument || {};

173

capabilities.textDocument.customFeature = {

174

dynamicRegistration: true

175

};

176

}

177

178

initialize(capabilities: ServerCapabilities, documentSelector: DocumentSelector | undefined): void {

179

this._state = FeatureState.Started;

180

}

181

182

register(data: RegistrationData<CustomRegistrationOptions>): void {

183

const registration = new CustomRegistration(data.id, data.registerOptions);

184

this._registrations.set(data.id, registration);

185

}

186

187

unregister(id: string): void {

188

const registration = this._registrations.get(id);

189

if (registration) {

190

registration.dispose();

191

this._registrations.delete(id);

192

}

193

}

194

195

getState(): FeatureState {

196

return this._state;

197

}

198

199

clear(): void {

200

for (const registration of this._registrations.values()) {

201

registration.dispose();

202

}

203

this._registrations.clear();

204

this._state = FeatureState.Disposed;

205

}

206

}

207

```

208

209

### Provider Features

210

211

Specialized interfaces for features that provide VS Code providers.

212

213

```typescript { .api }

214

/**

215

* Mixin interface for text document provider features

216

* Features implementing this can provide providers per text document

217

*/

218

interface TextDocumentProviderFeature<T> {

219

/**

220

* Get the provider for a specific text document

221

* @param textDocument - The text document to get provider for

222

* @returns Provider instance or undefined if not available

223

*/

224

getProvider(textDocument: TextDocument): T | undefined;

225

}

226

227

/**

228

* Interface for workspace provider features

229

* Features implementing this provide workspace-wide functionality

230

*/

231

interface WorkspaceProviderFeature<PR> {

232

/**

233

* Get all providers registered for workspace operations

234

* @returns Array of provider instances or undefined

235

*/

236

getProviders(): PR[] | undefined;

237

}

238

239

/**

240

* Interface for features that can be client-specific

241

*/

242

interface FeatureClient<M, PO> {

243

/** Get the method name for this feature */

244

getRegistrationType(): RegistrationType<PO>;

245

246

/** Fill client capabilities for this feature */

247

fillClientCapabilities(capabilities: ClientCapabilities): void;

248

249

/** Initialize the feature */

250

initialize(capabilities: M, documentSelector: DocumentSelector | undefined): void;

251

252

/** Register options for dynamic registration */

253

register(data: RegistrationData<PO>): void;

254

255

/** Unregister by ID */

256

unregister(id: string): void;

257

258

/** Dispose the feature */

259

dispose(): void;

260

}

261

```

262

263

### Text Document Features

264

265

Base classes for text document-based features.

266

267

```typescript { .api }

268

/**

269

* Base class for text document synchronization features

270

*/

271

abstract class TextDocumentSendFeature<T> implements DynamicFeature<T> {

272

protected _client: BaseLanguageClient;

273

protected _registrationType: RegistrationType<T>;

274

275

constructor(client: BaseLanguageClient, registrationType: RegistrationType<T>);

276

277

abstract fillClientCapabilities(capabilities: ClientCapabilities): void;

278

abstract initialize(capabilities: ServerCapabilities, documentSelector: DocumentSelector | undefined): void;

279

280

register(data: RegistrationData<T>): void;

281

unregister(id: string): void;

282

getState(): FeatureState;

283

clear(): void;

284

285

get registrationType(): RegistrationType<T>;

286

}

287

288

/**

289

* Interface for features that send text document notifications

290

*/

291

interface DidOpenTextDocumentFeatureShape {

292

/** Handle document open event */

293

didOpen(textDocument: TextDocument): void;

294

}

295

296

/**

297

* Interface for features that send text document close notifications

298

*/

299

interface DidCloseTextDocumentFeatureShape {

300

/** Handle document close event */

301

didClose(textDocument: TextDocument): void;

302

}

303

304

/**

305

* Interface for features that send text document change notifications

306

*/

307

interface DidChangeTextDocumentFeatureShape {

308

/** Handle document change event */

309

didChange(event: TextDocumentChangeEvent): void;

310

}

311

312

/**

313

* Interface for features that send text document save notifications

314

*/

315

interface DidSaveTextDocumentFeatureShape {

316

/** Handle document save event */

317

didSave(textDocument: TextDocument): void;

318

}

319

```

320

321

### Provider Shape Interfaces

322

323

Standard shapes for VS Code language providers.

324

325

```typescript { .api }

326

/**

327

* Shape interface for code lens providers

328

*/

329

interface CodeLensProviderShape {

330

/** Provide code lenses for a document */

331

provideCodeLenses(document: TextDocument, token: CancellationToken): ProviderResult<CodeLens[]>;

332

333

/** Resolve a code lens */

334

resolveCodeLens?(codeLens: CodeLens, token: CancellationToken): ProviderResult<CodeLens>;

335

336

/** Event fired when code lenses should be refreshed */

337

onDidChangeCodeLenses?: Event<void>;

338

}

339

340

/**

341

* Shape interface for diagnostic providers

342

*/

343

interface DiagnosticProviderShape {

344

/** Event fired when diagnostics change */

345

onDidChangeDiagnostics: Event<void>;

346

347

/** Provide diagnostics for a document */

348

provideDiagnostics(

349

document: TextDocument | Uri,

350

previousResultId: string | undefined,

351

token: CancellationToken

352

): ProviderResult<DocumentDiagnosticReport>;

353

354

/** Provide workspace diagnostics */

355

provideWorkspaceDiagnostics?(

356

resultIds: PreviousResultId[],

357

token: CancellationToken,

358

resultReporter: ResultReporter

359

): ProviderResult<WorkspaceDiagnosticReport>;

360

}

361

362

/**

363

* Shape interface for semantic tokens providers

364

*/

365

interface SemanticTokensProviderShape {

366

/** Provide semantic tokens for entire document */

367

provideDocumentSemanticTokens(document: TextDocument, token: CancellationToken): ProviderResult<SemanticTokens>;

368

369

/** Provide semantic token edits */

370

provideDocumentSemanticTokensEdits?(

371

document: TextDocument,

372

previousResultId: string,

373

token: CancellationToken

374

): ProviderResult<SemanticTokensEdits | SemanticTokens>;

375

376

/** Provide semantic tokens for a range */

377

provideDocumentRangeSemanticTokens?(

378

document: TextDocument,

379

range: Range,

380

token: CancellationToken

381

): ProviderResult<SemanticTokens>;

382

}

383

384

/**

385

* Shape interface for inlay hints providers

386

*/

387

interface InlayHintsProviderShape {

388

/** Provide inlay hints for a document range */

389

provideInlayHints(document: TextDocument, range: Range, token: CancellationToken): ProviderResult<InlayHint[]>;

390

391

/** Resolve an inlay hint */

392

resolveInlayHint?(item: InlayHint, token: CancellationToken): ProviderResult<InlayHint>;

393

394

/** Event fired when inlay hints should be refreshed */

395

onDidChangeInlayHints?: Event<void>;

396

}

397

398

/**

399

* Shape interface for inline value providers

400

*/

401

interface InlineValueProviderShape {

402

/** Provide inline values for a document range */

403

provideInlineValues(

404

document: TextDocument,

405

viewPort: Range,

406

context: InlineValueContext,

407

token: CancellationToken

408

): ProviderResult<InlineValue[]>;

409

410

/** Event fired when inline values should be refreshed */

411

onDidChangeInlineValues?: Event<void>;

412

}

413

```

414

415

### Feature Registration

416

417

Utilities for feature registration and management.

418

419

```typescript { .api }

420

/**

421

* Ensure a registration data object is properly formatted

422

*/

423

function ensure<T>(target: T, key: keyof T): T[typeof key];

424

425

/**

426

* Language Server Protocol cancellation error

427

*/

428

class LSPCancellationError extends Error {

429

/** LSP error data */

430

readonly data: any;

431

432

constructor(data: any);

433

}

434

435

/**

436

* Create all proposed features for experimental LSP capabilities

437

*/

438

function createAll(): (StaticFeature | DynamicFeature<any>)[];

439

```

440

441

**Usage Examples:**

442

443

Registering features with client:

444

445

```typescript

446

import { LanguageClient } from "vscode-languageclient/node";

447

448

const client = new LanguageClient(/* ... */);

449

450

// Register a static feature

451

const staticFeature = new CustomStaticFeature();

452

client.registerFeature(staticFeature);

453

454

// Register a dynamic feature

455

const dynamicFeature = new CustomDynamicFeature();

456

client.registerFeature(dynamicFeature);

457

458

// Register proposed features

459

const proposedFeatures = createAll();

460

proposedFeatures.forEach(feature => client.registerFeature(feature));

461

```

462

463

Feature with provider interface:

464

465

```typescript

466

class CustomProviderFeature implements DynamicFeature<CustomOptions>, TextDocumentProviderFeature<CustomProvider> {

467

private _providers = new Map<string, CustomProvider>();

468

469

getProvider(textDocument: TextDocument): CustomProvider | undefined {

470

// Find appropriate provider for document

471

for (const provider of this._providers.values()) {

472

if (provider.canHandle(textDocument)) {

473

return provider;

474

}

475

}

476

return undefined;

477

}

478

479

register(data: RegistrationData<CustomOptions>): void {

480

const provider = new CustomProvider(data.registerOptions);

481

this._providers.set(data.id, provider);

482

}

483

484

// ... implement other DynamicFeature methods

485

}

486

```