From ca162090325e35fe8479d90698b35b2d89360f7f Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Fri, 29 Jan 2016 14:43:50 -0800 Subject: [PATCH] Make compiler strictThis clean. --- src/compiler/core.ts | 19 ++++++----- src/compiler/program.ts | 3 +- src/compiler/sourcemap.ts | 8 ++--- src/compiler/sys.ts | 2 +- src/compiler/types.ts | 18 +++++----- src/compiler/utilities.ts | 20 +++++------ src/harness/harness.ts | 32 ++++++++--------- src/harness/loggedIO.ts | 34 ++++++++++--------- src/server/editorServices.ts | 2 +- src/server/node.d.ts | 4 +-- .../formatting/ruleOperationContext.ts | 4 +-- src/services/utilities.ts | 2 +- 12 files changed, 77 insertions(+), 71 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 21536da36ff..ab8de44ec98 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -818,25 +818,26 @@ namespace ts { getSignatureConstructor(): new (checker: TypeChecker) => Signature; } + // TODO: Add a 'this' parameter after I update the previous-version compiler function Symbol(flags: SymbolFlags, name: string) { - this.flags = flags; - this.name = name; - this.declarations = undefined; + (this).flags = flags; + (this).name = name; + (this).declarations = undefined; } function Type(checker: TypeChecker, flags: TypeFlags) { - this.flags = flags; + (this).flags = flags; } function Signature(checker: TypeChecker) { } function Node(kind: SyntaxKind, pos: number, end: number) { - this.kind = kind; - this.pos = pos; - this.end = end; - this.flags = NodeFlags.None; - this.parent = undefined; + (this).kind = kind; + (this).pos = pos; + (this).end = end; + (this).flags = NodeFlags.None; + (this).parent = undefined; } export let objectAllocator: ObjectAllocator = { diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 803ae47b0fd..88c77aa5759 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -933,8 +933,9 @@ namespace ts { return noDiagnosticsTypeChecker || (noDiagnosticsTypeChecker = createTypeChecker(program, /*produceDiagnostics:*/ false)); } + // TODO: needs to have this: Program function emit(sourceFile?: SourceFile, writeFileCallback?: WriteFileCallback, cancellationToken?: CancellationToken): EmitResult { - return runWithCancellationToken(() => emitWorker(this, sourceFile, writeFileCallback, cancellationToken)); + return runWithCancellationToken(() => emitWorker((this), sourceFile, writeFileCallback, cancellationToken)); } function isEmitBlocked(emitFileName: string): boolean { diff --git a/src/compiler/sourcemap.ts b/src/compiler/sourcemap.ts index 8abf1432b0c..fb61f8b78b8 100644 --- a/src/compiler/sourcemap.ts +++ b/src/compiler/sourcemap.ts @@ -4,10 +4,10 @@ namespace ts { export interface SourceMapWriter { getSourceMapData(): SourceMapData; - setSourceFile(sourceFile: SourceFile): void; - emitPos(pos: number): void; - emitStart(range: TextRange): void; - emitEnd(range: TextRange, stopOverridingSpan?: boolean): void; + setSourceFile: (sourceFile: SourceFile) => void; + emitPos: (pos: number) => void; + emitStart: (range: TextRange) => void; + emitEnd: (range: TextRange, stopOverridingSpan?: boolean) => void; changeEmitSourcePos(): void; getText(): string; getSourceMappingURL(): string; diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index bf25d39aa43..1a9da39bf9a 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -63,7 +63,7 @@ namespace ts { useCaseSensitiveFileNames?: boolean; echo(s: string): void; quit(exitCode?: number): void; - fileExists(path: string): boolean; + fileExists: (path: string) => boolean; directoryExists(path: string): boolean; createDirectory(path: string): void; resolvePath(path: string): string; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 796529d9d4f..9c2612d96b6 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1593,8 +1593,8 @@ namespace ts { } export interface ScriptReferenceHost { - getCompilerOptions(): CompilerOptions; - getSourceFile(fileName: string): SourceFile; + getCompilerOptions: () => CompilerOptions; + getSourceFile: (fileName: string) => SourceFile; getCurrentDirectory(): string; } @@ -1625,7 +1625,7 @@ namespace ts { /** * Get a list of files in the program */ - getSourceFiles(): SourceFile[]; + getSourceFiles: () => SourceFile[]; /** * Emits the JavaScript and declaration files. If targetSourceFile is not specified, then @@ -1650,7 +1650,7 @@ namespace ts { */ getTypeChecker(): TypeChecker; - /* @internal */ getCommonSourceDirectory(): string; + /* @internal */ getCommonSourceDirectory: () => string; // For testing purposes only. Should not be used by any other consumers (including the // language service). @@ -1781,7 +1781,7 @@ namespace ts { buildParameterDisplay(parameter: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; buildTypeParameterDisplay(tp: TypeParameter, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; buildTypeParameterDisplayFromSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaraiton?: Node, flags?: TypeFormatFlags): void; - buildDisplayForParametersAndDelimiters(parameters: Symbol[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; + buildDisplayForParametersAndDelimiters(thisType: Type, parameters: Symbol[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; buildDisplayForTypeParametersAndDelimiters(typeParameters: TypeParameter[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; buildReturnTypeDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; } @@ -1905,11 +1905,11 @@ namespace ts { getReferencedImportDeclaration(node: Identifier): Declaration; getReferencedDeclarationWithCollidingName(node: Identifier): Declaration; isDeclarationWithCollidingName(node: Declaration): boolean; - isValueAliasDeclaration(node: Node): boolean; - isReferencedAliasDeclaration(node: Node, checkChildren?: boolean): boolean; + isValueAliasDeclaration: (node: Node) => boolean; + isReferencedAliasDeclaration: (node: Node, checkChildren?: boolean) => boolean; isTopLevelValueImportEqualsWithEntityName(node: ImportEqualsDeclaration): boolean; getNodeCheckFlags(node: Node): NodeCheckFlags; - isDeclarationVisible(node: Declaration): boolean; + isDeclarationVisible: (node: Declaration) => boolean; collectLinkedAliases(node: Identifier): Node[]; isImplementationOfOverload(node: FunctionLikeDeclaration): boolean; writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void; @@ -2279,6 +2279,7 @@ namespace ts { declaration: SignatureDeclaration; // Originating declaration typeParameters: TypeParameter[]; // Type parameters (undefined if non-generic) parameters: Symbol[]; // Parameters + thisType?: Type; // type of this-type /* @internal */ resolvedReturnType: Type; // Resolved return type /* @internal */ @@ -2429,6 +2430,7 @@ namespace ts { rootDir?: string; sourceMap?: boolean; sourceRoot?: string; + strictThis?: boolean, suppressExcessPropertyErrors?: boolean; suppressImplicitAnyIndexErrors?: boolean; target?: ScriptTarget; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index bab66eb0688..bce821c3756 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -32,11 +32,11 @@ namespace ts { } export interface EmitHost extends ScriptReferenceHost { - getSourceFiles(): SourceFile[]; + getSourceFiles: () => SourceFile[]; - getCommonSourceDirectory(): string; - getCanonicalFileName(fileName: string): string; - getNewLine(): string; + getCommonSourceDirectory: () => string; + getCanonicalFileName: (fileName: string) => string; + getNewLine: () => string; isEmitBlocked(emitFileName: string): boolean; @@ -1869,11 +1869,11 @@ namespace ts { } export interface EmitTextWriter { - write(s: string): void; - writeTextOfNode(text: string, node: Node): void; - writeLine(): void; - increaseIndent(): void; - decreaseIndent(): void; + write: (s: string) => void; + writeTextOfNode: (text: string, node: Node) => void; + writeLine: () => void; + increaseIndent: () => void; + decreaseIndent: () => void; getText(): string; rawWrite(s: string): void; writeLiteral(s: string): void; @@ -2490,7 +2490,7 @@ namespace ts { * as the fallback implementation does not check for circular references by default. */ export const stringify: (value: any) => string = typeof JSON !== "undefined" && JSON.stringify - ? JSON.stringify + ? JSON.stringify : stringifyFallback; /** diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 2b0c95c0a61..3b211a0d91a 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -417,24 +417,24 @@ namespace Harness.Path { namespace Harness { export interface IO { - newLine(): string; - getCurrentDirectory(): string; - useCaseSensitiveFileNames(): boolean; - resolvePath(path: string): string; - readFile(path: string): string; - writeFile(path: string, contents: string): void; - directoryName(path: string): string; - createDirectory(path: string): void; - fileExists(fileName: string): boolean; - directoryExists(path: string): boolean; - deleteFile(fileName: string): void; - listFiles(path: string, filter: RegExp, options?: { recursive?: boolean }): string[]; - log(text: string): void; - getMemoryUsage?(): number; args(): string[]; - getExecutingFilePath(): string; - exit(exitCode?: number): void; + newLine(): string; + readFile(this: ts.System | IO, path: string): string; + writeFile(path: string, contents: string): void; + resolvePath(path: string): string; + fileExists: (fileName: string) => boolean; + directoryExists: (path: string) => boolean; + createDirectory(path: string): void; + getExecutingFilePath(this: ts.System | IO): string; + getCurrentDirectory(): string; readDirectory(path: string, extension?: string, exclude?: string[]): string[]; + getMemoryUsage?(): number; + exit(exitCode?: number): void; + deleteFile(fileName: string): void; + directoryName: (path: string) => string; + listFiles(path: string, filter: RegExp, options?: { recursive?: boolean }): string[]; + log: (text: string) => void; + useCaseSensitiveFileNames(): boolean; } export var IO: IO; diff --git a/src/harness/loggedIO.ts b/src/harness/loggedIO.ts index 3d51682f745..dbc05112f3e 100644 --- a/src/harness/loggedIO.ts +++ b/src/harness/loggedIO.ts @@ -70,11 +70,11 @@ interface IOLog { interface PlaybackControl { startReplayFromFile(logFileName: string): void; - startReplayFromString(logContents: string): void; - startReplayFromData(log: IOLog): void; + startReplayFromString(this: PlaybackControl, logContents: string): void; + startReplayFromData(this: PlaybackControl, log: IOLog): void; endReplay(): void; startRecord(logFileName: string): void; - endRecord(): void; + endRecord(this: PlaybackControl): void; } namespace Playback { @@ -127,6 +127,8 @@ namespace Playback { function initWrapper(wrapper: PlaybackSystem, underlying: ts.System): void; function initWrapper(wrapper: PlaybackIO, underlying: Harness.IO): void; function initWrapper(wrapper: PlaybackSystem | PlaybackIO, underlying: ts.System | Harness.IO): void { + // TODO: Define a common interface over ts.System | Harness.IO and stop passing a union type. + const underlyingShim: any = underlying; ts.forEach(Object.keys(underlying), prop => { (wrapper)[prop] = (underlying)[prop]; }); @@ -154,20 +156,20 @@ namespace Playback { }; wrapper.startReplayFromFile = logFn => { - wrapper.startReplayFromString(underlying.readFile(logFn)); + wrapper.startReplayFromString(underlyingShim.readFile(logFn)); }; wrapper.endRecord = () => { if (recordLog !== undefined) { let i = 0; const fn = () => recordLogFileNameBase + i + ".json"; - while (underlying.fileExists(fn())) i++; - underlying.writeFile(fn(), JSON.stringify(recordLog)); + while (underlyingShim.fileExists(fn())) i++; + underlyingShim.writeFile(fn(), JSON.stringify(recordLog)); recordLog = undefined; } }; wrapper.fileExists = recordReplay(wrapper.fileExists, underlying)( - path => callAndRecord(underlying.fileExists(path), recordLog.fileExists, { path }), + path => callAndRecord(underlyingShim.fileExists(path), recordLog.fileExists, { path }), memoize(path => { // If we read from the file, it must exist if (findResultByPath(wrapper, replayLog.filesRead, path, null) !== null) { @@ -184,10 +186,10 @@ namespace Playback { return replayLog.executingPath; } else if (recordLog !== undefined) { - return recordLog.executingPath = underlying.getExecutingFilePath(); + return recordLog.executingPath = underlyingShim.getExecutingFilePath(); } else { - return underlying.getExecutingFilePath(); + return underlyingShim.getExecutingFilePath(); } }; @@ -196,20 +198,20 @@ namespace Playback { return replayLog.currentDirectory || ""; } else if (recordLog !== undefined) { - return recordLog.currentDirectory = underlying.getCurrentDirectory(); + return recordLog.currentDirectory = underlyingShim.getCurrentDirectory(); } else { - return underlying.getCurrentDirectory(); + return underlyingShim.getCurrentDirectory(); } }; wrapper.resolvePath = recordReplay(wrapper.resolvePath, underlying)( - path => callAndRecord(underlying.resolvePath(path), recordLog.pathsResolved, { path }), + path => callAndRecord(underlyingShim.resolvePath(path), recordLog.pathsResolved, { path }), memoize(path => findResultByFields(replayLog.pathsResolved, { path }, !ts.isRootedDiskPath(ts.normalizeSlashes(path)) && replayLog.currentDirectory ? replayLog.currentDirectory + "/" + path : ts.normalizeSlashes(path)))); wrapper.readFile = recordReplay(wrapper.readFile, underlying)( path => { - const result = underlying.readFile(path); + const result = underlyingShim.readFile(path); const logEntry = { path, codepage: 0, result: { contents: result, codepage: 0 } }; recordLog.filesRead.push(logEntry); return result; @@ -226,14 +228,14 @@ namespace Playback { (path, extension, exclude) => findResultByPath(wrapper, replayLog.directoriesRead.filter(d => d.extension === extension && ts.arrayIsEqualTo(d.exclude, exclude)), path)); wrapper.writeFile = recordReplay(wrapper.writeFile, underlying)( - (path, contents) => callAndRecord(underlying.writeFile(path, contents), recordLog.filesWritten, { path, contents, bom: false }), - (path, contents) => noOpReplay("writeFile")); + (path: string, contents: string) => callAndRecord(underlyingShim.writeFile(path, contents), recordLog.filesWritten, { path, contents, bom: false }), + (path: string, contents: string) => noOpReplay("writeFile")); wrapper.exit = (exitCode) => { if (recordLog !== undefined) { wrapper.endRecord(); } - underlying.exit(exitCode); + underlyingShim.exit(exitCode); }; } diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index e2ec5cc159f..5516b18e0de 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -1834,7 +1834,7 @@ namespace ts.server { if (!rangeEnd) { rangeEnd = this.root.charCount(); } - const walkFns = { + const walkFns: ILineIndexWalker = { goSubtree: true, done: false, leaf: function (relativeStart: number, relativeLength: number, ll: LineLeaf) { diff --git a/src/server/node.d.ts b/src/server/node.d.ts index 0bde0bb6602..8e4d8c28e9b 100644 --- a/src/server/node.d.ts +++ b/src/server/node.d.ts @@ -68,7 +68,7 @@ interface BufferConstructor { new (array: any[]): Buffer; prototype: Buffer; isBuffer(obj: any): boolean; - byteLength(string: string, encoding?: string): number; + byteLength: (string: string, encoding?: string) => number; concat(list: Buffer[], totalLength?: number): Buffer; } declare var Buffer: BufferConstructor; @@ -190,7 +190,7 @@ declare namespace NodeJS { nextTick(callback: Function): void; umask(mask?: number): number; uptime(): number; - hrtime(time?: number[]): number[]; + hrtime: (time?: number[]) => number[]; // Worker send? (message: any, sendHandle?: any): void; diff --git a/src/services/formatting/ruleOperationContext.ts b/src/services/formatting/ruleOperationContext.ts index 47330faa0dd..3108095e8e6 100644 --- a/src/services/formatting/ruleOperationContext.ts +++ b/src/services/formatting/ruleOperationContext.ts @@ -6,8 +6,8 @@ namespace ts.formatting { export class RuleOperationContext { private customContextChecks: { (context: FormattingContext): boolean; }[]; - constructor(...funcs: { (context: FormattingContext): boolean; }[]) { - this.customContextChecks = funcs; + constructor(...funcs: { (this: typeof Rules, context: FormattingContext): boolean; }[]) { + this.customContextChecks = <{ (this: any, context: FormattingContext): boolean }[]>funcs; } static Any: RuleOperationContext = new RuleOperationContext(); diff --git a/src/services/utilities.ts b/src/services/utilities.ts index afdc85fffd8..0363e45a64a 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -769,7 +769,7 @@ namespace ts { * The default is CRLF. */ export function getNewLineOrDefaultFromHost(host: LanguageServiceHost | LanguageServiceShimHost) { - return host.getNewLine ? host.getNewLine() : carriageReturnLineFeed; + return (host).getNewLine ? (host).getNewLine() : carriageReturnLineFeed; } export function lineBreakPart() {