Move PHP extension to strict mode

Compile the PHP extension with strict mode TS. Mostly adding annotations where values can be null or undefined.
This commit is contained in:
Matt Bierner 2017-11-06 14:20:53 -08:00
parent e5b9b820ef
commit 6bab0e0cc0
6 changed files with 34 additions and 31 deletions

View file

@ -27,7 +27,7 @@ export default class PHPCompletionItemProvider implements CompletionItemProvider
} }
var added: any = {}; var added: any = {};
var createNewProposal = function (kind: CompletionItemKind, name: string, entry: phpGlobals.IEntry): CompletionItem { var createNewProposal = function (kind: CompletionItemKind, name: string, entry: phpGlobals.IEntry | null): CompletionItem {
var proposal: CompletionItem = new CompletionItem(name); var proposal: CompletionItem = new CompletionItem(name);
proposal.kind = kind; proposal.kind = kind;
if (entry) { if (entry) {
@ -85,7 +85,7 @@ export default class PHPCompletionItemProvider implements CompletionItemProvider
var text = document.getText(); var text = document.getText();
if (prefix[0] === '$') { if (prefix[0] === '$') {
var variableMatch = /\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)/g; var variableMatch = /\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)/g;
var match: RegExpExecArray = null; var match: RegExpExecArray | null = null;
while (match = variableMatch.exec(text)) { while (match = variableMatch.exec(text)) {
var word = match[0]; var word = match[0];
if (!added[word]) { if (!added[word]) {
@ -95,7 +95,7 @@ export default class PHPCompletionItemProvider implements CompletionItemProvider
} }
} }
var functionMatch = /function\s+([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\s*\(/g; var functionMatch = /function\s+([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\s*\(/g;
var match: RegExpExecArray = null; var match: RegExpExecArray | null = null;
while (match = functionMatch.exec(text)) { while (match = functionMatch.exec(text)) {
var word = match[1]; var word = match[1];
if (!added[word]) { if (!added[word]) {

View file

@ -11,10 +11,10 @@ import { textToMarkedString } from './utils/markedTextUtil';
export default class PHPHoverProvider implements HoverProvider { export default class PHPHoverProvider implements HoverProvider {
public provideHover(document: TextDocument, position: Position, token: CancellationToken): Hover { public provideHover(document: TextDocument, position: Position, token: CancellationToken): Hover | undefined {
let enable = workspace.getConfiguration('php').get<boolean>('suggest.basic', true); let enable = workspace.getConfiguration('php').get<boolean>('suggest.basic', true);
if (!enable) { if (!enable) {
return null; return;
} }
let wordRange = document.getWordRangeAtPosition(position); let wordRange = document.getWordRangeAtPosition(position);

View file

@ -69,7 +69,7 @@ class BackwardIterator {
export default class PHPSignatureHelpProvider implements SignatureHelpProvider { export default class PHPSignatureHelpProvider implements SignatureHelpProvider {
public provideSignatureHelp(document: TextDocument, position: Position, token: CancellationToken): Promise<SignatureHelp> { public provideSignatureHelp(document: TextDocument, position: Position, token: CancellationToken): Promise<SignatureHelp> | null {
let enable = workspace.getConfiguration('php').get<boolean>('suggest.basic', true); let enable = workspace.getConfiguration('php').get<boolean>('suggest.basic', true);
if (!enable) { if (!enable) {
return null; return null;
@ -95,7 +95,7 @@ export default class PHPSignatureHelpProvider implements SignatureHelpProvider {
let signatureInfo = new SignatureInformation(ident + paramsString, entry.description); let signatureInfo = new SignatureInformation(ident + paramsString, entry.description);
var re = /\w*\s+\&?\$[\w_\.]+|void/g; var re = /\w*\s+\&?\$[\w_\.]+|void/g;
var match: RegExpExecArray = null; var match: RegExpExecArray | null = null;
while ((match = re.exec(paramsString)) !== null) { while ((match = re.exec(paramsString)) !== null) {
signatureInfo.parameters.push({ label: match[0], documentation: '' }); signatureInfo.parameters.push({ label: match[0], documentation: '' });
} }

View file

@ -29,9 +29,9 @@ export interface ITask<T> {
*/ */
export class Throttler<T> { export class Throttler<T> {
private activePromise: Promise<T>; private activePromise: Promise<T> | null;
private queuedPromise: Promise<T>; private queuedPromise: Promise<T> | null;
private queuedPromiseFactory: ITask<Promise<T>>; private queuedPromiseFactory: ITask<Promise<T>> | null;
constructor() { constructor() {
this.activePromise = null; this.activePromise = null;
@ -47,26 +47,26 @@ export class Throttler<T> {
var onComplete = () => { var onComplete = () => {
this.queuedPromise = null; this.queuedPromise = null;
var result = this.queue(this.queuedPromiseFactory); var result = this.queue(this.queuedPromiseFactory!);
this.queuedPromiseFactory = null; this.queuedPromiseFactory = null;
return result; return result;
}; };
this.queuedPromise = new Promise<T>((resolve, reject) => { this.queuedPromise = new Promise<T>((resolve, reject) => {
this.activePromise.then(onComplete, onComplete).then(resolve); this.activePromise!.then(onComplete, onComplete).then(resolve);
}); });
} }
return new Promise<T>((resolve, reject) => { return new Promise<T>((resolve, reject) => {
this.queuedPromise.then(resolve, reject); this.queuedPromise!.then(resolve, reject);
}); });
} }
this.activePromise = promiseFactory(); this.activePromise = promiseFactory();
return new Promise<T>((resolve, reject) => { return new Promise<T>((resolve, reject) => {
this.activePromise.then((result: T) => { this.activePromise!.then((result: T) => {
this.activePromise = null; this.activePromise = null;
resolve(result); resolve(result);
}, (err: any) => { }, (err: any) => {
@ -103,10 +103,10 @@ export class Throttler<T> {
export class Delayer<T> { export class Delayer<T> {
public defaultDelay: number; public defaultDelay: number;
private timeout: NodeJS.Timer; private timeout: NodeJS.Timer | null;
private completionPromise: Promise<T>; private completionPromise: Promise<T> | null;
private onResolve: (value: T | Thenable<T>) => void; private onResolve: ((value: T | Thenable<T> | undefined) => void) | null;
private task: ITask<T>; private task: ITask<T> | null;
constructor(defaultDelay: number) { constructor(defaultDelay: number) {
this.defaultDelay = defaultDelay; this.defaultDelay = defaultDelay;
@ -127,7 +127,7 @@ export class Delayer<T> {
this.completionPromise = null; this.completionPromise = null;
this.onResolve = null; this.onResolve = null;
var result = this.task(); var result = this.task!();
this.task = null; this.task = null;
return result; return result;
@ -136,7 +136,7 @@ export class Delayer<T> {
this.timeout = setTimeout(() => { this.timeout = setTimeout(() => {
this.timeout = null; this.timeout = null;
this.onResolve(null); this.onResolve!(undefined);
}, delay); }, delay);
return this.completionPromise; return this.completionPromise;

View file

@ -16,7 +16,7 @@ let localize = nls.loadMessageBundle();
export class LineDecoder { export class LineDecoder {
private stringDecoder: NodeStringDecoder; private stringDecoder: NodeStringDecoder;
private remaining: string; private remaining: string | null;
constructor(encoding: string = 'utf8') { constructor(encoding: string = 'utf8') {
this.stringDecoder = new StringDecoder(encoding); this.stringDecoder = new StringDecoder(encoding);
@ -55,7 +55,7 @@ export class LineDecoder {
return result; return result;
} }
public end(): string { public end(): string | null {
return this.remaining; return this.remaining;
} }
} }
@ -88,17 +88,17 @@ export default class PHPValidationProvider {
private static FileArgs: string[] = ['-l', '-n', '-d', 'display_errors=On', '-d', 'log_errors=Off', '-f']; private static FileArgs: string[] = ['-l', '-n', '-d', 'display_errors=On', '-d', 'log_errors=Off', '-f'];
private validationEnabled: boolean; private validationEnabled: boolean;
private executableIsUserDefined: boolean; private executableIsUserDefined: boolean | undefined;
private executable: string; private executable: string | undefined;
private trigger: RunTrigger; private trigger: RunTrigger;
private pauseValidation: boolean; private pauseValidation: boolean;
private documentListener: vscode.Disposable; private documentListener: vscode.Disposable | null;
private diagnosticCollection: vscode.DiagnosticCollection; private diagnosticCollection: vscode.DiagnosticCollection;
private delayers: { [key: string]: ThrottledDelayer<void> }; private delayers: { [key: string]: ThrottledDelayer<void> };
constructor(private workspaceStore: vscode.Memento) { constructor(private workspaceStore: vscode.Memento) {
this.executable = null; this.executable = undefined;
this.validationEnabled = true; this.validationEnabled = true;
this.trigger = RunTrigger.onSave; this.trigger = RunTrigger.onSave;
this.pauseValidation = false; this.pauseValidation = false;
@ -145,7 +145,7 @@ export default class PHPValidationProvider {
} }
this.trigger = RunTrigger.from(section.get<string>('validate.run', RunTrigger.strings.onSave)); this.trigger = RunTrigger.from(section.get<string>('validate.run', RunTrigger.strings.onSave));
} }
if (this.executableIsUserDefined !== true && this.workspaceStore.get<string>(CheckedExecutablePath, undefined) !== void 0) { if (this.executableIsUserDefined !== true && this.workspaceStore.get<string | undefined>(CheckedExecutablePath, undefined) !== void 0) {
vscode.commands.executeCommand('setContext', 'php.untrustValidationExecutableContext', true); vscode.commands.executeCommand('setContext', 'php.untrustValidationExecutableContext', true);
} }
this.delayers = Object.create(null); this.delayers = Object.create(null);
@ -195,7 +195,7 @@ export default class PHPValidationProvider {
}; };
if (this.executableIsUserDefined !== void 0 && !this.executableIsUserDefined) { if (this.executableIsUserDefined !== void 0 && !this.executableIsUserDefined) {
let checkedExecutablePath = this.workspaceStore.get<string>(CheckedExecutablePath, undefined); let checkedExecutablePath = this.workspaceStore.get<string | undefined>(CheckedExecutablePath, undefined);
if (!checkedExecutablePath || checkedExecutablePath !== this.executable) { if (!checkedExecutablePath || checkedExecutablePath !== this.executable) {
vscode.window.showInformationMessage<MessageItem>( vscode.window.showInformationMessage<MessageItem>(
localize('php.useExecutablePath', 'Do you allow {0} (defined as a workspace setting) to be executed to lint PHP files?', this.executable), localize('php.useExecutablePath', 'Do you allow {0} (defined as a workspace setting) to be executed to lint PHP files?', this.executable),
@ -286,7 +286,7 @@ export default class PHPValidationProvider {
} }
private showError(error: any, executable: string): void { private showError(error: any, executable: string): void {
let message: string = null; let message: string | null = null;
if (error.code === 'ENOENT') { if (error.code === 'ENOENT') {
if (this.executable) { if (this.executable) {
message = localize('wrongExecutable', 'Cannot validate since {0} is not a valid php executable. Use the setting \'php.validate.executablePath\' to configure the PHP executable.', executable); message = localize('wrongExecutable', 'Cannot validate since {0} is not a valid php executable. Use the setting \'php.validate.executablePath\' to configure the PHP executable.', executable);
@ -296,6 +296,8 @@ export default class PHPValidationProvider {
} else { } else {
message = error.message ? error.message : localize('unknownReason', 'Failed to run php using path: {0}. Reason is unknown.', executable); message = error.message ? error.message : localize('unknownReason', 'Failed to run php using path: {0}. Reason is unknown.', executable);
} }
vscode.window.showInformationMessage(message); if (message) {
vscode.window.showInformationMessage(message);
}
} }
} }

View file

@ -5,7 +5,8 @@
"es2015" "es2015"
], ],
"module": "commonjs", "module": "commonjs",
"outDir": "./out" "outDir": "./out",
"strict": true
}, },
"include": [ "include": [
"src/**/*" "src/**/*"