or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

connection.mddocuments.mdextended-features.mdindex.mdlanguage-features.mdnotebooks.mdutilities.md

utilities.mddocs/

0

# Utility Classes

1

2

Helper classes for common language server tasks including semantic token building, error tracking, and progress reporting. These utilities simplify common operations in language server implementations.

3

4

## Capabilities

5

6

### Semantic Tokens Builder

7

8

Helper class for building semantic tokens responses with proper encoding and delta support.

9

10

```typescript { .api }

11

/**

12

* A helper class to build semantic tokens data arrays

13

*/

14

class SemanticTokensBuilder {

15

/** Create a new semantic tokens builder */

16

constructor();

17

18

/**

19

* Add a semantic token to the builder

20

* @param line Line number (0-based)

21

* @param char Character offset on line (0-based)

22

* @param length Length of the token in characters

23

* @param tokenType Token type index from legend

24

* @param tokenModifiers Token modifiers as bit flags from legend

25

*/

26

push(line: number, char: number, length: number, tokenType: number, tokenModifiers?: number): void;

27

28

/**

29

* Build the final semantic tokens result

30

* @returns SemanticTokens object with encoded data array

31

*/

32

build(): SemanticTokens;

33

34

/**

35

* Build semantic tokens edits for delta requests

36

* @returns SemanticTokensEdits for incremental updates

37

*/

38

buildEdits(): SemanticTokensEdits;

39

}

40

```

41

42

**Usage Example:**

43

44

```typescript

45

import { SemanticTokensBuilder } from "vscode-languageserver";

46

47

// Define token types and modifiers indices (should match client capabilities)

48

const TokenTypes = {

49

keyword: 0,

50

function: 1,

51

variable: 2,

52

string: 3,

53

number: 4,

54

comment: 5

55

};

56

57

const TokenModifiers = {

58

declaration: 1 << 0,

59

definition: 1 << 1,

60

readonly: 1 << 2,

61

static: 1 << 3,

62

deprecated: 1 << 4

63

};

64

65

connection.languages.semanticTokens.on((params) => {

66

const document = documents.get(params.textDocument.uri);

67

if (!document) return null;

68

69

const builder = new SemanticTokensBuilder();

70

71

const lines = document.getText().split('\n');

72

lines.forEach((line, lineIndex) => {

73

// Simple tokenization example

74

const words = line.split(/\s+/);

75

let charOffset = 0;

76

77

words.forEach(word => {

78

const wordStart = line.indexOf(word, charOffset);

79

80

if (word === 'function') {

81

builder.push(lineIndex, wordStart, word.length, TokenTypes.keyword, TokenModifiers.declaration);

82

} else if (word.startsWith('"') && word.endsWith('"')) {

83

builder.push(lineIndex, wordStart, word.length, TokenTypes.string);

84

} else if (/^\d+$/.test(word)) {

85

builder.push(lineIndex, wordStart, word.length, TokenTypes.number);

86

} else if (word.startsWith('//')) {

87

builder.push(lineIndex, wordStart, line.length - wordStart, TokenTypes.comment);

88

break; // Rest of line is comment

89

}

90

91

charOffset = wordStart + word.length;

92

});

93

});

94

95

return builder.build();

96

});

97

```

98

99

### Error Message Tracker

100

101

Helper class for tracking and deduplicating error messages before sending them to the client.

102

103

```typescript { .api }

104

/**

105

* Helps tracking error message. Equal occurrences of the same message are only stored once.

106

* This class is useful if text documents are validated in a loop and equal error messages

107

* should be folded into one.

108

*/

109

class ErrorMessageTracker {

110

/** Create a new error message tracker */

111

constructor();

112

113

/**

114

* Add a message to the tracker

115

* @param message The message to add

116

*/

117

add(message: string): void;

118

119

/**

120

* Send all tracked messages to the connection's window

121

* @param connection The connection established between client and server

122

*/

123

sendErrors(connection: { window: RemoteWindow }): void;

124

}

125

```

126

127

**Usage Example:**

128

129

```typescript

130

import { ErrorMessageTracker } from "vscode-languageserver";

131

132

const errorTracker = new ErrorMessageTracker();

133

134

// Validate multiple documents

135

documents.all().forEach(document => {

136

try {

137

validateDocument(document);

138

} catch (error) {

139

// Add errors to tracker (duplicates will be deduplicated)

140

errorTracker.add(`Error in ${document.uri}: ${error.message}`);

141

}

142

});

143

144

// Send all unique errors to client

145

errorTracker.sendErrors(connection);

146

```

147

148

### Progress Reporting

149

150

Interfaces for reporting work done progress and partial results during long-running operations.

151

152

```typescript { .api }

153

/**

154

* Interface for reporting work done progress

155

*/

156

interface WorkDoneProgressReporter {

157

/**

158

* Begin progress reporting

159

* @param title The title of the progress

160

* @param percentage Optional initial percentage (0-100)

161

* @param message Optional initial message

162

* @param cancellable Whether the operation can be cancelled

163

*/

164

begin(title: string, percentage?: number, message?: string, cancellable?: boolean): void;

165

166

/**

167

* Report progress with percentage

168

* @param percentage Progress percentage (0-100)

169

*/

170

report(percentage: number): void;

171

172

/**

173

* Report progress with message

174

* @param message Progress message

175

*/

176

report(message: string): void;

177

178

/**

179

* Report progress with percentage and message

180

* @param percentage Progress percentage (0-100)

181

* @param message Optional progress message

182

*/

183

report(percentage: number, message?: string): void;

184

185

/** Complete the progress reporting */

186

done(): void;

187

}

188

189

/**

190

* Server-side work done progress reporter

191

*/

192

interface WorkDoneProgressServerReporter extends WorkDoneProgressReporter {

193

/** The progress token */

194

readonly token: ProgressToken;

195

}

196

197

/**

198

* Interface for reporting partial results

199

*/

200

interface ResultProgressReporter<T> {

201

/**

202

* Report partial result data

203

* @param data The partial result data

204

*/

205

report(data: T): void;

206

}

207

```

208

209

**Usage Example:**

210

211

```typescript

212

connection.onWorkspaceSymbol((params, token, workDoneProgress, resultProgress) => {

213

// Begin progress reporting

214

workDoneProgress.begin('Searching workspace symbols');

215

216

const allSymbols: SymbolInformation[] = [];

217

const files = getAllWorkspaceFiles();

218

219

files.forEach((file, index) => {

220

// Report progress

221

const percentage = Math.round((index / files.length) * 100);

222

workDoneProgress.report(percentage, `Processing ${file}`);

223

224

// Get symbols from file

225

const symbols = getSymbolsFromFile(file, params.query);

226

allSymbols.push(...symbols);

227

228

// Report partial results

229

if (symbols.length > 0) {

230

resultProgress.report(symbols);

231

}

232

233

// Check for cancellation

234

if (token.isCancellationRequested) {

235

workDoneProgress.done();

236

return null;

237

}

238

});

239

240

// Complete progress

241

workDoneProgress.done();

242

return allSymbols;

243

});

244

```

245

246

### Registration Utilities

247

248

Interfaces for bulk registration and unregistration of capabilities.

249

250

```typescript { .api }

251

/**

252

* Interface for bulk capability registration

253

*/

254

interface BulkRegistration {

255

/**

256

* Add a registration to the bulk registration

257

* @param type The request/notification type to register

258

* @param registerOptions Optional registration options

259

*/

260

add<RO>(type: ProtocolRequestType0<any, any, any, RO> | ProtocolNotificationType0<RO>, registerOptions?: RO): void;

261

add<P, RO>(type: ProtocolRequestType<P, any, any, any, RO> | ProtocolNotificationType<P, RO>, registerOptions?: RO): void;

262

263

/**

264

* Convert to registration parameters for sending to client

265

*/

266

asRegistrationParams(): RegistrationParams;

267

}

268

269

/**

270

* Interface for bulk capability unregistration

271

*/

272

interface BulkUnregistration extends Disposable {

273

/**

274

* Add an unregistration to the bulk unregistration

275

* @param unregistration The unregistration to add

276

*/

277

add(unregistration: Unregistration): void;

278

279

/**

280

* Convert to unregistration parameters for sending to client

281

*/

282

asUnregistrationParams(): UnregistrationParams;

283

284

/** Dispose all registrations */

285

dispose(): void;

286

}

287

```

288

289

**Usage Example:**

290

291

```typescript

292

// Bulk register multiple capabilities

293

const bulkRegistration = BulkRegistration.create();

294

bulkRegistration.add(HoverRequest.type, { documentSelector: [{ scheme: 'file', language: 'typescript' }] });

295

bulkRegistration.add(CompletionRequest.type, { documentSelector: [{ scheme: 'file', language: 'typescript' }] });

296

bulkRegistration.add(DefinitionRequest.type, { documentSelector: [{ scheme: 'file', language: 'typescript' }] });

297

298

// Send bulk registration to client

299

connection.client.register(bulkRegistration.asRegistrationParams());

300

301

// Later, bulk unregister

302

const bulkUnregistration = BulkUnregistration.create();

303

bulkUnregistration.add({ id: 'hover-registration', method: 'textDocument/hover' });

304

bulkUnregistration.add({ id: 'completion-registration', method: 'textDocument/completion' });

305

306

connection.client.unregister(bulkUnregistration.asUnregistrationParams());

307

```

308

309

### UUID Utilities

310

311

Simple UUID generation utilities for creating unique identifiers.

312

313

```typescript { .api }

314

/**

315

* UUID generation utilities

316

*/

317

namespace UUID {

318

/**

319

* Generate a new UUID v4

320

* @returns A new UUID string

321

*/

322

function generateUuid(): string;

323

}

324

```

325

326

**Usage Example:**

327

328

```typescript

329

import { UUID } from "vscode-languageserver";

330

331

// Generate unique identifiers for registrations

332

const registrationId = UUID.generateUuid();

333

const workDoneToken = UUID.generateUuid();

334

335

connection.client.register({

336

registrations: [{

337

id: registrationId,

338

method: 'textDocument/hover',

339

registerOptions: { documentSelector: [{ scheme: 'file' }] }

340

}]

341

});

342

```

343

344

### Type Checking Utilities

345

346

Utility functions for runtime type checking and validation.

347

348

```typescript { .api }

349

/**

350

* Type checking utilities

351

*/

352

namespace Is {

353

/** Check if value is a function */

354

function func(value: any): value is Function;

355

356

/** Check if value is a string */

357

function string(value: any): value is string;

358

359

/** Check if value is a number */

360

function number(value: any): value is number;

361

362

/** Check if value is a boolean */

363

function boolean(value: any): value is boolean;

364

365

/** Check if value is undefined */

366

function undefined(value: any): value is undefined;

367

368

/** Check if value is defined (not undefined) */

369

function defined<T>(value: T | undefined): value is T;

370

}

371

```

372

373

**Usage Example:**

374

375

```typescript

376

import { Is } from "vscode-languageserver";

377

378

function processValue(value: any) {

379

if (Is.string(value)) {

380

// TypeScript knows value is string here

381

return value.toUpperCase();

382

} else if (Is.number(value)) {

383

// TypeScript knows value is number here

384

return value.toString();

385

} else if (Is.defined(value)) {

386

// TypeScript knows value is not undefined here

387

return JSON.stringify(value);

388

}

389

return 'undefined';

390

}

391

```

392

393

## Core Types

394

395

```typescript { .api }

396

interface SemanticTokens {

397

/** An optional result id */

398

resultId?: string;

399

/** The actual tokens */

400

data: number[];

401

}

402

403

interface SemanticTokensEdits {

404

/** An optional result id */

405

resultId?: string;

406

/** The edits to transform a previous result into a new result */

407

edits: SemanticTokensEdit[];

408

}

409

410

interface SemanticTokensEdit {

411

/** The start offset of the edit */

412

start: number;

413

/** The count of elements to remove */

414

deleteCount: number;

415

/** The elements to insert */

416

data?: number[];

417

}

418

419

interface RemoteWindow {

420

/** Show an error message */

421

showErrorMessage(message: string): void;

422

/** Show a warning message */

423

showWarningMessage(message: string): void;

424

/** Show an information message */

425

showInformationMessage(message: string): void;

426

}

427

428

type ProgressToken = number | string;

429

430

interface RegistrationParams {

431

registrations: Registration[];

432

}

433

434

interface Registration {

435

/** The id used to register the request */

436

id: string;

437

/** The method to register for */

438

method: string;

439

/** Options necessary for the registration */

440

registerOptions?: any;

441

}

442

443

interface UnregistrationParams {

444

unregisterations: Unregistration[];

445

}

446

447

interface Unregistration {

448

/** The id used to unregister the request or notification */

449

id: string;

450

/** The method to unregister for */

451

method: string;

452

}

453

454

interface Disposable {

455

dispose(): void;

456

}

457

```