Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use Strict Null Checks In TS Extension #16244

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 8 additions & 5 deletions extensions/typescript/src/features/bufferSyncSupport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,10 @@ export default class BufferSyncSupport {

public dispose(): void {
while (this.disposables.length) {
this.disposables.pop().dispose();
const obj = this.disposables.pop();
if (obj) {
obj.dispose();
}
}
}

Expand All @@ -191,7 +194,7 @@ export default class BufferSyncSupport {
}

private onDidCloseTextDocument(document: TextDocument): void {
let filepath: string = this.client.asAbsolutePath(document.uri);
let filepath = this.client.asAbsolutePath(document.uri);
if (!filepath) {
return;
}
Expand All @@ -208,7 +211,7 @@ export default class BufferSyncSupport {
}

private onDidChangeTextDocument(e: TextDocumentChangeEvent): void {
let filepath: string = this.client.asAbsolutePath(e.document.uri);
let filepath = this.client.asAbsolutePath(e.document.uri);
if (!filepath) {
return;
}
Expand All @@ -220,7 +223,7 @@ export default class BufferSyncSupport {
}

private onDidSaveTextDocument(document: TextDocument): void {
let filepath: string = this.client.asAbsolutePath(document.uri);
let filepath = this.client.asAbsolutePath(document.uri);
if (!filepath) {
return;
}
Expand Down Expand Up @@ -312,7 +315,7 @@ export default class BufferSyncSupport {
return cp.exec(cmd + ' ' + url);
}

let tscVersion: string = undefined;
let tscVersion: string | undefined = undefined;
try {
let out = cp.execSync('tsc --version', { encoding: 'utf8' });
if (out) {
Expand Down
29 changes: 18 additions & 11 deletions extensions/typescript/src/features/completionItemProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ export default class TypeScriptCompletionItemProvider implements CompletionItemP

public provideCompletionItems(document: TextDocument, position: Position, token: CancellationToken): Promise<CompletionItem[]> {
let filepath = this.client.asAbsolutePath(document.uri);
if (!filepath) {
return Promise.resolve<CompletionItem[]>([]);
}
let args: CompletionsRequestArgs = {
file: filepath,
line: position.line + 1,
Expand Down Expand Up @@ -120,14 +123,15 @@ export default class TypeScriptCompletionItemProvider implements CompletionItemP

let completionItems: CompletionItem[] = [];
let body = msg.body;

for (let i = 0; i < body.length; i++) {
let element = body[i];
let item = new MyCompletionItem(element);
item.document = document;
item.position = position;

completionItems.push(item);
if (body) {
for (let i = 0; i < body.length; i++) {
let element = body[i];
let item = new MyCompletionItem(element);
item.document = document;
item.position = position;

completionItems.push(item);
}
}

return completionItems;
Expand All @@ -139,16 +143,19 @@ export default class TypeScriptCompletionItemProvider implements CompletionItemP

public resolveCompletionItem(item: CompletionItem, token: CancellationToken): any | Thenable<any> {
if (item instanceof MyCompletionItem) {

const filepath = this.client.asAbsolutePath(item.document.uri);
if (!filepath) {
return null;
}
let args: CompletionDetailsRequestArgs = {
file: this.client.asAbsolutePath(item.document.uri),
file: filepath,
line: item.position.line + 1,
offset: item.position.character + 1,
entryNames: [item.label]
};
return this.client.execute('completionEntryDetails', args, token).then((response) => {
let details = response.body;
let detail: CompletionEntryDetails = null;
let detail: CompletionEntryDetails | null = null;
if (details && details.length > 0) {
detail = details[0];
item.documentation = Previewer.plain(detail.documentation);
Expand Down
20 changes: 12 additions & 8 deletions extensions/typescript/src/features/definitionProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

'use strict';

import { DefinitionProvider, TextDocument, Position, Range, CancellationToken, Location } from 'vscode';
import { DefinitionProvider, TextDocument, Position, Range, CancellationToken, Definition, Location } from 'vscode';

import * as Proto from '../protocol';
import { ITypescriptServiceClient } from '../typescriptService';
Expand All @@ -20,19 +20,23 @@ export default class TypeScriptDefinitionProvider implements DefinitionProvider
this.client = client;
}

public provideDefinition(document: TextDocument, position: Position, token: CancellationToken): Promise<Location> {
public provideDefinition(document: TextDocument, position: Position, token: CancellationToken): Promise<Definition | null> {
const filepath = this.client.asAbsolutePath(document.uri);
if (!filepath) {
return Promise.resolve(null);
}
let args: Proto.FileLocationRequestArgs = {
file: this.client.asAbsolutePath(document.uri),
file: filepath,
line: position.line + 1,
offset: position.character + 1
};
if (!args.file) {
return Promise.resolve<Location>(null);
return Promise.resolve(null);
}
return this.client.execute('definition', args, token).then(response => {
let locations: Proto.FileSpan[] = response.body;
let locations: Proto.FileSpan[] = response.body || [];
if (!locations || locations.length === 0) {
return null;
return [] as Definition;
}
return locations.map(location => {
let resource = this.client.asUrl(location.file);
Expand All @@ -41,10 +45,10 @@ export default class TypeScriptDefinitionProvider implements DefinitionProvider
} else {
return new Location(resource, new Range(location.start.line - 1, location.start.offset - 1, location.end.line - 1, location.end.offset - 1));
}
});
}).filter(x => x !== null) as Location[];
}, (error) => {
this.client.error(`'definition' request failed with error.`, error);
return null;
return [] as Definition;
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,12 @@ export default class TypeScriptDocumentHighlightProvider implements DocumentHigh
}

public provideDocumentHighlights(resource: TextDocument, position: Position, token: CancellationToken): Promise<DocumentHighlight[]> {
const filepath = this.client.asAbsolutePath(resource.uri);
if (!filepath) {
return Promise.resolve<DocumentHighlight[]>([]);
}
let args: Proto.FileLocationRequestArgs = {
file: this.client.asAbsolutePath(resource.uri),
file: filepath,
line: position.line + 1,
offset: position.character + 1
};
Expand All @@ -36,6 +40,7 @@ export default class TypeScriptDocumentHighlightProvider implements DocumentHigh
item.isWriteAccess ? DocumentHighlightKind.Write : DocumentHighlightKind.Read);
});
}
return [];
}, (err) => {
this.client.error(`'occurrences' request failed with error.`, err);
return [];
Expand Down
10 changes: 7 additions & 3 deletions extensions/typescript/src/features/documentSymbolProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,12 @@ export default class TypeScriptDocumentSymbolProvider implements DocumentSymbolP
}

public provideDocumentSymbols(resource: TextDocument, token: CancellationToken): Promise<SymbolInformation[]> {
const filepath = this.client.asAbsolutePath(resource.uri);
if (!filepath) {
return Promise.resolve<SymbolInformation[]>([]);
}
let args: Proto.FileRequestArgs = {
file: this.client.asAbsolutePath(resource.uri)
file: filepath
};
if (!args.file) {
return Promise.resolve<SymbolInformation[]>([]);
Expand All @@ -53,7 +57,7 @@ export default class TypeScriptDocumentSymbolProvider implements DocumentSymbolP
if (realIndent !== 0 && !foldingMap[key]) {
let result = new SymbolInformation(item.text,
outlineTypeTable[item.kind] || SymbolKind.Variable,
containerLabel,
'' + containerLabel,
new Location(resource.uri, textSpan2Range(item.spans[0])));
foldingMap[key] = result;
bucket.push(result);
Expand All @@ -68,7 +72,7 @@ export default class TypeScriptDocumentSymbolProvider implements DocumentSymbolP
function convertNavTree(bucket: SymbolInformation[], item: Proto.NavigationTree, containerLabel?: string): void {
let result = new SymbolInformation(item.text,
outlineTypeTable[item.kind] || SymbolKind.Variable,
containerLabel,
'' + containerLabel,
new Location(resource.uri, textSpan2Range(item.spans[0]))
);
if (item.childItems && item.childItems.length > 0) {
Expand Down
29 changes: 24 additions & 5 deletions extensions/typescript/src/features/formattingProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export default class TypeScriptFormattingProvider implements DocumentRangeFormat

private client: ITypescriptServiceClient;
private config: Configuration;
private formatOptions: { [key: string]: Proto.FormatCodeSettings; };
private formatOptions: { [key: string]: Proto.FormatCodeSettings | undefined; };

public constructor(client: ITypescriptServiceClient) {
this.client = client;
Expand Down Expand Up @@ -106,8 +106,12 @@ export default class TypeScriptFormattingProvider implements DocumentRangeFormat
if (currentOptions && currentOptions.tabSize === options.tabSize && currentOptions.indentSize === options.tabSize && currentOptions.convertTabsToSpaces === options.insertSpaces) {
return Promise.resolve(currentOptions);
} else {
const absPath = this.client.asAbsolutePath(document.uri);
if (!absPath) {
return Promise.resolve(Object.create(null));
}
let args: Proto.ConfigureRequestArguments = {
file: this.client.asAbsolutePath(document.uri),
file: absPath,
formatOptions: this.getFormatOptions(options)
};
return this.client.execute('configure', args, token).then((response) => {
Expand All @@ -120,7 +124,11 @@ export default class TypeScriptFormattingProvider implements DocumentRangeFormat
private doFormat(document: TextDocument, options: FormattingOptions, args: Proto.FormatRequestArgs, token: CancellationToken): Promise<TextEdit[]> {
return this.ensureFormatOptions(document, options, token).then(() => {
return this.client.execute('format', args, token).then((response): TextEdit[] => {
return response.body.map(this.codeEdit2SingleEditOperation);
if (response.body) {
return response.body.map(this.codeEdit2SingleEditOperation);
} else {
return [];
}
}, (err: any) => {
this.client.error(`'format' request failed with error.`, err);
return [];
Expand All @@ -129,8 +137,12 @@ export default class TypeScriptFormattingProvider implements DocumentRangeFormat
}

public provideDocumentRangeFormattingEdits(document: TextDocument, range: Range, options: FormattingOptions, token: CancellationToken): Promise<TextEdit[]> {
const absPath = this.client.asAbsolutePath(document.uri);
if (!absPath) {
return Promise.resolve([]);
}
let args: Proto.FormatRequestArgs = {
file: this.client.asAbsolutePath(document.uri),
file: absPath,
line: range.start.line + 1,
offset: range.start.character + 1,
endLine: range.end.line + 1,
Expand All @@ -140,8 +152,12 @@ export default class TypeScriptFormattingProvider implements DocumentRangeFormat
}

public provideOnTypeFormattingEdits(document: TextDocument, position: Position, ch: string, options: FormattingOptions, token: CancellationToken): Promise<TextEdit[]> {
const filepath = this.client.asAbsolutePath(document.uri);
if (!filepath) {
return Promise.resolve([]);
}
let args: Proto.FormatOnKeyRequestArgs = {
file: this.client.asAbsolutePath(document.uri),
file: filepath,
line: position.line + 1,
offset: position.character + 1,
key: ch
Expand All @@ -151,6 +167,9 @@ export default class TypeScriptFormattingProvider implements DocumentRangeFormat
return this.client.execute('formatonkey', args, token).then((response): TextEdit[] => {
let edits = response.body;
let result: TextEdit[] = [];
if (!edits) {
return result;
}
for (let edit of edits) {
let textEdit = this.codeEdit2SingleEditOperation(edit);
let range = textEdit.range;
Expand Down
12 changes: 8 additions & 4 deletions extensions/typescript/src/features/hoverProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,20 @@ export default class TypeScriptHoverProvider implements HoverProvider {
this.client = client;
}

public provideHover(document: TextDocument, position: Position, token: CancellationToken): Promise<Hover> {
public provideHover(document: TextDocument, position: Position, token: CancellationToken): Promise<Hover | undefined | null> {
const filepath = this.client.asAbsolutePath(document.uri);
if (!filepath) {
return Promise.resolve(null);
}
let args: Proto.FileLocationRequestArgs = {
file: this.client.asAbsolutePath(document.uri),
file: filepath,
line: position.line + 1,
offset: position.character + 1
};
if (!args.file) {
return Promise.resolve<Hover>(null);
return Promise.resolve(null);
}
return this.client.execute('quickinfo', args, token).then((response): Hover => {
return this.client.execute('quickinfo', args, token).then((response): Hover | undefined => {
let data = response.body;
if (data) {
return new Hover(
Expand Down