diff --git a/src/json/jsonMode.ts b/src/json/jsonMode.ts index 84254c58..395a864b 100644 --- a/src/json/jsonMode.ts +++ b/src/json/jsonMode.ts @@ -118,7 +118,7 @@ function asDisposable(disposables: IDisposable[]): IDisposable { function disposeAll(disposables: IDisposable[]) { while (disposables.length) { - disposables.pop().dispose(); + disposables.pop()!.dispose(); } } diff --git a/src/json/jsonWorker.ts b/src/json/jsonWorker.ts index 8df3fee2..fa486329 100644 --- a/src/json/jsonWorker.ts +++ b/src/json/jsonWorker.ts @@ -8,9 +8,9 @@ import type { worker } from '../fillers/monaco-editor-core'; import { URI } from 'vscode-uri'; import { DiagnosticsOptions } from './monaco.contribution'; -let defaultSchemaRequestService; +let defaultSchemaRequestService: ((url: string) => Promise) | undefined; if (typeof fetch !== 'undefined') { - defaultSchemaRequestService = function (url) { + defaultSchemaRequestService = function (url: string) { return fetch(url).then((response) => response.text()); }; } @@ -32,7 +32,7 @@ export class JSONWorker { return resolvePath(base, relativePath); } }, - schemaRequestService: createData.enableSchemaRequest && defaultSchemaRequestService + schemaRequestService: createData.enableSchemaRequest ? defaultSchemaRequestService : undefined }); this._languageService.configure(this._languageSettings); } @@ -48,26 +48,35 @@ export class JSONWorker { async doComplete( uri: string, position: jsonService.Position - ): Promise { + ): Promise { let document = this._getTextDocument(uri); + if (!document) { + return null; + } let jsonDocument = this._languageService.parseJSONDocument(document); return this._languageService.doComplete(document, position, jsonDocument); } async doResolve(item: jsonService.CompletionItem): Promise { return this._languageService.doResolve(item); } - async doHover(uri: string, position: jsonService.Position): Promise { + async doHover(uri: string, position: jsonService.Position): Promise { let document = this._getTextDocument(uri); + if (!document) { + return null; + } let jsonDocument = this._languageService.parseJSONDocument(document); return this._languageService.doHover(document, position, jsonDocument); } async format( uri: string, - range: jsonService.Range, + range: jsonService.Range | null, options: jsonService.FormattingOptions ): Promise { let document = this._getTextDocument(uri); - let textEdits = this._languageService.format(document, range, options); + if (!document) { + return []; + } + let textEdits = this._languageService.format(document, range! /* TODO */, options); return Promise.resolve(textEdits); } async resetSchema(uri: string): Promise { @@ -75,12 +84,18 @@ export class JSONWorker { } async findDocumentSymbols(uri: string): Promise { let document = this._getTextDocument(uri); + if (!document) { + return []; + } let jsonDocument = this._languageService.parseJSONDocument(document); let symbols = this._languageService.findDocumentSymbols(document, jsonDocument); return Promise.resolve(symbols); } async findDocumentColors(uri: string): Promise { let document = this._getTextDocument(uri); + if (!document) { + return []; + } let jsonDocument = this._languageService.parseJSONDocument(document); let colorSymbols = this._languageService.findDocumentColors(document, jsonDocument); return Promise.resolve(colorSymbols); @@ -91,6 +106,9 @@ export class JSONWorker { range: jsonService.Range ): Promise { let document = this._getTextDocument(uri); + if (!document) { + return []; + } let jsonDocument = this._languageService.parseJSONDocument(document); let colorPresentations = this._languageService.getColorPresentations( document, @@ -105,6 +123,9 @@ export class JSONWorker { context?: { rangeLimit?: number } ): Promise { let document = this._getTextDocument(uri); + if (!document) { + return []; + } let ranges = this._languageService.getFoldingRanges(document, context); return Promise.resolve(ranges); } @@ -113,11 +134,14 @@ export class JSONWorker { positions: jsonService.Position[] ): Promise { let document = this._getTextDocument(uri); + if (!document) { + return []; + } let jsonDocument = this._languageService.parseJSONDocument(document); let ranges = this._languageService.getSelectionRanges(document, positions, jsonDocument); return Promise.resolve(ranges); } - private _getTextDocument(uri: string): jsonService.TextDocument { + private _getTextDocument(uri: string): jsonService.TextDocument | null { let models = this._ctx.getMirrorModels(); for (let model of models) { if (model.uri.toString() === uri) { diff --git a/src/json/languageFeatures.ts b/src/json/languageFeatures.ts index a26bd236..78c5d3b3 100644 --- a/src/json/languageFeatures.ts +++ b/src/json/languageFeatures.ts @@ -125,7 +125,7 @@ export class DiagnosticsAdapter { } } -function toSeverity(lsSeverity: number): MarkerSeverity { +function toSeverity(lsSeverity: number | undefined): MarkerSeverity { switch (lsSeverity) { case lsTypes.DiagnosticSeverity.Error: return MarkerSeverity.Error; @@ -157,14 +157,20 @@ function toDiagnostics(resource: Uri, diag: lsTypes.Diagnostic): editor.IMarkerD // --- completion ------ -function fromPosition(position: Position): lsTypes.Position { +function fromPosition(position: Position): lsTypes.Position; +function fromPosition(position: undefined): undefined; +function fromPosition(position: Position | undefined): lsTypes.Position | undefined; +function fromPosition(position: Position | undefined): lsTypes.Position | undefined { if (!position) { return void 0; } return { character: position.column - 1, line: position.lineNumber - 1 }; } -function fromRange(range: IRange): lsTypes.Range { +function fromRange(range: IRange): lsTypes.Range; +function fromRange(range: undefined): undefined; +function fromRange(range: IRange | undefined): lsTypes.Range | undefined; +function fromRange(range: IRange | undefined): lsTypes.Range | undefined { if (!range) { return void 0; } @@ -176,7 +182,10 @@ function fromRange(range: IRange): lsTypes.Range { end: { line: range.endLineNumber - 1, character: range.endColumn - 1 } }; } -function toRange(range: lsTypes.Range): Range { +function toRange(range: lsTypes.Range): Range; +function toRange(range: undefined): undefined; +function toRange(range: lsTypes.Range | undefined): Range | undefined; +function toRange(range: lsTypes.Range | undefined): Range | undefined { if (!range) { return void 0; } @@ -212,7 +221,7 @@ function isInsertReplaceEdit( ); } -function toCompletionItemKind(kind: number): languages.CompletionItemKind { +function toCompletionItemKind(kind: number | undefined): languages.CompletionItemKind { let mItemKind = languages.CompletionItemKind; switch (kind) { @@ -300,7 +309,10 @@ function fromCompletionItemKind(kind: languages.CompletionItemKind): lsTypes.Com return lsTypes.CompletionItemKind.Property; } -function toTextEdit(textEdit: lsTypes.TextEdit): editor.ISingleEditOperation { +function toTextEdit(textEdit: lsTypes.TextEdit): languages.TextEdit; +function toTextEdit(textEdit: undefined): undefined; +function toTextEdit(textEdit: lsTypes.TextEdit | undefined): languages.TextEdit | undefined; +function toTextEdit(textEdit: lsTypes.TextEdit | undefined): languages.TextEdit | undefined { if (!textEdit) { return void 0; } @@ -310,7 +322,7 @@ function toTextEdit(textEdit: lsTypes.TextEdit): editor.ISingleEditOperation { }; } -function toCommand(c: lsTypes.Command | undefined): languages.Command { +function toCommand(c: lsTypes.Command | undefined): languages.Command | undefined { return c && c.command === 'editor.action.triggerSuggest' ? { id: c.command, title: c.title, arguments: c.arguments } : undefined; @@ -328,7 +340,7 @@ export class CompletionAdapter implements languages.CompletionItemProvider { position: Position, context: languages.CompletionContext, token: CancellationToken - ): Promise { + ): Promise { const resource = model.uri; return this._worker(resource) @@ -371,7 +383,7 @@ export class CompletionAdapter implements languages.CompletionItemProvider { item.insertText = entry.textEdit.newText; } if (entry.additionalTextEdits) { - item.additionalTextEdits = entry.additionalTextEdits.map(toTextEdit); + item.additionalTextEdits = entry.additionalTextEdits.map(toTextEdit); } if (entry.insertTextFormat === lsTypes.InsertTextFormat.Snippet) { item.insertTextRules = languages.CompletionItemInsertTextRule.InsertAsSnippet; @@ -415,7 +427,7 @@ function toMarkdownString(entry: lsTypes.MarkupContent | lsTypes.MarkedString): function toMarkedStringArray( contents: lsTypes.MarkupContent | lsTypes.MarkedString | lsTypes.MarkedString[] -): IMarkdownString[] { +): IMarkdownString[] | undefined { if (!contents) { return void 0; } @@ -434,7 +446,7 @@ export class HoverAdapter implements languages.HoverProvider { model: editor.IReadOnlyModel, position: Position, token: CancellationToken - ): Promise { + ): Promise { let resource = model.uri; return this._worker(resource) @@ -514,7 +526,7 @@ export class DocumentSymbolAdapter implements languages.DocumentSymbolProvider { public provideDocumentSymbols( model: editor.IReadOnlyModel, token: CancellationToken - ): Promise { + ): Promise { const resource = model.uri; return this._worker(resource) @@ -550,7 +562,7 @@ export class DocumentFormattingEditProvider implements languages.DocumentFormatt model: editor.IReadOnlyModel, options: languages.FormattingOptions, token: CancellationToken - ): Promise { + ): Promise { const resource = model.uri; return this._worker(resource).then((worker) => { @@ -560,7 +572,7 @@ export class DocumentFormattingEditProvider implements languages.DocumentFormatt if (!edits || edits.length === 0) { return; } - return edits.map(toTextEdit); + return edits.map(toTextEdit); }); }); } @@ -576,7 +588,7 @@ export class DocumentRangeFormattingEditProvider range: Range, options: languages.FormattingOptions, token: CancellationToken - ): Promise { + ): Promise { const resource = model.uri; return this._worker(resource).then((worker) => { @@ -586,7 +598,7 @@ export class DocumentRangeFormattingEditProvider if (!edits || edits.length === 0) { return; } - return edits.map(toTextEdit); + return edits.map(toTextEdit); }); }); } @@ -598,7 +610,7 @@ export class DocumentColorAdapter implements languages.DocumentColorProvider { public provideDocumentColors( model: editor.IReadOnlyModel, token: CancellationToken - ): Promise { + ): Promise { const resource = model.uri; return this._worker(resource) @@ -618,7 +630,7 @@ export class DocumentColorAdapter implements languages.DocumentColorProvider { model: editor.IReadOnlyModel, info: languages.IColorInformation, token: CancellationToken - ): Promise { + ): Promise { const resource = model.uri; return this._worker(resource) @@ -637,7 +649,7 @@ export class DocumentColorAdapter implements languages.DocumentColorProvider { item.textEdit = toTextEdit(presentation.textEdit); } if (presentation.additionalTextEdits) { - item.additionalTextEdits = presentation.additionalTextEdits.map(toTextEdit); + item.additionalTextEdits = presentation.additionalTextEdits.map(toTextEdit); } return item; }); @@ -652,7 +664,7 @@ export class FoldingRangeAdapter implements languages.FoldingRangeProvider { model: editor.IReadOnlyModel, context: languages.FoldingContext, token: CancellationToken - ): Promise { + ): Promise { const resource = model.uri; return this._worker(resource) @@ -675,7 +687,7 @@ export class FoldingRangeAdapter implements languages.FoldingRangeProvider { } } -function toFoldingRangeKind(kind: lsTypes.FoldingRangeKind): languages.FoldingRangeKind { +function toFoldingRangeKind(kind: lsTypes.FoldingRangeKind): languages.FoldingRangeKind | undefined { switch (kind) { case lsTypes.FoldingRangeKind.Comment: return languages.FoldingRangeKind.Comment; @@ -694,16 +706,16 @@ export class SelectionRangeAdapter implements languages.SelectionRangeProvider { model: editor.IReadOnlyModel, positions: Position[], token: CancellationToken - ): Promise { + ): Promise { const resource = model.uri; return this._worker(resource) - .then((worker) => worker.getSelectionRanges(resource.toString(), positions.map(fromPosition))) + .then((worker) => worker.getSelectionRanges(resource.toString(), positions.map(fromPosition))) .then((selectionRanges) => { if (!selectionRanges) { return; } - return selectionRanges.map((selectionRange) => { + return selectionRanges.map((selectionRange: lsTypes.SelectionRange | undefined) => { const result: languages.SelectionRange[] = []; while (selectionRange) { result.push({ range: toRange(selectionRange.range) }); diff --git a/src/json/monaco.contribution.ts b/src/json/monaco.contribution.ts index 4487061a..958b5537 100644 --- a/src/json/monaco.contribution.ts +++ b/src/json/monaco.contribution.ts @@ -126,8 +126,8 @@ export interface LanguageServiceDefaults { class LanguageServiceDefaultsImpl implements LanguageServiceDefaults { private _onDidChange = new Emitter(); - private _diagnosticsOptions: DiagnosticsOptions; - private _modeConfiguration: ModeConfiguration; + private _diagnosticsOptions!: DiagnosticsOptions; + private _modeConfiguration!: ModeConfiguration; private _languageId: string; constructor( diff --git a/src/json/tokenization.ts b/src/json/tokenization.ts index 61925359..76650673 100644 --- a/src/json/tokenization.ts +++ b/src/json/tokenization.ts @@ -9,8 +9,8 @@ import { languages } from '../fillers/monaco-editor-core'; export function createTokenizationSupport(supportComments: boolean): languages.TokensProvider { return { getInitialState: () => new JSONState(null, null, false, null), - tokenize: (line, state, offsetDelta?, stopAtOffset?) => - tokenize(supportComments, line, state, offsetDelta, stopAtOffset) + tokenize: (line, state?) => + tokenize(supportComments, line, state) }; } @@ -67,15 +67,15 @@ class ParentsStack { } class JSONState implements languages.IState { - private _state: languages.IState; + private _state: languages.IState | null; - public scanError: ScanError; + public scanError: ScanError | null; public lastWasColon: boolean; public parents: ParentsStack | null; constructor( - state: languages.IState, - scanError: ScanError, + state: languages.IState | null, + scanError: ScanError | null, lastWasColon: boolean, parents: ParentsStack | null ) { @@ -103,7 +103,7 @@ class JSONState implements languages.IState { ); } - public getStateData(): languages.IState { + public getStateData(): languages.IState | null { return this._state; } @@ -146,8 +146,7 @@ function tokenize( comments: boolean, line: string, state: JSONState, - offsetDelta: number = 0, - stopAtOffset?: number + offsetDelta: number = 0 ): languages.ILineTokens { // handle multiline strings and block comments let numberOfInsertedCharacters = 0; diff --git a/src/json/workerManager.ts b/src/json/workerManager.ts index fcb3e77c..06e04eb7 100644 --- a/src/json/workerManager.ts +++ b/src/json/workerManager.ts @@ -15,12 +15,13 @@ export class WorkerManager { private _lastUsedTime: number; private _configChangeListener: IDisposable; - private _worker: editor.MonacoWebWorker; - private _client: Promise; + private _worker: editor.MonacoWebWorker | null; + private _client: Promise | null; constructor(defaults: LanguageServiceDefaults) { this._defaults = defaults; this._worker = null; + this._client = null; this._idleCheckInterval = window.setInterval(() => this._checkIfIdle(), 30 * 1000); this._lastUsedTime = 0; this._configChangeListener = this._defaults.onDidChange(() => this._stopWorker()); @@ -81,7 +82,9 @@ export class WorkerManager { _client = client; }) .then((_) => { - return this._worker.withSyncedResources(resources); + if (this._worker) { + return this._worker.withSyncedResources(resources); + } }) .then((_) => _client); }