From b2ce6db229c4bdc1aeee29f5ade9c7aae54dfded Mon Sep 17 00:00:00 2001 From: zhengbli Date: Thu, 9 Jul 2015 14:45:39 -0700 Subject: [PATCH 01/93] Add API for project level GetErr --- src/server/editorServices.ts | 2 +- src/server/protocol.d.ts | 27 ++++++++++++++++- src/server/session.ts | 59 ++++++++++++++++++++++++++++++++++-- 3 files changed, 83 insertions(+), 5 deletions(-) diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 91d400ff263..1b9ea292357 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -304,7 +304,7 @@ namespace ts.server { return this.projectService.openFile(filename, false); } - getFileNameList() { + getFileNames() { let sourceFiles = this.program.getSourceFiles(); return sourceFiles.map(sourceFile => sourceFile.fileName); } diff --git a/src/server/protocol.d.ts b/src/server/protocol.d.ts index 017a8c1d81a..a40ca1f1318 100644 --- a/src/server/protocol.d.ts +++ b/src/server/protocol.d.ts @@ -116,7 +116,7 @@ declare namespace ts.server.protocol { /** * The list of normalized file name in the project, including 'lib.d.ts' */ - fileNameList?: string[]; + fileNames?: string[]; } /** @@ -854,6 +854,31 @@ declare namespace ts.server.protocol { export interface SignatureHelpResponse extends Response { body?: SignatureHelpItems; } + + /** + * Arguments for geterrForProject request. + */ + export interface GeterrForProjectRequestArgs { + /** + * the file requesting project error list + */ + file: string; + + /** + * Delay in milliseconds to wait before starting to compute + * errors for the files in the file list + */ + delay: number; + } + + /** + * GeterrForProjectRequest request; value of command field is + * "geterrForProject". It works similarly with 'Geterr', only + * it request for every file in this project. + */ + export interface GeterrForProjectRequest extends Request { + arguments: GeterrForProjectRequestArgs + } /** * Arguments for geterr messages. diff --git a/src/server/session.ts b/src/server/session.ts index c95b1a7cc1b..c35cdedffe9 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -86,6 +86,7 @@ namespace ts.server { export const Format = "format"; export const Formatonkey = "formatonkey"; export const Geterr = "geterr"; + export const GeterrForProject = "geterrForProject"; export const NavBar = "navbar"; export const Navto = "navto"; export const Occurrences = "occurrences"; @@ -344,15 +345,15 @@ namespace ts.server { } getProjectInfo(fileName: string, needFileNameList: boolean): protocol.ProjectInfo { - fileName = ts.normalizePath(fileName) - let project = this.projectService.getProjectForFile(fileName) + fileName = ts.normalizePath(fileName); + let project = this.projectService.getProjectForFile(fileName); let projectInfo: protocol.ProjectInfo = { configFileName: project.projectFilename } if (needFileNameList) { - projectInfo.fileNameList = project.getFileNameList(); + projectInfo.fileNames = project.getFileNames(); } return projectInfo; @@ -836,6 +837,51 @@ namespace ts.server { })); } + getDiagnosticsForProject(delay: number, fileName: string) { + let { configFileName, fileNames: fileNamesInProject } = this.getProjectInfo(fileName, true); + // No need to analyze lib.d.ts + fileNamesInProject = fileNamesInProject.filter((value, index, array) => value.indexOf("lib.d.ts") < 0); + + // Sort the file name list to make the recently touched files come first + let highPriorityFiles: string[] = []; + let mediumPriorityFiles: string[] = []; + let lowPriorityFiles: string[] = []; + let veryLowPriorityFiles: string[] = []; + let normalizedFileName = ts.normalizePath(fileName); + let project = this.projectService.getProjectForFile(normalizedFileName); + for (let fileNameInProject of fileNamesInProject) { + if (this.getCanonicalFileName(fileNameInProject) == this.getCanonicalFileName(fileName)) + highPriorityFiles.push(fileNameInProject); + else { + let info = this.projectService.getScriptInfo(fileNameInProject); + if (!info || !info.isOpen) { + if (fileNameInProject.indexOf(".d.ts") > 0) + veryLowPriorityFiles.push(fileNameInProject); + else + lowPriorityFiles.push(fileNameInProject); + } + else + mediumPriorityFiles.push(fileNameInProject); + } + } + + fileNamesInProject = highPriorityFiles.concat(mediumPriorityFiles).concat(lowPriorityFiles).concat(veryLowPriorityFiles); + + if (fileNamesInProject.length > 0) { + let checkList = fileNamesInProject.map((fileName: string) => { + let normalizedFileName = ts.normalizePath(fileName); + return { fileName: normalizedFileName, project }; + }); + this.updateErrorCheck(checkList, this.changeSeq, (n) => n == this.changeSeq, delay); + } + } + + getCanonicalFileName(fileName: string) { + let name = this.host.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(); + this.logger.info(ts.normalizePath(name)); + return ts.normalizePath(name); + } + exit() { } @@ -919,6 +965,13 @@ namespace ts.server { responseRequired = false; break; } + case CommandNames.GeterrForProject: { + this.logger.info(request.arguments); + let { file, delay } = request.arguments; + response = this.getDiagnosticsForProject(delay, file); + responseRequired = false; + break; + } case CommandNames.Change: { var changeArgs = request.arguments; this.change(changeArgs.line, changeArgs.offset, changeArgs.endLine, changeArgs.endOffset, From bbf1105c4657db4062c1267e85aafd55c5574d41 Mon Sep 17 00:00:00 2001 From: Zhengbo Li Date: Mon, 13 Jul 2015 14:01:03 -0700 Subject: [PATCH 02/93] Remove log statements --- src/server/protocol.d.ts | 2 +- src/server/session.ts | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/server/protocol.d.ts b/src/server/protocol.d.ts index a40ca1f1318..a68ffe79864 100644 --- a/src/server/protocol.d.ts +++ b/src/server/protocol.d.ts @@ -856,7 +856,7 @@ declare namespace ts.server.protocol { } /** - * Arguments for geterrForProject request. + * Arguments for GeterrForProject request. */ export interface GeterrForProjectRequestArgs { /** diff --git a/src/server/session.ts b/src/server/session.ts index c35cdedffe9..0df154eadf1 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -878,7 +878,6 @@ namespace ts.server { getCanonicalFileName(fileName: string) { let name = this.host.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(); - this.logger.info(ts.normalizePath(name)); return ts.normalizePath(name); } From 6ae543bf5451dcbba61836fe3147a6014095a20d Mon Sep 17 00:00:00 2001 From: Zhengbo Li Date: Mon, 13 Jul 2015 15:50:06 -0700 Subject: [PATCH 03/93] Remove unnecessary checking --- src/server/session.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/session.ts b/src/server/session.ts index 0df154eadf1..2efe75ee53f 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -854,7 +854,7 @@ namespace ts.server { highPriorityFiles.push(fileNameInProject); else { let info = this.projectService.getScriptInfo(fileNameInProject); - if (!info || !info.isOpen) { + if (!info.isOpen) { if (fileNameInProject.indexOf(".d.ts") > 0) veryLowPriorityFiles.push(fileNameInProject); else From 8f30ad17ed6654053118a9fc031deced3296fe13 Mon Sep 17 00:00:00 2001 From: Zhengbo Li Date: Mon, 13 Jul 2015 16:26:19 -0700 Subject: [PATCH 04/93] Fix tests --- src/harness/fourslash.ts | 2 +- src/server/client.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index c374f8add60..0d03f7d6236 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -1882,7 +1882,7 @@ module FourSlash { ); assert.equal( expected.join(","), - actual.fileNameList.map( file => { + actual.fileNames.map( file => { return file.replace(this.basePath + "/", "") }).join(",") ); diff --git a/src/server/client.ts b/src/server/client.ts index e4a524dd210..9a6fbaa3a77 100644 --- a/src/server/client.ts +++ b/src/server/client.ts @@ -183,7 +183,7 @@ namespace ts.server { return { configFileName: response.body.configFileName, - fileNameList: response.body.fileNameList + fileNames: response.body.fileNames }; } From 418369a13c0e9ee0add658cf4460935cb22edba6 Mon Sep 17 00:00:00 2001 From: Zhengbo Li Date: Mon, 13 Jul 2015 16:38:13 -0700 Subject: [PATCH 05/93] incorporate changes in master --- src/compiler/sys.ts | 16 ++- src/server/session.ts | 269 ++++++++++++++++++--------------------- src/services/services.ts | 1 + 3 files changed, 140 insertions(+), 146 deletions(-) diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 443c1c4789c..228b9516de1 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -29,6 +29,9 @@ namespace ts { declare var process: any; declare var global: any; declare var __filename: string; + declare var Buffer: { + new (str: string, encoding ?: string): any; + } declare class Enumerator { public atEnd(): boolean; @@ -267,10 +270,17 @@ namespace ts { args: process.argv.slice(2), newLine: _os.EOL, useCaseSensitiveFileNames: useCaseSensitiveFileNames, - write(s: string): void { + write(s: string): void { + var buffer = new Buffer(s, 'utf8'); + var offset: number = 0; + var toWrite: number = buffer.length; + var written = 0; // 1 is a standard descriptor for stdout - _fs.writeSync(1, s); - }, + while ((written = _fs.writeSync(1, buffer, offset, toWrite)) < toWrite) { + offset += written; + toWrite -= written; + } + }, readFile, writeFile, watchFile: (fileName, callback) => { diff --git a/src/server/session.ts b/src/server/session.ts index 2efe75ee53f..5873958d613 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -884,6 +884,131 @@ namespace ts.server { exit() { } + private handlers : Map<(request: protocol.Request) => {response?: any, responseRequired?: boolean}> = { + [CommandNames.Exit]: () => { + this.exit(); + return {}; + }, + [CommandNames.Definition]: (request: protocol.Request) => { + var defArgs = request.arguments; + return {response: this.getDefinition(defArgs.line, defArgs.offset, defArgs.file)}; + }, + [CommandNames.TypeDefinition]: (request: protocol.Request) => { + var defArgs = request.arguments; + return {response: this.getTypeDefinition(defArgs.line, defArgs.offset, defArgs.file)}; + }, + [CommandNames.References]: (request: protocol.Request) => { + var defArgs = request.arguments; + return {response: this.getReferences(defArgs.line, defArgs.offset, defArgs.file)}; + }, + [CommandNames.Rename]: (request: protocol.Request) => { + var renameArgs = request.arguments; + return {response: this.getRenameLocations(renameArgs.line, renameArgs.offset, renameArgs.file, renameArgs.findInComments, renameArgs.findInStrings)} + }, + [CommandNames.Open]: (request: protocol.Request) => { + var openArgs = request.arguments; + this.openClientFile(openArgs.file); + return {} + }, + [CommandNames.Quickinfo]: (request: protocol.Request) => { + var quickinfoArgs = request.arguments; + return {response: this.getQuickInfo(quickinfoArgs.line, quickinfoArgs.offset, quickinfoArgs.file)}; + }, + [CommandNames.Format]: (request: protocol.Request) => { + var formatArgs = request.arguments; + return {response: this.getFormattingEditsForRange(formatArgs.line, formatArgs.offset, formatArgs.endLine, formatArgs.endOffset, formatArgs.file)}; + }, + [CommandNames.Formatonkey]: (request: protocol.Request) => { + var formatOnKeyArgs = request.arguments; + return {response: this.getFormattingEditsAfterKeystroke(formatOnKeyArgs.line, formatOnKeyArgs.offset, formatOnKeyArgs.key, formatOnKeyArgs.file)}; + }, + [CommandNames.Completions]: (request: protocol.Request) => { + var completionsArgs = request.arguments; + return {response: this.getCompletions(completionsArgs.line, completionsArgs.offset, completionsArgs.prefix, completionsArgs.file)} + }, + [CommandNames.CompletionDetails]: (request: protocol.Request) => { + var completionDetailsArgs = request.arguments; + return {response: this.getCompletionEntryDetails(completionDetailsArgs.line,completionDetailsArgs.offset, + completionDetailsArgs.entryNames,completionDetailsArgs.file)} + }, + [CommandNames.SignatureHelp]: (request: protocol.Request) => { + var signatureHelpArgs = request.arguments; + return {response: this.getSignatureHelpItems(signatureHelpArgs.line, signatureHelpArgs.offset, signatureHelpArgs.file)} + }, + [CommandNames.Geterr]: (request: protocol.Request) => { + var geterrArgs = request.arguments; + return {response: this.getDiagnostics(geterrArgs.delay, geterrArgs.files), responseRequired: false}; + }, + [CommandNames.GeterrForProject]: (request: protocol.Request) => { + let { file, delay } = request.arguments; + return {response: this.getDiagnosticsForProject(delay, file), responseRequired: false}; + }, + [CommandNames.Change]: (request: protocol.Request) => { + var changeArgs = request.arguments; + this.change(changeArgs.line, changeArgs.offset, changeArgs.endLine, changeArgs.endOffset, + changeArgs.insertString, changeArgs.file); + return {responseRequired: false} + }, + [CommandNames.Configure]: (request: protocol.Request) => { + var configureArgs = request.arguments; + this.projectService.setHostConfiguration(configureArgs); + this.output(undefined, CommandNames.Configure, request.seq); + return {responseRequired: false} + }, + [CommandNames.Reload]: (request: protocol.Request) => { + var reloadArgs = request.arguments; + this.reload(reloadArgs.file, reloadArgs.tmpfile, request.seq); + return {responseRequired: false} + }, + [CommandNames.Saveto]: (request: protocol.Request) => { + var savetoArgs = request.arguments; + this.saveToTmp(savetoArgs.file, savetoArgs.tmpfile); + return {responseRequired: false} + }, + [CommandNames.Close]: (request: protocol.Request) => { + var closeArgs = request.arguments; + this.closeClientFile(closeArgs.file); + return {responseRequired: false}; + }, + [CommandNames.Navto]: (request: protocol.Request) => { + var navtoArgs = request.arguments; + return {response: this.getNavigateToItems(navtoArgs.searchValue, navtoArgs.file, navtoArgs.maxResultCount)}; + }, + [CommandNames.Brace]: (request: protocol.Request) => { + var braceArguments = request.arguments; + return {response: this.getBraceMatching(braceArguments.line, braceArguments.offset, braceArguments.file)}; + }, + [CommandNames.NavBar]: (request: protocol.Request) => { + var navBarArgs = request.arguments; + return {response: this.getNavigationBarItems(navBarArgs.file)}; + }, + [CommandNames.Occurrences]: (request: protocol.Request) => { + var { line, offset, file: fileName } = request.arguments; + return {response: this.getOccurrences(line, offset, fileName)}; + }, + [CommandNames.ProjectInfo]: (request: protocol.Request) => { + var { file, needFileNameList } = request.arguments; + return {response: this.getProjectInfo(file, needFileNameList)}; + }, + }; + addProtocolHandler(command: string, handler: (request: protocol.Request) => {response?: any, responseRequired: boolean}) { + if (this.handlers[command]) { + throw new Error(`Protocol handler already exists for command "${command}"`); + } + this.handlers[command] = handler; + } + + executeCommand(request: protocol.Request) : {response?: any, responseRequired?: boolean} { + var handler = this.handlers[request.command]; + if (handler) { + return handler(request); + } else { + this.projectService.log("Unrecognized JSON command: " + JSON.stringify(request)); + this.output(undefined, CommandNames.Unknown, request.seq, "Unrecognized JSON command: " + request.command); + return {responseRequired: false}; + } + } + onMessage(message: string) { if (this.logger.isVerbose()) { this.logger.info("request: " + message); @@ -891,149 +1016,7 @@ namespace ts.server { } try { var request = JSON.parse(message); - var response: any; - var errorMessage: string; - var responseRequired = true; - switch (request.command) { - case CommandNames.Exit: { - this.exit(); - responseRequired = false; - break; - } - case CommandNames.Definition: { - var defArgs = request.arguments; - response = this.getDefinition(defArgs.line, defArgs.offset, defArgs.file); - break; - } - case CommandNames.TypeDefinition: { - var defArgs = request.arguments; - response = this.getTypeDefinition(defArgs.line, defArgs.offset, defArgs.file); - break; - } - case CommandNames.References: { - var refArgs = request.arguments; - response = this.getReferences(refArgs.line, refArgs.offset, refArgs.file); - break; - } - case CommandNames.Rename: { - var renameArgs = request.arguments; - response = this.getRenameLocations(renameArgs.line, renameArgs.offset, renameArgs.file, renameArgs.findInComments, renameArgs.findInStrings); - break; - } - case CommandNames.Open: { - var openArgs = request.arguments; - this.openClientFile(openArgs.file); - responseRequired = false; - break; - } - case CommandNames.Quickinfo: { - var quickinfoArgs = request.arguments; - response = this.getQuickInfo(quickinfoArgs.line, quickinfoArgs.offset, quickinfoArgs.file); - break; - } - case CommandNames.Format: { - var formatArgs = request.arguments; - response = this.getFormattingEditsForRange(formatArgs.line, formatArgs.offset, formatArgs.endLine, formatArgs.endOffset, formatArgs.file); - break; - } - case CommandNames.Formatonkey: { - var formatOnKeyArgs = request.arguments; - response = this.getFormattingEditsAfterKeystroke(formatOnKeyArgs.line, formatOnKeyArgs.offset, formatOnKeyArgs.key, formatOnKeyArgs.file); - break; - } - case CommandNames.Completions: { - var completionsArgs = request.arguments; - response = this.getCompletions(completionsArgs.line, completionsArgs.offset, completionsArgs.prefix, completionsArgs.file); - break; - } - case CommandNames.CompletionDetails: { - var completionDetailsArgs = request.arguments; - response = - this.getCompletionEntryDetails(completionDetailsArgs.line,completionDetailsArgs.offset, - completionDetailsArgs.entryNames,completionDetailsArgs.file); - break; - } - case CommandNames.SignatureHelp: { - var signatureHelpArgs = request.arguments; - response = this.getSignatureHelpItems(signatureHelpArgs.line, signatureHelpArgs.offset, signatureHelpArgs.file); - break; - } - case CommandNames.Geterr: { - var geterrArgs = request.arguments; - response = this.getDiagnostics(geterrArgs.delay, geterrArgs.files); - responseRequired = false; - break; - } - case CommandNames.GeterrForProject: { - this.logger.info(request.arguments); - let { file, delay } = request.arguments; - response = this.getDiagnosticsForProject(delay, file); - responseRequired = false; - break; - } - case CommandNames.Change: { - var changeArgs = request.arguments; - this.change(changeArgs.line, changeArgs.offset, changeArgs.endLine, changeArgs.endOffset, - changeArgs.insertString, changeArgs.file); - responseRequired = false; - break; - } - case CommandNames.Configure: { - var configureArgs = request.arguments; - this.projectService.setHostConfiguration(configureArgs); - this.output(undefined, CommandNames.Configure, request.seq); - responseRequired = false; - break; - } - case CommandNames.Reload: { - var reloadArgs = request.arguments; - this.reload(reloadArgs.file, reloadArgs.tmpfile, request.seq); - responseRequired = false; - break; - } - case CommandNames.Saveto: { - var savetoArgs = request.arguments; - this.saveToTmp(savetoArgs.file, savetoArgs.tmpfile); - responseRequired = false; - break; - } - case CommandNames.Close: { - var closeArgs = request.arguments; - this.closeClientFile(closeArgs.file); - responseRequired = false; - break; - } - case CommandNames.Navto: { - var navtoArgs = request.arguments; - response = this.getNavigateToItems(navtoArgs.searchValue, navtoArgs.file, navtoArgs.maxResultCount); - break; - } - case CommandNames.Brace: { - var braceArguments = request.arguments; - response = this.getBraceMatching(braceArguments.line, braceArguments.offset, braceArguments.file); - break; - } - case CommandNames.NavBar: { - var navBarArgs = request.arguments; - response = this.getNavigationBarItems(navBarArgs.file); - break; - } - case CommandNames.Occurrences: { - var { line, offset, file: fileName } = request.arguments; - response = this.getOccurrences(line, offset, fileName); - break; - } - case CommandNames.ProjectInfo: { - var { file, needFileNameList } = request.arguments; - response = this.getProjectInfo(file, needFileNameList); - break; - } - default: { - this.projectService.log("Unrecognized JSON command: " + message); - this.output(undefined, CommandNames.Unknown, request.seq, "Unrecognized JSON command: " + request.command); - break; - } - } + var {response, responseRequired} = this.executeCommand(request); if (this.logger.isVerbose()) { var elapsed = this.hrtime(start); diff --git a/src/services/services.ts b/src/services/services.ts index 10e38f98613..c85c10dc411 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -4546,6 +4546,7 @@ namespace ts { if (hasKind(node.parent, SyntaxKind.GetAccessor) || hasKind(node.parent, SyntaxKind.SetAccessor)) { return getGetAndSetOccurrences(node.parent); } + break; default: if (isModifier(node.kind) && node.parent && (isDeclaration(node.parent) || node.parent.kind === SyntaxKind.VariableStatement)) { From 7923e8e6198d79068a88ddce13b1883e5d8c0056 Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Mon, 13 Jul 2015 18:56:38 -0700 Subject: [PATCH 06/93] Setup shim and stubbed out functions --- src/harness/harnessLanguageService.ts | 3 +++ src/server/client.ts | 4 ++++ src/services/services.ts | 7 +++++++ src/services/shims.ts | 13 +++++++++++++ 4 files changed, 27 insertions(+) diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index 6cb92df5948..995dec20aea 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -381,6 +381,9 @@ module Harness.LanguageService { getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: ts.FormatCodeOptions): ts.TextChange[] { return unwrapJSONCallResult(this.shim.getFormattingEditsAfterKeystroke(fileName, position, key, JSON.stringify(options))); } + getDocCommentScaffoldingAtPosition(fileName: string, position: number): string { + return unwrapJSONCallResult(this.shim.getDocCommentScaffoldingAtPosition(fileName, position)); + } getEmitOutput(fileName: string): ts.EmitOutput { return unwrapJSONCallResult(this.shim.getEmitOutput(fileName)); } diff --git a/src/server/client.ts b/src/server/client.ts index e4a524dd210..3f6770d7144 100644 --- a/src/server/client.ts +++ b/src/server/client.ts @@ -540,6 +540,10 @@ namespace ts.server { getTodoComments(fileName: string, descriptors: TodoCommentDescriptor[]): TodoComment[] { throw new Error("Not Implemented Yet."); } + + getDocCommentScaffoldingAtPosition(fileName: string, position: number): string { + throw new Error("Not Implemented Yet."); + } getBraceMatchingAtPosition(fileName: string, position: number): TextSpan[] { var lineOffset = this.positionToOneBasedLineOffset(fileName, position); diff --git a/src/services/services.ts b/src/services/services.ts index c85c10dc411..6b5c0e19054 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1032,6 +1032,8 @@ namespace ts { getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions): TextChange[]; getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions): TextChange[]; + getDocCommentScaffoldingAtPosition(fileName: string, position: number): string; + getEmitOutput(fileName: string): EmitOutput; getProgram(): Program; @@ -6698,6 +6700,10 @@ namespace ts { return []; } + + function getDocCommentScaffoldingAtPosition(filename: string, position: number): string { + return "/** getDocCommentScaffoldingAtPosition -- TS side! */"; + } function getTodoComments(fileName: string, descriptors: TodoCommentDescriptor[]): TodoComment[] { // Note: while getting todo comments seems like a syntactic operation, we actually @@ -6940,6 +6946,7 @@ namespace ts { getFormattingEditsForRange, getFormattingEditsForDocument, getFormattingEditsAfterKeystroke, + getDocCommentScaffoldingAtPosition, getEmitOutput, getSourceFile, getProgram diff --git a/src/services/shims.ts b/src/services/shims.ts index 6e765eff499..535e5a0c772 100644 --- a/src/services/shims.ts +++ b/src/services/shims.ts @@ -197,6 +197,8 @@ namespace ts { getFormattingEditsForDocument(fileName: string, options: string/*Services.FormatCodeOptions*/): string; getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: string/*Services.FormatCodeOptions*/): string; + getDocCommentScaffoldingAtPosition(fileName: string, position: number): string; + getEmitOutput(fileName: string): string; } @@ -785,6 +787,17 @@ namespace ts { }); } + public getDocCommentScaffoldingAtPosition(fileName: string, position: number): string { + return this.forwardJSONCall( + "getDocCommentScaffoldingAtPosition('" + fileName + "', " + position + ")", + () => { + var commentText = this.languageService.getDocCommentScaffoldingAtPosition(fileName, position); + return commentText; + } + + ) + } + /// NAVIGATE TO /** Return a list of symbols that are interesting to navigate to */ From 19793fe22da3048833108d3790d451ca4b7b7d6e Mon Sep 17 00:00:00 2001 From: Zhengbo Li Date: Tue, 14 Jul 2015 13:10:08 -0700 Subject: [PATCH 07/93] Update ErrorEventHandler type in worker --- src/lib/webworker.generated.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/webworker.generated.d.ts b/src/lib/webworker.generated.d.ts index 5c41869e487..db8b02f34d7 100644 --- a/src/lib/webworker.generated.d.ts +++ b/src/lib/webworker.generated.d.ts @@ -806,7 +806,7 @@ interface EventListenerObject { declare type EventListenerOrEventListenerObject = EventListener | EventListenerObject; interface ErrorEventHandler { - (event: Event | string, source?: string, fileno?: number, columnNumber?: number): void; + (message: string, filename?: string, lineno?: number, colno?: number, error?:Error): void; } interface PositionCallback { (position: Position): void; From 0b6c60d5cd883d3e56b3c9979f6db9b42b12677b Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Wed, 15 Jul 2015 10:33:22 -0700 Subject: [PATCH 08/93] Formatted a comment --- src/compiler/scanner.ts | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index d52f96c912b..9122cadc287 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -528,13 +528,17 @@ namespace ts { return pos; } - // Extract comments from the given source text starting at the given position. If trailing is - // false, whitespace is skipped until the first line break and comments between that location - // and the next token are returned.If trailing is true, comments occurring between the given - // position and the next line break are returned.The return value is an array containing a - // TextRange for each comment. Single-line comment ranges include the beginning '//' characters - // but not the ending line break. Multi - line comment ranges include the beginning '/* and - // ending '*/' characters.The return value is undefined if no comments were found. + /** + * Extract comments from the given source text starting at the given position. + * The return value is an array containing a TextRange for each comment. + * Single-line comment ranges include the beginning '//' characters but not the ending line break. + * Multi - line comment ranges include the beginning '/* and ending '/' characters. + * The return value is undefined if no comments were found. + * @param trailing + * If false, whitespace is skipped until the first line break and comments between that location + * and the next token are returned. + * If true, comments occurring between the given position and the next line break are returned. + */ function getCommentRanges(text: string, pos: number, trailing: boolean): CommentRange[] { let result: CommentRange[]; let collecting = trailing || pos === 0; @@ -629,9 +633,9 @@ namespace ts { ch >= CharacterCodes._0 && ch <= CharacterCodes._9 || ch === CharacterCodes.$ || ch === CharacterCodes._ || ch > CharacterCodes.maxAsciiCharacter && isUnicodeIdentifierPart(ch, languageVersion); } - + /* @internal */ - // Creates a scanner over a (possibly unspecified) range of a piece of text. + // Creates a scanner over a (possibly unspecified) range of a piece of text. export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean, languageVariant = LanguageVariant.Standard, From 6646187b0400caf02e181e7f34bc36e5db963970 Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Wed, 15 Jul 2015 10:33:45 -0700 Subject: [PATCH 09/93] Fixed indentation --- src/compiler/binder.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index e839d6d6c9a..336be9d1eda 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -74,7 +74,7 @@ namespace ts { // If the current node is a container that also container that also contains locals. Examples: // // Functions, Methods, Modules, Source-files. - IsContainerWithLocals = IsContainer | HasLocals + IsContainerWithLocals = IsContainer | HasLocals } export function bindSourceFile(file: SourceFile) { @@ -1056,4 +1056,4 @@ namespace ts { : declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes); } } -} +} From 82bdfd201d6da5cf81767046946ff629051e16c0 Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Thu, 16 Jul 2015 09:08:31 -0700 Subject: [PATCH 10/93] Doc notes. --- src/services/services.ts | 43 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/src/services/services.ts b/src/services/services.ts index 6b5c0e19054..4d4b708118f 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -6700,10 +6700,45 @@ namespace ts { return []; } - - function getDocCommentScaffoldingAtPosition(filename: string, position: number): string { - return "/** getDocCommentScaffoldingAtPosition -- TS side! */"; - } + + /** + * Checks if position points to a valid position to add JSDoc comments, and if so, + * returns the appropriate scaffolding. Otherwise returns a default string. + * @param fileName The file in which to perofrm the check + * @param position The (character-indexed) position in the file where the check should + * be performed. + */ + function getDocCommentScaffoldingAtPosition(fileName: string, position: number): string { + const nullResult = "/** */"; + let start = new Date().getTime(); + let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + log("getDocCommentScaffoldingAtPosition: getCurrentSourceFile: " + (new Date().getTime() - start)); + + // Check if in comment context + var nodeAtPos = getTokenAtPosition(sourceFile, position); + + return "/** token is : daniel cant copy/paste " + tokenToString(nodeAtPos.kind) + " */"; + + // Get the next non-comment token + + // check if token is a function keyword + + // Get the parsed object corresponding to the token + + // get the function's param list + + // map the params to JSDoc declarations. ie: + // foo: T -> '* @param foo ' + + // Get the indentation level + // * perhaps just use the carat's indentation? + + // Recall that the in-comment have one extra whitespace character + + // Create the JSDoc comment string from the parts + + return "/** getDocCommentScaffoldingAtPosition -- TS side! */"; + } function getTodoComments(fileName: string, descriptors: TodoCommentDescriptor[]): TodoComment[] { // Note: while getting todo comments seems like a syntactic operation, we actually From b620cace921493f9f20bfb72b57d53c015b6a77e Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Thu, 16 Jul 2015 15:13:31 -0700 Subject: [PATCH 11/93] Fixes an issue when resolving a type name as an expression when emitting type metadata for decorators --- src/compiler/checker.ts | 10 +++-- src/compiler/emitter.ts | 13 +++++- src/compiler/types.ts | 2 +- src/compiler/utilities.ts | 16 +++++++ .../baselines/reference/decoratorMetadata.js | 45 +++++++++++++++++++ .../reference/decoratorMetadata.symbols | 22 +++++++++ .../reference/decoratorMetadata.types | 22 +++++++++ .../decorators/decoratorMetadata.ts | 17 +++++++ 8 files changed, 140 insertions(+), 7 deletions(-) create mode 100644 tests/baselines/reference/decoratorMetadata.js create mode 100644 tests/baselines/reference/decoratorMetadata.symbols create mode 100644 tests/baselines/reference/decoratorMetadata.types create mode 100644 tests/cases/conformance/decorators/decoratorMetadata.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f8bafa7a38f..2fb68eb7ab8 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14016,15 +14016,17 @@ namespace ts { return type.flags & TypeFlags.ObjectType && getSignaturesOfType(type, SignatureKind.Call).length > 0; } - function getTypeReferenceSerializationKind(node: TypeReferenceNode): TypeReferenceSerializationKind { + function getTypeReferenceSerializationKind(typeName: EntityName): TypeReferenceSerializationKind { // Resolve the symbol as a value to ensure the type can be reached at runtime during emit. - let symbol = resolveEntityName(node.typeName, SymbolFlags.Value, /*ignoreErrors*/ true); - let constructorType = symbol ? getTypeOfSymbol(symbol) : undefined; + let valueSymbol = resolveEntityName(typeName, SymbolFlags.Value, /*ignoreErrors*/ true); + let constructorType = valueSymbol ? getTypeOfSymbol(valueSymbol) : undefined; if (constructorType && isConstructorType(constructorType)) { return TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue; } - let type = getTypeFromTypeNode(node); + // Resolve the symbol as a type so that we can provide a more useful hint for the type serializer. + let typeSymbol = resolveEntityName(typeName, SymbolFlags.Type, /*ignoreErrors*/ true); + let type = getDeclaredTypeOfSymbol(typeSymbol); if (type === unknownType) { return TypeReferenceSerializationKind.Unknown; } diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 9c8438565e7..98de37c752c 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -4897,8 +4897,16 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi /** Serializes a TypeReferenceNode to an appropriate JS constructor value. Used by the __metadata decorator. */ function emitSerializedTypeReferenceNode(node: TypeReferenceNode) { - let typeName = node.typeName; - let result = resolver.getTypeReferenceSerializationKind(node); + let location: Node = node.parent; + while (isDeclaration(location) || isTypeNode(location)) { + location = location.parent; + } + + // Clone the type name and parent it to a location outside of the current declaration. + let typeName = cloneEntityName(node.typeName); + typeName.parent = location; + + let result = resolver.getTypeReferenceSerializationKind(typeName); switch (result) { case TypeReferenceSerializationKind.Unknown: let temp = createAndRecordTempVariable(TempFlags.Auto); @@ -5030,6 +5038,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi argumentsWritten++; } if (shouldEmitParamTypesMetadata(node)) { + debugger; if (writeComma || argumentsWritten) { write(", "); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index e0f16a00c2b..bba3d81da52 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1573,7 +1573,7 @@ namespace ts { getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): number; getBlockScopedVariableId(node: Identifier): number; getReferencedValueDeclaration(reference: Identifier): Declaration; - getTypeReferenceSerializationKind(node: TypeReferenceNode): TypeReferenceSerializationKind; + getTypeReferenceSerializationKind(typeName: EntityName): TypeReferenceSerializationKind; } export const enum SymbolFlags { diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 5174589cdcf..79c16716be5 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1424,6 +1424,22 @@ namespace ts { return isFunctionLike(n) || n.kind === SyntaxKind.ModuleDeclaration || n.kind === SyntaxKind.SourceFile; } + export function cloneEntityName(node: EntityName): EntityName { + if (node.kind === SyntaxKind.Identifier) { + let clone = createSynthesizedNode(SyntaxKind.Identifier); + clone.text = (node).text; + return clone; + } + else { + let clone = createSynthesizedNode(SyntaxKind.QualifiedName); + clone.left = cloneEntityName((node).left); + clone.left.parent = clone; + clone.right = cloneEntityName((node).right); + clone.right.parent = clone; + return clone; + } + } + export function nodeIsSynthesized(node: Node): boolean { return node.pos === -1; } diff --git a/tests/baselines/reference/decoratorMetadata.js b/tests/baselines/reference/decoratorMetadata.js new file mode 100644 index 00000000000..71dc4de383a --- /dev/null +++ b/tests/baselines/reference/decoratorMetadata.js @@ -0,0 +1,45 @@ +//// [tests/cases/conformance/decorators/decoratorMetadata.ts] //// + +//// [service.ts] +export default class Service { +} +//// [component.ts] +import Service from "./service"; + +declare var decorator: any; + +@decorator +class MyComponent { + constructor(public Service: Service) { + } +} + +//// [service.js] +var Service = (function () { + function Service() { + } + return Service; +})(); +exports.default = Service; +//// [component.js] +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") return Reflect.decorate(decorators, target, key, desc); + switch (arguments.length) { + case 2: return decorators.reduceRight(function(o, d) { return (d && d(o)) || o; }, target); + case 3: return decorators.reduceRight(function(o, d) { return (d && d(target, key)), void 0; }, void 0); + case 4: return decorators.reduceRight(function(o, d) { return (d && d(target, key, o)) || o; }, desc); + } +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var MyComponent = (function () { + function MyComponent(Service) { + this.Service = Service; + } + MyComponent = __decorate([ + decorator, + __metadata('design:paramtypes', [service_1.default]) + ], MyComponent); + return MyComponent; +})(); diff --git a/tests/baselines/reference/decoratorMetadata.symbols b/tests/baselines/reference/decoratorMetadata.symbols new file mode 100644 index 00000000000..706f5ace8a9 --- /dev/null +++ b/tests/baselines/reference/decoratorMetadata.symbols @@ -0,0 +1,22 @@ +=== tests/cases/conformance/decorators/service.ts === +export default class Service { +>Service : Symbol(Service, Decl(service.ts, 0, 0)) +} +=== tests/cases/conformance/decorators/component.ts === +import Service from "./service"; +>Service : Symbol(Service, Decl(component.ts, 0, 6)) + +declare var decorator: any; +>decorator : Symbol(decorator, Decl(component.ts, 2, 11)) + +@decorator +>decorator : Symbol(decorator, Decl(component.ts, 2, 11)) + +class MyComponent { +>MyComponent : Symbol(MyComponent, Decl(component.ts, 2, 27)) + + constructor(public Service: Service) { +>Service : Symbol(Service, Decl(component.ts, 6, 16)) +>Service : Symbol(Service, Decl(component.ts, 0, 6)) + } +} diff --git a/tests/baselines/reference/decoratorMetadata.types b/tests/baselines/reference/decoratorMetadata.types new file mode 100644 index 00000000000..b0ce80fb1e4 --- /dev/null +++ b/tests/baselines/reference/decoratorMetadata.types @@ -0,0 +1,22 @@ +=== tests/cases/conformance/decorators/service.ts === +export default class Service { +>Service : Service +} +=== tests/cases/conformance/decorators/component.ts === +import Service from "./service"; +>Service : typeof Service + +declare var decorator: any; +>decorator : any + +@decorator +>decorator : any + +class MyComponent { +>MyComponent : MyComponent + + constructor(public Service: Service) { +>Service : Service +>Service : Service + } +} diff --git a/tests/cases/conformance/decorators/decoratorMetadata.ts b/tests/cases/conformance/decorators/decoratorMetadata.ts new file mode 100644 index 00000000000..3f622909309 --- /dev/null +++ b/tests/cases/conformance/decorators/decoratorMetadata.ts @@ -0,0 +1,17 @@ +// @experimentalDecorators: true +// @emitDecoratorMetadata: true +// @target: es5 +// @module: commonjs +// @filename: service.ts +export default class Service { +} +// @filename: component.ts +import Service from "./service"; + +declare var decorator: any; + +@decorator +class MyComponent { + constructor(public Service: Service) { + } +} \ No newline at end of file From efef7b30c10902a97109af90ac6224a071d171fa Mon Sep 17 00:00:00 2001 From: zhengbli Date: Thu, 16 Jul 2015 15:45:31 -0700 Subject: [PATCH 12/93] Update updateErrorCheck function --- src/server/session.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/server/session.ts b/src/server/session.ts index 5873958d613..3eea095d9d5 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -235,7 +235,7 @@ namespace ts.server { } updateErrorCheck(checkList: PendingErrorCheck[], seq: number, - matchSeq: (seq: number) => boolean, ms = 1500, followMs = 200) { + matchSeq: (seq: number) => boolean, ms = 1500, followMs = 200, requireOpen = true) { if (followMs > ms) { followMs = ms; } @@ -250,7 +250,7 @@ namespace ts.server { var checkOne = () => { if (matchSeq(seq)) { var checkSpec = checkList[index++]; - if (checkSpec.project.getSourceFileFromName(checkSpec.fileName, true)) { + if (checkSpec.project.getSourceFileFromName(checkSpec.fileName, requireOpen)) { this.syntacticCheck(checkSpec.fileName, checkSpec.project); this.immediateId = setImmediate(() => { this.semanticCheck(checkSpec.fileName, checkSpec.project); @@ -872,7 +872,7 @@ namespace ts.server { let normalizedFileName = ts.normalizePath(fileName); return { fileName: normalizedFileName, project }; }); - this.updateErrorCheck(checkList, this.changeSeq, (n) => n == this.changeSeq, delay); + this.updateErrorCheck(checkList, this.changeSeq, (n) => n == this.changeSeq, delay, 200, false); } } From b1e688c0567dec2bf16a63e0ff6df12c44ec9f66 Mon Sep 17 00:00:00 2001 From: zhengbli Date: Thu, 16 Jul 2015 16:05:29 -0700 Subject: [PATCH 13/93] Merge branch 'master' of https://github.com/Microsoft/TypeScript into errorlist --- Jakefile.js | 21 +- bin/tsc.js | 126 ++- bin/tsserver.js | 558 +++++++------ bin/typescript.d.ts | 2 + bin/typescript.js | 372 ++++++--- bin/typescriptServices.d.ts | 2 + bin/typescriptServices.js | 372 ++++++--- package.json | 1 + src/compiler/checker.ts | 129 +-- src/compiler/emitter.ts | 7 +- src/compiler/parser.ts | 9 +- src/compiler/utilities.ts | 2 +- src/harness/compilerRunner.ts | 129 +-- src/harness/fourslash.ts | 738 +++++++++--------- src/harness/fourslashRunner.ts | 120 +-- src/harness/harness.ts | 345 ++++---- src/harness/harnessLanguageService.ts | 64 +- src/harness/loggedIO.ts | 38 +- src/harness/projectsRunner.ts | 265 ++++--- src/harness/runner.ts | 22 +- src/harness/runnerbase.ts | 8 +- src/harness/rwcRunner.ts | 53 +- src/harness/sourceMapRecorder.ts | 107 +-- src/harness/test262Runner.ts | 28 +- src/harness/typeWriter.ts | 22 +- src/server/session.ts | 34 +- src/services/services.ts | 230 ++++-- src/services/shims.ts | 34 +- .../arrowFunctionExpressions.symbols | 2 + .../declarationEmitDestructuring1.symbols | 1 + ...tionEmitDestructuringArrayPattern2.symbols | 1 + ...tDestructuringObjectLiteralPattern.symbols | 9 + ...DestructuringObjectLiteralPattern1.symbols | 4 + ...DestructuringObjectLiteralPattern2.symbols | 5 + ...ectBindingPatternAndAssignment1ES5.symbols | 2 + ...ectBindingPatternAndAssignment1ES6.symbols | 2 + ...cturingParameterDeclaration1ES5.errors.txt | 20 +- ...structuringVariableDeclaration1ES5.symbols | 6 + ...structuringVariableDeclaration1ES6.symbols | 6 + .../reference/downlevelLetConst12.symbols | 2 + .../reference/downlevelLetConst13.symbols | 4 + .../reference/downlevelLetConst14.symbols | 4 + .../reference/downlevelLetConst15.symbols | 6 + .../reference/emitArrowFunctionES6.symbols | 2 + ...owFunctionWhenUsingArguments18_ES6.symbols | 1 + ...ationWithModuleSpecifierNameOnNextLine1.js | 34 + ...WithModuleSpecifierNameOnNextLine1.symbols | 28 + ...onWithModuleSpecifierNameOnNextLine1.types | 29 + tests/baselines/reference/for-of41.symbols | 2 + tests/baselines/reference/for-of42.symbols | 2 + ...initializePropertiesWithRenamedLet.symbols | 1 + .../reference/letInNonStrictMode.symbols | 1 + ...BindingPatternKeywordIdentifiers06.symbols | 1 + .../reference/strictModeInConstructor.js | 2 +- .../reference/superSymbolIndexedAccess1.js | 27 + .../superSymbolIndexedAccess1.symbols | 29 + .../reference/superSymbolIndexedAccess1.types | 34 + .../reference/superSymbolIndexedAccess2.js | 25 + .../superSymbolIndexedAccess2.symbols | 30 + .../reference/superSymbolIndexedAccess2.types | 33 + .../superSymbolIndexedAccess3.errors.txt | 19 + .../reference/superSymbolIndexedAccess3.js | 27 + .../superSymbolIndexedAccess4.errors.txt | 13 + .../reference/superSymbolIndexedAccess4.js | 16 + .../reference/superSymbolIndexedAccess5.js | 40 + .../superSymbolIndexedAccess5.symbols | 26 + .../reference/superSymbolIndexedAccess5.types | 29 + .../reference/superSymbolIndexedAccess6.js | 40 + .../superSymbolIndexedAccess6.symbols | 26 + .../reference/superSymbolIndexedAccess6.types | 29 + .../reference/systemModule13.symbols | 3 + .../baselines/reference/systemModule8.symbols | 3 + .../typeArgumentInferenceApparentType1.js | 12 + ...typeArgumentInferenceApparentType1.symbols | 16 + .../typeArgumentInferenceApparentType1.types | 18 + .../typeArgumentInferenceApparentType2.js | 17 + ...typeArgumentInferenceApparentType2.symbols | 27 + .../typeArgumentInferenceApparentType2.types | 28 + .../unclosedExportClause01.errors.txt | 44 ++ .../reference/unclosedExportClause01.js | 30 + .../unclosedExportClause02.errors.txt | 57 ++ .../reference/unclosedExportClause02.js | 32 + tests/baselines/reference/wideningTuples1.js | 9 + .../reference/wideningTuples1.symbols | 16 + .../baselines/reference/wideningTuples1.types | 21 + tests/baselines/reference/wideningTuples2.js | 13 + .../reference/wideningTuples2.symbols | 16 + .../baselines/reference/wideningTuples2.types | 22 + .../reference/wideningTuples3.errors.txt | 9 + tests/baselines/reference/wideningTuples3.js | 8 + tests/baselines/reference/wideningTuples4.js | 10 + .../reference/wideningTuples4.symbols | 12 + .../baselines/reference/wideningTuples4.types | 19 + .../reference/wideningTuples5.errors.txt | 10 + tests/baselines/reference/wideningTuples5.js | 5 + tests/baselines/reference/wideningTuples6.js | 9 + .../reference/wideningTuples6.symbols | 12 + .../baselines/reference/wideningTuples6.types | 18 + .../reference/wideningTuples7.errors.txt | 10 + tests/baselines/reference/wideningTuples7.js | 11 + ...ationWithModuleSpecifierNameOnNextLine1.ts | 20 + .../typeArgumentInferenceApparentType1.ts | 6 + .../typeArgumentInferenceApparentType2.ts | 8 + .../cases/compiler/unclosedExportClause01.ts | 16 + .../cases/compiler/unclosedExportClause02.ts | 20 + .../superSymbolIndexedAccess1.ts | 14 + .../superSymbolIndexedAccess2.ts | 13 + .../superSymbolIndexedAccess3.ts | 14 + .../superSymbolIndexedAccess4.ts | 8 + .../superSymbolIndexedAccess5.ts | 14 + .../superSymbolIndexedAccess6.ts | 14 + .../types/tuple/wideningTuples1.ts | 5 + .../types/tuple/wideningTuples2.ts | 6 + .../types/tuple/wideningTuples3.ts | 4 + .../types/tuple/wideningTuples4.ts | 4 + .../types/tuple/wideningTuples5.ts | 2 + .../types/tuple/wideningTuples6.ts | 3 + .../types/tuple/wideningTuples7.ts | 5 + ...tifierDefinitionLocations_destructuring.ts | 2 +- .../completionListInExportClause01.ts | 40 + .../completionListInExportClause02.ts | 14 + .../completionListInExportClause03.ts | 16 + .../completionListInImportClause01.ts | 1 + .../completionListInNamespaceImportName01.ts | 11 + ...lRefsObjectBindingElementPropertyName01.ts | 19 + ...lRefsObjectBindingElementPropertyName02.ts | 19 + ...lRefsObjectBindingElementPropertyName03.ts | 19 + ...lRefsObjectBindingElementPropertyName04.ts | 23 + ...lRefsObjectBindingElementPropertyName05.ts | 13 + ...lRefsObjectBindingElementPropertyName06.ts | 30 + ...lRefsObjectBindingElementPropertyName07.ts | 15 + ...lRefsObjectBindingElementPropertyName09.ts | 23 + ...lRefsObjectBindingElementPropertyName10.ts | 19 + .../fourslash/getOccurrencesAbstract01.ts | 24 + .../fourslash/getOccurrencesAbstract02.ts | 29 + ...etOccurrencesClassExpressionConstructor.ts | 23 + .../getOccurrencesClassExpressionPrivate.ts | 27 + .../getOccurrencesClassExpressionPublic.ts | 27 + .../getOccurrencesClassExpressionStatic.ts | 29 + ...itionObjectBindingElementPropertyName01.ts | 14 + .../quickInfoForObjectBindingElementName01.ts | 12 + .../quickInfoForObjectBindingElementName02.ts | 12 + ...foForObjectBindingElementPropertyName01.ts | 12 + ...foForObjectBindingElementPropertyName02.ts | 12 + ...foForObjectBindingElementPropertyName03.ts | 14 + ...foForObjectBindingElementPropertyName04.ts | 17 + ...enameObjectBindingElementPropertyName01.ts | 14 + .../shims/getSyntacticClassifications.ts | 4 +- .../syntacticClassificationWithErrors.ts | 4 +- .../fourslash/syntacticClassifications1.ts | 4 +- ...yntacticClassificationsConflictMarkers1.ts | 4 +- ...yntacticClassificationsConflictMarkers2.ts | 2 +- .../syntacticClassificationsDocComment1.ts | 2 +- .../syntacticClassificationsDocComment2.ts | 4 +- .../syntacticClassificationsDocComment3.ts | 2 +- .../syntacticClassificationsForOfKeyword.ts | 4 +- .../syntacticClassificationsForOfKeyword2.ts | 4 +- .../syntacticClassificationsForOfKeyword3.ts | 6 +- ...cticClassificationsFunctionWithComments.ts | 4 +- .../syntacticClassificationsObjectLiteral.ts | 18 +- .../syntacticClassificationsTemplates1.ts | 8 +- .../syntacticClassificationsTemplates2.ts | 2 +- 162 files changed, 4015 insertions(+), 1738 deletions(-) create mode 100644 tests/baselines/reference/exportDeclarationWithModuleSpecifierNameOnNextLine1.js create mode 100644 tests/baselines/reference/exportDeclarationWithModuleSpecifierNameOnNextLine1.symbols create mode 100644 tests/baselines/reference/exportDeclarationWithModuleSpecifierNameOnNextLine1.types create mode 100644 tests/baselines/reference/superSymbolIndexedAccess1.js create mode 100644 tests/baselines/reference/superSymbolIndexedAccess1.symbols create mode 100644 tests/baselines/reference/superSymbolIndexedAccess1.types create mode 100644 tests/baselines/reference/superSymbolIndexedAccess2.js create mode 100644 tests/baselines/reference/superSymbolIndexedAccess2.symbols create mode 100644 tests/baselines/reference/superSymbolIndexedAccess2.types create mode 100644 tests/baselines/reference/superSymbolIndexedAccess3.errors.txt create mode 100644 tests/baselines/reference/superSymbolIndexedAccess3.js create mode 100644 tests/baselines/reference/superSymbolIndexedAccess4.errors.txt create mode 100644 tests/baselines/reference/superSymbolIndexedAccess4.js create mode 100644 tests/baselines/reference/superSymbolIndexedAccess5.js create mode 100644 tests/baselines/reference/superSymbolIndexedAccess5.symbols create mode 100644 tests/baselines/reference/superSymbolIndexedAccess5.types create mode 100644 tests/baselines/reference/superSymbolIndexedAccess6.js create mode 100644 tests/baselines/reference/superSymbolIndexedAccess6.symbols create mode 100644 tests/baselines/reference/superSymbolIndexedAccess6.types create mode 100644 tests/baselines/reference/typeArgumentInferenceApparentType1.js create mode 100644 tests/baselines/reference/typeArgumentInferenceApparentType1.symbols create mode 100644 tests/baselines/reference/typeArgumentInferenceApparentType1.types create mode 100644 tests/baselines/reference/typeArgumentInferenceApparentType2.js create mode 100644 tests/baselines/reference/typeArgumentInferenceApparentType2.symbols create mode 100644 tests/baselines/reference/typeArgumentInferenceApparentType2.types create mode 100644 tests/baselines/reference/unclosedExportClause01.errors.txt create mode 100644 tests/baselines/reference/unclosedExportClause01.js create mode 100644 tests/baselines/reference/unclosedExportClause02.errors.txt create mode 100644 tests/baselines/reference/unclosedExportClause02.js create mode 100644 tests/baselines/reference/wideningTuples1.js create mode 100644 tests/baselines/reference/wideningTuples1.symbols create mode 100644 tests/baselines/reference/wideningTuples1.types create mode 100644 tests/baselines/reference/wideningTuples2.js create mode 100644 tests/baselines/reference/wideningTuples2.symbols create mode 100644 tests/baselines/reference/wideningTuples2.types create mode 100644 tests/baselines/reference/wideningTuples3.errors.txt create mode 100644 tests/baselines/reference/wideningTuples3.js create mode 100644 tests/baselines/reference/wideningTuples4.js create mode 100644 tests/baselines/reference/wideningTuples4.symbols create mode 100644 tests/baselines/reference/wideningTuples4.types create mode 100644 tests/baselines/reference/wideningTuples5.errors.txt create mode 100644 tests/baselines/reference/wideningTuples5.js create mode 100644 tests/baselines/reference/wideningTuples6.js create mode 100644 tests/baselines/reference/wideningTuples6.symbols create mode 100644 tests/baselines/reference/wideningTuples6.types create mode 100644 tests/baselines/reference/wideningTuples7.errors.txt create mode 100644 tests/baselines/reference/wideningTuples7.js create mode 100644 tests/cases/compiler/exportDeclarationWithModuleSpecifierNameOnNextLine1.ts create mode 100644 tests/cases/compiler/typeArgumentInferenceApparentType1.ts create mode 100644 tests/cases/compiler/typeArgumentInferenceApparentType2.ts create mode 100644 tests/cases/compiler/unclosedExportClause01.ts create mode 100644 tests/cases/compiler/unclosedExportClause02.ts create mode 100644 tests/cases/conformance/expressions/superPropertyAccess/superSymbolIndexedAccess1.ts create mode 100644 tests/cases/conformance/expressions/superPropertyAccess/superSymbolIndexedAccess2.ts create mode 100644 tests/cases/conformance/expressions/superPropertyAccess/superSymbolIndexedAccess3.ts create mode 100644 tests/cases/conformance/expressions/superPropertyAccess/superSymbolIndexedAccess4.ts create mode 100644 tests/cases/conformance/expressions/superPropertyAccess/superSymbolIndexedAccess5.ts create mode 100644 tests/cases/conformance/expressions/superPropertyAccess/superSymbolIndexedAccess6.ts create mode 100644 tests/cases/conformance/types/tuple/wideningTuples1.ts create mode 100644 tests/cases/conformance/types/tuple/wideningTuples2.ts create mode 100644 tests/cases/conformance/types/tuple/wideningTuples3.ts create mode 100644 tests/cases/conformance/types/tuple/wideningTuples4.ts create mode 100644 tests/cases/conformance/types/tuple/wideningTuples5.ts create mode 100644 tests/cases/conformance/types/tuple/wideningTuples6.ts create mode 100644 tests/cases/conformance/types/tuple/wideningTuples7.ts create mode 100644 tests/cases/fourslash/completionListInExportClause01.ts create mode 100644 tests/cases/fourslash/completionListInExportClause02.ts create mode 100644 tests/cases/fourslash/completionListInExportClause03.ts create mode 100644 tests/cases/fourslash/completionListInNamespaceImportName01.ts create mode 100644 tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName01.ts create mode 100644 tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName02.ts create mode 100644 tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName03.ts create mode 100644 tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName04.ts create mode 100644 tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName05.ts create mode 100644 tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName06.ts create mode 100644 tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName07.ts create mode 100644 tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName09.ts create mode 100644 tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName10.ts create mode 100644 tests/cases/fourslash/getOccurrencesAbstract01.ts create mode 100644 tests/cases/fourslash/getOccurrencesAbstract02.ts create mode 100644 tests/cases/fourslash/getOccurrencesClassExpressionConstructor.ts create mode 100644 tests/cases/fourslash/getOccurrencesClassExpressionPrivate.ts create mode 100644 tests/cases/fourslash/getOccurrencesClassExpressionPublic.ts create mode 100644 tests/cases/fourslash/getOccurrencesClassExpressionStatic.ts create mode 100644 tests/cases/fourslash/goToDefinitionObjectBindingElementPropertyName01.ts create mode 100644 tests/cases/fourslash/quickInfoForObjectBindingElementName01.ts create mode 100644 tests/cases/fourslash/quickInfoForObjectBindingElementName02.ts create mode 100644 tests/cases/fourslash/quickInfoForObjectBindingElementPropertyName01.ts create mode 100644 tests/cases/fourslash/quickInfoForObjectBindingElementPropertyName02.ts create mode 100644 tests/cases/fourslash/quickInfoForObjectBindingElementPropertyName03.ts create mode 100644 tests/cases/fourslash/quickInfoForObjectBindingElementPropertyName04.ts create mode 100644 tests/cases/fourslash/renameObjectBindingElementPropertyName01.ts diff --git a/Jakefile.js b/Jakefile.js index 33ad46c8b58..bd5074b43d6 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -113,7 +113,7 @@ var languageServiceLibrarySources = [ return path.join(serverDirectory, f); }).concat(servicesSources); -var harnessSources = [ +var harnessCoreSources = [ "harness.ts", "sourceMapRecorder.ts", "harnessLanguageService.ts", @@ -129,7 +129,9 @@ var harnessSources = [ "runner.ts" ].map(function (f) { return path.join(harnessDirectory, f); -}).concat([ +}); + +var harnessSources = harnessCoreSources.concat([ "incrementalParser.ts", "jsDocParsing.ts", "services/colorization.ts", @@ -566,7 +568,7 @@ task("runtests", ["tests", builtLocalDirectory], function() { colors = process.env.colors || process.env.color colors = colors ? ' --no-colors ' : ' --colors '; tests = tests ? ' -g ' + tests : ''; - reporter = process.env.reporter || process.env.r || 'dot'; + reporter = process.env.reporter || process.env.r || 'mocha-fivemat-progress-reporter'; // timeout normally isn't necessary but Travis-CI has been timing out on compiler baselines occasionally // default timeout is 2sec which really should be enough, but maybe we just need a small amount longer var cmd = host + " -R " + reporter + tests + colors + ' -t ' + testTimeout + ' ' + run; @@ -730,12 +732,13 @@ task("update-sublime", ["local", serverFile], function() { // run this task automatically desc("Runs tslint on the compiler sources"); task("lint", [], function() { - for(var i in compilerSources) { - var f = compilerSources[i]; + function success(f) { return function() { console.log('SUCCESS: No linter errors in ' + f + '\n'); }}; + function failure(f) { return function() { console.log('FAILURE: Please fix linting errors in ' + f + '\n') }}; + + var lintTargets = compilerSources.concat(harnessCoreSources); + for(var i in lintTargets) { + var f = lintTargets[i]; var cmd = 'tslint -f ' + f; - exec(cmd, - function() { console.log('SUCCESS: No linter errors'); }, - function() { console.log('FAILURE: Please fix linting errors in ' + f + '\n'); - }); + exec(cmd, success(f), failure(f)); } }, { async: true }); diff --git a/bin/tsc.js b/bin/tsc.js index f5a780a390d..185aca1ef44 100644 --- a/bin/tsc.js +++ b/bin/tsc.js @@ -933,7 +933,14 @@ var ts; newLine: _os.EOL, useCaseSensitiveFileNames: useCaseSensitiveFileNames, write: function (s) { - _fs.writeSync(1, s); + var buffer = new Buffer(s, 'utf8'); + var offset = 0; + var toWrite = buffer.length; + var written = 0; + while ((written = _fs.writeSync(1, buffer, offset, toWrite)) < toWrite) { + offset += written; + toWrite -= written; + } }, readFile: readFile, writeFile: writeFile, @@ -1401,7 +1408,7 @@ var ts; Classes_containing_abstract_methods_must_be_marked_abstract: { code: 2514, category: ts.DiagnosticCategory.Error, key: "Classes containing abstract methods must be marked abstract." }, Non_abstract_class_0_does_not_implement_inherited_abstract_member_1_from_class_2: { code: 2515, category: ts.DiagnosticCategory.Error, key: "Non-abstract class '{0}' does not implement inherited abstract member '{1}' from class '{2}'." }, All_declarations_of_an_abstract_method_must_be_consecutive: { code: 2516, category: ts.DiagnosticCategory.Error, key: "All declarations of an abstract method must be consecutive." }, - Constructor_objects_of_abstract_type_cannot_be_assigned_to_constructor_objects_of_non_abstract_type: { code: 2517, category: ts.DiagnosticCategory.Error, key: "Constructor objects of abstract type cannot be assigned to constructor objects of non-abstract type" }, + Cannot_assign_an_abstract_constructor_type_to_a_non_abstract_constructor_type: { code: 2517, category: ts.DiagnosticCategory.Error, key: "Cannot assign an abstract constructor type to a non-abstract constructor type." }, Only_an_ambient_class_can_be_merged_with_an_interface: { code: 2518, category: ts.DiagnosticCategory.Error, key: "Only an ambient class can be merged with an interface." }, Duplicate_identifier_0_Compiler_uses_declaration_1_to_support_async_functions: { code: 2520, category: ts.DiagnosticCategory.Error, key: "Duplicate identifier '{0}'. Compiler uses declaration '{1}' to support async functions." }, Expression_resolves_to_variable_declaration_0_that_compiler_uses_to_support_async_functions: { code: 2521, category: ts.DiagnosticCategory.Error, key: "Expression resolves to variable declaration '{0}' that compiler uses to support async functions." }, @@ -9187,7 +9194,8 @@ var ts; } else { node.exportClause = parseNamedImportsOrExports(226); - if (parseOptional(130)) { + if (token === 130 || (token === 8 && !scanner.hasPrecedingLineBreak())) { + parseExpected(130); node.moduleSpecifier = parseModuleSpecifier(); } } @@ -13263,7 +13271,7 @@ var ts; var id = getTypeListId(elementTypes); var type = tupleTypes[id]; if (!type) { - type = tupleTypes[id] = createObjectType(8192); + type = tupleTypes[id] = createObjectType(8192 | getWideningFlagsOfTypes(elementTypes)); type.elementTypes = elementTypes; } return type; @@ -14084,10 +14092,29 @@ var ts; var targetSignatures = getSignaturesOfType(target, kind); var result = -1; var saveErrorInfo = errorInfo; + var sourceSig = sourceSignatures[0]; + var targetSig = targetSignatures[0]; + if (sourceSig && targetSig) { + var sourceErasedSignature = getErasedSignature(sourceSig); + var targetErasedSignature = getErasedSignature(targetSig); + var sourceReturnType = sourceErasedSignature && getReturnTypeOfSignature(sourceErasedSignature); + var targetReturnType = targetErasedSignature && getReturnTypeOfSignature(targetErasedSignature); + var sourceReturnDecl = sourceReturnType && sourceReturnType.symbol && ts.getDeclarationOfKind(sourceReturnType.symbol, 211); + var targetReturnDecl = targetReturnType && targetReturnType.symbol && ts.getDeclarationOfKind(targetReturnType.symbol, 211); + var sourceIsAbstract = sourceReturnDecl && sourceReturnDecl.flags & 256; + var targetIsAbstract = targetReturnDecl && targetReturnDecl.flags & 256; + if (sourceIsAbstract && !targetIsAbstract) { + if (reportErrors) { + reportError(ts.Diagnostics.Cannot_assign_an_abstract_constructor_type_to_a_non_abstract_constructor_type); + } + return 0; + } + } outer: for (var _i = 0; _i < targetSignatures.length; _i++) { var t = targetSignatures[_i]; if (!t.hasStringLiterals || target.flags & 262144) { var localErrors = reportErrors; + var checkedAbstractAssignability = false; for (var _a = 0; _a < sourceSignatures.length; _a++) { var s = sourceSignatures[_a]; if (!s.hasStringLiterals || source.flags & 262144) { @@ -14135,12 +14162,12 @@ var ts; target = getErasedSignature(target); var result = -1; for (var i = 0; i < checkCount; i++) { - var s_1 = i < sourceMax ? getTypeOfSymbol(source.parameters[i]) : getRestTypeOfSignature(source); - var t_1 = i < targetMax ? getTypeOfSymbol(target.parameters[i]) : getRestTypeOfSignature(target); + var s = i < sourceMax ? getTypeOfSymbol(source.parameters[i]) : getRestTypeOfSignature(source); + var t = i < targetMax ? getTypeOfSymbol(target.parameters[i]) : getRestTypeOfSignature(target); var saveErrorInfo = errorInfo; - var related = isRelatedTo(s_1, t_1, reportErrors); + var related = isRelatedTo(s, t, reportErrors); if (!related) { - related = isRelatedTo(t_1, s_1, false); + related = isRelatedTo(t, s, false); if (!related) { if (reportErrors) { reportError(ts.Diagnostics.Types_of_parameters_0_and_1_are_incompatible, source.parameters[i < sourceMax ? i : sourceMax].name, target.parameters[i < targetMax ? i : targetMax].name); @@ -14178,11 +14205,11 @@ var ts; } return 0; } - var t = getReturnTypeOfSignature(target); - if (t === voidType) + var targetReturnType = getReturnTypeOfSignature(target); + if (targetReturnType === voidType) return result; - var s = getReturnTypeOfSignature(source); - return result & isRelatedTo(s, t, reportErrors); + var sourceReturnType = getReturnTypeOfSignature(source); + return result & isRelatedTo(sourceReturnType, targetReturnType, reportErrors); } function signaturesIdenticalTo(source, target, kind) { var sourceSignatures = getSignaturesOfType(source, kind); @@ -14395,7 +14422,7 @@ var ts; return !!getPropertyOfType(type, "0"); } function isTupleType(type) { - return (type.flags & 8192) && !!type.elementTypes; + return !!(type.flags & 8192); } function getWidenedTypeOfObjectLiteral(type) { var properties = getPropertiesOfObjectType(type); @@ -14437,25 +14464,36 @@ var ts; if (isArrayType(type)) { return createArrayType(getWidenedType(type.typeArguments[0])); } + if (isTupleType(type)) { + return createTupleType(ts.map(type.elementTypes, getWidenedType)); + } } return type; } function reportWideningErrorsInType(type) { + var errorReported = false; if (type.flags & 16384) { - var errorReported = false; - ts.forEach(type.types, function (t) { + for (var _i = 0, _a = type.types; _i < _a.length; _i++) { + var t = _a[_i]; if (reportWideningErrorsInType(t)) { errorReported = true; } - }); - return errorReported; + } } if (isArrayType(type)) { return reportWideningErrorsInType(type.typeArguments[0]); } + if (isTupleType(type)) { + for (var _b = 0, _c = type.elementTypes; _b < _c.length; _b++) { + var t = _c[_b]; + if (reportWideningErrorsInType(t)) { + errorReported = true; + } + } + } if (type.flags & 524288) { - var errorReported = false; - ts.forEach(getPropertiesOfObjectType(type), function (p) { + for (var _d = 0, _e = getPropertiesOfObjectType(type); _d < _e.length; _d++) { + var p = _e[_d]; var t = getTypeOfSymbol(p); if (t.flags & 1048576) { if (!reportWideningErrorsInType(t)) { @@ -14463,10 +14501,9 @@ var ts; } errorReported = true; } - }); - return errorReported; + } } - return false; + return errorReported; } function reportImplicitAnyError(declaration, type) { var typeAsString = typeToString(getWidenedType(type)); @@ -14614,28 +14651,31 @@ var ts; inferFromTypes(sourceType, target); } } - else if (source.flags & 80896 && (target.flags & (4096 | 8192) || - (target.flags & 65536) && target.symbol && target.symbol.flags & (8192 | 2048 | 32))) { - if (isInProcess(source, target)) { - return; + else { + source = getApparentType(source); + if (source.flags & 80896 && (target.flags & (4096 | 8192) || + (target.flags & 65536) && target.symbol && target.symbol.flags & (8192 | 2048 | 32))) { + if (isInProcess(source, target)) { + return; + } + if (isDeeplyNestedGeneric(source, sourceStack, depth) && isDeeplyNestedGeneric(target, targetStack, depth)) { + return; + } + if (depth === 0) { + sourceStack = []; + targetStack = []; + } + sourceStack[depth] = source; + targetStack[depth] = target; + depth++; + inferFromProperties(source, target); + inferFromSignatures(source, target, 0); + inferFromSignatures(source, target, 1); + inferFromIndexTypes(source, target, 0, 0); + inferFromIndexTypes(source, target, 1, 1); + inferFromIndexTypes(source, target, 0, 1); + depth--; } - if (isDeeplyNestedGeneric(source, sourceStack, depth) && isDeeplyNestedGeneric(target, targetStack, depth)) { - return; - } - if (depth === 0) { - sourceStack = []; - targetStack = []; - } - sourceStack[depth] = source; - targetStack[depth] = target; - depth++; - inferFromProperties(source, target); - inferFromSignatures(source, target, 0); - inferFromSignatures(source, target, 1); - inferFromIndexTypes(source, target, 0, 0); - inferFromIndexTypes(source, target, 1, 1); - inferFromIndexTypes(source, target, 0, 1); - depth--; } } function inferFromProperties(source, target) { diff --git a/bin/tsserver.js b/bin/tsserver.js index abc95f7a760..9d582485e2f 100644 --- a/bin/tsserver.js +++ b/bin/tsserver.js @@ -933,7 +933,14 @@ var ts; newLine: _os.EOL, useCaseSensitiveFileNames: useCaseSensitiveFileNames, write: function (s) { - _fs.writeSync(1, s); + var buffer = new Buffer(s, 'utf8'); + var offset = 0; + var toWrite = buffer.length; + var written = 0; + while ((written = _fs.writeSync(1, buffer, offset, toWrite)) < toWrite) { + offset += written; + toWrite -= written; + } }, readFile: readFile, writeFile: writeFile, @@ -1401,7 +1408,7 @@ var ts; Classes_containing_abstract_methods_must_be_marked_abstract: { code: 2514, category: ts.DiagnosticCategory.Error, key: "Classes containing abstract methods must be marked abstract." }, Non_abstract_class_0_does_not_implement_inherited_abstract_member_1_from_class_2: { code: 2515, category: ts.DiagnosticCategory.Error, key: "Non-abstract class '{0}' does not implement inherited abstract member '{1}' from class '{2}'." }, All_declarations_of_an_abstract_method_must_be_consecutive: { code: 2516, category: ts.DiagnosticCategory.Error, key: "All declarations of an abstract method must be consecutive." }, - Constructor_objects_of_abstract_type_cannot_be_assigned_to_constructor_objects_of_non_abstract_type: { code: 2517, category: ts.DiagnosticCategory.Error, key: "Constructor objects of abstract type cannot be assigned to constructor objects of non-abstract type" }, + Cannot_assign_an_abstract_constructor_type_to_a_non_abstract_constructor_type: { code: 2517, category: ts.DiagnosticCategory.Error, key: "Cannot assign an abstract constructor type to a non-abstract constructor type." }, Only_an_ambient_class_can_be_merged_with_an_interface: { code: 2518, category: ts.DiagnosticCategory.Error, key: "Only an ambient class can be merged with an interface." }, Duplicate_identifier_0_Compiler_uses_declaration_1_to_support_async_functions: { code: 2520, category: ts.DiagnosticCategory.Error, key: "Duplicate identifier '{0}'. Compiler uses declaration '{1}' to support async functions." }, Expression_resolves_to_variable_declaration_0_that_compiler_uses_to_support_async_functions: { code: 2521, category: ts.DiagnosticCategory.Error, key: "Expression resolves to variable declaration '{0}' that compiler uses to support async functions." }, @@ -8904,7 +8911,8 @@ var ts; } else { node.exportClause = parseNamedImportsOrExports(226); - if (parseOptional(130)) { + if (token === 130 || (token === 8 && !scanner.hasPrecedingLineBreak())) { + parseExpected(130); node.moduleSpecifier = parseModuleSpecifier(); } } @@ -13686,7 +13694,7 @@ var ts; var id = getTypeListId(elementTypes); var type = tupleTypes[id]; if (!type) { - type = tupleTypes[id] = createObjectType(8192); + type = tupleTypes[id] = createObjectType(8192 | getWideningFlagsOfTypes(elementTypes)); type.elementTypes = elementTypes; } return type; @@ -14507,10 +14515,29 @@ var ts; var targetSignatures = getSignaturesOfType(target, kind); var result = -1; var saveErrorInfo = errorInfo; + var sourceSig = sourceSignatures[0]; + var targetSig = targetSignatures[0]; + if (sourceSig && targetSig) { + var sourceErasedSignature = getErasedSignature(sourceSig); + var targetErasedSignature = getErasedSignature(targetSig); + var sourceReturnType = sourceErasedSignature && getReturnTypeOfSignature(sourceErasedSignature); + var targetReturnType = targetErasedSignature && getReturnTypeOfSignature(targetErasedSignature); + var sourceReturnDecl = sourceReturnType && sourceReturnType.symbol && ts.getDeclarationOfKind(sourceReturnType.symbol, 211); + var targetReturnDecl = targetReturnType && targetReturnType.symbol && ts.getDeclarationOfKind(targetReturnType.symbol, 211); + var sourceIsAbstract = sourceReturnDecl && sourceReturnDecl.flags & 256; + var targetIsAbstract = targetReturnDecl && targetReturnDecl.flags & 256; + if (sourceIsAbstract && !targetIsAbstract) { + if (reportErrors) { + reportError(ts.Diagnostics.Cannot_assign_an_abstract_constructor_type_to_a_non_abstract_constructor_type); + } + return 0; + } + } outer: for (var _i = 0; _i < targetSignatures.length; _i++) { var t = targetSignatures[_i]; if (!t.hasStringLiterals || target.flags & 262144) { var localErrors = reportErrors; + var checkedAbstractAssignability = false; for (var _a = 0; _a < sourceSignatures.length; _a++) { var s = sourceSignatures[_a]; if (!s.hasStringLiterals || source.flags & 262144) { @@ -14558,12 +14585,12 @@ var ts; target = getErasedSignature(target); var result = -1; for (var i = 0; i < checkCount; i++) { - var s_1 = i < sourceMax ? getTypeOfSymbol(source.parameters[i]) : getRestTypeOfSignature(source); - var t_1 = i < targetMax ? getTypeOfSymbol(target.parameters[i]) : getRestTypeOfSignature(target); + var s = i < sourceMax ? getTypeOfSymbol(source.parameters[i]) : getRestTypeOfSignature(source); + var t = i < targetMax ? getTypeOfSymbol(target.parameters[i]) : getRestTypeOfSignature(target); var saveErrorInfo = errorInfo; - var related = isRelatedTo(s_1, t_1, reportErrors); + var related = isRelatedTo(s, t, reportErrors); if (!related) { - related = isRelatedTo(t_1, s_1, false); + related = isRelatedTo(t, s, false); if (!related) { if (reportErrors) { reportError(ts.Diagnostics.Types_of_parameters_0_and_1_are_incompatible, source.parameters[i < sourceMax ? i : sourceMax].name, target.parameters[i < targetMax ? i : targetMax].name); @@ -14601,11 +14628,11 @@ var ts; } return 0; } - var t = getReturnTypeOfSignature(target); - if (t === voidType) + var targetReturnType = getReturnTypeOfSignature(target); + if (targetReturnType === voidType) return result; - var s = getReturnTypeOfSignature(source); - return result & isRelatedTo(s, t, reportErrors); + var sourceReturnType = getReturnTypeOfSignature(source); + return result & isRelatedTo(sourceReturnType, targetReturnType, reportErrors); } function signaturesIdenticalTo(source, target, kind) { var sourceSignatures = getSignaturesOfType(source, kind); @@ -14818,7 +14845,7 @@ var ts; return !!getPropertyOfType(type, "0"); } function isTupleType(type) { - return (type.flags & 8192) && !!type.elementTypes; + return !!(type.flags & 8192); } function getWidenedTypeOfObjectLiteral(type) { var properties = getPropertiesOfObjectType(type); @@ -14860,25 +14887,36 @@ var ts; if (isArrayType(type)) { return createArrayType(getWidenedType(type.typeArguments[0])); } + if (isTupleType(type)) { + return createTupleType(ts.map(type.elementTypes, getWidenedType)); + } } return type; } function reportWideningErrorsInType(type) { + var errorReported = false; if (type.flags & 16384) { - var errorReported = false; - ts.forEach(type.types, function (t) { + for (var _i = 0, _a = type.types; _i < _a.length; _i++) { + var t = _a[_i]; if (reportWideningErrorsInType(t)) { errorReported = true; } - }); - return errorReported; + } } if (isArrayType(type)) { return reportWideningErrorsInType(type.typeArguments[0]); } + if (isTupleType(type)) { + for (var _b = 0, _c = type.elementTypes; _b < _c.length; _b++) { + var t = _c[_b]; + if (reportWideningErrorsInType(t)) { + errorReported = true; + } + } + } if (type.flags & 524288) { - var errorReported = false; - ts.forEach(getPropertiesOfObjectType(type), function (p) { + for (var _d = 0, _e = getPropertiesOfObjectType(type); _d < _e.length; _d++) { + var p = _e[_d]; var t = getTypeOfSymbol(p); if (t.flags & 1048576) { if (!reportWideningErrorsInType(t)) { @@ -14886,10 +14924,9 @@ var ts; } errorReported = true; } - }); - return errorReported; + } } - return false; + return errorReported; } function reportImplicitAnyError(declaration, type) { var typeAsString = typeToString(getWidenedType(type)); @@ -15037,28 +15074,31 @@ var ts; inferFromTypes(sourceType, target); } } - else if (source.flags & 80896 && (target.flags & (4096 | 8192) || - (target.flags & 65536) && target.symbol && target.symbol.flags & (8192 | 2048 | 32))) { - if (isInProcess(source, target)) { - return; + else { + source = getApparentType(source); + if (source.flags & 80896 && (target.flags & (4096 | 8192) || + (target.flags & 65536) && target.symbol && target.symbol.flags & (8192 | 2048 | 32))) { + if (isInProcess(source, target)) { + return; + } + if (isDeeplyNestedGeneric(source, sourceStack, depth) && isDeeplyNestedGeneric(target, targetStack, depth)) { + return; + } + if (depth === 0) { + sourceStack = []; + targetStack = []; + } + sourceStack[depth] = source; + targetStack[depth] = target; + depth++; + inferFromProperties(source, target); + inferFromSignatures(source, target, 0); + inferFromSignatures(source, target, 1); + inferFromIndexTypes(source, target, 0, 0); + inferFromIndexTypes(source, target, 1, 1); + inferFromIndexTypes(source, target, 0, 1); + depth--; } - if (isDeeplyNestedGeneric(source, sourceStack, depth) && isDeeplyNestedGeneric(target, targetStack, depth)) { - return; - } - if (depth === 0) { - sourceStack = []; - targetStack = []; - } - sourceStack[depth] = source; - targetStack[depth] = target; - depth++; - inferFromProperties(source, target); - inferFromSignatures(source, target, 0); - inferFromSignatures(source, target, 1); - inferFromIndexTypes(source, target, 0, 0); - inferFromIndexTypes(source, target, 1, 1); - inferFromIndexTypes(source, target, 0, 1); - depth--; } } function inferFromProperties(source, target) { @@ -31937,15 +31977,15 @@ var ts; var t; var pos = scanner.getStartPos(); while (pos < endPos) { - var t_2 = scanner.getToken(); - if (!ts.isTrivia(t_2)) { + var t_1 = scanner.getToken(); + if (!ts.isTrivia(t_1)) { break; } scanner.scan(); var item = { pos: pos, end: scanner.getStartPos(), - kind: t_2 + kind: t_1 }; pos = scanner.getStartPos(); if (!leadingTrivia) { @@ -33289,6 +33329,8 @@ var ts; case 15: case 18: case 19: + case 16: + case 17: case 77: case 101: case 53: @@ -33390,7 +33432,7 @@ var ts; } else if (tokenInfo.token.kind === listStartToken) { startLine = sourceFile.getLineAndCharacterOfPosition(tokenInfo.token.pos).line; - var indentation_1 = computeIndentation(tokenInfo.token, startLine, -1, parent, parentDynamicIndentation, startLine); + var indentation_1 = computeIndentation(tokenInfo.token, startLine, -1, parent, parentDynamicIndentation, parentStartLine); listDynamicIndentation = getDynamicIndentation(parent, parentStartLine, indentation_1.indentation, indentation_1.delta); consumeTokenAndAdvanceScanner(tokenInfo, parent, listDynamicIndentation); } @@ -35052,6 +35094,12 @@ var ts; var newSourceFile = ts.updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks); setSourceFileFields(newSourceFile, scriptSnapshot, version); newSourceFile.nameTable = undefined; + if (sourceFile !== newSourceFile && sourceFile.scriptSnapshot) { + if (sourceFile.scriptSnapshot.dispose) { + sourceFile.scriptSnapshot.dispose(); + } + sourceFile.scriptSnapshot = undefined; + } return newSourceFile; } } @@ -35908,20 +35956,20 @@ var ts; } function tryGetGlobalSymbols() { var objectLikeContainer; - var importClause; + var namedImportsOrExports; var jsxContainer; if (objectLikeContainer = tryGetObjectLikeCompletionContainer(contextToken)) { return tryGetObjectLikeCompletionSymbols(objectLikeContainer); } - if (importClause = ts.getAncestor(contextToken, 220)) { - return tryGetImportClauseCompletionSymbols(importClause); + if (namedImportsOrExports = tryGetNamedImportsOrExportsForCompletion(contextToken)) { + return tryGetImportOrExportClauseCompletionSymbols(namedImportsOrExports); } if (jsxContainer = tryGetContainingJsxElement(contextToken)) { var attrsType; if ((jsxContainer.kind === 231) || (jsxContainer.kind === 232)) { attrsType = typeChecker.getJsxElementAttributesType(jsxContainer); if (attrsType) { - symbols = filterJsxAttributes(jsxContainer.attributes, typeChecker.getPropertiesOfType(attrsType)); + symbols = filterJsxAttributes(typeChecker.getPropertiesOfType(attrsType), jsxContainer.attributes); isMemberCompletion = true; isNewIdentifierLocation = false; return true; @@ -35951,19 +35999,11 @@ var ts; function isCompletionListBlocker(contextToken) { var start = new Date().getTime(); var result = isInStringOrRegularExpressionOrTemplateLiteral(contextToken) || - isIdentifierDefinitionLocation(contextToken) || + isSolelyIdentifierDefinitionLocation(contextToken) || isDotOfNumericLiteral(contextToken); log("getCompletionsAtPosition: isCompletionListBlocker: " + (new Date().getTime() - start)); return result; } - function shouldShowCompletionsInImportsClause(node) { - if (node) { - if (node.kind === 14 || node.kind === 23) { - return node.parent.kind === 222; - } - } - return false; - } function isNewIdentifierDefinitionLocation(previousToken) { if (previousToken) { var containingNodeKind = previousToken.parent.kind; @@ -36055,23 +36095,23 @@ var ts; } return true; } - function tryGetImportClauseCompletionSymbols(importClause) { - if (shouldShowCompletionsInImportsClause(contextToken)) { - isMemberCompletion = true; - isNewIdentifierLocation = false; - var importDeclaration = importClause.parent; - ts.Debug.assert(importDeclaration !== undefined && importDeclaration.kind === 219); - var exports_2; - var moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(importDeclaration.moduleSpecifier); - if (moduleSpecifierSymbol) { - exports_2 = typeChecker.getExportsOfModule(moduleSpecifierSymbol); - } - symbols = exports_2 ? filterModuleExports(exports_2, importDeclaration) : emptyArray; + function tryGetImportOrExportClauseCompletionSymbols(namedImportsOrExports) { + var declarationKind = namedImportsOrExports.kind === 222 ? + 219 : + 225; + var importOrExportDeclaration = ts.getAncestor(namedImportsOrExports, declarationKind); + var moduleSpecifier = importOrExportDeclaration.moduleSpecifier; + if (!moduleSpecifier) { + return false; } - else { - isMemberCompletion = false; - isNewIdentifierLocation = true; + isMemberCompletion = true; + isNewIdentifierLocation = false; + var exports; + var moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(importOrExportDeclaration.moduleSpecifier); + if (moduleSpecifierSymbol) { + exports = typeChecker.getExportsOfModule(moduleSpecifierSymbol); } + symbols = exports ? filterNamedImportOrExportCompletionItems(exports, namedImportsOrExports.elements) : emptyArray; return true; } function tryGetObjectLikeCompletionContainer(contextToken) { @@ -36088,6 +36128,20 @@ var ts; } return undefined; } + function tryGetNamedImportsOrExportsForCompletion(contextToken) { + if (contextToken) { + switch (contextToken.kind) { + case 14: + case 23: + switch (contextToken.parent.kind) { + case 222: + case 226: + return contextToken.parent; + } + } + } + return undefined; + } function tryGetContainingJsxElement(contextToken) { if (contextToken) { var parent_12 = contextToken.parent; @@ -36127,7 +36181,7 @@ var ts; } return false; } - function isIdentifierDefinitionLocation(contextToken) { + function isSolelyIdentifierDefinitionLocation(contextToken) { var containingNodeKind = contextToken.parent.kind; switch (contextToken.kind) { case 23: @@ -36173,6 +36227,10 @@ var ts; case 107: case 108: return containingNodeKind === 135; + case 113: + containingNodeKind === 223 || + containingNodeKind === 227 || + containingNodeKind === 221; case 70: case 78: case 104: @@ -36208,25 +36266,20 @@ var ts; } return false; } - function filterModuleExports(exports, importDeclaration) { - var exisingImports = {}; - if (!importDeclaration.importClause) { - return exports; + function filterNamedImportOrExportCompletionItems(exportsOfModule, namedImportsOrExports) { + var exisingImportsOrExports = {}; + for (var _i = 0; _i < namedImportsOrExports.length; _i++) { + var element = namedImportsOrExports[_i]; + if (element.getStart() <= position && position <= element.getEnd()) { + continue; + } + var name_31 = element.propertyName || element.name; + exisingImportsOrExports[name_31.text] = true; } - if (importDeclaration.importClause.namedBindings && - importDeclaration.importClause.namedBindings.kind === 222) { - ts.forEach(importDeclaration.importClause.namedBindings.elements, function (el) { - if (el.getStart() <= position && position <= el.getEnd()) { - return; - } - var name = el.propertyName || el.name; - exisingImports[name.text] = true; - }); + if (ts.isEmpty(exisingImportsOrExports)) { + return exportsOfModule; } - if (ts.isEmpty(exisingImports)) { - return exports; - } - return ts.filter(exports, function (e) { return !ts.lookUp(exisingImports, e.name); }); + return ts.filter(exportsOfModule, function (e) { return !ts.lookUp(exisingImportsOrExports, e.name); }); } function filterObjectMembersList(contextualMemberSymbols, existingMembers) { if (!existingMembers || existingMembers.length === 0) { @@ -36252,15 +36305,9 @@ var ts; } existingMemberNames[existingName] = true; } - var filteredMembers = []; - ts.forEach(contextualMemberSymbols, function (s) { - if (!existingMemberNames[s.name]) { - filteredMembers.push(s); - } - }); - return filteredMembers; + return ts.filter(contextualMemberSymbols, function (m) { return !ts.lookUp(existingMemberNames, m.name); }); } - function filterJsxAttributes(attributes, symbols) { + function filterJsxAttributes(symbols, attributes) { var seenNames = {}; for (var _i = 0; _i < attributes.length; _i++) { var attr = attributes[_i]; @@ -36271,14 +36318,7 @@ var ts; seenNames[attr.name.text] = true; } } - var result = []; - for (var _a = 0; _a < symbols.length; _a++) { - var sym = symbols[_a]; - if (!seenNames[sym.name]) { - result.push(sym); - } - } - return result; + return ts.filter(symbols, function (a) { return !ts.lookUp(seenNames, a.name); }); } } function getCompletionsAtPosition(fileName, position) { @@ -36310,10 +36350,10 @@ var ts; for (var _i = 0, _a = program.getSourceFiles(); _i < _a.length; _i++) { var sourceFile = _a[_i]; var nameTable = getNameTable(sourceFile); - for (var name_31 in nameTable) { - if (!allNames[name_31]) { - allNames[name_31] = name_31; - var displayName = getCompletionEntryDisplayName(name_31, target, true); + for (var name_32 in nameTable) { + if (!allNames[name_32]) { + allNames[name_32] = name_32; + var displayName = getCompletionEntryDisplayName(name_32, target, true); if (displayName) { var entry = { name: displayName, @@ -37117,6 +37157,7 @@ var ts; if (hasKind(node.parent, 142) || hasKind(node.parent, 143)) { return getGetAndSetOccurrences(node.parent); } + break; default: if (ts.isModifier(node.kind) && node.parent && (ts.isDeclaration(node.parent) || node.parent.kind === 190)) { @@ -37216,12 +37257,13 @@ var ts; var container = declaration.parent; if (ts.isAccessibilityModifier(modifier)) { if (!(container.kind === 211 || + container.kind === 183 || (declaration.kind === 135 && hasKind(container, 141)))) { return undefined; } } else if (modifier === 110) { - if (container.kind !== 211) { + if (!(container.kind === 211 || container.kind === 183)) { return undefined; } } @@ -37230,6 +37272,11 @@ var ts; return undefined; } } + else if (modifier === 112) { + if (!(container.kind === 211 || declaration.kind === 211)) { + return undefined; + } + } else { return undefined; } @@ -37239,12 +37286,18 @@ var ts; switch (container.kind) { case 216: case 245: - nodes = container.statements; + if (modifierFlag & 256) { + nodes = declaration.members.concat(declaration); + } + else { + nodes = container.statements; + } break; case 141: nodes = container.parameters.concat(container.parent.members); break; case 211: + case 183: nodes = container.members; if (modifierFlag & 112) { var constructor = ts.forEach(container.members, function (member) { @@ -37254,6 +37307,9 @@ var ts; nodes = nodes.concat(constructor.parameters); } } + else if (modifierFlag & 256) { + nodes = nodes.concat(container); + } break; default: ts.Debug.fail("Invalid container kind."); @@ -37278,6 +37334,8 @@ var ts; return 1; case 119: return 2; + case 112: + return 256; default: ts.Debug.fail(); } @@ -37975,17 +38033,17 @@ var ts; if (isNameOfPropertyAssignment(node)) { var objectLiteral = node.parent.parent; var contextualType = typeChecker.getContextualType(objectLiteral); - var name_32 = node.text; + var name_33 = node.text; if (contextualType) { if (contextualType.flags & 16384) { - var unionProperty = contextualType.getProperty(name_32); + var unionProperty = contextualType.getProperty(name_33); if (unionProperty) { return [unionProperty]; } else { var result_4 = []; ts.forEach(contextualType.types, function (t) { - var symbol = t.getProperty(name_32); + var symbol = t.getProperty(name_33); if (symbol) { result_4.push(symbol); } @@ -37994,7 +38052,7 @@ var ts; } } else { - var symbol_1 = contextualType.getProperty(name_32); + var symbol_1 = contextualType.getProperty(name_33); if (symbol_1) { return [symbol_1]; } @@ -38593,7 +38651,7 @@ var ts; return; } } - return 9; + return 2; } } function processElement(element) { @@ -39337,10 +39395,113 @@ var ts; this.fileHash = {}; this.nextFileId = 1; this.changeSeq = 0; + this.handlers = (_a = {}, + _a[CommandNames.Exit] = function () { + _this.exit(); + return {}; + }, + _a[CommandNames.Definition] = function (request) { + var defArgs = request.arguments; + return { response: _this.getDefinition(defArgs.line, defArgs.offset, defArgs.file) }; + }, + _a[CommandNames.TypeDefinition] = function (request) { + var defArgs = request.arguments; + return { response: _this.getTypeDefinition(defArgs.line, defArgs.offset, defArgs.file) }; + }, + _a[CommandNames.References] = function (request) { + var defArgs = request.arguments; + return { response: _this.getReferences(defArgs.line, defArgs.offset, defArgs.file) }; + }, + _a[CommandNames.Rename] = function (request) { + var renameArgs = request.arguments; + return { response: _this.getRenameLocations(renameArgs.line, renameArgs.offset, renameArgs.file, renameArgs.findInComments, renameArgs.findInStrings) }; + }, + _a[CommandNames.Open] = function (request) { + var openArgs = request.arguments; + _this.openClientFile(openArgs.file); + return {}; + }, + _a[CommandNames.Quickinfo] = function (request) { + var quickinfoArgs = request.arguments; + return { response: _this.getQuickInfo(quickinfoArgs.line, quickinfoArgs.offset, quickinfoArgs.file) }; + }, + _a[CommandNames.Format] = function (request) { + var formatArgs = request.arguments; + return { response: _this.getFormattingEditsForRange(formatArgs.line, formatArgs.offset, formatArgs.endLine, formatArgs.endOffset, formatArgs.file) }; + }, + _a[CommandNames.Formatonkey] = function (request) { + var formatOnKeyArgs = request.arguments; + return { response: _this.getFormattingEditsAfterKeystroke(formatOnKeyArgs.line, formatOnKeyArgs.offset, formatOnKeyArgs.key, formatOnKeyArgs.file) }; + }, + _a[CommandNames.Completions] = function (request) { + var completionsArgs = request.arguments; + return { response: _this.getCompletions(completionsArgs.line, completionsArgs.offset, completionsArgs.prefix, completionsArgs.file) }; + }, + _a[CommandNames.CompletionDetails] = function (request) { + var completionDetailsArgs = request.arguments; + return { response: _this.getCompletionEntryDetails(completionDetailsArgs.line, completionDetailsArgs.offset, completionDetailsArgs.entryNames, completionDetailsArgs.file) }; + }, + _a[CommandNames.SignatureHelp] = function (request) { + var signatureHelpArgs = request.arguments; + return { response: _this.getSignatureHelpItems(signatureHelpArgs.line, signatureHelpArgs.offset, signatureHelpArgs.file) }; + }, + _a[CommandNames.Geterr] = function (request) { + var geterrArgs = request.arguments; + return { response: _this.getDiagnostics(geterrArgs.delay, geterrArgs.files), responseRequired: false }; + }, + _a[CommandNames.Change] = function (request) { + var changeArgs = request.arguments; + _this.change(changeArgs.line, changeArgs.offset, changeArgs.endLine, changeArgs.endOffset, changeArgs.insertString, changeArgs.file); + return { responseRequired: false }; + }, + _a[CommandNames.Configure] = function (request) { + var configureArgs = request.arguments; + _this.projectService.setHostConfiguration(configureArgs); + _this.output(undefined, CommandNames.Configure, request.seq); + return { responseRequired: false }; + }, + _a[CommandNames.Reload] = function (request) { + var reloadArgs = request.arguments; + _this.reload(reloadArgs.file, reloadArgs.tmpfile, request.seq); + return { responseRequired: false }; + }, + _a[CommandNames.Saveto] = function (request) { + var savetoArgs = request.arguments; + _this.saveToTmp(savetoArgs.file, savetoArgs.tmpfile); + return { responseRequired: false }; + }, + _a[CommandNames.Close] = function (request) { + var closeArgs = request.arguments; + _this.closeClientFile(closeArgs.file); + return { responseRequired: false }; + }, + _a[CommandNames.Navto] = function (request) { + var navtoArgs = request.arguments; + return { response: _this.getNavigateToItems(navtoArgs.searchValue, navtoArgs.file, navtoArgs.maxResultCount) }; + }, + _a[CommandNames.Brace] = function (request) { + var braceArguments = request.arguments; + return { response: _this.getBraceMatching(braceArguments.line, braceArguments.offset, braceArguments.file) }; + }, + _a[CommandNames.NavBar] = function (request) { + var navBarArgs = request.arguments; + return { response: _this.getNavigationBarItems(navBarArgs.file) }; + }, + _a[CommandNames.Occurrences] = function (request) { + var _a = request.arguments, line = _a.line, offset = _a.offset, fileName = _a.file; + return { response: _this.getOccurrences(line, offset, fileName) }; + }, + _a[CommandNames.ProjectInfo] = function (request) { + var _a = request.arguments, file = _a.file, needFileNameList = _a.needFileNameList; + return { response: _this.getProjectInfo(file, needFileNameList) }; + }, + _a + ); this.projectService = new server.ProjectService(host, logger, function (eventName, project, fileName) { _this.handleEvent(eventName, project, fileName); }); + var _a; } Session.prototype.handleEvent = function (eventName, project, fileName) { var _this = this; @@ -39957,6 +40118,23 @@ var ts; }; Session.prototype.exit = function () { }; + Session.prototype.addProtocolHandler = function (command, handler) { + if (this.handlers[command]) { + throw new Error("Protocol handler already exists for command \"" + command + "\""); + } + this.handlers[command] = handler; + }; + Session.prototype.executeCommand = function (request) { + var handler = this.handlers[request.command]; + if (handler) { + return handler(request); + } + else { + this.projectService.log("Unrecognized JSON command: " + JSON.stringify(request)); + this.output(undefined, CommandNames.Unknown, request.seq, "Unrecognized JSON command: " + request.command); + return { responseRequired: false }; + } + }; Session.prototype.onMessage = function (message) { if (this.logger.isVerbose()) { this.logger.info("request: " + message); @@ -39964,140 +40142,7 @@ var ts; } try { var request = JSON.parse(message); - var response; - var errorMessage; - var responseRequired = true; - switch (request.command) { - case CommandNames.Exit: { - this.exit(); - responseRequired = false; - break; - } - case CommandNames.Definition: { - var defArgs = request.arguments; - response = this.getDefinition(defArgs.line, defArgs.offset, defArgs.file); - break; - } - case CommandNames.TypeDefinition: { - var defArgs = request.arguments; - response = this.getTypeDefinition(defArgs.line, defArgs.offset, defArgs.file); - break; - } - case CommandNames.References: { - var refArgs = request.arguments; - response = this.getReferences(refArgs.line, refArgs.offset, refArgs.file); - break; - } - case CommandNames.Rename: { - var renameArgs = request.arguments; - response = this.getRenameLocations(renameArgs.line, renameArgs.offset, renameArgs.file, renameArgs.findInComments, renameArgs.findInStrings); - break; - } - case CommandNames.Open: { - var openArgs = request.arguments; - this.openClientFile(openArgs.file); - responseRequired = false; - break; - } - case CommandNames.Quickinfo: { - var quickinfoArgs = request.arguments; - response = this.getQuickInfo(quickinfoArgs.line, quickinfoArgs.offset, quickinfoArgs.file); - break; - } - case CommandNames.Format: { - var formatArgs = request.arguments; - response = this.getFormattingEditsForRange(formatArgs.line, formatArgs.offset, formatArgs.endLine, formatArgs.endOffset, formatArgs.file); - break; - } - case CommandNames.Formatonkey: { - var formatOnKeyArgs = request.arguments; - response = this.getFormattingEditsAfterKeystroke(formatOnKeyArgs.line, formatOnKeyArgs.offset, formatOnKeyArgs.key, formatOnKeyArgs.file); - break; - } - case CommandNames.Completions: { - var completionsArgs = request.arguments; - response = this.getCompletions(completionsArgs.line, completionsArgs.offset, completionsArgs.prefix, completionsArgs.file); - break; - } - case CommandNames.CompletionDetails: { - var completionDetailsArgs = request.arguments; - response = - this.getCompletionEntryDetails(completionDetailsArgs.line, completionDetailsArgs.offset, completionDetailsArgs.entryNames, completionDetailsArgs.file); - break; - } - case CommandNames.SignatureHelp: { - var signatureHelpArgs = request.arguments; - response = this.getSignatureHelpItems(signatureHelpArgs.line, signatureHelpArgs.offset, signatureHelpArgs.file); - break; - } - case CommandNames.Geterr: { - var geterrArgs = request.arguments; - response = this.getDiagnostics(geterrArgs.delay, geterrArgs.files); - responseRequired = false; - break; - } - case CommandNames.Change: { - var changeArgs = request.arguments; - this.change(changeArgs.line, changeArgs.offset, changeArgs.endLine, changeArgs.endOffset, changeArgs.insertString, changeArgs.file); - responseRequired = false; - break; - } - case CommandNames.Configure: { - var configureArgs = request.arguments; - this.projectService.setHostConfiguration(configureArgs); - this.output(undefined, CommandNames.Configure, request.seq); - responseRequired = false; - break; - } - case CommandNames.Reload: { - var reloadArgs = request.arguments; - this.reload(reloadArgs.file, reloadArgs.tmpfile, request.seq); - responseRequired = false; - break; - } - case CommandNames.Saveto: { - var savetoArgs = request.arguments; - this.saveToTmp(savetoArgs.file, savetoArgs.tmpfile); - responseRequired = false; - break; - } - case CommandNames.Close: { - var closeArgs = request.arguments; - this.closeClientFile(closeArgs.file); - responseRequired = false; - break; - } - case CommandNames.Navto: { - var navtoArgs = request.arguments; - response = this.getNavigateToItems(navtoArgs.searchValue, navtoArgs.file, navtoArgs.maxResultCount); - break; - } - case CommandNames.Brace: { - var braceArguments = request.arguments; - response = this.getBraceMatching(braceArguments.line, braceArguments.offset, braceArguments.file); - break; - } - case CommandNames.NavBar: { - var navBarArgs = request.arguments; - response = this.getNavigationBarItems(navBarArgs.file); - break; - } - case CommandNames.Occurrences: { - var _a = request.arguments, line = _a.line, offset = _a.offset, fileName = _a.file; - response = this.getOccurrences(line, offset, fileName); - break; - } - case CommandNames.ProjectInfo: { - var _b = request.arguments, file = _b.file, needFileNameList = _b.needFileNameList; - response = this.getProjectInfo(file, needFileNameList); - break; - } - default: { - this.projectService.log("Unrecognized JSON command: " + message); - this.output(undefined, CommandNames.Unknown, request.seq, "Unrecognized JSON command: " + request.command); - break; - } - } + var _a = this.executeCommand(request), response = _a.response, responseRequired = _a.responseRequired; if (this.logger.isVerbose()) { var elapsed = this.hrtime(start); var seconds = elapsed[0]; @@ -42027,6 +42072,11 @@ var ts; var decoded = JSON.parse(encoded); return ts.createTextChangeRange(ts.createTextSpan(decoded.span.start, decoded.span.length), decoded.newLength); }; + ScriptSnapshotShimAdapter.prototype.dispose = function () { + if ("dispose" in this.scriptSnapshotShim) { + this.scriptSnapshotShim.dispose(); + } + }; return ScriptSnapshotShimAdapter; })(); var LanguageServiceShimHostAdapter = (function () { diff --git a/bin/typescript.d.ts b/bin/typescript.d.ts index 869fbb32d98..ee69b9ca909 100644 --- a/bin/typescript.d.ts +++ b/bin/typescript.d.ts @@ -1591,6 +1591,8 @@ declare module "typescript" { * not happen and the entire document will be re - parsed. */ getChangeRange(oldSnapshot: IScriptSnapshot): TextChangeRange; + /** Releases all resources held by this script snapshot */ + dispose?(): void; } module ScriptSnapshot { function fromString(text: string): IScriptSnapshot; diff --git a/bin/typescript.js b/bin/typescript.js index 219a0b3924f..6035d71fa2b 100644 --- a/bin/typescript.js +++ b/bin/typescript.js @@ -1775,8 +1775,15 @@ var ts; newLine: _os.EOL, useCaseSensitiveFileNames: useCaseSensitiveFileNames, write: function (s) { + var buffer = new Buffer(s, 'utf8'); + var offset = 0; + var toWrite = buffer.length; + var written = 0; // 1 is a standard descriptor for stdout - _fs.writeSync(1, s); + while ((written = _fs.writeSync(1, buffer, offset, toWrite)) < toWrite) { + offset += written; + toWrite -= written; + } }, readFile: readFile, writeFile: writeFile, @@ -2247,7 +2254,7 @@ var ts; Classes_containing_abstract_methods_must_be_marked_abstract: { code: 2514, category: ts.DiagnosticCategory.Error, key: "Classes containing abstract methods must be marked abstract." }, Non_abstract_class_0_does_not_implement_inherited_abstract_member_1_from_class_2: { code: 2515, category: ts.DiagnosticCategory.Error, key: "Non-abstract class '{0}' does not implement inherited abstract member '{1}' from class '{2}'." }, All_declarations_of_an_abstract_method_must_be_consecutive: { code: 2516, category: ts.DiagnosticCategory.Error, key: "All declarations of an abstract method must be consecutive." }, - Constructor_objects_of_abstract_type_cannot_be_assigned_to_constructor_objects_of_non_abstract_type: { code: 2517, category: ts.DiagnosticCategory.Error, key: "Constructor objects of abstract type cannot be assigned to constructor objects of non-abstract type" }, + Cannot_assign_an_abstract_constructor_type_to_a_non_abstract_constructor_type: { code: 2517, category: ts.DiagnosticCategory.Error, key: "Cannot assign an abstract constructor type to a non-abstract constructor type." }, Only_an_ambient_class_can_be_merged_with_an_interface: { code: 2518, category: ts.DiagnosticCategory.Error, key: "Only an ambient class can be merged with an interface." }, Duplicate_identifier_0_Compiler_uses_declaration_1_to_support_async_functions: { code: 2520, category: ts.DiagnosticCategory.Error, key: "Duplicate identifier '{0}'. Compiler uses declaration '{1}' to support async functions." }, Expression_resolves_to_variable_declaration_0_that_compiler_uses_to_support_async_functions: { code: 2521, category: ts.DiagnosticCategory.Error, key: "Expression resolves to variable declaration '{0}' that compiler uses to support async functions." }, @@ -11517,7 +11524,11 @@ var ts; } else { node.exportClause = parseNamedImportsOrExports(226 /* NamedExports */); - if (parseOptional(130 /* FromKeyword */)) { + // It is not uncommon to accidentally omit the 'from' keyword. Additionally, in editing scenarios, + // the 'from' keyword can be parsed as a named export when the export clause is unterminated (i.e. `export { from "moduleName";`) + // If we don't have a 'from' keyword, see if we have a string literal such that ASI won't take effect. + if (token === 130 /* FromKeyword */ || (token === 8 /* StringLiteral */ && !scanner.hasPrecedingLineBreak())) { + parseExpected(130 /* FromKeyword */); node.moduleSpecifier = parseModuleSpecifier(); } } @@ -16299,7 +16310,7 @@ var ts; var id = getTypeListId(elementTypes); var type = tupleTypes[id]; if (!type) { - type = tupleTypes[id] = createObjectType(8192 /* Tuple */); + type = tupleTypes[id] = createObjectType(8192 /* Tuple */ | getWideningFlagsOfTypes(elementTypes)); type.elementTypes = elementTypes; } return type; @@ -17200,10 +17211,33 @@ var ts; var targetSignatures = getSignaturesOfType(target, kind); var result = -1 /* True */; var saveErrorInfo = errorInfo; + // Because the "abstractness" of a class is the same across all construct signatures + // (internally we are checking the corresponding declaration), it is enough to perform + // the check and report an error once over all pairs of source and target construct signatures. + var sourceSig = sourceSignatures[0]; + // Note that in an extends-clause, targetSignatures is stripped, so the check never proceeds. + var targetSig = targetSignatures[0]; + if (sourceSig && targetSig) { + var sourceErasedSignature = getErasedSignature(sourceSig); + var targetErasedSignature = getErasedSignature(targetSig); + var sourceReturnType = sourceErasedSignature && getReturnTypeOfSignature(sourceErasedSignature); + var targetReturnType = targetErasedSignature && getReturnTypeOfSignature(targetErasedSignature); + var sourceReturnDecl = sourceReturnType && sourceReturnType.symbol && ts.getDeclarationOfKind(sourceReturnType.symbol, 211 /* ClassDeclaration */); + var targetReturnDecl = targetReturnType && targetReturnType.symbol && ts.getDeclarationOfKind(targetReturnType.symbol, 211 /* ClassDeclaration */); + var sourceIsAbstract = sourceReturnDecl && sourceReturnDecl.flags & 256 /* Abstract */; + var targetIsAbstract = targetReturnDecl && targetReturnDecl.flags & 256 /* Abstract */; + if (sourceIsAbstract && !targetIsAbstract) { + if (reportErrors) { + reportError(ts.Diagnostics.Cannot_assign_an_abstract_constructor_type_to_a_non_abstract_constructor_type); + } + return 0 /* False */; + } + } outer: for (var _i = 0; _i < targetSignatures.length; _i++) { var t = targetSignatures[_i]; if (!t.hasStringLiterals || target.flags & 262144 /* FromSignature */) { var localErrors = reportErrors; + var checkedAbstractAssignability = false; for (var _a = 0; _a < sourceSignatures.length; _a++) { var s = sourceSignatures[_a]; if (!s.hasStringLiterals || source.flags & 262144 /* FromSignature */) { @@ -17254,12 +17288,12 @@ var ts; target = getErasedSignature(target); var result = -1 /* True */; for (var i = 0; i < checkCount; i++) { - var s_1 = i < sourceMax ? getTypeOfSymbol(source.parameters[i]) : getRestTypeOfSignature(source); - var t_1 = i < targetMax ? getTypeOfSymbol(target.parameters[i]) : getRestTypeOfSignature(target); + var s = i < sourceMax ? getTypeOfSymbol(source.parameters[i]) : getRestTypeOfSignature(source); + var t = i < targetMax ? getTypeOfSymbol(target.parameters[i]) : getRestTypeOfSignature(target); var saveErrorInfo = errorInfo; - var related = isRelatedTo(s_1, t_1, reportErrors); + var related = isRelatedTo(s, t, reportErrors); if (!related) { - related = isRelatedTo(t_1, s_1, false); + related = isRelatedTo(t, s, false); if (!related) { if (reportErrors) { reportError(ts.Diagnostics.Types_of_parameters_0_and_1_are_incompatible, source.parameters[i < sourceMax ? i : sourceMax].name, target.parameters[i < targetMax ? i : targetMax].name); @@ -17297,11 +17331,11 @@ var ts; } return 0 /* False */; } - var t = getReturnTypeOfSignature(target); - if (t === voidType) + var targetReturnType = getReturnTypeOfSignature(target); + if (targetReturnType === voidType) return result; - var s = getReturnTypeOfSignature(source); - return result & isRelatedTo(s, t, reportErrors); + var sourceReturnType = getReturnTypeOfSignature(source); + return result & isRelatedTo(sourceReturnType, targetReturnType, reportErrors); } function signaturesIdenticalTo(source, target, kind) { var sourceSignatures = getSignaturesOfType(source, kind); @@ -17537,7 +17571,7 @@ var ts; * Prefer using isTupleLikeType() unless the use of `elementTypes` is required. */ function isTupleType(type) { - return (type.flags & 8192 /* Tuple */) && !!type.elementTypes; + return !!(type.flags & 8192 /* Tuple */); } function getWidenedTypeOfObjectLiteral(type) { var properties = getPropertiesOfObjectType(type); @@ -17579,25 +17613,47 @@ var ts; if (isArrayType(type)) { return createArrayType(getWidenedType(type.typeArguments[0])); } + if (isTupleType(type)) { + return createTupleType(ts.map(type.elementTypes, getWidenedType)); + } } return type; } + /** + * Reports implicit any errors that occur as a result of widening 'null' and 'undefined' + * to 'any'. A call to reportWideningErrorsInType is normally accompanied by a call to + * getWidenedType. But in some cases getWidenedType is called without reporting errors + * (type argument inference is an example). + * + * The return value indicates whether an error was in fact reported. The particular circumstances + * are on a best effort basis. Currently, if the null or undefined that causes widening is inside + * an object literal property (arbitrarily deeply), this function reports an error. If no error is + * reported, reportImplicitAnyError is a suitable fallback to report a general error. + */ function reportWideningErrorsInType(type) { + var errorReported = false; if (type.flags & 16384 /* Union */) { - var errorReported = false; - ts.forEach(type.types, function (t) { + for (var _i = 0, _a = type.types; _i < _a.length; _i++) { + var t = _a[_i]; if (reportWideningErrorsInType(t)) { errorReported = true; } - }); - return errorReported; + } } if (isArrayType(type)) { return reportWideningErrorsInType(type.typeArguments[0]); } + if (isTupleType(type)) { + for (var _b = 0, _c = type.elementTypes; _b < _c.length; _b++) { + var t = _c[_b]; + if (reportWideningErrorsInType(t)) { + errorReported = true; + } + } + } if (type.flags & 524288 /* ObjectLiteral */) { - var errorReported = false; - ts.forEach(getPropertiesOfObjectType(type), function (p) { + for (var _d = 0, _e = getPropertiesOfObjectType(type); _d < _e.length; _d++) { + var p = _e[_d]; var t = getTypeOfSymbol(p); if (t.flags & 1048576 /* ContainsUndefinedOrNull */) { if (!reportWideningErrorsInType(t)) { @@ -17605,10 +17661,9 @@ var ts; } errorReported = true; } - }); - return errorReported; + } } - return false; + return errorReported; } function reportImplicitAnyError(declaration, type) { var typeAsString = typeToString(getWidenedType(type)); @@ -17771,29 +17826,32 @@ var ts; inferFromTypes(sourceType, target); } } - else if (source.flags & 80896 /* ObjectType */ && (target.flags & (4096 /* Reference */ | 8192 /* Tuple */) || - (target.flags & 65536 /* Anonymous */) && target.symbol && target.symbol.flags & (8192 /* Method */ | 2048 /* TypeLiteral */ | 32 /* Class */))) { - // If source is an object type, and target is a type reference, a tuple type, the type of a method, or a type literal, infer from members - if (isInProcess(source, target)) { - return; + else { + source = getApparentType(source); + if (source.flags & 80896 /* ObjectType */ && (target.flags & (4096 /* Reference */ | 8192 /* Tuple */) || + (target.flags & 65536 /* Anonymous */) && target.symbol && target.symbol.flags & (8192 /* Method */ | 2048 /* TypeLiteral */ | 32 /* Class */))) { + // If source is an object type, and target is a type reference, a tuple type, the type of a method, or a type literal, infer from members + if (isInProcess(source, target)) { + return; + } + if (isDeeplyNestedGeneric(source, sourceStack, depth) && isDeeplyNestedGeneric(target, targetStack, depth)) { + return; + } + if (depth === 0) { + sourceStack = []; + targetStack = []; + } + sourceStack[depth] = source; + targetStack[depth] = target; + depth++; + inferFromProperties(source, target); + inferFromSignatures(source, target, 0 /* Call */); + inferFromSignatures(source, target, 1 /* Construct */); + inferFromIndexTypes(source, target, 0 /* String */, 0 /* String */); + inferFromIndexTypes(source, target, 1 /* Number */, 1 /* Number */); + inferFromIndexTypes(source, target, 0 /* String */, 1 /* Number */); + depth--; } - if (isDeeplyNestedGeneric(source, sourceStack, depth) && isDeeplyNestedGeneric(target, targetStack, depth)) { - return; - } - if (depth === 0) { - sourceStack = []; - targetStack = []; - } - sourceStack[depth] = source; - targetStack[depth] = target; - depth++; - inferFromProperties(source, target); - inferFromSignatures(source, target, 0 /* Call */); - inferFromSignatures(source, target, 1 /* Construct */); - inferFromIndexTypes(source, target, 0 /* String */, 0 /* String */); - inferFromIndexTypes(source, target, 1 /* Number */, 1 /* Number */); - inferFromIndexTypes(source, target, 0 /* String */, 1 /* Number */); - depth--; } } function inferFromProperties(source, target) { @@ -37768,8 +37826,8 @@ var ts; var pos = scanner.getStartPos(); // Read leading trivia and token while (pos < endPos) { - var t_2 = scanner.getToken(); - if (!ts.isTrivia(t_2)) { + var t_1 = scanner.getToken(); + if (!ts.isTrivia(t_1)) { break; } // consume leading trivia @@ -37777,7 +37835,7 @@ var ts; var item = { pos: pos, end: scanner.getStartPos(), - kind: t_2 + kind: t_1 }; pos = scanner.getStartPos(); if (!leadingTrivia) { @@ -39359,6 +39417,8 @@ var ts; case 15 /* CloseBraceToken */: case 18 /* OpenBracketToken */: case 19 /* CloseBracketToken */: + case 16 /* OpenParenToken */: + case 17 /* CloseParenToken */: case 77 /* ElseKeyword */: case 101 /* WhileKeyword */: case 53 /* AtToken */: @@ -39483,7 +39543,7 @@ var ts; else if (tokenInfo.token.kind === listStartToken) { // consume list start token startLine = sourceFile.getLineAndCharacterOfPosition(tokenInfo.token.pos).line; - var indentation_1 = computeIndentation(tokenInfo.token, startLine, -1 /* Unknown */, parent, parentDynamicIndentation, startLine); + var indentation_1 = computeIndentation(tokenInfo.token, startLine, -1 /* Unknown */, parent, parentDynamicIndentation, parentStartLine); listDynamicIndentation = getDynamicIndentation(parent, parentStartLine, indentation_1.indentation, indentation_1.delta); consumeTokenAndAdvanceScanner(tokenInfo, parent, listDynamicIndentation); } @@ -41389,6 +41449,13 @@ var ts; // after incremental parsing nameTable might not be up-to-date // drop it so it can be lazily recreated later newSourceFile.nameTable = undefined; + // dispose all resources held by old script snapshot + if (sourceFile !== newSourceFile && sourceFile.scriptSnapshot) { + if (sourceFile.scriptSnapshot.dispose) { + sourceFile.scriptSnapshot.dispose(); + } + sourceFile.scriptSnapshot = undefined; + } return newSourceFile; } } @@ -42410,15 +42477,15 @@ var ts; } function tryGetGlobalSymbols() { var objectLikeContainer; - var importClause; + var namedImportsOrExports; var jsxContainer; if (objectLikeContainer = tryGetObjectLikeCompletionContainer(contextToken)) { return tryGetObjectLikeCompletionSymbols(objectLikeContainer); } - if (importClause = ts.getAncestor(contextToken, 220 /* ImportClause */)) { + if (namedImportsOrExports = tryGetNamedImportsOrExportsForCompletion(contextToken)) { // cursor is in an import clause // try to show exported member for imported module - return tryGetImportClauseCompletionSymbols(importClause); + return tryGetImportOrExportClauseCompletionSymbols(namedImportsOrExports); } if (jsxContainer = tryGetContainingJsxElement(contextToken)) { var attrsType; @@ -42426,7 +42493,7 @@ var ts; // Cursor is inside a JSX self-closing element or opening element attrsType = typeChecker.getJsxElementAttributesType(jsxContainer); if (attrsType) { - symbols = filterJsxAttributes(jsxContainer.attributes, typeChecker.getPropertiesOfType(attrsType)); + symbols = filterJsxAttributes(typeChecker.getPropertiesOfType(attrsType), jsxContainer.attributes); isMemberCompletion = true; isNewIdentifierLocation = false; return true; @@ -42487,21 +42554,11 @@ var ts; function isCompletionListBlocker(contextToken) { var start = new Date().getTime(); var result = isInStringOrRegularExpressionOrTemplateLiteral(contextToken) || - isIdentifierDefinitionLocation(contextToken) || + isSolelyIdentifierDefinitionLocation(contextToken) || isDotOfNumericLiteral(contextToken); log("getCompletionsAtPosition: isCompletionListBlocker: " + (new Date().getTime() - start)); return result; } - function shouldShowCompletionsInImportsClause(node) { - if (node) { - // import {| - // import {a,| - if (node.kind === 14 /* OpenBraceToken */ || node.kind === 23 /* CommaToken */) { - return node.parent.kind === 222 /* NamedImports */; - } - } - return false; - } function isNewIdentifierDefinitionLocation(previousToken) { if (previousToken) { var containingNodeKind = previousToken.parent.kind; @@ -42610,34 +42667,37 @@ var ts; return true; } /** - * Aggregates relevant symbols for completion in import clauses; for instance, + * Aggregates relevant symbols for completion in import clauses and export clauses + * whose declarations have a module specifier; for instance, symbols will be aggregated for * - * import { $ } from "moduleName"; + * import { | } from "moduleName"; + * export { a as foo, | } from "moduleName"; + * + * but not for + * + * export { | }; * * Relevant symbols are stored in the captured 'symbols' variable. * * @returns true if 'symbols' was successfully populated; false otherwise. */ - function tryGetImportClauseCompletionSymbols(importClause) { - // cursor is in import clause - // try to show exported member for imported module - if (shouldShowCompletionsInImportsClause(contextToken)) { - isMemberCompletion = true; - isNewIdentifierLocation = false; - var importDeclaration = importClause.parent; - ts.Debug.assert(importDeclaration !== undefined && importDeclaration.kind === 219 /* ImportDeclaration */); - var exports; - var moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(importDeclaration.moduleSpecifier); - if (moduleSpecifierSymbol) { - exports = typeChecker.getExportsOfModule(moduleSpecifierSymbol); - } - //let exports = typeInfoResolver.getExportsOfImportDeclaration(importDeclaration); - symbols = exports ? filterModuleExports(exports, importDeclaration) : emptyArray; + function tryGetImportOrExportClauseCompletionSymbols(namedImportsOrExports) { + var declarationKind = namedImportsOrExports.kind === 222 /* NamedImports */ ? + 219 /* ImportDeclaration */ : + 225 /* ExportDeclaration */; + var importOrExportDeclaration = ts.getAncestor(namedImportsOrExports, declarationKind); + var moduleSpecifier = importOrExportDeclaration.moduleSpecifier; + if (!moduleSpecifier) { + return false; } - else { - isMemberCompletion = false; - isNewIdentifierLocation = true; + isMemberCompletion = true; + isNewIdentifierLocation = false; + var exports; + var moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(importOrExportDeclaration.moduleSpecifier); + if (moduleSpecifierSymbol) { + exports = typeChecker.getExportsOfModule(moduleSpecifierSymbol); } + symbols = exports ? filterNamedImportOrExportCompletionItems(exports, namedImportsOrExports.elements) : emptyArray; return true; } /** @@ -42658,6 +42718,24 @@ var ts; } return undefined; } + /** + * Returns the containing list of named imports or exports of a context token, + * on the condition that one exists and that the context implies completion should be given. + */ + function tryGetNamedImportsOrExportsForCompletion(contextToken) { + if (contextToken) { + switch (contextToken.kind) { + case 14 /* OpenBraceToken */: // import { | + case 23 /* CommaToken */: + switch (contextToken.parent.kind) { + case 222 /* NamedImports */: + case 226 /* NamedExports */: + return contextToken.parent; + } + } + } + return undefined; + } function tryGetContainingJsxElement(contextToken) { if (contextToken) { var parent_12 = contextToken.parent; @@ -42700,7 +42778,10 @@ var ts; } return false; } - function isIdentifierDefinitionLocation(contextToken) { + /** + * @returns true if we are certain that the currently edited location must define a new location; false otherwise. + */ + function isSolelyIdentifierDefinitionLocation(contextToken) { var containingNodeKind = contextToken.parent.kind; switch (contextToken.kind) { case 23 /* CommaToken */: @@ -42746,6 +42827,10 @@ var ts; case 107 /* PrivateKeyword */: case 108 /* ProtectedKeyword */: return containingNodeKind === 135 /* Parameter */; + case 113 /* AsKeyword */: + containingNodeKind === 223 /* ImportSpecifier */ || + containingNodeKind === 227 /* ExportSpecifier */ || + containingNodeKind === 221 /* NamespaceImport */; case 70 /* ClassKeyword */: case 78 /* EnumKeyword */: case 104 /* InterfaceKeyword */: @@ -42782,27 +42867,37 @@ var ts; } return false; } - function filterModuleExports(exports, importDeclaration) { - var exisingImports = {}; - if (!importDeclaration.importClause) { - return exports; + /** + * Filters out completion suggestions for named imports or exports. + * + * @param exportsOfModule The list of symbols which a module exposes. + * @param namedImportsOrExports The list of existing import/export specifiers in the import/export clause. + * + * @returns Symbols to be suggested at an import/export clause, barring those whose named imports/exports + * do not occur at the current position and have not otherwise been typed. + */ + function filterNamedImportOrExportCompletionItems(exportsOfModule, namedImportsOrExports) { + var exisingImportsOrExports = {}; + for (var _i = 0; _i < namedImportsOrExports.length; _i++) { + var element = namedImportsOrExports[_i]; + // If this is the current item we are editing right now, do not filter it out + if (element.getStart() <= position && position <= element.getEnd()) { + continue; + } + var name_31 = element.propertyName || element.name; + exisingImportsOrExports[name_31.text] = true; } - if (importDeclaration.importClause.namedBindings && - importDeclaration.importClause.namedBindings.kind === 222 /* NamedImports */) { - ts.forEach(importDeclaration.importClause.namedBindings.elements, function (el) { - // If this is the current item we are editing right now, do not filter it out - if (el.getStart() <= position && position <= el.getEnd()) { - return; - } - var name = el.propertyName || el.name; - exisingImports[name.text] = true; - }); + if (ts.isEmpty(exisingImportsOrExports)) { + return exportsOfModule; } - if (ts.isEmpty(exisingImports)) { - return exports; - } - return ts.filter(exports, function (e) { return !ts.lookUp(exisingImports, e.name); }); + return ts.filter(exportsOfModule, function (e) { return !ts.lookUp(exisingImportsOrExports, e.name); }); } + /** + * Filters out completion suggestions for named imports or exports. + * + * @returns Symbols to be suggested in an object binding pattern or object literal expression, barring those whose declarations + * do not occur at the current position and have not otherwise been typed. + */ function filterObjectMembersList(contextualMemberSymbols, existingMembers) { if (!existingMembers || existingMembers.length === 0) { return contextualMemberSymbols; @@ -42832,15 +42927,15 @@ var ts; } existingMemberNames[existingName] = true; } - var filteredMembers = []; - ts.forEach(contextualMemberSymbols, function (s) { - if (!existingMemberNames[s.name]) { - filteredMembers.push(s); - } - }); - return filteredMembers; + return ts.filter(contextualMemberSymbols, function (m) { return !ts.lookUp(existingMemberNames, m.name); }); } - function filterJsxAttributes(attributes, symbols) { + /** + * Filters out completion suggestions from 'symbols' according to existing JSX attributes. + * + * @returns Symbols to be suggested in a JSX element, barring those whose attributes + * do not occur at the current position and have not otherwise been typed. + */ + function filterJsxAttributes(symbols, attributes) { var seenNames = {}; for (var _i = 0; _i < attributes.length; _i++) { var attr = attributes[_i]; @@ -42852,14 +42947,7 @@ var ts; seenNames[attr.name.text] = true; } } - var result = []; - for (var _a = 0; _a < symbols.length; _a++) { - var sym = symbols[_a]; - if (!seenNames[sym.name]) { - result.push(sym); - } - } - return result; + return ts.filter(symbols, function (a) { return !ts.lookUp(seenNames, a.name); }); } } function getCompletionsAtPosition(fileName, position) { @@ -42892,10 +42980,10 @@ var ts; for (var _i = 0, _a = program.getSourceFiles(); _i < _a.length; _i++) { var sourceFile = _a[_i]; var nameTable = getNameTable(sourceFile); - for (var name_31 in nameTable) { - if (!allNames[name_31]) { - allNames[name_31] = name_31; - var displayName = getCompletionEntryDisplayName(name_31, target, true); + for (var name_32 in nameTable) { + if (!allNames[name_32]) { + allNames[name_32] = name_32; + var displayName = getCompletionEntryDisplayName(name_32, target, true); if (displayName) { var entry = { name: displayName, @@ -43764,6 +43852,7 @@ var ts; if (hasKind(node.parent, 142 /* GetAccessor */) || hasKind(node.parent, 143 /* SetAccessor */)) { return getGetAndSetOccurrences(node.parent); } + break; default: if (ts.isModifier(node.kind) && node.parent && (ts.isDeclaration(node.parent) || node.parent.kind === 190 /* VariableStatement */)) { @@ -43879,12 +43968,13 @@ var ts; // Make sure we only highlight the keyword when it makes sense to do so. if (ts.isAccessibilityModifier(modifier)) { if (!(container.kind === 211 /* ClassDeclaration */ || + container.kind === 183 /* ClassExpression */ || (declaration.kind === 135 /* Parameter */ && hasKind(container, 141 /* Constructor */)))) { return undefined; } } else if (modifier === 110 /* StaticKeyword */) { - if (container.kind !== 211 /* ClassDeclaration */) { + if (!(container.kind === 211 /* ClassDeclaration */ || container.kind === 183 /* ClassExpression */)) { return undefined; } } @@ -43893,6 +43983,11 @@ var ts; return undefined; } } + else if (modifier === 112 /* AbstractKeyword */) { + if (!(container.kind === 211 /* ClassDeclaration */ || declaration.kind === 211 /* ClassDeclaration */)) { + return undefined; + } + } else { // unsupported modifier return undefined; @@ -43903,12 +43998,19 @@ var ts; switch (container.kind) { case 216 /* ModuleBlock */: case 245 /* SourceFile */: - nodes = container.statements; + // Container is either a class declaration or the declaration is a classDeclaration + if (modifierFlag & 256 /* Abstract */) { + nodes = declaration.members.concat(declaration); + } + else { + nodes = container.statements; + } break; case 141 /* Constructor */: nodes = container.parameters.concat(container.parent.members); break; case 211 /* ClassDeclaration */: + case 183 /* ClassExpression */: nodes = container.members; // If we're an accessibility modifier, we're in an instance member and should search // the constructor's parameter list for instance members as well. @@ -43920,6 +44022,9 @@ var ts; nodes = nodes.concat(constructor.parameters); } } + else if (modifierFlag & 256 /* Abstract */) { + nodes = nodes.concat(container); + } break; default: ts.Debug.fail("Invalid container kind."); @@ -43944,6 +44049,8 @@ var ts; return 1 /* Export */; case 119 /* DeclareKeyword */: return 2 /* Ambient */; + case 112 /* AbstractKeyword */: + return 256 /* Abstract */; default: ts.Debug.fail(); } @@ -44761,19 +44868,19 @@ var ts; if (isNameOfPropertyAssignment(node)) { var objectLiteral = node.parent.parent; var contextualType = typeChecker.getContextualType(objectLiteral); - var name_32 = node.text; + var name_33 = node.text; if (contextualType) { if (contextualType.flags & 16384 /* Union */) { // This is a union type, first see if the property we are looking for is a union property (i.e. exists in all types) // if not, search the constituent types for the property - var unionProperty = contextualType.getProperty(name_32); + var unionProperty = contextualType.getProperty(name_33); if (unionProperty) { return [unionProperty]; } else { var result_4 = []; ts.forEach(contextualType.types, function (t) { - var symbol = t.getProperty(name_32); + var symbol = t.getProperty(name_33); if (symbol) { result_4.push(symbol); } @@ -44782,7 +44889,7 @@ var ts; } } else { - var symbol_1 = contextualType.getProperty(name_32); + var symbol_1 = contextualType.getProperty(name_33); if (symbol_1) { return [symbol_1]; } @@ -45464,7 +45571,7 @@ var ts; return; } } - return 9 /* text */; + return 2 /* identifier */; } } function processElement(element) { @@ -46760,6 +46867,13 @@ var ts; var decoded = JSON.parse(encoded); return ts.createTextChangeRange(ts.createTextSpan(decoded.span.start, decoded.span.length), decoded.newLength); }; + ScriptSnapshotShimAdapter.prototype.dispose = function () { + // if scriptSnapshotShim is a COM object then property check becomes method call with no arguments + // 'in' does not have this effect + if ("dispose" in this.scriptSnapshotShim) { + this.scriptSnapshotShim.dispose(); + } + }; return ScriptSnapshotShimAdapter; })(); var LanguageServiceShimHostAdapter = (function () { diff --git a/bin/typescriptServices.d.ts b/bin/typescriptServices.d.ts index cea8225468b..9840a5e688f 100644 --- a/bin/typescriptServices.d.ts +++ b/bin/typescriptServices.d.ts @@ -1591,6 +1591,8 @@ declare namespace ts { * not happen and the entire document will be re - parsed. */ getChangeRange(oldSnapshot: IScriptSnapshot): TextChangeRange; + /** Releases all resources held by this script snapshot */ + dispose?(): void; } module ScriptSnapshot { function fromString(text: string): IScriptSnapshot; diff --git a/bin/typescriptServices.js b/bin/typescriptServices.js index 219a0b3924f..6035d71fa2b 100644 --- a/bin/typescriptServices.js +++ b/bin/typescriptServices.js @@ -1775,8 +1775,15 @@ var ts; newLine: _os.EOL, useCaseSensitiveFileNames: useCaseSensitiveFileNames, write: function (s) { + var buffer = new Buffer(s, 'utf8'); + var offset = 0; + var toWrite = buffer.length; + var written = 0; // 1 is a standard descriptor for stdout - _fs.writeSync(1, s); + while ((written = _fs.writeSync(1, buffer, offset, toWrite)) < toWrite) { + offset += written; + toWrite -= written; + } }, readFile: readFile, writeFile: writeFile, @@ -2247,7 +2254,7 @@ var ts; Classes_containing_abstract_methods_must_be_marked_abstract: { code: 2514, category: ts.DiagnosticCategory.Error, key: "Classes containing abstract methods must be marked abstract." }, Non_abstract_class_0_does_not_implement_inherited_abstract_member_1_from_class_2: { code: 2515, category: ts.DiagnosticCategory.Error, key: "Non-abstract class '{0}' does not implement inherited abstract member '{1}' from class '{2}'." }, All_declarations_of_an_abstract_method_must_be_consecutive: { code: 2516, category: ts.DiagnosticCategory.Error, key: "All declarations of an abstract method must be consecutive." }, - Constructor_objects_of_abstract_type_cannot_be_assigned_to_constructor_objects_of_non_abstract_type: { code: 2517, category: ts.DiagnosticCategory.Error, key: "Constructor objects of abstract type cannot be assigned to constructor objects of non-abstract type" }, + Cannot_assign_an_abstract_constructor_type_to_a_non_abstract_constructor_type: { code: 2517, category: ts.DiagnosticCategory.Error, key: "Cannot assign an abstract constructor type to a non-abstract constructor type." }, Only_an_ambient_class_can_be_merged_with_an_interface: { code: 2518, category: ts.DiagnosticCategory.Error, key: "Only an ambient class can be merged with an interface." }, Duplicate_identifier_0_Compiler_uses_declaration_1_to_support_async_functions: { code: 2520, category: ts.DiagnosticCategory.Error, key: "Duplicate identifier '{0}'. Compiler uses declaration '{1}' to support async functions." }, Expression_resolves_to_variable_declaration_0_that_compiler_uses_to_support_async_functions: { code: 2521, category: ts.DiagnosticCategory.Error, key: "Expression resolves to variable declaration '{0}' that compiler uses to support async functions." }, @@ -11517,7 +11524,11 @@ var ts; } else { node.exportClause = parseNamedImportsOrExports(226 /* NamedExports */); - if (parseOptional(130 /* FromKeyword */)) { + // It is not uncommon to accidentally omit the 'from' keyword. Additionally, in editing scenarios, + // the 'from' keyword can be parsed as a named export when the export clause is unterminated (i.e. `export { from "moduleName";`) + // If we don't have a 'from' keyword, see if we have a string literal such that ASI won't take effect. + if (token === 130 /* FromKeyword */ || (token === 8 /* StringLiteral */ && !scanner.hasPrecedingLineBreak())) { + parseExpected(130 /* FromKeyword */); node.moduleSpecifier = parseModuleSpecifier(); } } @@ -16299,7 +16310,7 @@ var ts; var id = getTypeListId(elementTypes); var type = tupleTypes[id]; if (!type) { - type = tupleTypes[id] = createObjectType(8192 /* Tuple */); + type = tupleTypes[id] = createObjectType(8192 /* Tuple */ | getWideningFlagsOfTypes(elementTypes)); type.elementTypes = elementTypes; } return type; @@ -17200,10 +17211,33 @@ var ts; var targetSignatures = getSignaturesOfType(target, kind); var result = -1 /* True */; var saveErrorInfo = errorInfo; + // Because the "abstractness" of a class is the same across all construct signatures + // (internally we are checking the corresponding declaration), it is enough to perform + // the check and report an error once over all pairs of source and target construct signatures. + var sourceSig = sourceSignatures[0]; + // Note that in an extends-clause, targetSignatures is stripped, so the check never proceeds. + var targetSig = targetSignatures[0]; + if (sourceSig && targetSig) { + var sourceErasedSignature = getErasedSignature(sourceSig); + var targetErasedSignature = getErasedSignature(targetSig); + var sourceReturnType = sourceErasedSignature && getReturnTypeOfSignature(sourceErasedSignature); + var targetReturnType = targetErasedSignature && getReturnTypeOfSignature(targetErasedSignature); + var sourceReturnDecl = sourceReturnType && sourceReturnType.symbol && ts.getDeclarationOfKind(sourceReturnType.symbol, 211 /* ClassDeclaration */); + var targetReturnDecl = targetReturnType && targetReturnType.symbol && ts.getDeclarationOfKind(targetReturnType.symbol, 211 /* ClassDeclaration */); + var sourceIsAbstract = sourceReturnDecl && sourceReturnDecl.flags & 256 /* Abstract */; + var targetIsAbstract = targetReturnDecl && targetReturnDecl.flags & 256 /* Abstract */; + if (sourceIsAbstract && !targetIsAbstract) { + if (reportErrors) { + reportError(ts.Diagnostics.Cannot_assign_an_abstract_constructor_type_to_a_non_abstract_constructor_type); + } + return 0 /* False */; + } + } outer: for (var _i = 0; _i < targetSignatures.length; _i++) { var t = targetSignatures[_i]; if (!t.hasStringLiterals || target.flags & 262144 /* FromSignature */) { var localErrors = reportErrors; + var checkedAbstractAssignability = false; for (var _a = 0; _a < sourceSignatures.length; _a++) { var s = sourceSignatures[_a]; if (!s.hasStringLiterals || source.flags & 262144 /* FromSignature */) { @@ -17254,12 +17288,12 @@ var ts; target = getErasedSignature(target); var result = -1 /* True */; for (var i = 0; i < checkCount; i++) { - var s_1 = i < sourceMax ? getTypeOfSymbol(source.parameters[i]) : getRestTypeOfSignature(source); - var t_1 = i < targetMax ? getTypeOfSymbol(target.parameters[i]) : getRestTypeOfSignature(target); + var s = i < sourceMax ? getTypeOfSymbol(source.parameters[i]) : getRestTypeOfSignature(source); + var t = i < targetMax ? getTypeOfSymbol(target.parameters[i]) : getRestTypeOfSignature(target); var saveErrorInfo = errorInfo; - var related = isRelatedTo(s_1, t_1, reportErrors); + var related = isRelatedTo(s, t, reportErrors); if (!related) { - related = isRelatedTo(t_1, s_1, false); + related = isRelatedTo(t, s, false); if (!related) { if (reportErrors) { reportError(ts.Diagnostics.Types_of_parameters_0_and_1_are_incompatible, source.parameters[i < sourceMax ? i : sourceMax].name, target.parameters[i < targetMax ? i : targetMax].name); @@ -17297,11 +17331,11 @@ var ts; } return 0 /* False */; } - var t = getReturnTypeOfSignature(target); - if (t === voidType) + var targetReturnType = getReturnTypeOfSignature(target); + if (targetReturnType === voidType) return result; - var s = getReturnTypeOfSignature(source); - return result & isRelatedTo(s, t, reportErrors); + var sourceReturnType = getReturnTypeOfSignature(source); + return result & isRelatedTo(sourceReturnType, targetReturnType, reportErrors); } function signaturesIdenticalTo(source, target, kind) { var sourceSignatures = getSignaturesOfType(source, kind); @@ -17537,7 +17571,7 @@ var ts; * Prefer using isTupleLikeType() unless the use of `elementTypes` is required. */ function isTupleType(type) { - return (type.flags & 8192 /* Tuple */) && !!type.elementTypes; + return !!(type.flags & 8192 /* Tuple */); } function getWidenedTypeOfObjectLiteral(type) { var properties = getPropertiesOfObjectType(type); @@ -17579,25 +17613,47 @@ var ts; if (isArrayType(type)) { return createArrayType(getWidenedType(type.typeArguments[0])); } + if (isTupleType(type)) { + return createTupleType(ts.map(type.elementTypes, getWidenedType)); + } } return type; } + /** + * Reports implicit any errors that occur as a result of widening 'null' and 'undefined' + * to 'any'. A call to reportWideningErrorsInType is normally accompanied by a call to + * getWidenedType. But in some cases getWidenedType is called without reporting errors + * (type argument inference is an example). + * + * The return value indicates whether an error was in fact reported. The particular circumstances + * are on a best effort basis. Currently, if the null or undefined that causes widening is inside + * an object literal property (arbitrarily deeply), this function reports an error. If no error is + * reported, reportImplicitAnyError is a suitable fallback to report a general error. + */ function reportWideningErrorsInType(type) { + var errorReported = false; if (type.flags & 16384 /* Union */) { - var errorReported = false; - ts.forEach(type.types, function (t) { + for (var _i = 0, _a = type.types; _i < _a.length; _i++) { + var t = _a[_i]; if (reportWideningErrorsInType(t)) { errorReported = true; } - }); - return errorReported; + } } if (isArrayType(type)) { return reportWideningErrorsInType(type.typeArguments[0]); } + if (isTupleType(type)) { + for (var _b = 0, _c = type.elementTypes; _b < _c.length; _b++) { + var t = _c[_b]; + if (reportWideningErrorsInType(t)) { + errorReported = true; + } + } + } if (type.flags & 524288 /* ObjectLiteral */) { - var errorReported = false; - ts.forEach(getPropertiesOfObjectType(type), function (p) { + for (var _d = 0, _e = getPropertiesOfObjectType(type); _d < _e.length; _d++) { + var p = _e[_d]; var t = getTypeOfSymbol(p); if (t.flags & 1048576 /* ContainsUndefinedOrNull */) { if (!reportWideningErrorsInType(t)) { @@ -17605,10 +17661,9 @@ var ts; } errorReported = true; } - }); - return errorReported; + } } - return false; + return errorReported; } function reportImplicitAnyError(declaration, type) { var typeAsString = typeToString(getWidenedType(type)); @@ -17771,29 +17826,32 @@ var ts; inferFromTypes(sourceType, target); } } - else if (source.flags & 80896 /* ObjectType */ && (target.flags & (4096 /* Reference */ | 8192 /* Tuple */) || - (target.flags & 65536 /* Anonymous */) && target.symbol && target.symbol.flags & (8192 /* Method */ | 2048 /* TypeLiteral */ | 32 /* Class */))) { - // If source is an object type, and target is a type reference, a tuple type, the type of a method, or a type literal, infer from members - if (isInProcess(source, target)) { - return; + else { + source = getApparentType(source); + if (source.flags & 80896 /* ObjectType */ && (target.flags & (4096 /* Reference */ | 8192 /* Tuple */) || + (target.flags & 65536 /* Anonymous */) && target.symbol && target.symbol.flags & (8192 /* Method */ | 2048 /* TypeLiteral */ | 32 /* Class */))) { + // If source is an object type, and target is a type reference, a tuple type, the type of a method, or a type literal, infer from members + if (isInProcess(source, target)) { + return; + } + if (isDeeplyNestedGeneric(source, sourceStack, depth) && isDeeplyNestedGeneric(target, targetStack, depth)) { + return; + } + if (depth === 0) { + sourceStack = []; + targetStack = []; + } + sourceStack[depth] = source; + targetStack[depth] = target; + depth++; + inferFromProperties(source, target); + inferFromSignatures(source, target, 0 /* Call */); + inferFromSignatures(source, target, 1 /* Construct */); + inferFromIndexTypes(source, target, 0 /* String */, 0 /* String */); + inferFromIndexTypes(source, target, 1 /* Number */, 1 /* Number */); + inferFromIndexTypes(source, target, 0 /* String */, 1 /* Number */); + depth--; } - if (isDeeplyNestedGeneric(source, sourceStack, depth) && isDeeplyNestedGeneric(target, targetStack, depth)) { - return; - } - if (depth === 0) { - sourceStack = []; - targetStack = []; - } - sourceStack[depth] = source; - targetStack[depth] = target; - depth++; - inferFromProperties(source, target); - inferFromSignatures(source, target, 0 /* Call */); - inferFromSignatures(source, target, 1 /* Construct */); - inferFromIndexTypes(source, target, 0 /* String */, 0 /* String */); - inferFromIndexTypes(source, target, 1 /* Number */, 1 /* Number */); - inferFromIndexTypes(source, target, 0 /* String */, 1 /* Number */); - depth--; } } function inferFromProperties(source, target) { @@ -37768,8 +37826,8 @@ var ts; var pos = scanner.getStartPos(); // Read leading trivia and token while (pos < endPos) { - var t_2 = scanner.getToken(); - if (!ts.isTrivia(t_2)) { + var t_1 = scanner.getToken(); + if (!ts.isTrivia(t_1)) { break; } // consume leading trivia @@ -37777,7 +37835,7 @@ var ts; var item = { pos: pos, end: scanner.getStartPos(), - kind: t_2 + kind: t_1 }; pos = scanner.getStartPos(); if (!leadingTrivia) { @@ -39359,6 +39417,8 @@ var ts; case 15 /* CloseBraceToken */: case 18 /* OpenBracketToken */: case 19 /* CloseBracketToken */: + case 16 /* OpenParenToken */: + case 17 /* CloseParenToken */: case 77 /* ElseKeyword */: case 101 /* WhileKeyword */: case 53 /* AtToken */: @@ -39483,7 +39543,7 @@ var ts; else if (tokenInfo.token.kind === listStartToken) { // consume list start token startLine = sourceFile.getLineAndCharacterOfPosition(tokenInfo.token.pos).line; - var indentation_1 = computeIndentation(tokenInfo.token, startLine, -1 /* Unknown */, parent, parentDynamicIndentation, startLine); + var indentation_1 = computeIndentation(tokenInfo.token, startLine, -1 /* Unknown */, parent, parentDynamicIndentation, parentStartLine); listDynamicIndentation = getDynamicIndentation(parent, parentStartLine, indentation_1.indentation, indentation_1.delta); consumeTokenAndAdvanceScanner(tokenInfo, parent, listDynamicIndentation); } @@ -41389,6 +41449,13 @@ var ts; // after incremental parsing nameTable might not be up-to-date // drop it so it can be lazily recreated later newSourceFile.nameTable = undefined; + // dispose all resources held by old script snapshot + if (sourceFile !== newSourceFile && sourceFile.scriptSnapshot) { + if (sourceFile.scriptSnapshot.dispose) { + sourceFile.scriptSnapshot.dispose(); + } + sourceFile.scriptSnapshot = undefined; + } return newSourceFile; } } @@ -42410,15 +42477,15 @@ var ts; } function tryGetGlobalSymbols() { var objectLikeContainer; - var importClause; + var namedImportsOrExports; var jsxContainer; if (objectLikeContainer = tryGetObjectLikeCompletionContainer(contextToken)) { return tryGetObjectLikeCompletionSymbols(objectLikeContainer); } - if (importClause = ts.getAncestor(contextToken, 220 /* ImportClause */)) { + if (namedImportsOrExports = tryGetNamedImportsOrExportsForCompletion(contextToken)) { // cursor is in an import clause // try to show exported member for imported module - return tryGetImportClauseCompletionSymbols(importClause); + return tryGetImportOrExportClauseCompletionSymbols(namedImportsOrExports); } if (jsxContainer = tryGetContainingJsxElement(contextToken)) { var attrsType; @@ -42426,7 +42493,7 @@ var ts; // Cursor is inside a JSX self-closing element or opening element attrsType = typeChecker.getJsxElementAttributesType(jsxContainer); if (attrsType) { - symbols = filterJsxAttributes(jsxContainer.attributes, typeChecker.getPropertiesOfType(attrsType)); + symbols = filterJsxAttributes(typeChecker.getPropertiesOfType(attrsType), jsxContainer.attributes); isMemberCompletion = true; isNewIdentifierLocation = false; return true; @@ -42487,21 +42554,11 @@ var ts; function isCompletionListBlocker(contextToken) { var start = new Date().getTime(); var result = isInStringOrRegularExpressionOrTemplateLiteral(contextToken) || - isIdentifierDefinitionLocation(contextToken) || + isSolelyIdentifierDefinitionLocation(contextToken) || isDotOfNumericLiteral(contextToken); log("getCompletionsAtPosition: isCompletionListBlocker: " + (new Date().getTime() - start)); return result; } - function shouldShowCompletionsInImportsClause(node) { - if (node) { - // import {| - // import {a,| - if (node.kind === 14 /* OpenBraceToken */ || node.kind === 23 /* CommaToken */) { - return node.parent.kind === 222 /* NamedImports */; - } - } - return false; - } function isNewIdentifierDefinitionLocation(previousToken) { if (previousToken) { var containingNodeKind = previousToken.parent.kind; @@ -42610,34 +42667,37 @@ var ts; return true; } /** - * Aggregates relevant symbols for completion in import clauses; for instance, + * Aggregates relevant symbols for completion in import clauses and export clauses + * whose declarations have a module specifier; for instance, symbols will be aggregated for * - * import { $ } from "moduleName"; + * import { | } from "moduleName"; + * export { a as foo, | } from "moduleName"; + * + * but not for + * + * export { | }; * * Relevant symbols are stored in the captured 'symbols' variable. * * @returns true if 'symbols' was successfully populated; false otherwise. */ - function tryGetImportClauseCompletionSymbols(importClause) { - // cursor is in import clause - // try to show exported member for imported module - if (shouldShowCompletionsInImportsClause(contextToken)) { - isMemberCompletion = true; - isNewIdentifierLocation = false; - var importDeclaration = importClause.parent; - ts.Debug.assert(importDeclaration !== undefined && importDeclaration.kind === 219 /* ImportDeclaration */); - var exports; - var moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(importDeclaration.moduleSpecifier); - if (moduleSpecifierSymbol) { - exports = typeChecker.getExportsOfModule(moduleSpecifierSymbol); - } - //let exports = typeInfoResolver.getExportsOfImportDeclaration(importDeclaration); - symbols = exports ? filterModuleExports(exports, importDeclaration) : emptyArray; + function tryGetImportOrExportClauseCompletionSymbols(namedImportsOrExports) { + var declarationKind = namedImportsOrExports.kind === 222 /* NamedImports */ ? + 219 /* ImportDeclaration */ : + 225 /* ExportDeclaration */; + var importOrExportDeclaration = ts.getAncestor(namedImportsOrExports, declarationKind); + var moduleSpecifier = importOrExportDeclaration.moduleSpecifier; + if (!moduleSpecifier) { + return false; } - else { - isMemberCompletion = false; - isNewIdentifierLocation = true; + isMemberCompletion = true; + isNewIdentifierLocation = false; + var exports; + var moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(importOrExportDeclaration.moduleSpecifier); + if (moduleSpecifierSymbol) { + exports = typeChecker.getExportsOfModule(moduleSpecifierSymbol); } + symbols = exports ? filterNamedImportOrExportCompletionItems(exports, namedImportsOrExports.elements) : emptyArray; return true; } /** @@ -42658,6 +42718,24 @@ var ts; } return undefined; } + /** + * Returns the containing list of named imports or exports of a context token, + * on the condition that one exists and that the context implies completion should be given. + */ + function tryGetNamedImportsOrExportsForCompletion(contextToken) { + if (contextToken) { + switch (contextToken.kind) { + case 14 /* OpenBraceToken */: // import { | + case 23 /* CommaToken */: + switch (contextToken.parent.kind) { + case 222 /* NamedImports */: + case 226 /* NamedExports */: + return contextToken.parent; + } + } + } + return undefined; + } function tryGetContainingJsxElement(contextToken) { if (contextToken) { var parent_12 = contextToken.parent; @@ -42700,7 +42778,10 @@ var ts; } return false; } - function isIdentifierDefinitionLocation(contextToken) { + /** + * @returns true if we are certain that the currently edited location must define a new location; false otherwise. + */ + function isSolelyIdentifierDefinitionLocation(contextToken) { var containingNodeKind = contextToken.parent.kind; switch (contextToken.kind) { case 23 /* CommaToken */: @@ -42746,6 +42827,10 @@ var ts; case 107 /* PrivateKeyword */: case 108 /* ProtectedKeyword */: return containingNodeKind === 135 /* Parameter */; + case 113 /* AsKeyword */: + containingNodeKind === 223 /* ImportSpecifier */ || + containingNodeKind === 227 /* ExportSpecifier */ || + containingNodeKind === 221 /* NamespaceImport */; case 70 /* ClassKeyword */: case 78 /* EnumKeyword */: case 104 /* InterfaceKeyword */: @@ -42782,27 +42867,37 @@ var ts; } return false; } - function filterModuleExports(exports, importDeclaration) { - var exisingImports = {}; - if (!importDeclaration.importClause) { - return exports; + /** + * Filters out completion suggestions for named imports or exports. + * + * @param exportsOfModule The list of symbols which a module exposes. + * @param namedImportsOrExports The list of existing import/export specifiers in the import/export clause. + * + * @returns Symbols to be suggested at an import/export clause, barring those whose named imports/exports + * do not occur at the current position and have not otherwise been typed. + */ + function filterNamedImportOrExportCompletionItems(exportsOfModule, namedImportsOrExports) { + var exisingImportsOrExports = {}; + for (var _i = 0; _i < namedImportsOrExports.length; _i++) { + var element = namedImportsOrExports[_i]; + // If this is the current item we are editing right now, do not filter it out + if (element.getStart() <= position && position <= element.getEnd()) { + continue; + } + var name_31 = element.propertyName || element.name; + exisingImportsOrExports[name_31.text] = true; } - if (importDeclaration.importClause.namedBindings && - importDeclaration.importClause.namedBindings.kind === 222 /* NamedImports */) { - ts.forEach(importDeclaration.importClause.namedBindings.elements, function (el) { - // If this is the current item we are editing right now, do not filter it out - if (el.getStart() <= position && position <= el.getEnd()) { - return; - } - var name = el.propertyName || el.name; - exisingImports[name.text] = true; - }); + if (ts.isEmpty(exisingImportsOrExports)) { + return exportsOfModule; } - if (ts.isEmpty(exisingImports)) { - return exports; - } - return ts.filter(exports, function (e) { return !ts.lookUp(exisingImports, e.name); }); + return ts.filter(exportsOfModule, function (e) { return !ts.lookUp(exisingImportsOrExports, e.name); }); } + /** + * Filters out completion suggestions for named imports or exports. + * + * @returns Symbols to be suggested in an object binding pattern or object literal expression, barring those whose declarations + * do not occur at the current position and have not otherwise been typed. + */ function filterObjectMembersList(contextualMemberSymbols, existingMembers) { if (!existingMembers || existingMembers.length === 0) { return contextualMemberSymbols; @@ -42832,15 +42927,15 @@ var ts; } existingMemberNames[existingName] = true; } - var filteredMembers = []; - ts.forEach(contextualMemberSymbols, function (s) { - if (!existingMemberNames[s.name]) { - filteredMembers.push(s); - } - }); - return filteredMembers; + return ts.filter(contextualMemberSymbols, function (m) { return !ts.lookUp(existingMemberNames, m.name); }); } - function filterJsxAttributes(attributes, symbols) { + /** + * Filters out completion suggestions from 'symbols' according to existing JSX attributes. + * + * @returns Symbols to be suggested in a JSX element, barring those whose attributes + * do not occur at the current position and have not otherwise been typed. + */ + function filterJsxAttributes(symbols, attributes) { var seenNames = {}; for (var _i = 0; _i < attributes.length; _i++) { var attr = attributes[_i]; @@ -42852,14 +42947,7 @@ var ts; seenNames[attr.name.text] = true; } } - var result = []; - for (var _a = 0; _a < symbols.length; _a++) { - var sym = symbols[_a]; - if (!seenNames[sym.name]) { - result.push(sym); - } - } - return result; + return ts.filter(symbols, function (a) { return !ts.lookUp(seenNames, a.name); }); } } function getCompletionsAtPosition(fileName, position) { @@ -42892,10 +42980,10 @@ var ts; for (var _i = 0, _a = program.getSourceFiles(); _i < _a.length; _i++) { var sourceFile = _a[_i]; var nameTable = getNameTable(sourceFile); - for (var name_31 in nameTable) { - if (!allNames[name_31]) { - allNames[name_31] = name_31; - var displayName = getCompletionEntryDisplayName(name_31, target, true); + for (var name_32 in nameTable) { + if (!allNames[name_32]) { + allNames[name_32] = name_32; + var displayName = getCompletionEntryDisplayName(name_32, target, true); if (displayName) { var entry = { name: displayName, @@ -43764,6 +43852,7 @@ var ts; if (hasKind(node.parent, 142 /* GetAccessor */) || hasKind(node.parent, 143 /* SetAccessor */)) { return getGetAndSetOccurrences(node.parent); } + break; default: if (ts.isModifier(node.kind) && node.parent && (ts.isDeclaration(node.parent) || node.parent.kind === 190 /* VariableStatement */)) { @@ -43879,12 +43968,13 @@ var ts; // Make sure we only highlight the keyword when it makes sense to do so. if (ts.isAccessibilityModifier(modifier)) { if (!(container.kind === 211 /* ClassDeclaration */ || + container.kind === 183 /* ClassExpression */ || (declaration.kind === 135 /* Parameter */ && hasKind(container, 141 /* Constructor */)))) { return undefined; } } else if (modifier === 110 /* StaticKeyword */) { - if (container.kind !== 211 /* ClassDeclaration */) { + if (!(container.kind === 211 /* ClassDeclaration */ || container.kind === 183 /* ClassExpression */)) { return undefined; } } @@ -43893,6 +43983,11 @@ var ts; return undefined; } } + else if (modifier === 112 /* AbstractKeyword */) { + if (!(container.kind === 211 /* ClassDeclaration */ || declaration.kind === 211 /* ClassDeclaration */)) { + return undefined; + } + } else { // unsupported modifier return undefined; @@ -43903,12 +43998,19 @@ var ts; switch (container.kind) { case 216 /* ModuleBlock */: case 245 /* SourceFile */: - nodes = container.statements; + // Container is either a class declaration or the declaration is a classDeclaration + if (modifierFlag & 256 /* Abstract */) { + nodes = declaration.members.concat(declaration); + } + else { + nodes = container.statements; + } break; case 141 /* Constructor */: nodes = container.parameters.concat(container.parent.members); break; case 211 /* ClassDeclaration */: + case 183 /* ClassExpression */: nodes = container.members; // If we're an accessibility modifier, we're in an instance member and should search // the constructor's parameter list for instance members as well. @@ -43920,6 +44022,9 @@ var ts; nodes = nodes.concat(constructor.parameters); } } + else if (modifierFlag & 256 /* Abstract */) { + nodes = nodes.concat(container); + } break; default: ts.Debug.fail("Invalid container kind."); @@ -43944,6 +44049,8 @@ var ts; return 1 /* Export */; case 119 /* DeclareKeyword */: return 2 /* Ambient */; + case 112 /* AbstractKeyword */: + return 256 /* Abstract */; default: ts.Debug.fail(); } @@ -44761,19 +44868,19 @@ var ts; if (isNameOfPropertyAssignment(node)) { var objectLiteral = node.parent.parent; var contextualType = typeChecker.getContextualType(objectLiteral); - var name_32 = node.text; + var name_33 = node.text; if (contextualType) { if (contextualType.flags & 16384 /* Union */) { // This is a union type, first see if the property we are looking for is a union property (i.e. exists in all types) // if not, search the constituent types for the property - var unionProperty = contextualType.getProperty(name_32); + var unionProperty = contextualType.getProperty(name_33); if (unionProperty) { return [unionProperty]; } else { var result_4 = []; ts.forEach(contextualType.types, function (t) { - var symbol = t.getProperty(name_32); + var symbol = t.getProperty(name_33); if (symbol) { result_4.push(symbol); } @@ -44782,7 +44889,7 @@ var ts; } } else { - var symbol_1 = contextualType.getProperty(name_32); + var symbol_1 = contextualType.getProperty(name_33); if (symbol_1) { return [symbol_1]; } @@ -45464,7 +45571,7 @@ var ts; return; } } - return 9 /* text */; + return 2 /* identifier */; } } function processElement(element) { @@ -46760,6 +46867,13 @@ var ts; var decoded = JSON.parse(encoded); return ts.createTextChangeRange(ts.createTextSpan(decoded.span.start, decoded.span.length), decoded.newLength); }; + ScriptSnapshotShimAdapter.prototype.dispose = function () { + // if scriptSnapshotShim is a COM object then property check becomes method call with no arguments + // 'in' does not have this effect + if ("dispose" in this.scriptSnapshotShim) { + this.scriptSnapshotShim.dispose(); + } + }; return ScriptSnapshotShimAdapter; })(); var LanguageServiceShimHostAdapter = (function () { diff --git a/package.json b/package.json index 82ab734d6f1..70ada6fef15 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "chai": "latest", "browserify": "latest", "istanbul": "latest", + "mocha-fivemat-progress-reporter": "latest", "tslint": "latest" }, "scripts": { diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index da45c08ab44..7d022825ea7 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2307,6 +2307,7 @@ namespace ts { if (declaration.parent.parent.kind === SyntaxKind.ForInStatement) { return anyType; } + if (declaration.parent.parent.kind === SyntaxKind.ForOfStatement) { // checkRightHandSideOfForOf will return undefined if the for-of expression type was // missing properties/signatures required to get its iteratedType (like @@ -2314,13 +2315,16 @@ namespace ts { // or it may have led to an error inside getElementTypeOfIterable. return checkRightHandSideOfForOf((declaration.parent.parent).expression) || anyType; } + if (isBindingPattern(declaration.parent)) { return getTypeForBindingElement(declaration); } + // Use type from type annotation if one is present if (declaration.type) { return getTypeFromTypeNode(declaration.type); } + if (declaration.kind === SyntaxKind.Parameter) { let func = declaration.parent; // For a parameter of a set accessor, use the type of the get accessor if one is present @@ -2336,14 +2340,22 @@ namespace ts { return type; } } + // Use the type of the initializer expression if one is present if (declaration.initializer) { return checkExpressionCached(declaration.initializer); } + // If it is a short-hand property assignment, use the type of the identifier if (declaration.kind === SyntaxKind.ShorthandPropertyAssignment) { return checkIdentifier(declaration.name); } + + // If the declaration specifies a binding pattern, use the type implied by the binding pattern + if (isBindingPattern(declaration.name)) { + return getTypeFromBindingPattern(declaration.name); + } + // No type specified and nothing can be inferred return undefined; } @@ -2429,13 +2441,10 @@ namespace ts { // tools see the actual type. return declaration.kind !== SyntaxKind.PropertyAssignment ? getWidenedType(type) : type; } - // If no type was specified and nothing could be inferred, and if the declaration specifies a binding pattern, use - // the type implied by the binding pattern - if (isBindingPattern(declaration.name)) { - return getTypeFromBindingPattern(declaration.name); - } + // Rest parameters default to type any[], other parameters default to type any type = declaration.dotDotDotToken ? anyArrayType : anyType; + // Report implicit any errors unless this is a private property within an ambient declaration if (reportErrors && compilerOptions.noImplicitAny) { let root = getRootDeclaration(declaration); @@ -3943,7 +3952,7 @@ namespace ts { let id = getTypeListId(elementTypes); let type = tupleTypes[id]; if (!type) { - type = tupleTypes[id] = createObjectType(TypeFlags.Tuple); + type = tupleTypes[id] = createObjectType(TypeFlags.Tuple | getWideningFlagsOfTypes(elementTypes)); type.elementTypes = elementTypes; } return type; @@ -5299,8 +5308,8 @@ namespace ts { * Check if a Type was written as a tuple type literal. * Prefer using isTupleLikeType() unless the use of `elementTypes` is required. */ - function isTupleType(type: Type): boolean { - return (type.flags & TypeFlags.Tuple) && !!(type).elementTypes; + function isTupleType(type: Type): type is TupleType { + return !!(type.flags & TypeFlags.Tuple); } function getWidenedTypeOfObjectLiteral(type: Type): Type { @@ -5341,26 +5350,45 @@ namespace ts { if (isArrayType(type)) { return createArrayType(getWidenedType((type).typeArguments[0])); } + if (isTupleType(type)) { + return createTupleType(map(type.elementTypes, getWidenedType)); + } } return type; } + /** + * Reports implicit any errors that occur as a result of widening 'null' and 'undefined' + * to 'any'. A call to reportWideningErrorsInType is normally accompanied by a call to + * getWidenedType. But in some cases getWidenedType is called without reporting errors + * (type argument inference is an example). + * + * The return value indicates whether an error was in fact reported. The particular circumstances + * are on a best effort basis. Currently, if the null or undefined that causes widening is inside + * an object literal property (arbitrarily deeply), this function reports an error. If no error is + * reported, reportImplicitAnyError is a suitable fallback to report a general error. + */ function reportWideningErrorsInType(type: Type): boolean { + let errorReported = false; if (type.flags & TypeFlags.Union) { - let errorReported = false; - forEach((type).types, t => { + for (let t of (type).types) { if (reportWideningErrorsInType(t)) { errorReported = true; } - }); - return errorReported; + } } if (isArrayType(type)) { return reportWideningErrorsInType((type).typeArguments[0]); } + if (isTupleType(type)) { + for (let t of type.elementTypes) { + if (reportWideningErrorsInType(t)) { + errorReported = true; + } + } + } if (type.flags & TypeFlags.ObjectLiteral) { - let errorReported = false; - forEach(getPropertiesOfObjectType(type), p => { + for (let p of getPropertiesOfObjectType(type)) { let t = getTypeOfSymbol(p); if (t.flags & TypeFlags.ContainsUndefinedOrNull) { if (!reportWideningErrorsInType(t)) { @@ -5368,10 +5396,9 @@ namespace ts { } errorReported = true; } - }); - return errorReported; + } } - return false; + return errorReported; } function reportImplicitAnyError(declaration: Declaration, type: Type) { @@ -5538,30 +5565,33 @@ namespace ts { inferFromTypes(sourceType, target); } } - else if (source.flags & TypeFlags.ObjectType && (target.flags & (TypeFlags.Reference | TypeFlags.Tuple) || - (target.flags & TypeFlags.Anonymous) && target.symbol && target.symbol.flags & (SymbolFlags.Method | SymbolFlags.TypeLiteral | SymbolFlags.Class))) { - // If source is an object type, and target is a type reference, a tuple type, the type of a method, or a type literal, infer from members - if (isInProcess(source, target)) { - return; - } - if (isDeeplyNestedGeneric(source, sourceStack, depth) && isDeeplyNestedGeneric(target, targetStack, depth)) { - return; - } + else { + source = getApparentType(source); + if (source.flags & TypeFlags.ObjectType && (target.flags & (TypeFlags.Reference | TypeFlags.Tuple) || + (target.flags & TypeFlags.Anonymous) && target.symbol && target.symbol.flags & (SymbolFlags.Method | SymbolFlags.TypeLiteral | SymbolFlags.Class))) { + // If source is an object type, and target is a type reference, a tuple type, the type of a method, or a type literal, infer from members + if (isInProcess(source, target)) { + return; + } + if (isDeeplyNestedGeneric(source, sourceStack, depth) && isDeeplyNestedGeneric(target, targetStack, depth)) { + return; + } - if (depth === 0) { - sourceStack = []; - targetStack = []; + if (depth === 0) { + sourceStack = []; + targetStack = []; + } + sourceStack[depth] = source; + targetStack[depth] = target; + depth++; + inferFromProperties(source, target); + inferFromSignatures(source, target, SignatureKind.Call); + inferFromSignatures(source, target, SignatureKind.Construct); + inferFromIndexTypes(source, target, IndexKind.String, IndexKind.String); + inferFromIndexTypes(source, target, IndexKind.Number, IndexKind.Number); + inferFromIndexTypes(source, target, IndexKind.String, IndexKind.Number); + depth--; } - sourceStack[depth] = source; - targetStack[depth] = target; - depth++; - inferFromProperties(source, target); - inferFromSignatures(source, target, SignatureKind.Call); - inferFromSignatures(source, target, SignatureKind.Construct); - inferFromIndexTypes(source, target, IndexKind.String, IndexKind.String); - inferFromIndexTypes(source, target, IndexKind.Number, IndexKind.Number); - inferFromIndexTypes(source, target, IndexKind.String, IndexKind.Number); - depth--; } } @@ -6961,7 +6991,6 @@ namespace ts { } } - function checkJsxSelfClosingElement(node: JsxSelfClosingElement) { checkJsxOpeningLikeElement(node); return jsxElementType || anyType; @@ -13650,10 +13679,22 @@ namespace ts { return getSymbolOfNode(node.parent); } - if (node.kind === SyntaxKind.Identifier && isInRightSideOfImportOrExportAssignment(node)) { - return node.parent.kind === SyntaxKind.ExportAssignment - ? getSymbolOfEntityNameOrPropertyAccessExpression(node) - : getSymbolOfPartOfRightHandSideOfImportEquals(node); + if (node.kind === SyntaxKind.Identifier) { + if (isInRightSideOfImportOrExportAssignment(node)) { + return node.parent.kind === SyntaxKind.ExportAssignment + ? getSymbolOfEntityNameOrPropertyAccessExpression(node) + : getSymbolOfPartOfRightHandSideOfImportEquals(node); + } + else if (node.parent.kind === SyntaxKind.BindingElement && + node.parent.parent.kind === SyntaxKind.ObjectBindingPattern && + node === (node.parent).propertyName) { + let typeOfPattern = getTypeAtLocation(node.parent.parent); + let propertyDeclaration = typeOfPattern && getPropertyOfType(typeOfPattern, (node).text); + + if (propertyDeclaration) { + return propertyDeclaration; + } + } } switch (node.kind) { diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index fd0d4ad796e..9c8438565e7 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -4215,10 +4215,15 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi } } + let startIndex = 0; + write(" {"); scopeEmitStart(node, "constructor"); increaseIndent(); if (ctor) { + // Emit all the directive prologues (like "use strict"). These have to come before + // any other preamble code we write (like parameter initializers). + startIndex = emitDirectivePrologues(ctor.body.statements, /*startWithNewLine*/ true); emitDetachedComments(ctor.body.statements); } emitCaptureThisForNodeIfNecessary(node); @@ -4253,7 +4258,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi if (superCall) { statements = statements.slice(1); } - emitLines(statements); + emitLinesStartingAt(statements, startIndex); } emitTempDeclarations(/*newLine*/ true); writeLine(); diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index fecff11b1b4..127d1b58ee4 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -3295,7 +3295,7 @@ namespace ts { function parseSuperExpression(): MemberExpression { let expression = parseTokenNode(); - if (token === SyntaxKind.OpenParenToken || token === SyntaxKind.DotToken) { + if (token === SyntaxKind.OpenParenToken || token === SyntaxKind.DotToken || token === SyntaxKind.OpenBracketToken) { return expression; } @@ -5135,7 +5135,12 @@ namespace ts { } else { node.exportClause = parseNamedImportsOrExports(SyntaxKind.NamedExports); - if (parseOptional(SyntaxKind.FromKeyword)) { + + // It is not uncommon to accidentally omit the 'from' keyword. Additionally, in editing scenarios, + // the 'from' keyword can be parsed as a named export when the export clause is unterminated (i.e. `export { from "moduleName";`) + // If we don't have a 'from' keyword, see if we have a string literal such that ASI won't take effect. + if (token === SyntaxKind.FromKeyword || (token === SyntaxKind.StringLiteral && !scanner.hasPrecedingLineBreak())) { + parseExpected(SyntaxKind.FromKeyword) node.moduleSpecifier = parseModuleSpecifier(); } } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 5174589cdcf..df3f1c9f174 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -568,7 +568,7 @@ namespace ts { } } - export function isVariableLike(node: Node): boolean { + export function isVariableLike(node: Node): node is VariableLikeDeclaration { if (node) { switch (node.kind) { case SyntaxKind.BindingElement: diff --git a/src/harness/compilerRunner.ts b/src/harness/compilerRunner.ts index 1b399e1b706..b1d43302372 100644 --- a/src/harness/compilerRunner.ts +++ b/src/harness/compilerRunner.ts @@ -10,6 +10,7 @@ const enum CompilerTestType { class CompilerBaselineRunner extends RunnerBase { private basePath = 'tests/cases'; + private testSuiteName: string; private errors: boolean; private emit: boolean; private decl: boolean; @@ -24,43 +25,43 @@ class CompilerBaselineRunner extends RunnerBase { this.decl = true; this.output = true; if (testType === CompilerTestType.Conformance) { - this.basePath += '/conformance'; + this.testSuiteName = 'conformance'; } else if (testType === CompilerTestType.Regressions) { - this.basePath += '/compiler'; + this.testSuiteName = 'compiler'; } else if (testType === CompilerTestType.Test262) { - this.basePath += '/test262'; + this.testSuiteName = 'test262'; } else { - this.basePath += '/compiler'; // default to this for historical reasons + this.testSuiteName = 'compiler'; // default to this for historical reasons } + this.basePath += '/' + this.testSuiteName; } public checkTestCodeOutput(fileName: string) { describe('compiler tests for ' + fileName, () => { // Mocha holds onto the closure environment of the describe callback even after the test is done. // Everything declared here should be cleared out in the "after" callback. - var justName: string; - var content: string; - var testCaseContent: { settings: Harness.TestCaseParser.CompilerSetting[]; testUnitData: Harness.TestCaseParser.TestUnitData[]; } + let justName: string; + let content: string; + let testCaseContent: { settings: Harness.TestCaseParser.CompilerSetting[]; testUnitData: Harness.TestCaseParser.TestUnitData[]; }; - var units: Harness.TestCaseParser.TestUnitData[]; - var tcSettings: Harness.TestCaseParser.CompilerSetting[]; - var createNewInstance: boolean; + let units: Harness.TestCaseParser.TestUnitData[]; + let tcSettings: Harness.TestCaseParser.CompilerSetting[]; - var lastUnit: Harness.TestCaseParser.TestUnitData; - var rootDir: string; + let lastUnit: Harness.TestCaseParser.TestUnitData; + let rootDir: string; - var result: Harness.Compiler.CompilerResult; - var program: ts.Program; - var options: ts.CompilerOptions; + let result: Harness.Compiler.CompilerResult; + let program: ts.Program; + let options: ts.CompilerOptions; // equivalent to the files that will be passed on the command line - var toBeCompiled: { unitName: string; content: string }[]; + let toBeCompiled: { unitName: string; content: string }[]; // equivalent to other files on the file system not directly passed to the compiler (ie things that are referenced by other files) - var otherFiles: { unitName: string; content: string }[]; - var harnessCompiler: Harness.Compiler.HarnessCompiler; + let otherFiles: { unitName: string; content: string }[]; + let harnessCompiler: Harness.Compiler.HarnessCompiler; - var createNewInstance = false; + let createNewInstance = false; before(() => { justName = fileName.replace(/^.*[\\\/]/, ''); // strips the fileName from the path. @@ -100,10 +101,10 @@ class CompilerBaselineRunner extends RunnerBase { }); beforeEach(() => { - /* The compiler doesn't handle certain flags flipping during a single compilation setting. Tests on these flags will need + /* The compiler doesn't handle certain flags flipping during a single compilation setting. Tests on these flags will need a fresh compiler instance for themselves and then create a fresh one for the next test. Would be nice to get dev fixes eventually to remove this limitation. */ - for (var i = 0; i < tcSettings.length; ++i) { + for (let i = 0; i < tcSettings.length; ++i) { // noImplicitAny is passed to getCompiler, but target is just passed in the settings blob to setCompilerSettings if (!createNewInstance && (tcSettings[i].flag == "noimplicitany" || tcSettings[i].flag === 'target')) { harnessCompiler = Harness.Compiler.getCompiler(); @@ -160,7 +161,7 @@ class CompilerBaselineRunner extends RunnerBase { it('Correct sourcemap content for ' + fileName, () => { if (options.sourceMap || options.inlineSourceMap) { Harness.Baseline.runBaseline('Correct sourcemap content for ' + fileName, justName.replace(/\.tsx?$/, '.sourcemap.txt'), () => { - var record = result.getSourceMapRecord(); + let record = result.getSourceMapRecord(); if (options.noEmitOnError && result.errors.length !== 0 && record === undefined) { // Because of the noEmitOnError option no files are created. We need to return null because baselining isn't required. return null; @@ -178,18 +179,18 @@ class CompilerBaselineRunner extends RunnerBase { // check js output Harness.Baseline.runBaseline('Correct JS output for ' + fileName, justName.replace(/\.tsx?/, '.js'), () => { - var tsCode = ''; - var tsSources = otherFiles.concat(toBeCompiled); + let tsCode = ''; + let tsSources = otherFiles.concat(toBeCompiled); if (tsSources.length > 1) { tsCode += '//// [' + fileName + '] ////\r\n\r\n'; } - for (var i = 0; i < tsSources.length; i++) { + for (let i = 0; i < tsSources.length; i++) { tsCode += '//// [' + Harness.Path.getFileName(tsSources[i].unitName) + ']\r\n'; tsCode += tsSources[i].content + (i < (tsSources.length - 1) ? '\r\n' : ''); } - var jsCode = ''; - for (var i = 0; i < result.files.length; i++) { + let jsCode = ''; + for (let i = 0; i < result.files.length; i++) { jsCode += '//// [' + Harness.Path.getFileName(result.files[i].fileName) + ']\r\n'; jsCode += getByteOrderMarkText(result.files[i]); jsCode += result.files[i].code; @@ -197,14 +198,14 @@ class CompilerBaselineRunner extends RunnerBase { if (result.declFilesCode.length > 0) { jsCode += '\r\n\r\n'; - for (var i = 0; i < result.declFilesCode.length; i++) { + for (let i = 0; i < result.declFilesCode.length; i++) { jsCode += '//// [' + Harness.Path.getFileName(result.declFilesCode[i].fileName) + ']\r\n'; jsCode += getByteOrderMarkText(result.declFilesCode[i]); jsCode += result.declFilesCode[i].code; } } - var declFileCompilationResult = harnessCompiler.compileDeclarationFiles(toBeCompiled, otherFiles, result, function (settings) { + let declFileCompilationResult = harnessCompiler.compileDeclarationFiles(toBeCompiled, otherFiles, result, function (settings) { harnessCompiler.setCompilerSettings(tcSettings); }, options); @@ -242,8 +243,8 @@ class CompilerBaselineRunner extends RunnerBase { return null; } - var sourceMapCode = ''; - for (var i = 0; i < result.sourceMaps.length; i++) { + let sourceMapCode = ''; + for (let i = 0; i < result.sourceMaps.length; i++) { sourceMapCode += '//// [' + Harness.Path.getFileName(result.sourceMaps[i].fileName) + ']\r\n'; sourceMapCode += getByteOrderMarkText(result.sourceMaps[i]); sourceMapCode += result.sourceMaps[i].code; @@ -261,19 +262,19 @@ class CompilerBaselineRunner extends RunnerBase { // NEWTODO: Type baselines if (result.errors.length === 0) { - // The full walker simulates the types that you would get from doing a full + // The full walker simulates the types that you would get from doing a full // compile. The pull walker simulates the types you get when you just do // a type query for a random node (like how the LS would do it). Most of the // time, these will be the same. However, occasionally, they can be different. // Specifically, when the compiler internally depends on symbol IDs to order - // things, then we may see different results because symbols can be created in a + // things, then we may see different results because symbols can be created in a // different order with 'pull' operations, and thus can produce slightly differing // output. // // For example, with a full type check, we may see a type outputed as: number | string // But with a pull type check, we may see it as: string | number // - // These types are equivalent, but depend on what order the compiler observed + // These types are equivalent, but depend on what order the compiler observed // certain parts of the program. let allFiles = toBeCompiled.concat(otherFiles).filter(file => !!program.getSourceFile(file.unitName)); @@ -291,7 +292,7 @@ class CompilerBaselineRunner extends RunnerBase { // Produce baselines. The first gives the types for all expressions. // The second gives symbols for all identifiers. - var e1: Error, e2: Error; + let e1: Error, e2: Error; try { checkBaseLines(/*isSymbolBaseLine:*/ false); } @@ -333,20 +334,20 @@ class CompilerBaselineRunner extends RunnerBase { let typeMap: { [fileName: string]: { [lineNum: number]: string[]; } } = {}; allFiles.forEach(file => { - var codeLines = file.content.split('\n'); + let codeLines = file.content.split('\n'); typeWriterResults[file.unitName].forEach(result => { if (isSymbolBaseline && !result.symbol) { return; } - var typeOrSymbolString = isSymbolBaseline ? result.symbol : result.type; - var formattedLine = result.sourceText.replace(/\r?\n/g, "") + " : " + typeOrSymbolString; + let typeOrSymbolString = isSymbolBaseline ? result.symbol : result.type; + let formattedLine = result.sourceText.replace(/\r?\n/g, "") + " : " + typeOrSymbolString; if (!typeMap[file.unitName]) { typeMap[file.unitName] = {}; } - var typeInfo = [formattedLine]; - var existingTypeInfo = typeMap[file.unitName][result.line]; + let typeInfo = [formattedLine]; + let existingTypeInfo = typeMap[file.unitName][result.line]; if (existingTypeInfo) { typeInfo = existingTypeInfo.concat(typeInfo); } @@ -354,11 +355,11 @@ class CompilerBaselineRunner extends RunnerBase { }); typeLines.push('=== ' + file.unitName + ' ===\r\n'); - for (var i = 0; i < codeLines.length; i++) { - var currentCodeLine = codeLines[i]; + for (let i = 0; i < codeLines.length; i++) { + let currentCodeLine = codeLines[i]; typeLines.push(currentCodeLine + '\r\n'); if (typeMap[file.unitName]) { - var typeInfo = typeMap[file.unitName][i]; + let typeInfo = typeMap[file.unitName][i]; if (typeInfo) { typeInfo.forEach(ty => { typeLines.push('>' + ty + '\r\n'); @@ -384,25 +385,27 @@ class CompilerBaselineRunner extends RunnerBase { } public initializeTests() { - describe("Setup compiler for compiler baselines", () => { - var harnessCompiler = Harness.Compiler.getCompiler(); - this.parseOptions(); - }); - - // this will set up a series of describe/it blocks to run between the setup and cleanup phases - if (this.tests.length === 0) { - var testFiles = this.enumerateFiles(this.basePath, /\.tsx?$/, { recursive: true }); - testFiles.forEach(fn => { - fn = fn.replace(/\\/g, "/"); - this.checkTestCodeOutput(fn); + describe(this.testSuiteName + ' tests', () => { + describe("Setup compiler for compiler baselines", () => { + let harnessCompiler = Harness.Compiler.getCompiler(); + this.parseOptions(); }); - } - else { - this.tests.forEach(test => this.checkTestCodeOutput(test)); - } - describe("Cleanup after compiler baselines", () => { - var harnessCompiler = Harness.Compiler.getCompiler(); + // this will set up a series of describe/it blocks to run between the setup and cleanup phases + if (this.tests.length === 0) { + let testFiles = this.enumerateFiles(this.basePath, /\.tsx?$/, { recursive: true }); + testFiles.forEach(fn => { + fn = fn.replace(/\\/g, "/"); + this.checkTestCodeOutput(fn); + }); + } + else { + this.tests.forEach(test => this.checkTestCodeOutput(test)); + } + + describe("Cleanup after compiler baselines", () => { + let harnessCompiler = Harness.Compiler.getCompiler(); + }); }); } @@ -413,8 +416,8 @@ class CompilerBaselineRunner extends RunnerBase { this.decl = false; this.output = false; - var opts = this.options.split(','); - for (var i = 0; i < opts.length; i++) { + let opts = this.options.split(','); + for (let i = 0; i < opts.length; i++) { switch (opts[i]) { case 'error': this.errors = true; @@ -434,4 +437,4 @@ class CompilerBaselineRunner extends RunnerBase { } } } -} \ No newline at end of file +} diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 0d03f7d6236..5c8e6bc8981 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -1,6 +1,6 @@ // // Copyright (c) Microsoft Corporation. All rights reserved. -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -100,7 +100,7 @@ module FourSlash { end: number; } - var entityMap: ts.Map = { + let entityMap: ts.Map = { '&': '&', '"': '"', "'": ''', @@ -116,7 +116,7 @@ module FourSlash { // Name of testcase metadata including ts.CompilerOptions properties that will be used by globalOptions // To add additional option, add property into the testOptMetadataNames, refer the property in either globalMetadataNames or fileMetadataNames // Add cases into convertGlobalOptionsToCompilationsSettings function for the compiler to acknowledge such option from meta data - var metadataOptionNames = { + let metadataOptionNames = { baselineFile: 'BaselineFile', declaration: 'declaration', emitThisFile: 'emitThisFile', // This flag is used for testing getEmitOutput feature. It allows test-cases to indicate what file to be output in multiple files project @@ -132,15 +132,15 @@ module FourSlash { }; // List of allowed metadata names - var fileMetadataNames = [metadataOptionNames.fileName, metadataOptionNames.emitThisFile, metadataOptionNames.resolveReference]; - var globalMetadataNames = [metadataOptionNames.allowNonTsExtensions, metadataOptionNames.baselineFile, metadataOptionNames.declaration, + let fileMetadataNames = [metadataOptionNames.fileName, metadataOptionNames.emitThisFile, metadataOptionNames.resolveReference]; + let globalMetadataNames = [metadataOptionNames.allowNonTsExtensions, metadataOptionNames.baselineFile, metadataOptionNames.declaration, metadataOptionNames.mapRoot, metadataOptionNames.module, metadataOptionNames.out, - metadataOptionNames.outDir, metadataOptionNames.sourceMap, metadataOptionNames.sourceRoot] + metadataOptionNames.outDir, metadataOptionNames.sourceMap, metadataOptionNames.sourceRoot]; function convertGlobalOptionsToCompilerOptions(globalOptions: { [idx: string]: string }): ts.CompilerOptions { - var settings: ts.CompilerOptions = { target: ts.ScriptTarget.ES5 }; + let settings: ts.CompilerOptions = { target: ts.ScriptTarget.ES5 }; // Convert all property in globalOptions into ts.CompilationSettings - for (var prop in globalOptions) { + for (let prop in globalOptions) { if (globalOptions.hasOwnProperty(prop)) { switch (prop) { case metadataOptionNames.allowNonTsExtensions: @@ -185,14 +185,14 @@ module FourSlash { return settings; } - export var currentTestState: TestState = null; + export let currentTestState: TestState = null; function assertionMessage(msg: string) { return "\nMarker: " + currentTestState.lastKnownMarker + "\nChecking: " + msg + "\n\n"; } export class TestCancellationToken implements ts.HostCancellationToken { // 0 - cancelled - // >0 - not cancelled + // >0 - not cancelled // <0 - not cancelled and value denotes number of isCancellationRequested after which token become cancelled private static NotCanceled: number = -1; private numberOfCallsBeforeCancellation: number = TestCancellationToken.NotCanceled; @@ -271,11 +271,11 @@ module FourSlash { private taoInvalidReason: string = null; private inputFiles: ts.Map = {}; // Map between inputFile's fileName and its content for easily looking up when resolving references - + // Add input file which has matched file name with the given reference-file path. // This is necessary when resolveReference flag is specified private addMatchedInputFile(referenceFilePath: string) { - var inputFile = this.inputFiles[referenceFilePath]; + let inputFile = this.inputFiles[referenceFilePath]; if (inputFile && !Harness.isLibraryFile(referenceFilePath)) { this.languageServiceAdapterHost.addScript(referenceFilePath, inputFile); } @@ -297,13 +297,13 @@ module FourSlash { constructor(private basePath: string, private testType: FourSlashTestType, public testData: FourSlashData) { // Create a new Services Adapter this.cancellationToken = new TestCancellationToken(); - var compilationOptions = convertGlobalOptionsToCompilerOptions(this.testData.globalOptions); - var languageServiceAdapter = this.getLanguageServiceAdapter(testType, this.cancellationToken, compilationOptions); + let compilationOptions = convertGlobalOptionsToCompilerOptions(this.testData.globalOptions); + let languageServiceAdapter = this.getLanguageServiceAdapter(testType, this.cancellationToken, compilationOptions); this.languageServiceAdapterHost = languageServiceAdapter.getHost(); this.languageService = languageServiceAdapter.getLanguageService(); // Initialize the language service with all the scripts - var startResolveFileRef: FourSlashFile; + let startResolveFileRef: FourSlashFile; ts.forEach(testData.files, file => { // Create map between fileName and its content for easily looking up when resolveReference flag is specified @@ -320,14 +320,14 @@ module FourSlash { // Add the entry-point file itself into the languageServiceShimHost this.languageServiceAdapterHost.addScript(startResolveFileRef.fileName, startResolveFileRef.content); - var resolvedResult = languageServiceAdapter.getPreProcessedFileInfo(startResolveFileRef.fileName, startResolveFileRef.content); - var referencedFiles: ts.FileReference[] = resolvedResult.referencedFiles; - var importedFiles: ts.FileReference[] = resolvedResult.importedFiles; + let resolvedResult = languageServiceAdapter.getPreProcessedFileInfo(startResolveFileRef.fileName, startResolveFileRef.content); + let referencedFiles: ts.FileReference[] = resolvedResult.referencedFiles; + let importedFiles: ts.FileReference[] = resolvedResult.importedFiles; // Add triple reference files into language-service host ts.forEach(referencedFiles, referenceFile => { // Fourslash insert tests/cases/fourslash into inputFile.unitName so we will properly append the same base directory to refFile path - var referenceFilePath = this.basePath + '/' + referenceFile.fileName; + let referenceFilePath = this.basePath + '/' + referenceFile.fileName; this.addMatchedInputFile(referenceFilePath); }); @@ -335,7 +335,7 @@ module FourSlash { ts.forEach(importedFiles, importedFile => { // Fourslash insert tests/cases/fourslash into inputFile.unitName and import statement doesn't require ".ts" // so convert them before making appropriate comparison - var importedFilePath = this.basePath + '/' + importedFile.fileName + ".ts"; + let importedFilePath = this.basePath + '/' + importedFile.fileName + ".ts"; this.addMatchedInputFile(importedFilePath); }); @@ -370,8 +370,8 @@ module FourSlash { }; this.testData.files.forEach(file => { - var fileName = file.fileName.replace(Harness.IO.directoryName(file.fileName), '').substr(1); - var fileNameWithoutExtension = fileName.substr(0, fileName.lastIndexOf(".")); + let fileName = file.fileName.replace(Harness.IO.directoryName(file.fileName), '').substr(1); + let fileNameWithoutExtension = fileName.substr(0, fileName.lastIndexOf(".")); this.scenarioActions.push(''); }); @@ -380,18 +380,18 @@ module FourSlash { } private getFileContent(fileName: string): string { - var script = this.languageServiceAdapterHost.getScriptInfo(fileName); + let script = this.languageServiceAdapterHost.getScriptInfo(fileName); return script.content; } // Entry points from fourslash.ts public goToMarker(name = '') { - var marker = this.getMarkerByName(name); + let marker = this.getMarkerByName(name); if (this.activeFile.fileName !== marker.fileName) { this.openFile(marker.fileName); } - var content = this.getFileContent(marker.fileName); + let content = this.getFileContent(marker.fileName); if (marker.position === -1 || marker.position > content.length) { throw new Error('Marker "' + name + '" has been invalidated by unrecoverable edits to the file.'); } @@ -402,8 +402,8 @@ module FourSlash { public goToPosition(pos: number) { this.currentCaretPosition = pos; - var lineStarts = ts.computeLineStarts(this.getFileContent(this.activeFile.fileName)); - var lineCharPos = ts.computeLineAndCharacterOfPosition(lineStarts, pos); + let lineStarts = ts.computeLineStarts(this.getFileContent(this.activeFile.fileName)); + let lineCharPos = ts.computeLineAndCharacterOfPosition(lineStarts, pos); this.scenarioActions.push(``); } @@ -421,24 +421,24 @@ module FourSlash { public openFile(index: number): void; public openFile(name: string): void; public openFile(indexOrName: any) { - var fileToOpen: FourSlashFile = this.findFile(indexOrName); + let fileToOpen: FourSlashFile = this.findFile(indexOrName); fileToOpen.fileName = ts.normalizeSlashes(fileToOpen.fileName); this.activeFile = fileToOpen; - var fileName = fileToOpen.fileName.replace(Harness.IO.directoryName(fileToOpen.fileName), '').substr(1); + let fileName = fileToOpen.fileName.replace(Harness.IO.directoryName(fileToOpen.fileName), '').substr(1); this.scenarioActions.push(''); - + // Let the host know that this file is now open this.languageServiceAdapterHost.openFile(fileToOpen.fileName); } public verifyErrorExistsBetweenMarkers(startMarkerName: string, endMarkerName: string, negative: boolean) { - var startMarker = this.getMarkerByName(startMarkerName); - var endMarker = this.getMarkerByName(endMarkerName); - var predicate = function (errorMinChar: number, errorLimChar: number, startPos: number, endPos: number) { + let startMarker = this.getMarkerByName(startMarkerName); + let endMarker = this.getMarkerByName(endMarkerName); + let predicate = function (errorMinChar: number, errorLimChar: number, startPos: number, endPos: number) { return ((errorMinChar === startPos) && (errorLimChar === endPos)) ? true : false; }; - var exists = this.anyErrorInRange(predicate, startMarker, endMarker); + let exists = this.anyErrorInRange(predicate, startMarker, endMarker); this.taoInvalidReason = 'verifyErrorExistsBetweenMarkers NYI'; @@ -458,10 +458,10 @@ module FourSlash { } private getDiagnostics(fileName: string): ts.Diagnostic[] { - var syntacticErrors = this.languageService.getSyntacticDiagnostics(fileName); - var semanticErrors = this.languageService.getSemanticDiagnostics(fileName); + let syntacticErrors = this.languageService.getSyntacticDiagnostics(fileName); + let semanticErrors = this.languageService.getSemanticDiagnostics(fileName); - var diagnostics: ts.Diagnostic[] = []; + let diagnostics: ts.Diagnostic[] = []; diagnostics.push.apply(diagnostics, syntacticErrors); diagnostics.push.apply(diagnostics, semanticErrors); @@ -469,10 +469,10 @@ module FourSlash { } private getAllDiagnostics(): ts.Diagnostic[] { - var diagnostics: ts.Diagnostic[] = []; + let diagnostics: ts.Diagnostic[] = []; - var fileNames = this.languageServiceAdapterHost.getFilenames(); - for (var i = 0, n = fileNames.length; i < n; i++) { + let fileNames = this.languageServiceAdapterHost.getFilenames(); + for (let i = 0, n = fileNames.length; i < n; i++) { diagnostics.push.apply(this.getDiagnostics(fileNames[i])); } @@ -480,8 +480,8 @@ module FourSlash { } public verifyErrorExistsAfterMarker(markerName: string, negative: boolean, after: boolean) { - var marker: Marker = this.getMarkerByName(markerName); - var predicate: (errorMinChar: number, errorLimChar: number, startPos: number, endPos: number) => boolean; + let marker: Marker = this.getMarkerByName(markerName); + let predicate: (errorMinChar: number, errorLimChar: number, startPos: number, endPos: number) => boolean; if (after) { predicate = function (errorMinChar: number, errorLimChar: number, startPos: number, endPos: number) { @@ -495,8 +495,8 @@ module FourSlash { this.taoInvalidReason = 'verifyErrorExistsAfterMarker NYI'; - var exists = this.anyErrorInRange(predicate, marker); - var diagnostics = this.getAllDiagnostics(); + let exists = this.anyErrorInRange(predicate, marker); + let diagnostics = this.getAllDiagnostics(); if (exists !== negative) { this.printErrorLog(negative, diagnostics); @@ -506,12 +506,13 @@ module FourSlash { private anyErrorInRange(predicate: (errorMinChar: number, errorLimChar: number, startPos: number, endPos: number) => boolean, startMarker: Marker, endMarker?: Marker) { - var errors = this.getDiagnostics(startMarker.fileName); - var exists = false; + let errors = this.getDiagnostics(startMarker.fileName); + let exists = false; - var startPos = startMarker.position; + let startPos = startMarker.position; + let endPos: number = undefined; if (endMarker !== undefined) { - var endPos = endMarker.position; + endPos = endMarker.position; } errors.forEach(function (error: ts.Diagnostic) { @@ -538,40 +539,40 @@ module FourSlash { } public verifyNumberOfErrorsInCurrentFile(expected: number) { - var errors = this.getDiagnostics(this.activeFile.fileName); - var actual = errors.length; + let errors = this.getDiagnostics(this.activeFile.fileName); + let actual = errors.length; this.scenarioActions.push(''); if (actual !== expected) { this.printErrorLog(false, errors); - var errorMsg = "Actual number of errors (" + actual + ") does not match expected number (" + expected + ")"; + let errorMsg = "Actual number of errors (" + actual + ") does not match expected number (" + expected + ")"; Harness.IO.log(errorMsg); this.raiseError(errorMsg); } } public verifyEval(expr: string, value: any) { - var emit = this.languageService.getEmitOutput(this.activeFile.fileName); + let emit = this.languageService.getEmitOutput(this.activeFile.fileName); if (emit.outputFiles.length !== 1) { throw new Error("Expected exactly one output from emit of " + this.activeFile.fileName); } this.taoInvalidReason = 'verifyEval impossible'; - var evaluation = new Function(emit.outputFiles[0].text + ';\r\nreturn (' + expr + ');')(); + let evaluation = new Function(emit.outputFiles[0].text + ';\r\nreturn (' + expr + ');')(); if (evaluation !== value) { this.raiseError('Expected evaluation of expression "' + expr + '" to equal "' + value + '", but got "' + evaluation + '"'); } } public verifyGetEmitOutputForCurrentFile(expected: string): void { - var emit = this.languageService.getEmitOutput(this.activeFile.fileName); + let emit = this.languageService.getEmitOutput(this.activeFile.fileName); if (emit.outputFiles.length !== 1) { throw new Error("Expected exactly one output from emit of " + this.activeFile.fileName); } this.taoInvalidReason = 'verifyGetEmitOutputForCurrentFile impossible'; - var actual = emit.outputFiles[0].text; + let actual = emit.outputFiles[0].text; if (actual !== expected) { this.raiseError("Expected emit output to be '" + expected + "', but got '" + actual + "'"); } @@ -585,7 +586,7 @@ module FourSlash { this.taoInvalidReason = 'verifyMemberListContains only supports the "symbol" parameter'; } - var members = this.getMemberListAtCaret(); + let members = this.getMemberListAtCaret(); if (members) { this.assertItemInCompletionList(members.entries, symbol, text, documentation, kind); } @@ -607,10 +608,10 @@ module FourSlash { this.scenarioActions.push(''); } - var members = this.getMemberListAtCaret(); + let members = this.getMemberListAtCaret(); if (members) { - var match = members.entries.length === expectedCount; + let match = members.entries.length === expectedCount; if ((!match && !negative) || (match && negative)) { this.raiseError("Member list count was " + members.entries.length + ". Expected " + expectedCount); @@ -625,7 +626,7 @@ module FourSlash { this.scenarioActions.push(''); this.scenarioActions.push(''); - var members = this.getMemberListAtCaret(); + let members = this.getMemberListAtCaret(); if (members && members.entries.filter(e => e.name === symbol).length !== 0) { this.raiseError('Member list did contain ' + symbol); } @@ -634,8 +635,8 @@ module FourSlash { public verifyCompletionListItemsCountIsGreaterThan(count: number) { this.taoInvalidReason = 'verifyCompletionListItemsCountIsGreaterThan NYI'; - var completions = this.getCompletionListAtCaret(); - var itemsCount = completions.entries.length; + let completions = this.getCompletionListAtCaret(); + let itemsCount = completions.entries.length; if (itemsCount <= count) { this.raiseError('Expected completion list items count to be greater than ' + count + ', but is actually ' + itemsCount); @@ -649,13 +650,13 @@ module FourSlash { this.scenarioActions.push(''); } - var members = this.getMemberListAtCaret(); + let members = this.getMemberListAtCaret(); if ((!members || members.entries.length === 0) && negative) { this.raiseError("Member list is empty at Caret"); } else if ((members && members.entries.length !== 0) && !negative) { - var errorMsg = "\n" + "Member List contains: [" + members.entries[0].name; - for (var i = 1; i < members.entries.length; i++) { + let errorMsg = "\n" + "Member List contains: [" + members.entries[0].name; + for (let i = 1; i < members.entries.length; i++) { errorMsg += ", " + members.entries[i].name; } errorMsg += "]\n"; @@ -668,24 +669,24 @@ module FourSlash { public verifyCompletionListIsEmpty(negative: boolean) { this.scenarioActions.push(''); - var completions = this.getCompletionListAtCaret(); + let completions = this.getCompletionListAtCaret(); if ((!completions || completions.entries.length === 0) && negative) { - this.raiseError("Completion list is empty at Caret"); - } else if ((completions && completions.entries.length !== 0) && !negative) { - - var errorMsg = "\n" + "Completion List contains: [" + completions.entries[0].name; - for (var i = 1; i < completions.entries.length; i++) { + this.raiseError("Completion list is empty at caret at position " + this.activeFile.fileName + " " + this.currentCaretPosition); + } + else if (completions && completions.entries.length !== 0 && !negative) { + let errorMsg = "\n" + "Completion List contains: [" + completions.entries[0].name; + for (let i = 1; i < completions.entries.length; i++) { errorMsg += ", " + completions.entries[i].name; } errorMsg += "]\n"; - Harness.IO.log(errorMsg); - this.raiseError("Completion list is not empty at Caret"); + this.raiseError("Completion list is not empty at caret at position " + this.activeFile.fileName + " " + this.currentCaretPosition + errorMsg); } } + public verifyCompletionListAllowsNewIdentifier(negative: boolean) { - var completions = this.getCompletionListAtCaret(); + let completions = this.getCompletionListAtCaret(); if ((completions && !completions.isNewIdentifierLocation) && !negative) { this.raiseError("Expected builder completion entry"); @@ -695,7 +696,7 @@ module FourSlash { } public verifyCompletionListContains(symbol: string, text?: string, documentation?: string, kind?: string) { - var completions = this.getCompletionListAtCaret(); + let completions = this.getCompletionListAtCaret(); if (completions) { this.assertItemInCompletionList(completions.entries, symbol, text, documentation, kind); } @@ -737,7 +738,7 @@ module FourSlash { this.scenarioActions.push(''); this.scenarioActions.push(''); - var completions = this.getCompletionListAtCaret(); + let completions = this.getCompletionListAtCaret(); if (completions) { let filterCompletions = completions.entries.filter(e => e.name === symbol); filterCompletions = expectedKind ? filterCompletions.filter(e => e.kind === expectedKind) : filterCompletions; @@ -755,7 +756,7 @@ module FourSlash { error += "Expected documentation: " + expectedDocumentation + " to equal: " + ts.displayPartsToString(details.documentation) + "."; } if (expectedKind) { - error += "Expected kind: " + expectedKind + " to equal: " + filterCompletions[0].kind + "." + error += "Expected kind: " + expectedKind + " to equal: " + filterCompletions[0].kind + "."; } this.raiseError(error); } @@ -765,7 +766,7 @@ module FourSlash { public verifyCompletionEntryDetails(entryName: string, expectedText: string, expectedDocumentation?: string, kind?: string) { this.taoInvalidReason = 'verifyCompletionEntryDetails NYI'; - var details = this.getCompletionEntryDetails(entryName); + let details = this.getCompletionEntryDetails(entryName); assert.equal(ts.displayPartsToString(details.displayParts), expectedText, assertionMessage("completion entry details text")); @@ -781,14 +782,14 @@ module FourSlash { public verifyReferencesAtPositionListContains(fileName: string, start: number, end: number, isWriteAccess?: boolean) { this.taoInvalidReason = 'verifyReferencesAtPositionListContains NYI'; - var references = this.getReferencesAtCaret(); + let references = this.getReferencesAtCaret(); if (!references || references.length === 0) { this.raiseError('verifyReferencesAtPositionListContains failed - found 0 references, expected at least one.'); } - for (var i = 0; i < references.length; i++) { - var reference = references[i]; + for (let i = 0; i < references.length; i++) { + let reference = references[i]; if (reference && reference.fileName === fileName && reference.textSpan.start === start && ts.textSpanEnd(reference.textSpan) === end) { if (typeof isWriteAccess !== "undefined" && reference.isWriteAccess !== isWriteAccess) { this.raiseError('verifyReferencesAtPositionListContains failed - item isWriteAccess value does not match, actual: ' + reference.isWriteAccess + ', expected: ' + isWriteAccess + '.'); @@ -797,18 +798,18 @@ module FourSlash { } } - var missingItem = { fileName: fileName, start: start, end: end, isWriteAccess: isWriteAccess }; + let missingItem = { fileName: fileName, start: start, end: end, isWriteAccess: isWriteAccess }; this.raiseError('verifyReferencesAtPositionListContains failed - could not find the item: ' + JSON.stringify(missingItem) + ' in the returned list: (' + JSON.stringify(references) + ')'); } public verifyReferencesCountIs(count: number, localFilesOnly: boolean = true) { this.taoInvalidReason = 'verifyReferences NYI'; - var references = this.getReferencesAtCaret(); - var referencesCount = 0; + let references = this.getReferencesAtCaret(); + let referencesCount = 0; if (localFilesOnly) { - var localFiles = this.testData.files.map(file => file.fileName); + let localFiles = this.testData.files.map(file => file.fileName); // Count only the references in local files. Filter the ones in lib and other files. ts.forEach(references, entry => { if (localFiles.some((fileName) => fileName === entry.fileName)) { @@ -821,7 +822,7 @@ module FourSlash { } if (referencesCount !== count) { - var condition = localFilesOnly ? "excluding libs" : "including libs"; + let condition = localFilesOnly ? "excluding libs" : "including libs"; this.raiseError("Expected references count (" + condition + ") to be " + count + ", but is actually " + referencesCount); } } @@ -847,18 +848,18 @@ module FourSlash { } public getSyntacticDiagnostics(expected: string) { - var diagnostics = this.languageService.getSyntacticDiagnostics(this.activeFile.fileName); + let diagnostics = this.languageService.getSyntacticDiagnostics(this.activeFile.fileName); this.testDiagnostics(expected, diagnostics); } public getSemanticDiagnostics(expected: string) { - var diagnostics = this.languageService.getSemanticDiagnostics(this.activeFile.fileName); + let diagnostics = this.languageService.getSemanticDiagnostics(this.activeFile.fileName); this.testDiagnostics(expected, diagnostics); } private testDiagnostics(expected: string, diagnostics: ts.Diagnostic[]) { - var realized = ts.realizeDiagnostics(diagnostics, "\r\n"); - var actual = JSON.stringify(realized, null, " "); + let realized = ts.realizeDiagnostics(diagnostics, "\r\n"); + let actual = JSON.stringify(realized, null, " "); assert.equal(actual, expected); } @@ -870,9 +871,9 @@ module FourSlash { } }); - var actualQuickInfo = this.languageService.getQuickInfoAtPosition(this.activeFile.fileName, this.currentCaretPosition); - var actualQuickInfoText = actualQuickInfo ? ts.displayPartsToString(actualQuickInfo.displayParts) : ""; - var actualQuickInfoDocumentation = actualQuickInfo ? ts.displayPartsToString(actualQuickInfo.documentation) : ""; + let actualQuickInfo = this.languageService.getQuickInfoAtPosition(this.activeFile.fileName, this.currentCaretPosition); + let actualQuickInfoText = actualQuickInfo ? ts.displayPartsToString(actualQuickInfo.displayParts) : ""; + let actualQuickInfoDocumentation = actualQuickInfo ? ts.displayPartsToString(actualQuickInfo.documentation) : ""; if (negative) { if (expectedText !== undefined) { @@ -900,7 +901,7 @@ module FourSlash { this.scenarioActions.push(''); function getDisplayPartsJson(displayParts: ts.SymbolDisplayPart[]) { - var result = ""; + let result = ""; ts.forEach(displayParts, part => { if (result) { result += ",\n "; @@ -917,7 +918,7 @@ module FourSlash { return result; } - var actualQuickInfo = this.languageService.getQuickInfoAtPosition(this.activeFile.fileName, this.currentCaretPosition); + let actualQuickInfo = this.languageService.getQuickInfoAtPosition(this.activeFile.fileName, this.currentCaretPosition); assert.equal(actualQuickInfo.kind, kind, this.messageAtLastKnownMarker("QuickInfo kind")); assert.equal(actualQuickInfo.kindModifiers, kindModifiers, this.messageAtLastKnownMarker("QuickInfo kindModifiers")); assert.equal(JSON.stringify(actualQuickInfo.textSpan), JSON.stringify(textSpan), this.messageAtLastKnownMarker("QuickInfo textSpan")); @@ -926,12 +927,12 @@ module FourSlash { } public verifyRenameLocations(findInStrings: boolean, findInComments: boolean) { - var renameInfo = this.languageService.getRenameInfo(this.activeFile.fileName, this.currentCaretPosition); + let renameInfo = this.languageService.getRenameInfo(this.activeFile.fileName, this.currentCaretPosition); if (renameInfo.canRename) { - var references = this.languageService.findRenameLocations( + let references = this.languageService.findRenameLocations( this.activeFile.fileName, this.currentCaretPosition, findInStrings, findInComments); - var ranges = this.getRanges(); + let ranges = this.getRanges(); if (!references) { if (ranges.length !== 0) { @@ -947,9 +948,9 @@ module FourSlash { ranges = ranges.sort((r1, r2) => r1.start - r2.start); references = references.sort((r1, r2) => r1.textSpan.start - r2.textSpan.start); - for (var i = 0, n = ranges.length; i < n; i++) { - var reference = references[i]; - var range = ranges[i]; + for (let i = 0, n = ranges.length; i < n; i++) { + let reference = references[i]; + let range = ranges[i]; if (reference.textSpan.start !== range.start || ts.textSpanEnd(reference.textSpan) !== range.end) { @@ -966,7 +967,7 @@ module FourSlash { public verifyQuickInfoExists(negative: boolean) { this.taoInvalidReason = 'verifyQuickInfoExists NYI'; - var actualQuickInfo = this.languageService.getQuickInfoAtPosition(this.activeFile.fileName, this.currentCaretPosition); + let actualQuickInfo = this.languageService.getQuickInfoAtPosition(this.activeFile.fileName, this.currentCaretPosition); if (negative) { if (actualQuickInfo) { this.raiseError('verifyQuickInfoExists failed. Expected quick info NOT to exist'); @@ -982,17 +983,17 @@ module FourSlash { public verifyCurrentSignatureHelpIs(expected: string) { this.taoInvalidReason = 'verifyCurrentSignatureHelpIs NYI'; - var help = this.getActiveSignatureHelpItem(); + let help = this.getActiveSignatureHelpItem(); assert.equal( ts.displayPartsToString(help.prefixDisplayParts) + help.parameters.map(p => ts.displayPartsToString(p.displayParts)).join(ts.displayPartsToString(help.separatorDisplayParts)) + ts.displayPartsToString(help.suffixDisplayParts), expected); } - public verifyCurrentParameterIsVariable(isVariable: boolean) { - this.taoInvalidReason = 'verifyCurrentParameterIsVariable NYI'; + public verifyCurrentParameterIsletiable(isVariable: boolean) { + this.taoInvalidReason = 'verifyCurrentParameterIsletiable NYI'; - var signature = this.getActiveSignatureHelpItem(); + let signature = this.getActiveSignatureHelpItem(); assert.isNotNull(signature); assert.equal(isVariable, signature.isVariadic); } @@ -1000,24 +1001,24 @@ module FourSlash { public verifyCurrentParameterHelpName(name: string) { this.taoInvalidReason = 'verifyCurrentParameterHelpName NYI'; - var activeParameter = this.getActiveParameter(); - var activeParameterName = activeParameter.name; + let activeParameter = this.getActiveParameter(); + let activeParameterName = activeParameter.name; assert.equal(activeParameterName, name); } public verifyCurrentParameterSpanIs(parameter: string) { this.taoInvalidReason = 'verifyCurrentParameterSpanIs NYI'; - var activeSignature = this.getActiveSignatureHelpItem(); - var activeParameter = this.getActiveParameter(); + let activeSignature = this.getActiveSignatureHelpItem(); + let activeParameter = this.getActiveParameter(); assert.equal(ts.displayPartsToString(activeParameter.displayParts), parameter); } public verifyCurrentParameterHelpDocComment(docComment: string) { this.taoInvalidReason = 'verifyCurrentParameterHelpDocComment NYI'; - var activeParameter = this.getActiveParameter(); - var activeParameterDocComment = activeParameter.documentation; + let activeParameter = this.getActiveParameter(); + let activeParameterDocComment = activeParameter.documentation; assert.equal(ts.displayPartsToString(activeParameterDocComment), docComment, assertionMessage("current parameter Help DocComment")); } @@ -1036,7 +1037,7 @@ module FourSlash { public verifyCurrentSignatureHelpDocComment(docComment: string) { this.taoInvalidReason = 'verifyCurrentSignatureHelpDocComment NYI'; - var actualDocComment = this.getActiveSignatureHelpItem().documentation; + let actualDocComment = this.getActiveSignatureHelpItem().documentation; assert.equal(ts.displayPartsToString(actualDocComment), docComment, assertionMessage("current signature help doc comment")); } @@ -1044,22 +1045,22 @@ module FourSlash { this.scenarioActions.push(''); this.scenarioActions.push(''); - var help = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition); - var actual = help && help.items ? help.items.length : 0; + let help = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition); + let actual = help && help.items ? help.items.length : 0; assert.equal(actual, expected); } public verifySignatureHelpArgumentCount(expected: number) { this.taoInvalidReason = 'verifySignatureHelpArgumentCount NYI'; - var signatureHelpItems = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition); - var actual = signatureHelpItems.argumentCount; + let signatureHelpItems = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition); + let actual = signatureHelpItems.argumentCount; assert.equal(actual, expected); } public verifySignatureHelpPresent(shouldBePresent = true) { this.taoInvalidReason = 'verifySignatureHelpPresent NYI'; - var actual = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition); + let actual = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition); if (shouldBePresent) { if (!actual) { this.raiseError("Expected signature help to be present, but it wasn't"); @@ -1078,7 +1079,7 @@ module FourSlash { } public verifyRenameInfoSucceeded(displayName?: string, fullDisplayName?: string, kind?: string, kindModifiers?: string) { - var renameInfo = this.languageService.getRenameInfo(this.activeFile.fileName, this.currentCaretPosition); + let renameInfo = this.languageService.getRenameInfo(this.activeFile.fileName, this.currentCaretPosition); if (!renameInfo.canRename) { this.raiseError("Rename did not succeed"); } @@ -1092,7 +1093,7 @@ module FourSlash { this.raiseError("Expected a single range to be selected in the test file."); } - var expectedRange = this.getRanges()[0]; + let expectedRange = this.getRanges()[0]; if (renameInfo.triggerSpan.start !== expectedRange.start || ts.textSpanEnd(renameInfo.triggerSpan) !== expectedRange.end) { this.raiseError("Expected triggerSpan [" + expectedRange.start + "," + expectedRange.end + "). Got [" + @@ -1101,7 +1102,7 @@ module FourSlash { } public verifyRenameInfoFailed(message?: string) { - var renameInfo = this.languageService.getRenameInfo(this.activeFile.fileName, this.currentCaretPosition); + let renameInfo = this.languageService.getRenameInfo(this.activeFile.fileName, this.currentCaretPosition); if (renameInfo.canRename) { this.raiseError("Rename was expected to fail"); } @@ -1110,26 +1111,26 @@ module FourSlash { } private getActiveSignatureHelpItem() { - var help = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition); - var index = help.selectedItemIndex; + let help = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition); + let index = help.selectedItemIndex; return help.items[index]; } private getActiveParameter(): ts.SignatureHelpParameter { - var help = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition); - var item = help.items[help.selectedItemIndex]; - var currentParam = help.argumentIndex; + let help = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition); + let item = help.items[help.selectedItemIndex]; + let currentParam = help.argumentIndex; return item.parameters[currentParam]; } private alignmentForExtraInfo = 50; private spanInfoToString(pos: number, spanInfo: ts.TextSpan, prefixString: string) { - var resultString = "SpanInfo: " + JSON.stringify(spanInfo); + let resultString = "SpanInfo: " + JSON.stringify(spanInfo); if (spanInfo) { - var spanString = this.activeFile.content.substr(spanInfo.start, spanInfo.length); - var spanLineMap = ts.computeLineStarts(spanString); - for (var i = 0; i < spanLineMap.length; i++) { + let spanString = this.activeFile.content.substr(spanInfo.start, spanInfo.length); + let spanLineMap = ts.computeLineStarts(spanString); + for (let i = 0; i < spanLineMap.length; i++) { if (!i) { resultString += "\n"; } @@ -1142,19 +1143,20 @@ module FourSlash { } private baselineCurrentFileLocations(getSpanAtPos: (pos: number) => ts.TextSpan): string { - var fileLineMap = ts.computeLineStarts(this.activeFile.content); - var nextLine = 0; - var resultString = ""; - var currentLine: string; - var previousSpanInfo: string; - var startColumn: number; - var length: number; - var prefixString = " >"; + let fileLineMap = ts.computeLineStarts(this.activeFile.content); + let nextLine = 0; + let resultString = ""; + let currentLine: string; + let previousSpanInfo: string; + let startColumn: number; + let length: number; + let prefixString = " >"; - var addSpanInfoString = () => { + let pos = 0; + let addSpanInfoString = () => { if (previousSpanInfo) { resultString += currentLine; - var thisLineMarker = repeatString(startColumn, " ") + repeatString(length, "~"); + let thisLineMarker = repeatString(startColumn, " ") + repeatString(length, "~"); thisLineMarker += repeatString(this.alignmentForExtraInfo - thisLineMarker.length - prefixString.length + 1, " "); resultString += thisLineMarker; resultString += "=> Pos: (" + (pos - length) + " to " + (pos - 1) + ") "; @@ -1163,7 +1165,7 @@ module FourSlash { } }; - for (var pos = 0; pos < this.activeFile.content.length; pos++) { + for (; pos < this.activeFile.content.length; pos++) { if (pos === 0 || pos === fileLineMap[nextLine]) { nextLine++; addSpanInfoString(); @@ -1174,7 +1176,7 @@ module FourSlash { startColumn = 0; length = 0; } - var spanInfo = this.spanInfoToString(pos, getSpanAtPos(pos), prefixString); + let spanInfo = this.spanInfoToString(pos, getSpanAtPos(pos), prefixString); if (previousSpanInfo && previousSpanInfo !== spanInfo) { addSpanInfoString(); previousSpanInfo = spanInfo; @@ -1190,8 +1192,8 @@ module FourSlash { return resultString; function repeatString(count: number, char: string) { - var result = ""; - for (var i = 0; i < count; i++) { + let result = ""; + for (let i = 0; i < count; i++) { result += char; } return result; @@ -1218,11 +1220,11 @@ module FourSlash { public baselineGetEmitOutput() { this.taoInvalidReason = 'baselineGetEmitOutput impossible'; // Find file to be emitted - var emitFiles: FourSlashFile[] = []; // List of FourSlashFile that has emitThisFile flag on + let emitFiles: FourSlashFile[] = []; // List of FourSlashFile that has emitThisFile flag on - var allFourSlashFiles = this.testData.files; - for (var idx = 0; idx < allFourSlashFiles.length; ++idx) { - var file = allFourSlashFiles[idx]; + let allFourSlashFiles = this.testData.files; + for (let idx = 0; idx < allFourSlashFiles.length; ++idx) { + let file = allFourSlashFiles[idx]; if (file.fileOptions[metadataOptionNames.emitThisFile] === "true") { // Find a file with the flag emitThisFile turned on emitFiles.push(file); @@ -1238,23 +1240,23 @@ module FourSlash { "Generate getEmitOutput baseline : " + emitFiles.join(" "), this.testData.globalOptions[metadataOptionNames.baselineFile], () => { - var resultString = ""; + let resultString = ""; // Loop through all the emittedFiles and emit them one by one emitFiles.forEach(emitFile => { - var emitOutput = this.languageService.getEmitOutput(emitFile.fileName); + let emitOutput = this.languageService.getEmitOutput(emitFile.fileName); // Print emitOutputStatus in readable format resultString += "EmitSkipped: " + emitOutput.emitSkipped + ts.sys.newLine; if (emitOutput.emitSkipped) { resultString += "Diagnostics:" + ts.sys.newLine; - var diagnostics = ts.getPreEmitDiagnostics(this.languageService.getProgram()); - for (var i = 0, n = diagnostics.length; i < n; i++) { + let diagnostics = ts.getPreEmitDiagnostics(this.languageService.getProgram()); + for (let i = 0, n = diagnostics.length; i < n; i++) { resultString += " " + diagnostics[0].messageText + ts.sys.newLine; } } emitOutput.outputFiles.forEach((outputFile, idx, array) => { - var fileName = "FileName : " + outputFile.name + ts.sys.newLine; + let fileName = "FileName : " + outputFile.name + ts.sys.newLine; resultString = resultString + fileName + outputFile.text; }); resultString += ts.sys.newLine; @@ -1274,19 +1276,19 @@ module FourSlash { } public printCurrentParameterHelp() { - var help = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition); + let help = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition); Harness.IO.log(JSON.stringify(help)); } public printCurrentQuickInfo() { - var quickInfo = this.languageService.getQuickInfoAtPosition(this.activeFile.fileName, this.currentCaretPosition); + let quickInfo = this.languageService.getQuickInfoAtPosition(this.activeFile.fileName, this.currentCaretPosition); Harness.IO.log(JSON.stringify(quickInfo)); } public printErrorList() { - var syntacticErrors = this.languageService.getSyntacticDiagnostics(this.activeFile.fileName); - var semanticErrors = this.languageService.getSemanticDiagnostics(this.activeFile.fileName); - var errorList = syntacticErrors.concat(semanticErrors); + let syntacticErrors = this.languageService.getSyntacticDiagnostics(this.activeFile.fileName); + let semanticErrors = this.languageService.getSemanticDiagnostics(this.activeFile.fileName); + let errorList = syntacticErrors.concat(semanticErrors); Harness.IO.log('Error list (' + errorList.length + ' errors)'); if (errorList.length) { @@ -1300,11 +1302,11 @@ module FourSlash { } public printCurrentFileState(makeWhitespaceVisible = false, makeCaretVisible = true) { - for (var i = 0; i < this.testData.files.length; i++) { - var file = this.testData.files[i]; - var active = (this.activeFile === file); + for (let i = 0; i < this.testData.files.length; i++) { + let file = this.testData.files[i]; + let active = (this.activeFile === file); Harness.IO.log('=== Script (' + file.fileName + ') ' + (active ? '(active, cursor at |)' : '') + ' ==='); - var content = this.getFileContent(file.fileName); + let content = this.getFileContent(file.fileName); if (active) { content = content.substr(0, this.currentCaretPosition) + (makeCaretVisible ? '|' : "") + content.substr(this.currentCaretPosition); } @@ -1316,22 +1318,22 @@ module FourSlash { } public printCurrentSignatureHelp() { - var sigHelp = this.getActiveSignatureHelpItem(); + let sigHelp = this.getActiveSignatureHelpItem(); Harness.IO.log(JSON.stringify(sigHelp)); } public printMemberListMembers() { - var members = this.getMemberListAtCaret(); + let members = this.getMemberListAtCaret(); Harness.IO.log(JSON.stringify(members)); } public printCompletionListMembers() { - var completions = this.getCompletionListAtCaret(); + let completions = this.getCompletionListAtCaret(); Harness.IO.log(JSON.stringify(completions)); } public printReferences() { - var references = this.getReferencesAtCaret(); + let references = this.getReferencesAtCaret(); ts.forEach(references, entry => { Harness.IO.log(JSON.stringify(entry)); }); @@ -1344,26 +1346,26 @@ module FourSlash { public deleteChar(count = 1) { this.scenarioActions.push(''); - var offset = this.currentCaretPosition; - var ch = ""; + let offset = this.currentCaretPosition; + let ch = ""; - var checkCadence = (count >> 2) + 1 + let checkCadence = (count >> 2) + 1; - for (var i = 0; i < count; i++) { + for (let i = 0; i < count; i++) { // Make the edit this.languageServiceAdapterHost.editScript(this.activeFile.fileName, offset, offset + 1, ch); this.updateMarkersForEdit(this.activeFile.fileName, offset, offset + 1, ch); if (i % checkCadence === 0) { - this.checkPostEditInvariants(); + this.checkPostEditInletiants(); } // Handle post-keystroke formatting if (this.enableFormatting) { - var edits = this.languageService.getFormattingEditsAfterKeystroke(this.activeFile.fileName, offset, ch, this.formatCodeOptions); + let edits = this.languageService.getFormattingEditsAfterKeystroke(this.activeFile.fileName, offset, ch, this.formatCodeOptions); if (edits.length) { offset += this.applyEdits(this.activeFile.fileName, edits, true); - //this.checkPostEditInvariants(); + // this.checkPostEditInletiants(); } } } @@ -1372,7 +1374,7 @@ module FourSlash { this.currentCaretPosition = offset; this.fixCaretPosition(); - this.checkPostEditInvariants(); + this.checkPostEditInletiants(); } public replace(start: number, length: number, text: string) { @@ -1380,29 +1382,29 @@ module FourSlash { this.languageServiceAdapterHost.editScript(this.activeFile.fileName, start, start + length, text); this.updateMarkersForEdit(this.activeFile.fileName, start, start + length, text); - this.checkPostEditInvariants(); + this.checkPostEditInletiants(); } public deleteCharBehindMarker(count = 1) { this.scenarioActions.push(''); - var offset = this.currentCaretPosition; - var ch = ""; - var checkCadence = (count >> 2) + 1 + let offset = this.currentCaretPosition; + let ch = ""; + let checkCadence = (count >> 2) + 1; - for (var i = 0; i < count; i++) { + for (let i = 0; i < count; i++) { offset--; // Make the edit this.languageServiceAdapterHost.editScript(this.activeFile.fileName, offset, offset + 1, ch); this.updateMarkersForEdit(this.activeFile.fileName, offset, offset + 1, ch); if (i % checkCadence === 0) { - this.checkPostEditInvariants(); + this.checkPostEditInletiants(); } // Handle post-keystroke formatting if (this.enableFormatting) { - var edits = this.languageService.getFormattingEditsAfterKeystroke(this.activeFile.fileName, offset, ch, this.formatCodeOptions); + let edits = this.languageService.getFormattingEditsAfterKeystroke(this.activeFile.fileName, offset, ch, this.formatCodeOptions); if (edits.length) { offset += this.applyEdits(this.activeFile.fileName, edits, true); } @@ -1413,7 +1415,7 @@ module FourSlash { this.currentCaretPosition = offset; this.fixCaretPosition(); - this.checkPostEditInvariants(); + this.checkPostEditInletiants(); } // Enters lines of text at the current caret position @@ -1431,13 +1433,13 @@ module FourSlash { // language service APIs to mimic Visual Studio's behavior // as much as possible private typeHighFidelity(text: string) { - var offset = this.currentCaretPosition; - var prevChar = ' '; - var checkCadence = (text.length >> 2) + 1; + let offset = this.currentCaretPosition; + let prevChar = ' '; + let checkCadence = (text.length >> 2) + 1; - for (var i = 0; i < text.length; i++) { + for (let i = 0; i < text.length; i++) { // Make the edit - var ch = text.charAt(i); + let ch = text.charAt(i); this.languageServiceAdapterHost.editScript(this.activeFile.fileName, offset, offset, ch); this.languageService.getBraceMatchingAtPosition(this.activeFile.fileName, offset); @@ -1453,17 +1455,17 @@ module FourSlash { } if (i % checkCadence === 0) { - this.checkPostEditInvariants(); + this.checkPostEditInletiants(); // this.languageService.getSyntacticDiagnostics(this.activeFile.fileName); // this.languageService.getSemanticDiagnostics(this.activeFile.fileName); } // Handle post-keystroke formatting if (this.enableFormatting) { - var edits = this.languageService.getFormattingEditsAfterKeystroke(this.activeFile.fileName, offset, ch, this.formatCodeOptions); + let edits = this.languageService.getFormattingEditsAfterKeystroke(this.activeFile.fileName, offset, ch, this.formatCodeOptions); if (edits.length) { offset += this.applyEdits(this.activeFile.fileName, edits, true); - // this.checkPostEditInvariants(); + // this.checkPostEditInletiants(); } } } @@ -1472,26 +1474,26 @@ module FourSlash { this.currentCaretPosition = offset; this.fixCaretPosition(); - this.checkPostEditInvariants(); + this.checkPostEditInletiants(); } // Enters text as if the user had pasted it public paste(text: string) { this.scenarioActions.push(''); - var start = this.currentCaretPosition; - var offset = this.currentCaretPosition; + let start = this.currentCaretPosition; + let offset = this.currentCaretPosition; this.languageServiceAdapterHost.editScript(this.activeFile.fileName, offset, offset, text); this.updateMarkersForEdit(this.activeFile.fileName, offset, offset, text); - this.checkPostEditInvariants(); + this.checkPostEditInletiants(); offset += text.length; // Handle formatting if (this.enableFormatting) { - var edits = this.languageService.getFormattingEditsForRange(this.activeFile.fileName, start, offset, this.formatCodeOptions); + let edits = this.languageService.getFormattingEditsForRange(this.activeFile.fileName, start, offset, this.formatCodeOptions); if (edits.length) { offset += this.applyEdits(this.activeFile.fileName, edits, true); - this.checkPostEditInvariants(); + this.checkPostEditInletiants(); } } @@ -1499,27 +1501,27 @@ module FourSlash { this.currentCaretPosition = offset; this.fixCaretPosition(); - this.checkPostEditInvariants(); + this.checkPostEditInletiants(); } - private checkPostEditInvariants() { - if (this.testType !== FourSlashTestType.Native) { - // getSourcefile() results can not be serialized. Only perform these verifications + private checkPostEditInletiants() { + if (this.testType !== FourSlashTestType.Native) { + // getSourcefile() results can not be serialized. Only perform these verifications // if running against a native LS object. return; } - var incrementalSourceFile = this.languageService.getSourceFile(this.activeFile.fileName); + let incrementalSourceFile = this.languageService.getSourceFile(this.activeFile.fileName); Utils.assertInvariants(incrementalSourceFile, /*parent:*/ undefined); - var incrementalSyntaxDiagnostics = incrementalSourceFile.parseDiagnostics; + let incrementalSyntaxDiagnostics = incrementalSourceFile.parseDiagnostics; // Check syntactic structure - var content = this.getFileContent(this.activeFile.fileName); + let content = this.getFileContent(this.activeFile.fileName); - var referenceSourceFile = ts.createLanguageServiceSourceFile( + let referenceSourceFile = ts.createLanguageServiceSourceFile( this.activeFile.fileName, createScriptSnapShot(content), ts.ScriptTarget.Latest, /*version:*/ "0", /*setNodeParents:*/ false); - var referenceSyntaxDiagnostics = referenceSourceFile.parseDiagnostics; + let referenceSyntaxDiagnostics = referenceSourceFile.parseDiagnostics; Utils.assertDiagnosticsEquals(incrementalSyntaxDiagnostics, referenceSyntaxDiagnostics); Utils.assertStructuralEquals(incrementalSourceFile, referenceSourceFile); @@ -1529,7 +1531,7 @@ module FourSlash { // The caret can potentially end up between the \r and \n, which is confusing. If // that happens, move it back one character if (this.currentCaretPosition > 0) { - var ch = this.getFileContent(this.activeFile.fileName).substring(this.currentCaretPosition - 1, this.currentCaretPosition); + let ch = this.getFileContent(this.activeFile.fileName).substring(this.currentCaretPosition - 1, this.currentCaretPosition); if (ch === '\r') { this.currentCaretPosition--; } @@ -1539,21 +1541,21 @@ module FourSlash { private applyEdits(fileName: string, edits: ts.TextChange[], isFormattingEdit = false): number { // We get back a set of edits, but langSvc.editScript only accepts one at a time. Use this to keep track // of the incremental offset from each edit to the next. Assumption is that these edit ranges don't overlap - var runningOffset = 0; + let runningOffset = 0; edits = edits.sort((a, b) => a.span.start - b.span.start); // Get a snapshot of the content of the file so we can make sure any formatting edits didn't destroy non-whitespace characters - var oldContent = this.getFileContent(this.activeFile.fileName); - for (var j = 0; j < edits.length; j++) { + let oldContent = this.getFileContent(this.activeFile.fileName); + for (let j = 0; j < edits.length; j++) { this.languageServiceAdapterHost.editScript(fileName, edits[j].span.start + runningOffset, ts.textSpanEnd(edits[j].span) + runningOffset, edits[j].newText); this.updateMarkersForEdit(fileName, edits[j].span.start + runningOffset, ts.textSpanEnd(edits[j].span) + runningOffset, edits[j].newText); - var change = (edits[j].span.start - ts.textSpanEnd(edits[j].span)) + edits[j].newText.length; + let change = (edits[j].span.start - ts.textSpanEnd(edits[j].span)) + edits[j].newText.length; runningOffset += change; // TODO: Consider doing this at least some of the time for higher fidelity. Currently causes a failure (bug 707150) // this.languageService.getScriptLexicalStructure(fileName); } if (isFormattingEdit) { - var newContent = this.getFileContent(fileName); + let newContent = this.getFileContent(fileName); if (newContent.replace(/\s/g, '') !== oldContent.replace(/\s/g, '')) { this.raiseError('Formatting operation destroyed non-whitespace content'); @@ -1567,7 +1569,7 @@ module FourSlash { } public setFormatOptions(formatCodeOptions: ts.FormatCodeOptions): ts.FormatCodeOptions { - var oldFormatCodeOptions = this.formatCodeOptions; + let oldFormatCodeOptions = this.formatCodeOptions; this.formatCodeOptions = formatCodeOptions; return oldFormatCodeOptions; } @@ -1575,7 +1577,7 @@ module FourSlash { public formatDocument() { this.scenarioActions.push(''); - var edits = this.languageService.getFormattingEditsForDocument(this.activeFile.fileName, this.formatCodeOptions); + let edits = this.languageService.getFormattingEditsForDocument(this.activeFile.fileName, this.formatCodeOptions); this.currentCaretPosition += this.applyEdits(this.activeFile.fileName, edits, true); this.fixCaretPosition(); } @@ -1583,14 +1585,14 @@ module FourSlash { public formatSelection(start: number, end: number) { this.taoInvalidReason = 'formatSelection NYI'; - var edits = this.languageService.getFormattingEditsForRange(this.activeFile.fileName, start, end, this.formatCodeOptions); + let edits = this.languageService.getFormattingEditsForRange(this.activeFile.fileName, start, end, this.formatCodeOptions); this.currentCaretPosition += this.applyEdits(this.activeFile.fileName, edits, true); this.fixCaretPosition(); } private updateMarkersForEdit(fileName: string, minChar: number, limChar: number, text: string) { - for (var i = 0; i < this.testData.markers.length; i++) { - var marker = this.testData.markers[i]; + for (let i = 0; i < this.testData.markers.length; i++) { + let marker = this.testData.markers[i]; if (marker.fileName === fileName) { if (marker.position > minChar) { if (marker.position < limChar) { @@ -1610,7 +1612,7 @@ module FourSlash { } public goToEOF() { - var len = this.getFileContent(this.activeFile.fileName).length; + let len = this.getFileContent(this.activeFile.fileName).length; this.goToPosition(len); } @@ -1621,7 +1623,7 @@ module FourSlash { this.taoInvalidReason = 'GoToDefinition not supported for non-zero definition indices'; } - var definitions = this.languageService.getDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition); + let definitions = this.languageService.getDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition); if (!definitions || !definitions.length) { this.raiseError('goToDefinition failed - expected to at least one definition location but got 0'); } @@ -1630,7 +1632,7 @@ module FourSlash { this.raiseError('goToDefinition failed - definitionIndex value (' + definitionIndex + ') exceeds definition list size (' + definitions.length + ')'); } - var definition = definitions[definitionIndex]; + let definition = definitions[definitionIndex]; this.openFile(definition.fileName); this.currentCaretPosition = definition.textSpan.start; } @@ -1643,7 +1645,7 @@ module FourSlash { this.taoInvalidReason = 'GoToTypeDefinition not supported for non-zero definition indices'; } - var definitions = this.languageService.getTypeDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition); + let definitions = this.languageService.getTypeDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition); if (!definitions || !definitions.length) { this.raiseError('goToTypeDefinition failed - expected to at least one definition location but got 0'); } @@ -1652,7 +1654,7 @@ module FourSlash { this.raiseError('goToTypeDefinition failed - definitionIndex value (' + definitionIndex + ') exceeds definition list size (' + definitions.length + ')'); } - var definition = definitions[definitionIndex]; + let definition = definitions[definitionIndex]; this.openFile(definition.fileName); this.currentCaretPosition = definition.textSpan.start; } @@ -1660,9 +1662,9 @@ module FourSlash { public verifyDefinitionLocationExists(negative: boolean) { this.taoInvalidReason = 'verifyDefinitionLocationExists NYI'; - var definitions = this.languageService.getDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition); + let definitions = this.languageService.getDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition); - var foundDefinitions = definitions && definitions.length; + let foundDefinitions = definitions && definitions.length; if (foundDefinitions && negative) { this.raiseError('goToDefinition - expected to 0 definition locations but got ' + definitions.length); @@ -1673,19 +1675,19 @@ module FourSlash { } public verifyDefinitionsCount(negative: boolean, expectedCount: number) { - var assertFn = negative ? assert.notEqual : assert.equal; + let assertFn = negative ? assert.notEqual : assert.equal; - var definitions = this.languageService.getDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition); - var actualCount = definitions && definitions.length || 0; + let definitions = this.languageService.getDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition); + let actualCount = definitions && definitions.length || 0; assertFn(actualCount, expectedCount, this.messageAtLastKnownMarker("Definitions Count")); } public verifyTypeDefinitionsCount(negative: boolean, expectedCount: number) { - var assertFn = negative ? assert.notEqual : assert.equal; + let assertFn = negative ? assert.notEqual : assert.equal; - var definitions = this.languageService.getTypeDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition); - var actualCount = definitions && definitions.length || 0; + let definitions = this.languageService.getTypeDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition); + let actualCount = definitions && definitions.length || 0; assertFn(actualCount, expectedCount, this.messageAtLastKnownMarker("Type definitions Count")); } @@ -1693,9 +1695,9 @@ module FourSlash { public verifyDefinitionsName(negative: boolean, expectedName: string, expectedContainerName: string) { this.taoInvalidReason = 'verifyDefinititionsInfo NYI'; - var definitions = this.languageService.getDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition); - var actualDefinitionName = definitions && definitions.length ? definitions[0].name : ""; - var actualDefinitionContainerName = definitions && definitions.length ? definitions[0].containerName : ""; + let definitions = this.languageService.getDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition); + let actualDefinitionName = definitions && definitions.length ? definitions[0].name : ""; + let actualDefinitionContainerName = definitions && definitions.length ? definitions[0].containerName : ""; if (negative) { assert.notEqual(actualDefinitionName, expectedName, this.messageAtLastKnownMarker("Definition Info Name")); assert.notEqual(actualDefinitionContainerName, expectedContainerName, this.messageAtLastKnownMarker("Definition Info Container Name")); @@ -1718,7 +1720,7 @@ module FourSlash { public verifyCaretAtMarker(markerName = '') { this.taoInvalidReason = 'verifyCaretAtMarker NYI'; - var pos = this.getMarkerByName(markerName); + let pos = this.getMarkerByName(markerName); if (pos.fileName !== this.activeFile.fileName) { throw new Error('verifyCaretAtMarker failed - expected to be in file "' + pos.fileName + '", but was in file "' + this.activeFile.fileName + '"'); } @@ -1734,8 +1736,8 @@ module FourSlash { public verifyIndentationAtCurrentPosition(numberOfSpaces: number) { this.taoInvalidReason = 'verifyIndentationAtCurrentPosition NYI'; - var actual = this.getIndentation(this.activeFile.fileName, this.currentCaretPosition); - var lineCol = this.getLineColStringAtPosition(this.currentCaretPosition); + let actual = this.getIndentation(this.activeFile.fileName, this.currentCaretPosition); + let lineCol = this.getLineColStringAtPosition(this.currentCaretPosition); if (actual !== numberOfSpaces) { this.raiseError('verifyIndentationAtCurrentPosition failed at ' + lineCol + ' - expected: ' + numberOfSpaces + ', actual: ' + actual); } @@ -1744,8 +1746,8 @@ module FourSlash { public verifyIndentationAtPosition(fileName: string, position: number, numberOfSpaces: number) { this.taoInvalidReason = 'verifyIndentationAtPosition NYI'; - var actual = this.getIndentation(fileName, position); - var lineCol = this.getLineColStringAtPosition(position); + let actual = this.getIndentation(fileName, position); + let lineCol = this.getLineColStringAtPosition(position); if (actual !== numberOfSpaces) { this.raiseError('verifyIndentationAtPosition failed at ' + lineCol + ' - expected: ' + numberOfSpaces + ', actual: ' + actual); } @@ -1754,7 +1756,7 @@ module FourSlash { public verifyCurrentLineContent(text: string) { this.taoInvalidReason = 'verifyCurrentLineContent NYI'; - var actual = this.getCurrentLineContent(); + let actual = this.getCurrentLineContent(); if (actual !== text) { throw new Error('verifyCurrentLineContent\n' + '\tExpected: "' + text + '"\n' + @@ -1765,8 +1767,8 @@ module FourSlash { public verifyCurrentFileContent(text: string) { this.taoInvalidReason = 'verifyCurrentFileContent NYI'; - var actual = this.getFileContent(this.activeFile.fileName); - var replaceNewlines = (str: string) => str.replace(/\r\n/g, "\n"); + let actual = this.getFileContent(this.activeFile.fileName); + let replaceNewlines = (str: string) => str.replace(/\r\n/g, "\n"); if (replaceNewlines(actual) !== replaceNewlines(text)) { throw new Error('verifyCurrentFileContent\n' + '\tExpected: "' + text + '"\n' + @@ -1777,7 +1779,7 @@ module FourSlash { public verifyTextAtCaretIs(text: string) { this.taoInvalidReason = 'verifyCurrentFileContent NYI'; - var actual = this.getFileContent(this.activeFile.fileName).substring(this.currentCaretPosition, this.currentCaretPosition + text.length); + let actual = this.getFileContent(this.activeFile.fileName).substring(this.currentCaretPosition, this.currentCaretPosition + text.length); if (actual !== text) { throw new Error('verifyTextAtCaretIs\n' + '\tExpected: "' + text + '"\n' + @@ -1788,14 +1790,14 @@ module FourSlash { public verifyCurrentNameOrDottedNameSpanText(text: string) { this.taoInvalidReason = 'verifyCurrentNameOrDottedNameSpanText NYI'; - var span = this.languageService.getNameOrDottedNameSpan(this.activeFile.fileName, this.currentCaretPosition, this.currentCaretPosition); + let span = this.languageService.getNameOrDottedNameSpan(this.activeFile.fileName, this.currentCaretPosition, this.currentCaretPosition); if (!span) { this.raiseError('verifyCurrentNameOrDottedNameSpanText\n' + '\tExpected: "' + text + '"\n' + '\t Actual: undefined'); } - var actual = this.getFileContent(this.activeFile.fileName).substring(span.start, ts.textSpanEnd(span)); + let actual = this.getFileContent(this.activeFile.fileName).substring(span.start, ts.textSpanEnd(span)); if (actual !== text) { this.raiseError('verifyCurrentNameOrDottedNameSpanText\n' + '\tExpected: "' + text + '"\n' + @@ -1832,11 +1834,11 @@ module FourSlash { jsonMismatchString()); } - for (var i = 0; i < expected.length; i++) { - var expectedClassification = expected[i]; - var actualClassification = actual[i]; + for (let i = 0; i < expected.length; i++) { + let expectedClassification = expected[i]; + let actualClassification = actual[i]; - var expectedType: string = (ts.ClassificationTypeNames)[expectedClassification.classificationType]; + let expectedType: string = (ts.ClassificationTypeNames)[expectedClassification.classificationType]; if (expectedType !== actualClassification.classificationType) { this.raiseError('verifyClassifications failed - expected classifications type to be ' + expectedType + ', but was ' + @@ -1844,11 +1846,11 @@ module FourSlash { jsonMismatchString()); } - var expectedSpan = expectedClassification.textSpan; - var actualSpan = actualClassification.textSpan; + let expectedSpan = expectedClassification.textSpan; + let actualSpan = actualClassification.textSpan; if (expectedSpan) { - var expectedLength = expectedSpan.end - expectedSpan.start; + let expectedLength = expectedSpan.end - expectedSpan.start; if (expectedSpan.start !== actualSpan.start || expectedLength !== actualSpan.length) { this.raiseError("verifyClassifications failed - expected span of text to be " + @@ -1858,7 +1860,7 @@ module FourSlash { } } - var actualText = this.activeFile.content.substr(actualSpan.start, actualSpan.length); + let actualText = this.activeFile.content.substr(actualSpan.start, actualSpan.length); if (expectedClassification.text !== actualText) { this.raiseError('verifyClassifications failed - expected classified text to be ' + expectedClassification.text + ', but was ' + @@ -1882,22 +1884,22 @@ module FourSlash { ); assert.equal( expected.join(","), - actual.fileNames.map( file => { - return file.replace(this.basePath + "/", "") + actual.fileNameList.map( file => { + return file.replace(this.basePath + "/", ""); }).join(",") ); } } public verifySemanticClassifications(expected: { classificationType: string; text: string }[]) { - var actual = this.languageService.getSemanticClassifications(this.activeFile.fileName, + let actual = this.languageService.getSemanticClassifications(this.activeFile.fileName, ts.createTextSpan(0, this.activeFile.content.length)); this.verifyClassifications(expected, actual); } public verifySyntacticClassifications(expected: { classificationType: string; text: string }[]) { - var actual = this.languageService.getSyntacticClassifications(this.activeFile.fileName, + let actual = this.languageService.getSyntacticClassifications(this.activeFile.fileName, ts.createTextSpan(0, this.activeFile.content.length)); this.verifyClassifications(expected, actual); @@ -1906,15 +1908,15 @@ module FourSlash { public verifyOutliningSpans(spans: TextSpan[]) { this.taoInvalidReason = 'verifyOutliningSpans NYI'; - var actual = this.languageService.getOutliningSpans(this.activeFile.fileName); + let actual = this.languageService.getOutliningSpans(this.activeFile.fileName); if (actual.length !== spans.length) { this.raiseError('verifyOutliningSpans failed - expected total spans to be ' + spans.length + ', but was ' + actual.length); } - for (var i = 0; i < spans.length; i++) { - var expectedSpan = spans[i]; - var actualSpan = actual[i]; + for (let i = 0; i < spans.length; i++) { + let expectedSpan = spans[i]; + let actualSpan = actual[i]; if (expectedSpan.start !== actualSpan.textSpan.start || expectedSpan.end !== ts.textSpanEnd(actualSpan.textSpan)) { this.raiseError('verifyOutliningSpans failed - span ' + (i + 1) + ' expected: (' + expectedSpan.start + ',' + expectedSpan.end + '), actual: (' + actualSpan.textSpan.start + ',' + ts.textSpanEnd(actualSpan.textSpan) + ')'); } @@ -1922,17 +1924,17 @@ module FourSlash { } public verifyTodoComments(descriptors: string[], spans: TextSpan[]) { - var actual = this.languageService.getTodoComments(this.activeFile.fileName, + let actual = this.languageService.getTodoComments(this.activeFile.fileName, descriptors.map(d => { return { text: d, priority: 0 }; })); if (actual.length !== spans.length) { this.raiseError('verifyTodoComments failed - expected total spans to be ' + spans.length + ', but was ' + actual.length); } - for (var i = 0; i < spans.length; i++) { - var expectedSpan = spans[i]; - var actualComment = actual[i]; - var actualCommentSpan = ts.createTextSpan(actualComment.position, actualComment.message.length); + for (let i = 0; i < spans.length; i++) { + let expectedSpan = spans[i]; + let actualComment = actual[i]; + let actualCommentSpan = ts.createTextSpan(actualComment.position, actualComment.message.length); if (expectedSpan.start !== actualCommentSpan.start || expectedSpan.end !== ts.textSpanEnd(actualCommentSpan)) { this.raiseError('verifyOutliningSpans failed - span ' + (i + 1) + ' expected: (' + expectedSpan.start + ',' + expectedSpan.end + '), actual: (' + actualCommentSpan.start + ',' + ts.textSpanEnd(actualCommentSpan) + ')'); @@ -1943,13 +1945,13 @@ module FourSlash { public verifyMatchingBracePosition(bracePosition: number, expectedMatchPosition: number) { this.taoInvalidReason = 'verifyMatchingBracePosition NYI'; - var actual = this.languageService.getBraceMatchingAtPosition(this.activeFile.fileName, bracePosition); + let actual = this.languageService.getBraceMatchingAtPosition(this.activeFile.fileName, bracePosition); if (actual.length !== 2) { this.raiseError('verifyMatchingBracePosition failed - expected result to contain 2 spans, but it had ' + actual.length); } - var actualMatchPosition = -1; + let actualMatchPosition = -1; if (bracePosition === actual[0].start) { actualMatchPosition = actual[1].start; } else if (bracePosition === actual[1].start) { @@ -1966,7 +1968,7 @@ module FourSlash { public verifyNoMatchingBracePosition(bracePosition: number) { this.taoInvalidReason = 'verifyNoMatchingBracePosition NYI'; - var actual = this.languageService.getBraceMatchingAtPosition(this.activeFile.fileName, bracePosition); + let actual = this.languageService.getBraceMatchingAtPosition(this.activeFile.fileName, bracePosition); if (actual.length !== 0) { this.raiseError('verifyNoMatchingBracePosition failed - expected: 0 spans, actual: ' + actual.length); @@ -1980,12 +1982,12 @@ module FourSlash { public verifyNavigationItemsCount(expected: number, searchValue: string, matchKind?: string) { this.taoInvalidReason = 'verifyNavigationItemsCount NYI'; - var items = this.languageService.getNavigateToItems(searchValue); - var actual = 0; - var item: ts.NavigateToItem = null; + let items = this.languageService.getNavigateToItems(searchValue); + let actual = 0; + let item: ts.NavigateToItem = null; // Count only the match that match the same MatchKind - for (var i = 0; i < items.length; ++i) { + for (let i = 0; i < items.length; ++i) { item = items[i]; if (!matchKind || item.matchKind === matchKind) { actual++; @@ -2010,14 +2012,14 @@ module FourSlash { parentName?: string) { this.taoInvalidReason = 'verifyNavigationItemsListContains NYI'; - var items = this.languageService.getNavigateToItems(searchValue); + let items = this.languageService.getNavigateToItems(searchValue); if (!items || items.length === 0) { this.raiseError('verifyNavigationItemsListContains failed - found 0 navigation items, expected at least one.'); } - for (var i = 0; i < items.length; i++) { - var item = items[i]; + for (let i = 0; i < items.length; i++) { + let item = items[i]; if (item && item.name === name && item.kind === kind && (matchKind === undefined || item.matchKind === matchKind) && (fileName === undefined || item.fileName === fileName) && @@ -2028,7 +2030,7 @@ module FourSlash { // if there was an explicit match kind specified, then it should be validated. if (matchKind !== undefined) { - var missingItem = { name: name, kind: kind, searchValue: searchValue, matchKind: matchKind, fileName: fileName, parentName: parentName }; + let missingItem = { name: name, kind: kind, searchValue: searchValue, matchKind: matchKind, fileName: fileName, parentName: parentName }; this.raiseError('verifyNavigationItemsListContains failed - could not find the item: ' + JSON.stringify(missingItem) + ' in the returned list: (' + JSON.stringify(items) + ')'); } } @@ -2036,8 +2038,8 @@ module FourSlash { public verifyGetScriptLexicalStructureListCount(expected: number) { this.taoInvalidReason = 'verifyNavigationItemsListContains impossible'; - var items = this.languageService.getNavigationBarItems(this.activeFile.fileName); - var actual = this.getNavigationBarItemsCount(items); + let items = this.languageService.getNavigationBarItems(this.activeFile.fileName); + let actual = this.getNavigationBarItemsCount(items); if (expected !== actual) { this.raiseError('verifyGetScriptLexicalStructureListCount failed - found: ' + actual + ' navigation items, expected: ' + expected + '.'); @@ -2045,9 +2047,9 @@ module FourSlash { } private getNavigationBarItemsCount(items: ts.NavigationBarItem[]) { - var result = 0; + let result = 0; if (items) { - for (var i = 0, n = items.length; i < n; i++) { + for (let i = 0, n = items.length; i < n; i++) { result++; result += this.getNavigationBarItemsCount(items[i].childItems); } @@ -2062,7 +2064,7 @@ module FourSlash { markerPosition?: number) { this.taoInvalidReason = 'verifGetScriptLexicalStructureListContains impossible'; - var items = this.languageService.getNavigationBarItems(this.activeFile.fileName); + let items = this.languageService.getNavigationBarItems(this.activeFile.fileName); if (!items || items.length === 0) { this.raiseError('verifyGetScriptLexicalStructureListContains failed - found 0 navigation items, expected at least one.'); @@ -2072,14 +2074,14 @@ module FourSlash { return; } - var missingItem = { name: name, kind: kind }; + let missingItem = { name: name, kind: kind }; this.raiseError('verifyGetScriptLexicalStructureListContains failed - could not find the item: ' + JSON.stringify(missingItem) + ' in the returned list: (' + JSON.stringify(items, null, " ") + ')'); } private navigationBarItemsContains(items: ts.NavigationBarItem[], name: string, kind: string) { if (items) { - for (var i = 0; i < items.length; i++) { - var item = items[i]; + for (let i = 0; i < items.length; i++) { + let item = items[i]; if (item && item.text === name && item.kind === kind) { return true; } @@ -2094,25 +2096,25 @@ module FourSlash { } public printNavigationItems(searchValue: string) { - var items = this.languageService.getNavigateToItems(searchValue); - var length = items && items.length; + let items = this.languageService.getNavigateToItems(searchValue); + let length = items && items.length; Harness.IO.log('NavigationItems list (' + length + ' items)'); - for (var i = 0; i < length; i++) { - var item = items[i]; + for (let i = 0; i < length; i++) { + let item = items[i]; Harness.IO.log('name: ' + item.name + ', kind: ' + item.kind + ', parentName: ' + item.containerName + ', fileName: ' + item.fileName); } } public printScriptLexicalStructureItems() { - var items = this.languageService.getNavigationBarItems(this.activeFile.fileName); - var length = items && items.length; + let items = this.languageService.getNavigationBarItems(this.activeFile.fileName); + let length = items && items.length; Harness.IO.log('NavigationItems list (' + length + ' items)'); - for (var i = 0; i < length; i++) { - var item = items[i]; + for (let i = 0; i < length; i++) { + let item = items[i]; Harness.IO.log('name: ' + item.text + ', kind: ' + item.kind); } } @@ -2124,14 +2126,14 @@ module FourSlash { public verifyOccurrencesAtPositionListContains(fileName: string, start: number, end: number, isWriteAccess?: boolean) { this.taoInvalidReason = 'verifyOccurrencesAtPositionListContains NYI'; - var occurances = this.getOccurancesAtCurrentPosition(); + let occurances = this.getOccurancesAtCurrentPosition(); if (!occurances || occurances.length === 0) { this.raiseError('verifyOccurancesAtPositionListContains failed - found 0 references, expected at least one.'); } - for (var i = 0; i < occurances.length; i++) { - var occurance = occurances[i]; + for (let i = 0; i < occurances.length; i++) { + let occurance = occurances[i]; if (occurance && occurance.fileName === fileName && occurance.textSpan.start === start && ts.textSpanEnd(occurance.textSpan) === end) { if (typeof isWriteAccess !== "undefined" && occurance.isWriteAccess !== isWriteAccess) { this.raiseError('verifyOccurancesAtPositionListContains failed - item isWriteAccess value doe not match, actual: ' + occurance.isWriteAccess + ', expected: ' + isWriteAccess + '.'); @@ -2140,15 +2142,15 @@ module FourSlash { } } - var missingItem = { fileName: fileName, start: start, end: end, isWriteAccess: isWriteAccess }; + let missingItem = { fileName: fileName, start: start, end: end, isWriteAccess: isWriteAccess }; this.raiseError('verifyOccurancesAtPositionListContains failed - could not find the item: ' + JSON.stringify(missingItem) + ' in the returned list: (' + JSON.stringify(occurances) + ')'); } public verifyOccurrencesAtPositionListCount(expectedCount: number) { this.taoInvalidReason = 'verifyOccurrencesAtPositionListCount NYI'; - var occurances = this.getOccurancesAtCurrentPosition(); - var actualCount = occurances ? occurances.length : 0; + let occurances = this.getOccurancesAtCurrentPosition(); + let actualCount = occurances ? occurances.length : 0; if (expectedCount !== actualCount) { this.raiseError('verifyOccurrencesAtPositionListCount failed - actual: ' + actualCount + ', expected:' + expectedCount); } @@ -2156,13 +2158,13 @@ module FourSlash { // Get the text of the entire line the caret is currently at private getCurrentLineContent() { - var text = this.getFileContent(this.activeFile.fileName) + let text = this.getFileContent(this.activeFile.fileName); - var pos = this.currentCaretPosition; - var startPos = pos, endPos = pos; + let pos = this.currentCaretPosition; + let startPos = pos, endPos = pos; while (startPos > 0) { - var ch = text.charCodeAt(startPos - 1); + let ch = text.charCodeAt(startPos - 1); if (ch === ts.CharacterCodes.carriageReturn || ch === ts.CharacterCodes.lineFeed) { break; } @@ -2171,7 +2173,7 @@ module FourSlash { } while (endPos < text.length) { - var ch = text.charCodeAt(endPos); + let ch = text.charCodeAt(endPos); if (ch === ts.CharacterCodes.carriageReturn || ch === ts.CharacterCodes.lineFeed) { break; @@ -2191,11 +2193,11 @@ module FourSlash { this.taoInvalidReason = 'assertItemInCompletionList only supports the "name" parameter'; } - for (var i = 0; i < items.length; i++) { - var item = items[i]; + for (let i = 0; i < items.length; i++) { + let item = items[i]; if (item.name === name) { if (documentation != undefined || text !== undefined) { - var details = this.getCompletionEntryDetails(item.name); + let details = this.getCompletionEntryDetails(item.name); if (documentation !== undefined) { assert.equal(ts.displayPartsToString(details.documentation), documentation, assertionMessage("completion item documentation")); @@ -2213,30 +2215,30 @@ module FourSlash { } } - var itemsString = items.map((item) => JSON.stringify({ name: item.name, kind: item.kind })).join(",\n"); + let itemsString = items.map((item) => JSON.stringify({ name: item.name, kind: item.kind })).join(",\n"); this.raiseError('Expected "' + JSON.stringify({ name, text, documentation, kind }) + '" to be in list [' + itemsString + ']'); } private findFile(indexOrName: any) { - var result: FourSlashFile = null; + let result: FourSlashFile = null; if (typeof indexOrName === 'number') { - var index = indexOrName; + let index = indexOrName; if (index >= this.testData.files.length) { throw new Error('File index (' + index + ') in openFile was out of range. There are only ' + this.testData.files.length + ' files in this test.'); } else { result = this.testData.files[index]; } } else if (typeof indexOrName === 'string') { - var name = indexOrName; + let name = indexOrName; // names are stored in the compiler with this relative path, this allows people to use goTo.file on just the fileName name = name.indexOf('/') === -1 ? (this.basePath + '/' + name) : name; - var availableNames: string[] = []; - var foundIt = false; - for (var i = 0; i < this.testData.files.length; i++) { - var fn = this.testData.files[i].fileName; + let availableNames: string[] = []; + let foundIt = false; + for (let i = 0; i < this.testData.files.length; i++) { + let fn = this.testData.files[i].fileName; if (fn) { if (fn === name) { result = this.testData.files[i]; @@ -2258,15 +2260,15 @@ module FourSlash { } private getLineColStringAtPosition(position: number) { - var pos = this.languageServiceAdapterHost.positionToLineAndCharacter(this.activeFile.fileName, position); + let pos = this.languageServiceAdapterHost.positionToLineAndCharacter(this.activeFile.fileName, position); return 'line ' + (pos.line + 1) + ', col ' + pos.character; } private getMarkerByName(markerName: string) { - var markerPos = this.testData.markerPositions[markerName]; + let markerPos = this.testData.markerPositions[markerName]; if (markerPos === undefined) { - var markerNames: string[] = []; - for (var m in this.testData.markerPositions) markerNames.push(m); + let markerNames: string[] = []; + for (let m in this.testData.markerPositions) markerNames.push(m); throw new Error('Unknown marker "' + markerName + '" Available markers: ' + markerNames.map(m => '"' + m + '"').join(', ')); } else { return markerPos; @@ -2286,7 +2288,7 @@ module FourSlash { } public setCancelled(numberOfCalls: number): void { - this.cancellationToken.setCancelled(numberOfCalls) + this.cancellationToken.setCancelled(numberOfCalls); } public resetCancelled(): void { @@ -2295,12 +2297,12 @@ module FourSlash { } // TOOD: should these just use the Harness's stdout/stderr? - var fsOutput = new Harness.Compiler.WriterAggregator(); - var fsErrors = new Harness.Compiler.WriterAggregator(); - export var xmlData: TestXmlData[] = []; + let fsOutput = new Harness.Compiler.WriterAggregator(); + let fsErrors = new Harness.Compiler.WriterAggregator(); + export let xmlData: TestXmlData[] = []; export function runFourSlashTest(basePath: string, testType: FourSlashTestType, fileName: string) { - var content = Harness.IO.readFile(fileName); - var xml = runFourSlashTestContent(basePath, testType, content, fileName); + let content = Harness.IO.readFile(fileName); + let xml = runFourSlashTestContent(basePath, testType, content, fileName); xmlData.push(xml); } @@ -2365,8 +2367,8 @@ module FourSlash { } function chompLeadingSpace(content: string) { - var lines = content.split("\n"); - for (var i = 0; i < lines.length; i++) { + let lines = content.split("\n"); + for (let i = 0; i < lines.length; i++) { if ((lines[i].length !== 0) && (lines[i].charAt(0) !== ' ')) { return content; } @@ -2377,31 +2379,31 @@ module FourSlash { function parseTestData(basePath: string, contents: string, fileName: string): FourSlashData { // Regex for parsing options in the format "@Alpha: Value of any sort" - var optionRegex = /^\s*@(\w+): (.*)\s*/; + let optionRegex = /^\s*@(\w+): (.*)\s*/; // List of all the subfiles we've parsed out - var files: FourSlashFile[] = []; + let files: FourSlashFile[] = []; // Global options - var globalOptions: { [s: string]: string; } = {}; + let globalOptions: { [s: string]: string; } = {}; // Marker positions // Split up the input file by line // Note: IE JS engine incorrectly handles consecutive delimiters here when using RegExp split, so // we have to string-based splitting instead and try to figure out the delimiting chars - var lines = contents.split('\n'); + let lines = contents.split('\n'); - var markerPositions: MarkerMap = {}; - var markers: Marker[] = []; - var ranges: Range[] = []; + let markerPositions: MarkerMap = {}; + let markers: Marker[] = []; + let ranges: Range[] = []; // Stuff related to the subfile we're parsing - var currentFileContent: string = null; - var currentFileName = fileName; - var currentFileOptions: { [s: string]: string } = {}; + let currentFileContent: string = null; + let currentFileName = fileName; + let currentFileOptions: { [s: string]: string } = {}; - for (var i = 0; i < lines.length; i++) { - var line = lines[i]; - var lineLength = line.length; + for (let i = 0; i < lines.length; i++) { + let line = lines[i]; + let lineLength = line.length; if (lineLength > 0 && line.charAt(lineLength - 1) === '\r') { line = line.substr(0, lineLength - 1); @@ -2421,17 +2423,17 @@ module FourSlash { currentFileContent = currentFileContent + line.substr(4); } else if (line.substr(0, 2) === '//') { // Comment line, check for global/file @options and record them - var match = optionRegex.exec(line.substr(2)); + let match = optionRegex.exec(line.substr(2)); if (match) { - var globalMetadataNamesIndex = globalMetadataNames.indexOf(match[1]); - var fileMetadataNamesIndex = fileMetadataNames.indexOf(match[1]); + let globalMetadataNamesIndex = globalMetadataNames.indexOf(match[1]); + let fileMetadataNamesIndex = fileMetadataNames.indexOf(match[1]); if (globalMetadataNamesIndex === -1) { if (fileMetadataNamesIndex === -1) { throw new Error('Unrecognized metadata name "' + match[1] + '". Available global metadata names are: ' + globalMetadataNames.join(', ') + '; file metadata names are: ' + fileMetadataNames.join(', ')); } else if (fileMetadataNamesIndex === fileMetadataNames.indexOf(metadataOptionNames.fileName)) { // Found an @FileName directive, if this is not the first then create a new subfile if (currentFileContent) { - var file = parseFileContent(currentFileContent, currentFileName, markerPositions, markers, ranges); + let file = parseFileContent(currentFileContent, currentFileName, markerPositions, markers, ranges); file.fileOptions = currentFileOptions; // Store result file @@ -2464,7 +2466,7 @@ module FourSlash { } else { // Empty line or code line, terminate current subfile if there is one if (currentFileContent) { - var file = parseFileContent(currentFileContent, currentFileName, markerPositions, markers, ranges); + let file = parseFileContent(currentFileContent, currentFileName, markerPositions, markers, ranges); file.fileOptions = currentFileOptions; // Store result file @@ -2494,12 +2496,12 @@ module FourSlash { } function reportError(fileName: string, line: number, col: number, message: string) { - var errorMessage = fileName + "(" + line + "," + col + "): " + message; + let errorMessage = fileName + "(" + line + "," + col + "): " + message; throw new Error(errorMessage); } function recordObjectMarker(fileName: string, location: ILocationInformation, text: string, markerMap: MarkerMap, markers: Marker[]): Marker { - var markerValue: any = undefined; + let markerValue: any = undefined; try { // Attempt to parse the marker value as JSON markerValue = JSON.parse("{ " + text + " }"); @@ -2512,7 +2514,7 @@ module FourSlash { return null; } - var marker: Marker = { + let marker: Marker = { fileName: fileName, position: location.position, data: markerValue @@ -2529,14 +2531,14 @@ module FourSlash { } function recordMarker(fileName: string, location: ILocationInformation, name: string, markerMap: MarkerMap, markers: Marker[]): Marker { - var marker: Marker = { + let marker: Marker = { fileName: fileName, position: location.position }; // Verify markers for uniqueness if (markerMap[name] !== undefined) { - var message = "Marker '" + name + "' is duplicated in the source file contents."; + let message = "Marker '" + name + "' is duplicated in the source file contents."; reportError(marker.fileName, location.sourceLine, location.sourceColumn, message); return null; } else { @@ -2550,34 +2552,34 @@ module FourSlash { content = chompLeadingSpace(content); // Any slash-star comment with a character not in this string is not a marker. - var validMarkerChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz$1234567890_'; + let validMarkerChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz$1234567890_'; /// The file content (minus metacharacters) so far - var output: string = ""; + let output: string = ""; /// The current marker (or maybe multi-line comment?) we're parsing, possibly - var openMarker: ILocationInformation = null; + let openMarker: ILocationInformation = null; /// A stack of the open range markers that are still unclosed - var openRanges: IRangeLocationInformation[] = []; + let openRanges: IRangeLocationInformation[] = []; /// A list of ranges we've collected so far */ - var localRanges: Range[] = []; + let localRanges: Range[] = []; /// The latest position of the start of an unflushed plain text area - var lastNormalCharPosition: number = 0; + let lastNormalCharPosition: number = 0; /// The total number of metacharacters removed from the file (so far) - var difference: number = 0; + let difference: number = 0; /// The fourslash file state object we are generating - var state: State = State.none; + let state: State = State.none; /// Current position data - var line: number = 1; - var column: number = 1; + let line: number = 1; + let column: number = 1; - var flush = (lastSafeCharIndex: number) => { + let flush = (lastSafeCharIndex: number) => { if (lastSafeCharIndex === undefined) { output = output + content.substr(lastNormalCharPosition); } else { @@ -2586,9 +2588,9 @@ module FourSlash { }; if (content.length > 0) { - var previousChar = content.charAt(0); - for (var i = 1; i < content.length; i++) { - var currentChar = content.charAt(i); + let previousChar = content.charAt(0); + for (let i = 1; i < content.length; i++) { + let currentChar = content.charAt(i); switch (state) { case State.none: if (previousChar === "[" && currentChar === "|") { @@ -2605,12 +2607,12 @@ module FourSlash { difference += 2; } else if (previousChar === "|" && currentChar === "]") { // found a range end - var rangeStart = openRanges.pop(); + let rangeStart = openRanges.pop(); if (!rangeStart) { reportError(fileName, line, column, "Found range end with no matching start."); } - var range: Range = { + let range: Range = { fileName: fileName, start: rangeStart.position, end: (i - 1) - difference, @@ -2648,8 +2650,8 @@ module FourSlash { // Object markers are only ever terminated by |} and have no content restrictions if (previousChar === "|" && currentChar === "}") { // Record the marker - var objectMarkerNameText = content.substring(openMarker.sourcePosition + 2, i - 1).trim(); - var marker = recordObjectMarker(fileName, openMarker, objectMarkerNameText, markerMap, markers); + let objectMarkerNameText = content.substring(openMarker.sourcePosition + 2, i - 1).trim(); + let marker = recordObjectMarker(fileName, openMarker, objectMarkerNameText, markerMap, markers); if (openRanges.length > 0) { openRanges[openRanges.length - 1].marker = marker; @@ -2669,8 +2671,8 @@ module FourSlash { if (previousChar === "*" && currentChar === "/") { // Record the marker // start + 2 to ignore the */, -1 on the end to ignore the * (/ is next) - var markerNameText = content.substring(openMarker.sourcePosition + 2, i - 1).trim(); - var marker = recordMarker(fileName, openMarker, markerNameText, markerMap, markers); + let markerNameText = content.substring(openMarker.sourcePosition + 2, i - 1).trim(); + let marker = recordMarker(fileName, openMarker, markerNameText, markerMap, markers); if (openRanges.length > 0) { openRanges[openRanges.length - 1].marker = marker; @@ -2718,7 +2720,7 @@ module FourSlash { flush(undefined); if (openRanges.length > 0) { - var openRange = openRanges[0]; + let openRange = openRanges[0]; reportError(fileName, openRange.sourceLine, openRange.sourceColumn, "Unterminated range."); } diff --git a/src/harness/fourslashRunner.ts b/src/harness/fourslashRunner.ts index 0db01c30f32..05a11c4f52d 100644 --- a/src/harness/fourslashRunner.ts +++ b/src/harness/fourslashRunner.ts @@ -2,7 +2,7 @@ /// /// -const enum FourSlashTestType { +const enum FourSlashTestType { Native, Shims, Server @@ -35,70 +35,72 @@ class FourSlashRunner extends RunnerBase { this.tests = this.enumerateFiles(this.basePath, /\.ts/i, { recursive: false }); } - this.tests.forEach((fn: string) => { - describe(fn, () => { - fn = ts.normalizeSlashes(fn); - var justName = fn.replace(/^.*[\\\/]/, ''); + describe(this.testSuiteName + ' tests', () => { + this.tests.forEach((fn: string) => { + describe(fn, () => { + fn = ts.normalizeSlashes(fn); + let justName = fn.replace(/^.*[\\\/]/, ''); - // Convert to relative path - var testIndex = fn.indexOf('tests/'); - if (testIndex >= 0) fn = fn.substr(testIndex); + // Convert to relative path + let testIndex = fn.indexOf('tests/'); + if (testIndex >= 0) fn = fn.substr(testIndex); - if (justName && !justName.match(/fourslash\.ts$/i) && !justName.match(/\.d\.ts$/i)) { - it(this.testSuiteName + ' test ' + justName + ' runs correctly', () => { - FourSlash.runFourSlashTest(this.basePath, this.testType, fn); - }); - } + if (justName && !justName.match(/fourslash\.ts$/i) && !justName.match(/\.d\.ts$/i)) { + it(this.testSuiteName + ' test ' + justName + ' runs correctly', () => { + FourSlash.runFourSlashTest(this.basePath, this.testType, fn); + }); + } + }); }); - }); - describe('Generate Tao XML', () => { - var invalidReasons: any = {}; - FourSlash.xmlData.forEach(xml => { - if (xml.invalidReason !== null) { - invalidReasons[xml.invalidReason] = (invalidReasons[xml.invalidReason] || 0) + 1; + describe('Generate Tao XML', () => { + let invalidReasons: any = {}; + FourSlash.xmlData.forEach(xml => { + if (xml.invalidReason !== null) { + invalidReasons[xml.invalidReason] = (invalidReasons[xml.invalidReason] || 0) + 1; + } + }); + let invalidReport: { reason: string; count: number }[] = []; + for (let reason in invalidReasons) { + if (invalidReasons.hasOwnProperty(reason)) { + invalidReport.push({ reason: reason, count: invalidReasons[reason] }); + } } - }); - var invalidReport: { reason: string; count: number }[] = []; - for (var reason in invalidReasons) { - if (invalidReasons.hasOwnProperty(reason)) { - invalidReport.push({ reason: reason, count: invalidReasons[reason] }); - } - } - invalidReport.sort((lhs, rhs) => lhs.count > rhs.count ? -1 : lhs.count === rhs.count ? 0 : 1); + invalidReport.sort((lhs, rhs) => lhs.count > rhs.count ? -1 : lhs.count === rhs.count ? 0 : 1); - var lines: string[] = []; - lines.push(''); + lines.push(''); + lines.push(' '); + lines.push(' '); + lines.push(' '); + lines.push(' '); + FourSlash.xmlData.forEach(xml => { + if (xml.invalidReason !== null) { + lines.push(''); + } else { + lines.push(' '); + xml.actions.forEach(action => { + lines.push(' ' + action); + }); + lines.push(' '); + } + }); + lines.push(' '); + lines.push(' '); + lines.push(' '); + lines.push(' '); + lines.push(' '); + lines.push(' '); + lines.push(' '); + lines.push(' '); + lines.push(''); + Harness.IO.writeFile('built/local/fourslash.xml', lines.join('\r\n')); }); - lines.push('-->'); - lines.push(''); - lines.push(' '); - lines.push(' '); - lines.push(' '); - lines.push(' '); - FourSlash.xmlData.forEach(xml => { - if (xml.invalidReason !== null) { - lines.push(''); - } else { - lines.push(' '); - xml.actions.forEach(action => { - lines.push(' ' + action); - }); - lines.push(' '); - } - }); - lines.push(' '); - lines.push(' '); - lines.push(' '); - lines.push(' '); - lines.push(' '); - lines.push(' '); - lines.push(' '); - lines.push(' '); - lines.push(''); - Harness.IO.writeFile('built/local/fourslash.xml', lines.join('\r\n')); }); } } @@ -108,4 +110,4 @@ class GeneratedFourslashRunner extends FourSlashRunner { super(testType); this.basePath += '/generated/'; } -} \ No newline at end of file +} diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 9f26887ff90..17aa0dd325c 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -33,8 +33,6 @@ declare var __dirname: string; // Node-specific var global = Function("return this").call(null); module Utils { - var global = Function("return this").call(null); - // Setup some globals based on the current environment export const enum ExecutionEnvironment { Node, @@ -54,17 +52,17 @@ module Utils { } } - export var currentExecutionEnvironment = getExecutionEnvironment(); + export let currentExecutionEnvironment = getExecutionEnvironment(); export function evalFile(fileContents: string, fileName: string, nodeContext?: any) { - var environment = getExecutionEnvironment(); + let environment = getExecutionEnvironment(); switch (environment) { case ExecutionEnvironment.CScript: case ExecutionEnvironment.Browser: eval(fileContents); break; case ExecutionEnvironment.Node: - var vm = require('vm'); + let vm = require('vm'); if (nodeContext) { vm.runInNewContext(fileContents, nodeContext, fileName); } else { @@ -81,7 +79,7 @@ module Utils { // Split up the input file by line // Note: IE JS engine incorrectly handles consecutive delimiters here when using RegExp split, so // we have to use string-based splitting instead and try to figure out the delimiting chars - var lines = content.split('\r\n'); + let lines = content.split('\r\n'); if (lines.length === 1) { lines = content.split('\n'); @@ -98,8 +96,9 @@ module Utils { path = "tests/" + path; } + let content: string = undefined; try { - var content = ts.sys.readFile(Harness.userSpecifiedRoot + path); + content = ts.sys.readFile(Harness.userSpecifiedRoot + path); } catch (err) { return undefined; @@ -109,11 +108,11 @@ module Utils { } export function memoize(f: T): T { - var cache: { [idx: string]: any } = {}; + let cache: { [idx: string]: any } = {}; return (function () { - var key = Array.prototype.join.call(arguments); - var cachedResult = cache[key]; + let key = Array.prototype.join.call(arguments); + let cachedResult = cache[key]; if (cachedResult) { return cachedResult; } else { @@ -140,7 +139,7 @@ module Utils { }); // Make sure each of the children is in order. - var currentPos = 0; + let currentPos = 0; ts.forEachChild(node, child => { assert.isFalse(child.pos < currentPos, "child.pos < currentPos"); @@ -151,22 +150,22 @@ module Utils { assert.isFalse(array.end > node.end, "array.end > node.end"); assert.isFalse(array.pos < currentPos, "array.pos < currentPos"); - for (var i = 0, n = array.length; i < n; i++) { + for (let i = 0, n = array.length; i < n; i++) { assert.isFalse(array[i].pos < currentPos, "array[i].pos < currentPos"); - currentPos = array[i].end + currentPos = array[i].end; } currentPos = array.end; }); - var childNodesAndArrays: any[] = []; - ts.forEachChild(node, child => { childNodesAndArrays.push(child) }, array => { childNodesAndArrays.push(array) }); + let childNodesAndArrays: any[] = []; + ts.forEachChild(node, child => { childNodesAndArrays.push(child); }, array => { childNodesAndArrays.push(array); }); - for (var childName in node) { + for (let childName in node) { if (childName === "parent" || childName === "nextContainer" || childName === "modifiers" || childName === "externalModuleIndicator") { continue; } - var child = (node)[childName]; + let child = (node)[childName]; if (isNodeOrArray(child)) { assert.isFalse(childNodesAndArrays.indexOf(child) < 0, "Missing child when forEach'ing over node: " + (ts).SyntaxKind[node.kind] + "-" + childName); @@ -194,7 +193,7 @@ module Utils { } export function sourceFileToJSON(file: ts.Node): string { - return JSON.stringify(file,(k, v) => { + return JSON.stringify(file, (k, v) => { return isNodeOrArray(v) ? serializeNode(v) : v; }, " "); @@ -203,7 +202,7 @@ module Utils { return k; } - return (ts).SyntaxKind[k] + return (ts).SyntaxKind[k]; } function getFlagName(flags: any, f: number): any { @@ -211,7 +210,7 @@ module Utils { return 0; } - var result = ""; + let result = ""; ts.forEach(Object.getOwnPropertyNames(flags), (v: any) => { if (isFinite(v)) { v = +v; @@ -234,7 +233,7 @@ module Utils { function getParserContextFlagName(f: number) { return getFlagName((ts).ParserContextFlags, f); } function serializeNode(n: ts.Node): any { - var o: any = { kind: getKindName(n.kind) }; + let o: any = { kind: getKindName(n.kind) }; if (ts.containsParseError(n)) { o.containsParseError = true; } @@ -268,7 +267,7 @@ module Utils { // Clear the flag that are produced by aggregating child values.. That is ephemeral // data we don't care about in the dump. We only care what the parser set directly // on the ast. - var value = n.parserContextFlags & ts.ParserContextFlags.ParserGeneratedFlags; + let value = n.parserContextFlags & ts.ParserContextFlags.ParserGeneratedFlags; if (value) { o[propertyName] = getParserContextFlagName(value); } @@ -313,9 +312,9 @@ module Utils { assert.equal(array1.length, array2.length, "array1.length !== array2.length"); - for (var i = 0, n = array1.length; i < n; i++) { - var d1 = array1[i]; - var d2 = array2[i]; + for (let i = 0, n = array1.length; i < n; i++) { + let d1 = array1[i]; + let d2 = array2[i]; assert.equal(d1.start, d2.start, "d1.start !== d2.start"); assert.equal(d1.length, d2.length, "d1.length !== d2.length"); @@ -346,14 +345,14 @@ module Utils { ts.forEachChild(node1, child1 => { - var childName = findChildName(node1, child1); - var child2: ts.Node = (node2)[childName]; + let childName = findChildName(node1, child1); + let child2: ts.Node = (node2)[childName]; assertStructuralEquals(child1, child2); }, (array1: ts.NodeArray) => { - var childName = findChildName(node1, array1); - var array2: ts.NodeArray = (node2)[childName]; + let childName = findChildName(node1, array1); + let array2: ts.NodeArray = (node2)[childName]; assertArrayStructuralEquals(array1, array2); }); @@ -370,13 +369,13 @@ module Utils { assert.equal(array1.end, array2.end, "array1.end !== array2.end"); assert.equal(array1.length, array2.length, "array1.length !== array2.length"); - for (var i = 0, n = array1.length; i < n; i++) { + for (let i = 0, n = array1.length; i < n; i++) { assertStructuralEquals(array1[i], array2[i]); } } function findChildName(parent: any, child: any) { - for (var name in parent) { + for (let name in parent) { if (parent.hasOwnProperty(name) && parent[name] === child) { return name; } @@ -393,8 +392,8 @@ module Harness.Path { export function filePath(fullPath: string) { fullPath = ts.normalizeSlashes(fullPath); - var components = fullPath.split("/"); - var path: string[] = components.slice(0, components.length - 1); + let components = fullPath.split("/"); + let path: string[] = components.slice(0, components.length - 1); return path.join("/") + "/"; } } @@ -422,19 +421,19 @@ module Harness { } export module CScript { - var fso: any; + let fso: any; if (global.ActiveXObject) { fso = new global.ActiveXObject("Scripting.FileSystemObject"); } else { fso = {}; } - export var readFile: typeof IO.readFile = ts.sys.readFile; - export var writeFile: typeof IO.writeFile = ts.sys.writeFile; - export var directoryName: typeof IO.directoryName = fso.GetParentFolderName; - export var directoryExists: typeof IO.directoryExists = fso.FolderExists; - export var fileExists: typeof IO.fileExists = fso.FileExists; - export var log: typeof IO.log = global.WScript && global.WScript.StdOut.WriteLine; + export let readFile: typeof IO.readFile = ts.sys.readFile; + export let writeFile: typeof IO.writeFile = ts.sys.writeFile; + export let directoryName: typeof IO.directoryName = fso.GetParentFolderName; + export let directoryExists: typeof IO.directoryExists = fso.FolderExists; + export let fileExists: typeof IO.fileExists = fso.FileExists; + export let log: typeof IO.log = global.WScript && global.WScript.StdOut.WriteLine; export function createDirectory(path: string) { if (directoryExists(path)) { @@ -448,11 +447,11 @@ module Harness { } } - export var listFiles: typeof IO.listFiles = (path, spec?, options?) => { + export let listFiles: typeof IO.listFiles = (path, spec?, options?) => { options = options || <{ recursive?: boolean; }>{}; function filesInFolder(folder: any, root: string): string[] { - var paths: string[] = []; - var fc: any; + let paths: string[] = []; + let fc: any; if (options.recursive) { fc = new Enumerator(folder.subfolders); @@ -473,17 +472,16 @@ module Harness { return paths; } - var folder: any = fso.GetFolder(path); - var paths: string[] = []; + let folder: any = fso.GetFolder(path); + let paths: string[] = []; return filesInFolder(folder, path); - - } + }; } export module Node { - declare var require: any; - var fs: any, pathModule: any; + declare let require: any; + let fs: any, pathModule: any; if (require) { fs = require('fs'); pathModule = require('path'); @@ -491,10 +489,10 @@ module Harness { fs = pathModule = {}; } - export var readFile: typeof IO.readFile = ts.sys.readFile; - export var writeFile: typeof IO.writeFile = ts.sys.writeFile; - export var fileExists: typeof IO.fileExists = fs.existsSync; - export var log: typeof IO.log = console.log; + export let readFile: typeof IO.readFile = ts.sys.readFile; + export let writeFile: typeof IO.writeFile = ts.sys.writeFile; + export let fileExists: typeof IO.fileExists = fs.existsSync; + export let log: typeof IO.log = console.log; export function createDirectory(path: string) { if (!directoryExists(path)) { @@ -514,7 +512,7 @@ module Harness { } export function directoryName(path: string) { - var dirPath = pathModule.dirname(path); + let dirPath = pathModule.dirname(path); // Node will just continue to repeat the root path, rather than return null if (dirPath === path) { @@ -524,16 +522,16 @@ module Harness { } } - export var listFiles: typeof IO.listFiles = (path, spec?, options?) => { + export let listFiles: typeof IO.listFiles = (path, spec?, options?) => { options = options || <{ recursive?: boolean; }>{}; function filesInFolder(folder: string): string[] { - var paths: string[] = []; + let paths: string[] = []; - var files = fs.readdirSync(folder); - for (var i = 0; i < files.length; i++) { - var pathToFile = pathModule.join(folder, files[i]); - var stat = fs.statSync(pathToFile); + let files = fs.readdirSync(folder); + for (let i = 0; i < files.length; i++) { + let pathToFile = pathModule.join(folder, files[i]); + let stat = fs.statSync(pathToFile); if (options.recursive && stat.isDirectory()) { paths = paths.concat(filesInFolder(pathToFile)); } @@ -546,23 +544,23 @@ module Harness { } return filesInFolder(path); - } + }; - export var getMemoryUsage: typeof IO.getMemoryUsage = () => { + export let getMemoryUsage: typeof IO.getMemoryUsage = () => { if (global.gc) { global.gc(); } return process.memoryUsage().heapUsed; - } + }; } export module Network { - var serverRoot = "http://localhost:8888/"; + let serverRoot = "http://localhost:8888/"; // Unused? - var newLine = '\r\n'; - var currentDirectory = () => ''; - var supportsCodePage = () => false; + let newLine = '\r\n'; + let currentDirectory = () => ''; + let supportsCodePage = () => false; module Http { function waitForXHR(xhr: XMLHttpRequest) { @@ -572,7 +570,7 @@ module Harness { /// Ask the server to use node's path.resolve to resolve the given path function getResolvedPathFromServer(path: string) { - var xhr = new XMLHttpRequest(); + let xhr = new XMLHttpRequest(); try { xhr.open("GET", path + "?resolve", false); xhr.send(); @@ -591,7 +589,7 @@ module Harness { /// Ask the server for the contents of the file at the given URL via a simple GET request export function getFileFromServerSync(url: string): XHRResponse { - var xhr = new XMLHttpRequest(); + let xhr = new XMLHttpRequest(); try { xhr.open("GET", url, false); xhr.send(); @@ -605,10 +603,10 @@ module Harness { /// Submit a POST request to the server to do the given action (ex WRITE, DELETE) on the provided URL export function writeToServerSync(url: string, action: string, contents?: string): XHRResponse { - var xhr = new XMLHttpRequest(); + let xhr = new XMLHttpRequest(); try { - var action = '?action=' + action; - xhr.open('POST', url + action, false); + let actionMsg = '?action=' + action; + xhr.open('POST', url + actionMsg, false); xhr.setRequestHeader('Access-Control-Allow-Origin', '*'); xhr.send(contents); } @@ -633,7 +631,7 @@ module Harness { } function directoryNameImpl(path: string) { - var dirPath = path; + let dirPath = path; // root of the server if (dirPath.match(/localhost:\d+$/) || dirPath.match(/localhost:\d+\/$/)) { dirPath = null; @@ -646,22 +644,22 @@ module Harness { if (dirPath.match(/.*\/$/)) { dirPath = dirPath.substring(0, dirPath.length - 2); } - var dirPath = dirPath.substring(0, dirPath.lastIndexOf('/')); + dirPath = dirPath.substring(0, dirPath.lastIndexOf('/')); } return dirPath; } - export var directoryName: typeof IO.directoryName = Utils.memoize(directoryNameImpl); + export let directoryName: typeof IO.directoryName = Utils.memoize(directoryNameImpl); export function fileExists(path: string): boolean { - var response = Http.getFileFromServerSync(serverRoot + path); + let response = Http.getFileFromServerSync(serverRoot + path); return response.status === 200; } export function _listFilesImpl(path: string, spec?: RegExp, options?: any) { - var response = Http.getFileFromServerSync(serverRoot + path); + let response = Http.getFileFromServerSync(serverRoot + path); if (response.status === 200) { - var results = response.responseText.split(','); + let results = response.responseText.split(','); if (spec) { return results.filter(file => spec.test(file)); } else { @@ -672,12 +670,12 @@ module Harness { return ['']; } }; - export var listFiles = Utils.memoize(_listFilesImpl); + export let listFiles = Utils.memoize(_listFilesImpl); - export var log = console.log; + export let log = console.log; export function readFile(file: string) { - var response = Http.getFileFromServerSync(serverRoot + file); + let response = Http.getFileFromServerSync(serverRoot + file); if (response.status === 200) { return response.responseText; } else { @@ -706,9 +704,9 @@ module Harness { } module Harness { - var tcServicesFileName = "typescriptServices.js"; + let tcServicesFileName = "typescriptServices.js"; - export var libFolder: string; + export let libFolder: string; switch (Utils.getExecutionEnvironment()) { case Utils.ExecutionEnvironment.CScript: libFolder = "built/local/"; @@ -725,7 +723,7 @@ module Harness { default: throw new Error('Unknown context'); } - export var tcServicesFile = IO.readFile(tcServicesFileName); + export let tcServicesFile = IO.readFile(tcServicesFileName); export interface SourceMapEmitterCallback { (emittedFile: string, emittedLine: number, emittedColumn: number, sourceFile: string, sourceLine: number, sourceColumn: number, sourceName: string): void; @@ -777,7 +775,7 @@ module Harness { /** create file gets the whole path to create, so this works as expected with the --out parameter */ public writeFile(s: string, contents: string, writeByteOrderMark: boolean): void { - var writer: ITextWriter; + let writer: ITextWriter; if (this.fileCollection[s]) { writer = this.fileCollection[s]; } @@ -795,10 +793,10 @@ module Harness { public reset() { this.fileCollection = {}; } public toArray(): { fileName: string; file: WriterAggregator; }[] { - var result: { fileName: string; file: WriterAggregator; }[] = []; - for (var p in this.fileCollection) { + let result: { fileName: string; file: WriterAggregator; }[] = []; + for (let p in this.fileCollection) { if (this.fileCollection.hasOwnProperty(p)) { - var current = this.fileCollection[p]; + let current = this.fileCollection[p]; if (current.lines.length > 0) { if (p.indexOf('.d.ts') !== -1) { current.lines.unshift(['////[', Path.getFileName(p), ']'].join('')); } result.push({ fileName: p, file: this.fileCollection[p] }); @@ -813,11 +811,11 @@ module Harness { fileName: string, sourceText: string, languageVersion: ts.ScriptTarget) { - // We'll only assert invariants outside of light mode. + // We'll only assert inletiants outside of light mode. const shouldAssertInvariants = !Harness.lightMode; - // Only set the parent nodes if we're asserting invariants. We don't need them otherwise. - var result = ts.createSourceFile(fileName, sourceText, languageVersion, /*setParentNodes:*/ shouldAssertInvariants); + // Only set the parent nodes if we're asserting inletiants. We don't need them otherwise. + let result = ts.createSourceFile(fileName, sourceText, languageVersion, /*setParentNodes:*/ shouldAssertInvariants); if (shouldAssertInvariants) { Utils.assertInvariants(result, /*parent:*/ undefined); @@ -829,13 +827,13 @@ module Harness { const carriageReturnLineFeed = "\r\n"; const lineFeed = "\n"; - export var defaultLibFileName = 'lib.d.ts'; - export var defaultLibSourceFile = createSourceFileAndAssertInvariants(defaultLibFileName, IO.readFile(libFolder + 'lib.core.d.ts'), /*languageVersion*/ ts.ScriptTarget.Latest); - export var defaultES6LibSourceFile = createSourceFileAndAssertInvariants(defaultLibFileName, IO.readFile(libFolder + 'lib.core.es6.d.ts'), /*languageVersion*/ ts.ScriptTarget.Latest); + export let defaultLibFileName = 'lib.d.ts'; + export let defaultLibSourceFile = createSourceFileAndAssertInvariants(defaultLibFileName, IO.readFile(libFolder + 'lib.core.d.ts'), /*languageVersion*/ ts.ScriptTarget.Latest); + export let defaultES6LibSourceFile = createSourceFileAndAssertInvariants(defaultLibFileName, IO.readFile(libFolder + 'lib.core.es6.d.ts'), /*languageVersion*/ ts.ScriptTarget.Latest); // Cache these between executions so we don't have to re-parse them for every test - export var fourslashFileName = 'fourslash.ts'; - export var fourslashSourceFile: ts.SourceFile; + export let fourslashFileName = 'fourslash.ts'; + export let fourslashSourceFile: ts.SourceFile; export function getCanonicalFileName(fileName: string): string { return ts.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(); @@ -855,13 +853,13 @@ module Harness { return useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(); } - var filemap: { [fileName: string]: ts.SourceFile; } = {}; - var getCurrentDirectory = currentDirectory === undefined ? ts.sys.getCurrentDirectory : () => currentDirectory; + let filemap: { [fileName: string]: ts.SourceFile; } = {}; + let getCurrentDirectory = currentDirectory === undefined ? ts.sys.getCurrentDirectory : () => currentDirectory; // Register input files function register(file: { unitName: string; content: string; }) { if (file.content !== undefined) { - var fileName = ts.normalizePath(file.unitName); + let fileName = ts.normalizePath(file.unitName); filemap[getCanonicalFileName(fileName)] = createSourceFileAndAssertInvariants(fileName, file.content, scriptTarget); } }; @@ -880,11 +878,11 @@ module Harness { return filemap[getCanonicalFileName(fn)]; } else if (currentDirectory) { - var canonicalAbsolutePath = getCanonicalFileName(ts.getNormalizedAbsolutePath(fn, currentDirectory)); + let canonicalAbsolutePath = getCanonicalFileName(ts.getNormalizedAbsolutePath(fn, currentDirectory)); return Object.prototype.hasOwnProperty.call(filemap, getCanonicalFileName(canonicalAbsolutePath)) ? filemap[canonicalAbsolutePath] : undefined; } else if (fn === fourslashFileName) { - var tsFn = 'tests/cases/fourslash/' + fourslashFileName; + let tsFn = 'tests/cases/fourslash/' + fourslashFileName; fourslashSourceFile = fourslashSourceFile || createSourceFileAndAssertInvariants(tsFn, Harness.IO.readFile(tsFn), scriptTarget); return fourslashSourceFile; } @@ -980,27 +978,27 @@ module Harness { // Files from built\local that are requested by test "@includeBuiltFiles" to be in the context. // Treat them as library files, so include them in build, but not in baselines. - var includeBuiltFiles: { unitName: string; content: string }[] = []; + let includeBuiltFiles: { unitName: string; content: string }[] = []; - var useCaseSensitiveFileNames = ts.sys.useCaseSensitiveFileNames; + let useCaseSensitiveFileNames = ts.sys.useCaseSensitiveFileNames; this.settings.forEach(setCompilerOptionForSetting); - var fileOutputs: GeneratedFile[] = []; + let fileOutputs: GeneratedFile[] = []; - var programFiles = inputFiles.concat(includeBuiltFiles).map(file => file.unitName); + let programFiles = inputFiles.concat(includeBuiltFiles).map(file => file.unitName); - var compilerHost = createCompilerHost( + let compilerHost = createCompilerHost( inputFiles.concat(includeBuiltFiles).concat(otherFiles), (fn, contents, writeByteOrderMark) => fileOutputs.push({ fileName: fn, code: contents, writeByteOrderMark: writeByteOrderMark }), options.target, useCaseSensitiveFileNames, currentDirectory, options.newLine); - var program = ts.createProgram(programFiles, options, compilerHost); + let program = ts.createProgram(programFiles, options, compilerHost); - var emitResult = program.emit(); + let emitResult = program.emit(); - var errors = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics); + let errors = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics); this.lastErrors = errors; - var result = new CompilerResult(fileOutputs, errors, program, ts.sys.getCurrentDirectory(), emitResult.sourceMaps); + let result = new CompilerResult(fileOutputs, errors, program, ts.sys.getCurrentDirectory(), emitResult.sourceMaps); onComplete(result, program); // reset what newline means in case the last test changed it @@ -1193,12 +1191,12 @@ module Harness { throw new Error('There were no errors and declFiles generated did not match number of js files generated'); } + let declInputFiles: { unitName: string; content: string }[] = []; + let declOtherFiles: { unitName: string; content: string }[] = []; + let declResult: Harness.Compiler.CompilerResult; + // if the .d.ts is non-empty, confirm it compiles correctly as well if (options.declaration && result.errors.length === 0 && result.declFilesCode.length > 0) { - var declInputFiles: { unitName: string; content: string }[] = []; - var declOtherFiles: { unitName: string; content: string }[] = []; - var declResult: Harness.Compiler.CompilerResult; - ts.forEach(inputFiles, file => addDtsFile(file, declInputFiles)); ts.forEach(otherFiles, file => addDtsFile(file, declOtherFiles)); this.compileFiles(declInputFiles, declOtherFiles, function (compileResult) { declResult = compileResult; }, @@ -1212,20 +1210,20 @@ module Harness { dtsFiles.push(file); } else if (isTS(file.unitName)) { - var declFile = findResultCodeFile(file.unitName); + let declFile = findResultCodeFile(file.unitName); if (!findUnit(declFile.fileName, declInputFiles) && !findUnit(declFile.fileName, declOtherFiles)) { dtsFiles.push({ unitName: declFile.fileName, content: declFile.code }); } } function findResultCodeFile(fileName: string) { - var sourceFile = result.program.getSourceFile(fileName); + let sourceFile = result.program.getSourceFile(fileName); assert(sourceFile, "Program has no source file with name '" + fileName + "'"); // Is this file going to be emitted separately - var sourceFileName: string; + let sourceFileName: string; if (ts.isExternalModule(sourceFile) || !options.out) { if (options.outDir) { - var sourceFilePath = ts.getNormalizedAbsolutePath(sourceFile.fileName, result.currentDirectoryForProgram); + let sourceFilePath = ts.getNormalizedAbsolutePath(sourceFile.fileName, result.currentDirectoryForProgram); sourceFilePath = sourceFilePath.replace(result.program.getCommonSourceDirectory(), ""); sourceFileName = ts.combinePaths(options.outDir, sourceFilePath); } @@ -1238,7 +1236,7 @@ module Harness { sourceFileName = options.out; } - var dTsFileName = ts.removeFileExtension(sourceFileName) + ".d.ts"; + let dTsFileName = ts.removeFileExtension(sourceFileName) + ".d.ts"; return ts.forEach(result.declFilesCode, declFile => declFile.fileName === dTsFileName ? declFile : undefined); } @@ -1251,7 +1249,7 @@ module Harness { } function normalizeLineEndings(text: string, lineEnding: string): string { - var normalized = text.replace(/\r\n?/g, '\n'); + let normalized = text.replace(/\r\n?/g, '\n'); if (lineEnding !== '\n') { normalized = normalized.replace(/\n/g, lineEnding); } @@ -1260,10 +1258,10 @@ module Harness { export function minimalDiagnosticsToString(diagnostics: ts.Diagnostic[]) { // This is basically copied from tsc.ts's reportError to replicate what tsc does - var errorOutput = ""; + let errorOutput = ""; ts.forEach(diagnostics, diagnostic => { if (diagnostic.file) { - var lineAndCharacter = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start); + let lineAndCharacter = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start); errorOutput += diagnostic.file.fileName + "(" + (lineAndCharacter.line + 1) + "," + (lineAndCharacter.character + 1) + "): "; } @@ -1275,14 +1273,14 @@ module Harness { export function getErrorBaseline(inputFiles: { unitName: string; content: string }[], diagnostics: ts.Diagnostic[]) { diagnostics.sort(ts.compareDiagnostics); - var outputLines: string[] = []; + let outputLines: string[] = []; // Count up all the errors we find so we don't miss any - var totalErrorsReported = 0; + let totalErrorsReported = 0; function outputErrorText(error: ts.Diagnostic) { - var message = ts.flattenDiagnosticMessageText(error.messageText, ts.sys.newLine); + let message = ts.flattenDiagnosticMessageText(error.messageText, ts.sys.newLine); - var errLines = RunnerBase.removeFullPaths(message) + let errLines = RunnerBase.removeFullPaths(message) .split('\n') .map(s => s.length > 0 && s.charAt(s.length - 1) === '\r' ? s.substr(0, s.length - 1) : s) .filter(s => s.length > 0) @@ -1293,14 +1291,14 @@ module Harness { } // Report global errors - var globalErrors = diagnostics.filter(err => !err.file); + let globalErrors = diagnostics.filter(err => !err.file); globalErrors.forEach(outputErrorText); // 'merge' the lines of each input file with any errors associated with it inputFiles.filter(f => f.content !== undefined).forEach(inputFile => { // Filter down to the errors in the file - var fileErrors = diagnostics.filter(e => { - var errFn = e.file; + let fileErrors = diagnostics.filter(e => { + let errFn = e.file; return errFn && errFn.fileName === inputFile.unitName; }); @@ -1309,13 +1307,13 @@ module Harness { outputLines.push('==== ' + inputFile.unitName + ' (' + fileErrors.length + ' errors) ===='); // Make sure we emit something for every error - var markedErrorCount = 0; + let markedErrorCount = 0; // For each line, emit the line followed by any error squiggles matching this line // Note: IE JS engine incorrectly handles consecutive delimiters here when using RegExp split, so // we have to string-based splitting instead and try to figure out the delimiting chars - var lineStarts = ts.computeLineStarts(inputFile.content); - var lines = inputFile.content.split('\n'); + let lineStarts = ts.computeLineStarts(inputFile.content); + let lines = inputFile.content.split('\n'); if (lines.length === 1) { lines = lines[0].split("\r"); } @@ -1325,8 +1323,8 @@ module Harness { line = line.substr(0, line.length - 1); } - var thisLineStart = lineStarts[lineIndex]; - var nextLineStart: number; + let thisLineStart = lineStarts[lineIndex]; + let nextLineStart: number; // On the last line of the file, fake the next line start number so that we handle errors on the last character of the file correctly if (lineIndex === lines.length - 1) { nextLineStart = inputFile.content.length; @@ -1340,11 +1338,11 @@ module Harness { let end = ts.textSpanEnd(err); if ((end >= thisLineStart) && ((err.start < nextLineStart) || (lineIndex === lines.length - 1))) { // How many characters from the start of this line the error starts at (could be positive or negative) - var relativeOffset = err.start - thisLineStart; + let relativeOffset = err.start - thisLineStart; // How many characters of the error are on this line (might be longer than this line in reality) - var length = (end - err.start) - Math.max(0, thisLineStart - err.start); + let length = (end - err.start) - Math.max(0, thisLineStart - err.start); // Calculate the start of the squiggle - var squiggleStart = Math.max(0, relativeOffset); + let squiggleStart = Math.max(0, relativeOffset); // TODO/REVIEW: this doesn't work quite right in the browser if a multi file test has files whose names are just the right length relative to one another outputLines.push(' ' + line.substr(0, squiggleStart).replace(/[^\s]/g, ' ') + new Array(Math.min(length, line.length - squiggleStart) + 1).join('~')); @@ -1364,11 +1362,11 @@ module Harness { assert.equal(markedErrorCount, fileErrors.length, 'count of errors in ' + inputFile.unitName); }); - var numLibraryDiagnostics = ts.countWhere(diagnostics, diagnostic => { + let numLibraryDiagnostics = ts.countWhere(diagnostics, diagnostic => { return diagnostic.file && (isLibraryFile(diagnostic.file.fileName) || isBuiltFile(diagnostic.file.fileName)); }); - var numTest262HarnessDiagnostics = ts.countWhere(diagnostics, diagnostic => { + let numTest262HarnessDiagnostics = ts.countWhere(diagnostics, diagnostic => { // Count an error generated from tests262-harness folder.This should only apply for test262 return diagnostic.file && diagnostic.file.fileName.indexOf("test262-harness") >= 0; }); @@ -1385,7 +1383,7 @@ module Harness { outputFiles.sort((a, b) => cleanName(a.fileName).localeCompare(cleanName(b.fileName))); // Emit them - var result = ''; + let result = ''; for (let outputFile of outputFiles) { // Some extra spacing if this isn't the first file if (result.length) { @@ -1401,13 +1399,13 @@ module Harness { return result; function cleanName(fn: string) { - var lastSlash = ts.normalizeSlashes(fn).lastIndexOf('/'); + let lastSlash = ts.normalizeSlashes(fn).lastIndexOf('/'); return fn.substr(lastSlash + 1).toLowerCase(); } } /** The harness' compiler instance used when tests are actually run. Reseting or changing settings of this compiler instance must be done within a test case (i.e., describe/it) */ - var harnessCompiler: HarnessCompiler; + let harnessCompiler: HarnessCompiler; /** Returns the singleton harness compiler instance for generating and running tests. If required a fresh compiler instance will be created, otherwise the existing singleton will be re-used. @@ -1420,8 +1418,6 @@ module Harness { export function compileString(code: string, unitName: string, callback: (result: CompilerResult) => void) { // NEWTODO: Re-implement 'compileString' throw new Error('compileString NYI'); - //var harnessCompiler = Harness.Compiler.getCompiler(Harness.Compiler.CompilerInstance.RunTime); - //harnessCompiler.compileString(code, unitName, callback); } export interface GeneratedFile { @@ -1513,10 +1509,10 @@ module Harness { } // Regex for parsing options in the format "@Alpha: Value of any sort" - var optionRegex = /^[\/]{2}\s*@(\w+)\s*:\s*(\S*)/gm; // multiple matches on multiple lines + let optionRegex = /^[\/]{2}\s*@(\w+)\s*:\s*(\S*)/gm; // multiple matches on multiple lines // List of allowed metadata names - var fileMetadataNames = ["filename", "comments", "declaration", "module", + let fileMetadataNames = ["filename", "comments", "declaration", "module", "nolib", "sourcemap", "target", "out", "outdir", "noemithelpers", "noemitonerror", "noimplicitany", "noresolve", "newline", "normalizenewline", "emitbom", "errortruncation", "usecasesensitivefilenames", "preserveconstenums", @@ -1527,9 +1523,9 @@ module Harness { function extractCompilerSettings(content: string): CompilerSetting[] { - var opts: CompilerSetting[] = []; + let opts: CompilerSetting[] = []; - var match: RegExpExecArray; + let match: RegExpExecArray; while ((match = optionRegex.exec(content)) != null) { opts.push({ flag: match[1], value: match[2] }); } @@ -1539,26 +1535,26 @@ module Harness { /** Given a test file containing // @FileName directives, return an array of named units of code to be added to an existing compiler instance */ export function makeUnitsFromTest(code: string, fileName: string): { settings: CompilerSetting[]; testUnitData: TestUnitData[]; } { - var settings = extractCompilerSettings(code); + let settings = extractCompilerSettings(code); // List of all the subfiles we've parsed out - var testUnitData: TestUnitData[] = []; + let testUnitData: TestUnitData[] = []; - var lines = Utils.splitContentByNewlines(code); + let lines = Utils.splitContentByNewlines(code); // Stuff related to the subfile we're parsing - var currentFileContent: string = null; - var currentFileOptions: any = {}; - var currentFileName: any = null; - var refs: string[] = []; + let currentFileContent: string = null; + let currentFileOptions: any = {}; + let currentFileName: any = null; + let refs: string[] = []; - for (var i = 0; i < lines.length; i++) { - var line = lines[i]; - var testMetaData = optionRegex.exec(line); + for (let i = 0; i < lines.length; i++) { + let line = lines[i]; + let testMetaData = optionRegex.exec(line); if (testMetaData) { // Comment line, check for global/file @options and record them optionRegex.lastIndex = 0; - var metaDataName = testMetaData[1].toLowerCase(); + let metaDataName = testMetaData[1].toLowerCase(); if (metaDataName === "filename") { currentFileOptions[testMetaData[1]] = testMetaData[2]; } else { @@ -1568,8 +1564,7 @@ module Harness { // New metadata statement after having collected some code to go with the previous metadata if (currentFileName) { // Store result file - var newTestFile = - { + let newTestFile = { content: currentFileContent, name: currentFileName, fileOptions: currentFileOptions, @@ -1604,7 +1599,7 @@ module Harness { currentFileName = testUnitData.length > 0 ? currentFileName : Path.getFileName(fileName); // EOF, push whatever remains - var newTestFile2 = { + let newTestFile2 = { content: currentFileContent || '', name: currentFileName, fileOptions: currentFileOptions, @@ -1651,7 +1646,7 @@ module Harness { } } - var fileCache: { [idx: string]: boolean } = {}; + let fileCache: { [idx: string]: boolean } = {}; function generateActual(actualFileName: string, generateContent: () => string): string { // For now this is written using TypeScript, because sys is not available when running old test cases. // But we need to move to sys once we have @@ -1662,7 +1657,7 @@ module Harness { return; } - var parentDirectory = IO.directoryName(dirName); + let parentDirectory = IO.directoryName(dirName); if (parentDirectory != "") { createDirectoryStructure(parentDirectory); } @@ -1678,7 +1673,7 @@ module Harness { IO.deleteFile(actualFileName); } - var actual = generateContent(); + let actual = generateContent(); if (actual === undefined) { throw new Error('The generated content was "undefined". Return "null" if no baselining is required."'); @@ -1701,13 +1696,13 @@ module Harness { return; } - var refFileName = referencePath(relativeFileName, opts && opts.Baselinefolder, opts && opts.Subfolder); + let refFileName = referencePath(relativeFileName, opts && opts.Baselinefolder, opts && opts.Subfolder); if (actual === null) { actual = ''; } - var expected = ''; + let expected = ''; if (IO.fileExists(refFileName)) { expected = IO.readFile(refFileName); } @@ -1716,10 +1711,10 @@ module Harness { } function writeComparison(expected: string, actual: string, relativeFileName: string, actualFileName: string, descriptionForDescribe: string) { - var encoded_actual = (new Buffer(actual)).toString('utf8') + let encoded_actual = (new Buffer(actual)).toString('utf8'); if (expected != encoded_actual) { // Overwrite & issue error - var errMsg = 'The baseline file ' + relativeFileName + ' has changed'; + let errMsg = 'The baseline file ' + relativeFileName + ' has changed'; throw new Error(errMsg); } } @@ -1731,17 +1726,17 @@ module Harness { runImmediately = false, opts?: BaselineOptions): void { - var actual = undefined; - var actualFileName = localPath(relativeFileName, opts && opts.Baselinefolder, opts && opts.Subfolder); + let actual = undefined; + let actualFileName = localPath(relativeFileName, opts && opts.Baselinefolder, opts && opts.Subfolder); if (runImmediately) { actual = generateActual(actualFileName, generateContent); - var comparison = compareToBaseline(actual, relativeFileName, opts); + let comparison = compareToBaseline(actual, relativeFileName, opts); writeComparison(comparison.expected, comparison.actual, relativeFileName, actualFileName, descriptionForDescribe); } else { actual = generateActual(actualFileName, generateContent); - var comparison = compareToBaseline(actual, relativeFileName, opts); + let comparison = compareToBaseline(actual, relativeFileName, opts); writeComparison(comparison.expected, comparison.actual, relativeFileName, actualFileName, descriptionForDescribe); } } @@ -1756,11 +1751,11 @@ module Harness { } export function getDefaultLibraryFile(): { unitName: string, content: string } { - var libFile = Harness.userSpecifiedRoot + Harness.libFolder + "/" + "lib.d.ts"; + let libFile = Harness.userSpecifiedRoot + Harness.libFolder + "/" + "lib.d.ts"; return { unitName: libFile, content: IO.readFile(libFile) - } + }; } if (Error) (Error).stackTraceLimit = 1; diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index 6cb92df5948..3c543e50566 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -26,9 +26,9 @@ module Harness.LanguageService { public editContent(start: number, end: number, newText: string): void { // Apply edits - var prefix = this.content.substring(0, start); - var middle = newText; - var suffix = this.content.substring(end); + let prefix = this.content.substring(0, start); + let middle = newText; + let suffix = this.content.substring(end); this.setContent(prefix + middle + suffix); // Store edit range + new length of script @@ -48,10 +48,10 @@ module Harness.LanguageService { return ts.unchangedTextChangeRange; } - var initialEditRangeIndex = this.editRanges.length - (this.version - startVersion); - var lastEditRangeIndex = this.editRanges.length - (this.version - endVersion); + let initialEditRangeIndex = this.editRanges.length - (this.version - startVersion); + let lastEditRangeIndex = this.editRanges.length - (this.version - endVersion); - var entries = this.editRanges.slice(initialEditRangeIndex, lastEditRangeIndex); + let entries = this.editRanges.slice(initialEditRangeIndex, lastEditRangeIndex); return ts.collapseTextChangeRangesAcrossMultipleVersions(entries.map(e => e.textChangeRange)); } } @@ -74,7 +74,7 @@ module Harness.LanguageService { } public getChangeRange(oldScript: ts.IScriptSnapshot): ts.TextChangeRange { - var oldShim = oldScript; + let oldShim = oldScript; return this.scriptInfo.getTextChangeRangeBetweenVersions(oldShim.version, this.version); } } @@ -92,9 +92,9 @@ module Harness.LanguageService { } public getChangeRange(oldScript: ts.ScriptSnapshotShim): string { - var oldShim = oldScript; + let oldShim = oldScript; - var range = this.scriptSnapshot.getChangeRange(oldShim.scriptSnapshot); + let range = this.scriptSnapshot.getChangeRange(oldShim.scriptSnapshot); if (range === null) { return null; } @@ -130,8 +130,8 @@ module Harness.LanguageService { } public getFilenames(): string[] { - var fileNames: string[] = []; - ts.forEachKey(this.fileNameToScript,(fileName) => { fileNames.push(fileName); }); + let fileNames: string[] = []; + ts.forEachKey(this.fileNameToScript, (fileName) => { fileNames.push(fileName); }); return fileNames; } @@ -144,7 +144,7 @@ module Harness.LanguageService { } public editScript(fileName: string, start: number, end: number, newText: string) { - var script = this.getScriptInfo(fileName); + let script = this.getScriptInfo(fileName); if (script !== null) { script.editContent(start, end, newText); return; @@ -161,7 +161,7 @@ module Harness.LanguageService { * @param col 0 based index */ public positionToLineAndCharacter(fileName: string, position: number): ts.LineAndCharacter { - var script: ScriptInfo = this.fileNameToScript[fileName]; + let script: ScriptInfo = this.fileNameToScript[fileName]; assert.isNotNull(script); return ts.computeLineAndCharacterOfPosition(script.lineMap, position); @@ -176,11 +176,11 @@ module Harness.LanguageService { getDefaultLibFileName(): string { return ""; } getScriptFileNames(): string[] { return this.getFilenames(); } getScriptSnapshot(fileName: string): ts.IScriptSnapshot { - var script = this.getScriptInfo(fileName); + let script = this.getScriptInfo(fileName); return script ? new ScriptSnapshot(script) : undefined; } getScriptVersion(fileName: string): string { - var script = this.getScriptInfo(fileName); + let script = this.getScriptInfo(fileName); return script ? script.version.toString() : undefined; } @@ -220,7 +220,7 @@ module Harness.LanguageService { getDefaultLibFileName(): string { return this.nativeHost.getDefaultLibFileName(); } getScriptFileNames(): string { return JSON.stringify(this.nativeHost.getScriptFileNames()); } getScriptSnapshot(fileName: string): ts.ScriptSnapshotShim { - var nativeScriptSnapshot = this.nativeHost.getScriptSnapshot(fileName); + let nativeScriptSnapshot = this.nativeHost.getScriptSnapshot(fileName); return nativeScriptSnapshot && new ScriptSnapshotProxy(nativeScriptSnapshot); } getScriptVersion(fileName: string): string { return this.nativeHost.getScriptVersion(fileName); } @@ -242,13 +242,13 @@ module Harness.LanguageService { throw new Error("NYI"); } getClassificationsForLine(text: string, lexState: ts.EndOfLineState, classifyKeywordsInGenerics?: boolean): ts.ClassificationResult { - var result = this.shim.getClassificationsForLine(text, lexState, classifyKeywordsInGenerics).split('\n'); - var entries: ts.ClassificationInfo[] = []; - var i = 0; - var position = 0; + let result = this.shim.getClassificationsForLine(text, lexState, classifyKeywordsInGenerics).split('\n'); + let entries: ts.ClassificationInfo[] = []; + let i = 0; + let position = 0; for (; i < result.length - 1; i += 2) { - var t = entries[i / 2] = { + let t = entries[i / 2] = { length: parseInt(result[i]), classification: parseInt(result[i + 1]) }; @@ -256,7 +256,7 @@ module Harness.LanguageService { assert.isTrue(t.length > 0, "Result length should be greater than 0, got :" + t.length); position += t.length; } - var finalLexState = parseInt(result[result.length - 1]); + let finalLexState = parseInt(result[result.length - 1]); assert.equal(position, text.length, "Expected cumulative length of all entries to match the length of the source. expected: " + text.length + ", but got: " + position); @@ -268,7 +268,7 @@ module Harness.LanguageService { } function unwrapJSONCallResult(result: string): any { - var parsedResult = JSON.parse(result); + let parsedResult = JSON.parse(result); if (parsedResult.error) { throw new Error("Language Service Shim Error: " + JSON.stringify(parsedResult.error)); } @@ -282,7 +282,7 @@ module Harness.LanguageService { constructor(private shim: ts.LanguageServiceShim) { } private unwrappJSONCallResult(result: string): any { - var parsedResult = JSON.parse(result); + let parsedResult = JSON.parse(result); if (parsedResult.error) { throw new Error("Language Service Shim Error: " + JSON.stringify(parsedResult.error)); } @@ -404,16 +404,16 @@ module Harness.LanguageService { getLanguageService(): ts.LanguageService { return new LanguageServiceShimProxy(this.factory.createLanguageServiceShim(this.host)); } getClassifier(): ts.Classifier { return new ClassifierShimProxy(this.factory.createClassifierShim(this.host)); } getPreProcessedFileInfo(fileName: string, fileContents: string): ts.PreProcessedFileInfo { - var shimResult: { + let shimResult: { referencedFiles: ts.IFileReference[]; importedFiles: ts.IFileReference[]; isLibFile: boolean; }; - var coreServicesShim = this.factory.createCoreServicesShim(this.host); + let coreServicesShim = this.factory.createCoreServicesShim(this.host); shimResult = unwrapJSONCallResult(coreServicesShim.getPreProcessedFileInfo(fileName, ts.ScriptSnapshot.fromString(fileContents))); - var convertResult: ts.PreProcessedFileInfo = { + let convertResult: ts.PreProcessedFileInfo = { referencedFiles: [], importedFiles: [], isLibFile: shimResult.isLibFile @@ -496,7 +496,7 @@ module Harness.LanguageService { fileName = Harness.Compiler.defaultLibFileName; } - var snapshot = this.host.getScriptSnapshot(fileName); + let snapshot = this.host.getScriptSnapshot(fileName); return snapshot && snapshot.getText(0, snapshot.getLength()); } @@ -574,13 +574,13 @@ module Harness.LanguageService { private client: ts.server.SessionClient; constructor(cancellationToken?: ts.HostCancellationToken, options?: ts.CompilerOptions) { // This is the main host that tests use to direct tests - var clientHost = new SessionClientHost(cancellationToken, options); - var client = new ts.server.SessionClient(clientHost); + let clientHost = new SessionClientHost(cancellationToken, options); + let client = new ts.server.SessionClient(clientHost); // This host is just a proxy for the clientHost, it uses the client // host to answer server queries about files on disk - var serverHost = new SessionServerHost(clientHost); - var server = new ts.server.Session(serverHost, Buffer.byteLength, process.hrtime, serverHost); + let serverHost = new SessionServerHost(clientHost); + let server = new ts.server.Session(serverHost, Buffer.byteLength, process.hrtime, serverHost); // Fake the connection between the client and the server serverHost.writeMessage = client.onMessage.bind(client); diff --git a/src/harness/loggedIO.ts b/src/harness/loggedIO.ts index 8ba38043e78..0ce567e9563 100644 --- a/src/harness/loggedIO.ts +++ b/src/harness/loggedIO.ts @@ -70,9 +70,9 @@ interface PlaybackControl { } module Playback { - var recordLog: IOLog = undefined; - var replayLog: IOLog = undefined; - var recordLogFileNameBase = ''; + let recordLog: IOLog = undefined; + let replayLog: IOLog = undefined; + let recordLogFileNameBase = ''; interface Memoized { (s: string): T; @@ -80,8 +80,8 @@ module Playback { } function memoize(func: (s: string) => T): Memoized { - var lookup: { [s: string]: T } = {}; - var run: Memoized = >((s: string) => { + let lookup: { [s: string]: T } = {}; + let run: Memoized = >((s: string) => { if (lookup.hasOwnProperty(s)) return lookup[s]; return lookup[s] = func(s); }); @@ -161,10 +161,10 @@ module Playback { } function findResultByFields(logArray: { result?: T }[], expectedFields: {}, defaultValue?: T): T { - var predicate = (entry: { result?: T }) => { + let predicate = (entry: { result?: T }) => { return Object.getOwnPropertyNames(expectedFields).every((name) => (entry)[name] === (expectedFields)[name]); }; - var results = logArray.filter(entry => predicate(entry)); + let results = logArray.filter(entry => predicate(entry)); if (results.length === 0) { if (defaultValue !== undefined) { return defaultValue; @@ -176,17 +176,17 @@ module Playback { } function findResultByPath(wrapper: { resolvePath(s: string): string }, logArray: { path: string; result?: T }[], expectedPath: string, defaultValue?: T): T { - var normalizedName = ts.normalizeSlashes(expectedPath).toLowerCase(); + let normalizedName = ts.normalizeSlashes(expectedPath).toLowerCase(); // Try to find the result through normal fileName - for (var i = 0; i < logArray.length; i++) { + for (let i = 0; i < logArray.length; i++) { if (ts.normalizeSlashes(logArray[i].path).toLowerCase() === normalizedName) { return logArray[i].result; } } // Fallback, try to resolve the target paths as well if (replayLog.pathsResolved.length > 0) { - var normalizedResolvedName = wrapper.resolvePath(expectedPath).toLowerCase(); - for (var i = 0; i < logArray.length; i++) { + let normalizedResolvedName = wrapper.resolvePath(expectedPath).toLowerCase(); + for (let i = 0; i < logArray.length; i++) { if (wrapper.resolvePath(logArray[i].path).toLowerCase() === normalizedResolvedName) { return logArray[i].result; } @@ -200,9 +200,9 @@ module Playback { } } - var pathEquivCache: any = {}; + let pathEquivCache: any = {}; function pathsAreEquivalent(left: string, right: string, wrapper: { resolvePath(s: string): string }) { - var key = left + '-~~-' + right; + let key = left + '-~~-' + right; function areSame(a: string, b: string) { return ts.normalizeSlashes(a).toLowerCase() === ts.normalizeSlashes(b).toLowerCase(); } @@ -219,11 +219,11 @@ module Playback { } function noOpReplay(name: string) { - //console.log("Swallowed write operation during replay: " + name); + // console.log("Swallowed write operation during replay: " + name); } export function wrapSystem(underlying: ts.System): PlaybackSystem { - var wrapper: PlaybackSystem = {}; + let wrapper: PlaybackSystem = {}; initWrapper(wrapper, underlying); wrapper.startReplayFromFile = logFn => { @@ -231,8 +231,8 @@ module Playback { }; wrapper.endRecord = () => { if (recordLog !== undefined) { - var i = 0; - var fn = () => recordLogFileNameBase + i + '.json'; + let i = 0; + let fn = () => recordLogFileNameBase + i + '.json'; while (underlying.fileExists(fn())) i++; underlying.writeFile(fn(), JSON.stringify(recordLog)); recordLog = undefined; @@ -289,8 +289,8 @@ module Playback { wrapper.readFile = recordReplay(wrapper.readFile, underlying)( (path) => { - var result = underlying.readFile(path); - var logEntry = { path: path, codepage: 0, result: { contents: result, codepage: 0 } }; + let result = underlying.readFile(path); + let logEntry = { path: path, codepage: 0, result: { contents: result, codepage: 0 } }; recordLog.filesRead.push(logEntry); return result; }, diff --git a/src/harness/projectsRunner.ts b/src/harness/projectsRunner.ts index 5eb0016ff8d..5ea118aacbf 100644 --- a/src/harness/projectsRunner.ts +++ b/src/harness/projectsRunner.ts @@ -46,7 +46,7 @@ interface BatchCompileProjectTestCaseResult extends CompileProjectFilesResult { class ProjectRunner extends RunnerBase { public initializeTests() { if (this.tests.length === 0) { - var testFiles = this.enumerateFiles("tests/cases/project", /\.json$/, { recursive: true }); + let testFiles = this.enumerateFiles("tests/cases/project", /\.json$/, { recursive: true }); testFiles.forEach(fn => { fn = fn.replace(/\\/g, "/"); this.runProjectTestCase(fn); @@ -58,10 +58,11 @@ class ProjectRunner extends RunnerBase { } private runProjectTestCase(testCaseFileName: string) { - var testCase: ProjectRunnerTestCase; + let testCase: ProjectRunnerTestCase; + let testFileText: string = null; try { - var testFileText = ts.sys.readFile(testCaseFileName); + testFileText = ts.sys.readFile(testCaseFileName); } catch (e) { assert(false, "Unable to open testcase file: " + testCaseFileName + ": " + e.message); @@ -73,7 +74,7 @@ class ProjectRunner extends RunnerBase { catch (e) { assert(false, "Testcase: " + testCaseFileName + " does not contain valid json format: " + e.message); } - var testCaseJustName = testCaseFileName.replace(/^.*[\\\/]/, '').replace(/\.json/, ""); + let testCaseJustName = testCaseFileName.replace(/^.*[\\\/]/, '').replace(/\.json/, ""); function moduleNameToString(moduleKind: ts.ModuleKind) { return moduleKind === ts.ModuleKind.AMD @@ -89,7 +90,7 @@ class ProjectRunner extends RunnerBase { } // When test case output goes to tests/baselines/local/projectOutput/testCaseName/moduleKind/ - // We have these two separate locations because when comparing baselines the baseline verifier will delete the existing file + // We have these two separate locations because when comparing baselines the baseline verifier will delete the existing file // so even if it was created by compiler in that location, the file will be deleted by verified before we can read it // so lets keep these two locations separate function getProjectOutputFolder(fileName: string, moduleKind: ts.ModuleKind) { @@ -97,9 +98,9 @@ class ProjectRunner extends RunnerBase { } function cleanProjectUrl(url: string) { - var diskProjectPath = ts.normalizeSlashes(ts.sys.resolvePath(testCase.projectRoot)); - var projectRootUrl = "file:///" + diskProjectPath; - var normalizedProjectRoot = ts.normalizeSlashes(testCase.projectRoot); + let diskProjectPath = ts.normalizeSlashes(ts.sys.resolvePath(testCase.projectRoot)); + let projectRootUrl = "file:///" + diskProjectPath; + let normalizedProjectRoot = ts.normalizeSlashes(testCase.projectRoot); diskProjectPath = diskProjectPath.substr(0, diskProjectPath.lastIndexOf(normalizedProjectRoot)); projectRootUrl = projectRootUrl.substr(0, projectRootUrl.lastIndexOf(normalizedProjectRoot)); if (url && url.length) { @@ -124,21 +125,21 @@ class ProjectRunner extends RunnerBase { return ts.sys.resolvePath(testCase.projectRoot); } - function compileProjectFiles(moduleKind: ts.ModuleKind, getInputFiles: ()=> string[], + function compileProjectFiles(moduleKind: ts.ModuleKind, getInputFiles: () => string[], getSourceFileText: (fileName: string) => string, writeFile: (fileName: string, data: string, writeByteOrderMark: boolean) => void): CompileProjectFilesResult { - var program = ts.createProgram(getInputFiles(), createCompilerOptions(), createCompilerHost()); - var errors = ts.getPreEmitDiagnostics(program); + let program = ts.createProgram(getInputFiles(), createCompilerOptions(), createCompilerHost()); + let errors = ts.getPreEmitDiagnostics(program); - var emitResult = program.emit(); + let emitResult = program.emit(); errors = ts.concatenate(errors, emitResult.diagnostics); - var sourceMapData = emitResult.sourceMaps; + let sourceMapData = emitResult.sourceMaps; // Clean up source map data that will be used in baselining if (sourceMapData) { - for (var i = 0; i < sourceMapData.length; i++) { - for (var j = 0; j < sourceMapData[i].sourceMapSources.length; j++) { + for (let i = 0; i < sourceMapData.length; i++) { + for (let j = 0; j < sourceMapData[i].sourceMapSources.length; j++) { sourceMapData[i].sourceMapSources[j] = cleanProjectUrl(sourceMapData[i].sourceMapSources[j]); } sourceMapData[i].jsSourceMappingURL = cleanProjectUrl(sourceMapData[i].jsSourceMappingURL); @@ -168,12 +169,12 @@ class ProjectRunner extends RunnerBase { } function getSourceFile(fileName: string, languageVersion: ts.ScriptTarget): ts.SourceFile { - var sourceFile: ts.SourceFile = undefined; + let sourceFile: ts.SourceFile = undefined; if (fileName === Harness.Compiler.defaultLibFileName) { sourceFile = languageVersion === ts.ScriptTarget.ES6 ? Harness.Compiler.defaultES6LibSourceFile : Harness.Compiler.defaultLibSourceFile; } else { - var text = getSourceFileText(fileName); + let text = getSourceFileText(fileName); if (text !== undefined) { sourceFile = Harness.Compiler.createSourceFileAndAssertInvariants(fileName, text, languageVersion); } @@ -194,13 +195,13 @@ class ProjectRunner extends RunnerBase { }; } } - + function batchCompilerProjectTestCase(moduleKind: ts.ModuleKind): BatchCompileProjectTestCaseResult{ - var nonSubfolderDiskFiles = 0; + let nonSubfolderDiskFiles = 0; - var outputFiles: BatchCompileProjectTestCaseEmittedFile[] = []; + let outputFiles: BatchCompileProjectTestCaseEmittedFile[] = []; - var projectCompilerResult = compileProjectFiles(moduleKind, () => testCase.inputFiles, getSourceFileText, writeFile); + let projectCompilerResult = compileProjectFiles(moduleKind, () => testCase.inputFiles, getSourceFileText, writeFile); return { moduleKind, program: projectCompilerResult.program, @@ -211,8 +212,9 @@ class ProjectRunner extends RunnerBase { }; function getSourceFileText(fileName: string): string { + let text: string = undefined; try { - var text = ts.sys.readFile(ts.isRootedDiskPath(fileName) + text = ts.sys.readFile(ts.isRootedDiskPath(fileName) ? fileName : ts.normalizeSlashes(testCase.projectRoot) + "/" + ts.normalizeSlashes(fileName)); } @@ -223,14 +225,14 @@ class ProjectRunner extends RunnerBase { } function writeFile(fileName: string, data: string, writeByteOrderMark: boolean) { - var diskFileName = ts.isRootedDiskPath(fileName) + let diskFileName = ts.isRootedDiskPath(fileName) ? fileName : ts.normalizeSlashes(testCase.projectRoot) + "/" + ts.normalizeSlashes(fileName); - var diskRelativeName = ts.getRelativePathToDirectoryOrUrl(testCase.projectRoot, diskFileName, + let diskRelativeName = ts.getRelativePathToDirectoryOrUrl(testCase.projectRoot, diskFileName, getCurrentDirectory(), Harness.Compiler.getCanonicalFileName, /*isAbsolutePathAnUrl*/ false); if (ts.isRootedDiskPath(diskRelativeName) || diskRelativeName.substr(0, 3) === "../") { - // If the generated output file resides in the parent folder or is rooted path, + // If the generated output file resides in the parent folder or is rooted path, // we need to instead create files that can live in the project reference folder // but make sure extension of these files matches with the fileName the compiler asked to write diskRelativeName = "diskFile" + nonSubfolderDiskFiles++ + @@ -240,22 +242,22 @@ class ProjectRunner extends RunnerBase { if (Harness.Compiler.isJS(fileName)) { // Make sure if there is URl we have it cleaned up - var indexOfSourceMapUrl = data.lastIndexOf("//# sourceMappingURL="); + let indexOfSourceMapUrl = data.lastIndexOf("//# sourceMappingURL="); if (indexOfSourceMapUrl !== -1) { data = data.substring(0, indexOfSourceMapUrl + 21) + cleanProjectUrl(data.substring(indexOfSourceMapUrl + 21)); } } else if (Harness.Compiler.isJSMap(fileName)) { // Make sure sources list is cleaned - var sourceMapData = JSON.parse(data); - for (var i = 0; i < sourceMapData.sources.length; i++) { + let sourceMapData = JSON.parse(data); + for (let i = 0; i < sourceMapData.sources.length; i++) { sourceMapData.sources[i] = cleanProjectUrl(sourceMapData.sources[i]); } sourceMapData.sourceRoot = cleanProjectUrl(sourceMapData.sourceRoot); data = JSON.stringify(sourceMapData); } - var outputFilePath = getProjectOutputFolder(diskRelativeName, moduleKind); + let outputFilePath = getProjectOutputFolder(diskRelativeName, moduleKind); // Actual writing of file as in tc.ts function ensureDirectoryStructure(directoryname: string) { if (directoryname) { @@ -273,36 +275,37 @@ class ProjectRunner extends RunnerBase { } function compileCompileDTsFiles(compilerResult: BatchCompileProjectTestCaseResult) { - var allInputFiles: { emittedFileName: string; code: string; }[] = []; - var compilerOptions = compilerResult.program.getCompilerOptions(); + let allInputFiles: { emittedFileName: string; code: string; }[] = []; + let compilerOptions = compilerResult.program.getCompilerOptions(); ts.forEach(compilerResult.program.getSourceFiles(), sourceFile => { if (Harness.Compiler.isDTS(sourceFile.fileName)) { allInputFiles.unshift({ emittedFileName: sourceFile.fileName, code: sourceFile.text }); } else if (ts.shouldEmitToOwnFile(sourceFile, compilerResult.program.getCompilerOptions())) { + let emitOutputFilePathWithoutExtension: string = undefined; if (compilerOptions.outDir) { - var sourceFilePath = ts.getNormalizedAbsolutePath(sourceFile.fileName, compilerResult.program.getCurrentDirectory()); + let sourceFilePath = ts.getNormalizedAbsolutePath(sourceFile.fileName, compilerResult.program.getCurrentDirectory()); sourceFilePath = sourceFilePath.replace(compilerResult.program.getCommonSourceDirectory(), ""); - var emitOutputFilePathWithoutExtension = ts.removeFileExtension(ts.combinePaths(compilerOptions.outDir, sourceFilePath)); + emitOutputFilePathWithoutExtension = ts.removeFileExtension(ts.combinePaths(compilerOptions.outDir, sourceFilePath)); } else { - var emitOutputFilePathWithoutExtension = ts.removeFileExtension(sourceFile.fileName); + emitOutputFilePathWithoutExtension = ts.removeFileExtension(sourceFile.fileName); } - var outputDtsFileName = emitOutputFilePathWithoutExtension + ".d.ts"; + let outputDtsFileName = emitOutputFilePathWithoutExtension + ".d.ts"; allInputFiles.unshift(findOutpuDtsFile(outputDtsFileName)); } else { - var outputDtsFileName = ts.removeFileExtension(compilerOptions.out) + ".d.ts"; - var outputDtsFile = findOutpuDtsFile(outputDtsFileName); + let outputDtsFileName = ts.removeFileExtension(compilerOptions.out) + ".d.ts"; + let outputDtsFile = findOutpuDtsFile(outputDtsFileName); if (!ts.contains(allInputFiles, outputDtsFile)) { allInputFiles.unshift(outputDtsFile); } } }); - return compileProjectFiles(compilerResult.moduleKind,getInputFiles, getSourceFileText, writeFile); + return compileProjectFiles(compilerResult.moduleKind, getInputFiles, getSourceFileText, writeFile); function findOutpuDtsFile(fileName: string) { return ts.forEach(compilerResult.outputFiles, outputFile => outputFile.emittedFileName === fileName ? outputFile : undefined); @@ -319,7 +322,7 @@ class ProjectRunner extends RunnerBase { } function getErrorsBaseline(compilerResult: CompileProjectFilesResult) { - var inputFiles = ts.map(ts.filter(compilerResult.program.getSourceFiles(), + let inputFiles = ts.map(ts.filter(compilerResult.program.getSourceFiles(), sourceFile => sourceFile.fileName !== "lib.d.ts"), sourceFile => { return { unitName: sourceFile.fileName, content: sourceFile.text }; @@ -328,110 +331,112 @@ class ProjectRunner extends RunnerBase { return Harness.Compiler.getErrorBaseline(inputFiles, compilerResult.errors); } - var name = 'Compiling project for ' + testCase.scenario + ': testcase ' + testCaseFileName; + let name = 'Compiling project for ' + testCase.scenario + ': testcase ' + testCaseFileName; - describe(name, () => { - function verifyCompilerResults(moduleKind: ts.ModuleKind) { - function getCompilerResolutionInfo() { - var resolutionInfo: ProjectRunnerTestCaseResolutionInfo = { - scenario: testCase.scenario, - projectRoot: testCase.projectRoot, - inputFiles: testCase.inputFiles, - out: testCase.out, - outDir: testCase.outDir, - sourceMap: testCase.sourceMap, - mapRoot: testCase.mapRoot, - resolveMapRoot: testCase.resolveMapRoot, - sourceRoot: testCase.sourceRoot, - resolveSourceRoot: testCase.resolveSourceRoot, - declaration: testCase.declaration, - baselineCheck: testCase.baselineCheck, - runTest: testCase.runTest, - bug: testCase.bug, - rootDir: testCase.rootDir, - resolvedInputFiles: ts.map(compilerResult.program.getSourceFiles(), inputFile => inputFile.fileName), - emittedFiles: ts.map(compilerResult.outputFiles, outputFile => outputFile.emittedFileName) - }; + describe('Projects tests', () => { + describe(name, () => { + function verifyCompilerResults(moduleKind: ts.ModuleKind) { + let compilerResult: BatchCompileProjectTestCaseResult; - return resolutionInfo; - } + function getCompilerResolutionInfo() { + let resolutionInfo: ProjectRunnerTestCaseResolutionInfo = { + scenario: testCase.scenario, + projectRoot: testCase.projectRoot, + inputFiles: testCase.inputFiles, + out: testCase.out, + outDir: testCase.outDir, + sourceMap: testCase.sourceMap, + mapRoot: testCase.mapRoot, + resolveMapRoot: testCase.resolveMapRoot, + sourceRoot: testCase.sourceRoot, + resolveSourceRoot: testCase.resolveSourceRoot, + declaration: testCase.declaration, + baselineCheck: testCase.baselineCheck, + runTest: testCase.runTest, + bug: testCase.bug, + rootDir: testCase.rootDir, + resolvedInputFiles: ts.map(compilerResult.program.getSourceFiles(), inputFile => inputFile.fileName), + emittedFiles: ts.map(compilerResult.outputFiles, outputFile => outputFile.emittedFileName) + }; - var compilerResult: BatchCompileProjectTestCaseResult; + return resolutionInfo; + } - it(name + ": " + moduleNameToString(moduleKind) , () => { - // Compile using node - compilerResult = batchCompilerProjectTestCase(moduleKind); - }); - - it('Resolution information of (' + moduleNameToString(moduleKind) + '): ' + testCaseFileName, () => { - Harness.Baseline.runBaseline('Resolution information of (' + moduleNameToString(compilerResult.moduleKind) + '): ' + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + testCaseJustName + '.json', () => { - return JSON.stringify(getCompilerResolutionInfo(), undefined, " "); + it(name + ": " + moduleNameToString(moduleKind) , () => { + // Compile using node + compilerResult = batchCompilerProjectTestCase(moduleKind); }); - }); - - it('Errors for (' + moduleNameToString(moduleKind) + '): ' + testCaseFileName, () => { - if (compilerResult.errors.length) { - Harness.Baseline.runBaseline('Errors for (' + moduleNameToString(compilerResult.moduleKind) + '): ' + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + testCaseJustName + '.errors.txt', () => { - return getErrorsBaseline(compilerResult); + it('Resolution information of (' + moduleNameToString(moduleKind) + '): ' + testCaseFileName, () => { + Harness.Baseline.runBaseline('Resolution information of (' + moduleNameToString(compilerResult.moduleKind) + '): ' + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + testCaseJustName + '.json', () => { + return JSON.stringify(getCompilerResolutionInfo(), undefined, " "); }); - } - }); + }); - it('Baseline of emitted result (' + moduleNameToString(moduleKind) + '): ' + testCaseFileName, () => { - if (testCase.baselineCheck) { - ts.forEach(compilerResult.outputFiles, outputFile => { - - Harness.Baseline.runBaseline('Baseline of emitted result (' + moduleNameToString(compilerResult.moduleKind) + '): ' + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + outputFile.fileName, () => { - try { - return ts.sys.readFile(getProjectOutputFolder(outputFile.fileName, compilerResult.moduleKind)); - } - catch (e) { - return undefined; - } - }); - }); - } - }); - - - it('SourceMapRecord for (' + moduleNameToString(moduleKind) + '): ' + testCaseFileName, () => { - if (compilerResult.sourceMapData) { - Harness.Baseline.runBaseline('SourceMapRecord for (' + moduleNameToString(compilerResult.moduleKind) + '): ' + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + testCaseJustName + '.sourcemap.txt', () => { - return Harness.SourceMapRecoder.getSourceMapRecord(compilerResult.sourceMapData, compilerResult.program, - ts.filter(compilerResult.outputFiles, outputFile => Harness.Compiler.isJS(outputFile.emittedFileName))); - }); - } - }); - - // Verify that all the generated .d.ts files compile - - it('Errors in generated Dts files for (' + moduleNameToString(moduleKind) + '): ' + testCaseFileName, () => { - if (!compilerResult.errors.length && testCase.declaration) { - var dTsCompileResult = compileCompileDTsFiles(compilerResult); - if (dTsCompileResult.errors.length) { - Harness.Baseline.runBaseline('Errors in generated Dts files for (' + moduleNameToString(compilerResult.moduleKind) + '): ' + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + testCaseJustName + '.dts.errors.txt', () => { - return getErrorsBaseline(dTsCompileResult); + it('Errors for (' + moduleNameToString(moduleKind) + '): ' + testCaseFileName, () => { + if (compilerResult.errors.length) { + Harness.Baseline.runBaseline('Errors for (' + moduleNameToString(compilerResult.moduleKind) + '): ' + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + testCaseJustName + '.errors.txt', () => { + return getErrorsBaseline(compilerResult); }); } - } - }); + }); + + + it('Baseline of emitted result (' + moduleNameToString(moduleKind) + '): ' + testCaseFileName, () => { + if (testCase.baselineCheck) { + ts.forEach(compilerResult.outputFiles, outputFile => { + + Harness.Baseline.runBaseline('Baseline of emitted result (' + moduleNameToString(compilerResult.moduleKind) + '): ' + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + outputFile.fileName, () => { + try { + return ts.sys.readFile(getProjectOutputFolder(outputFile.fileName, compilerResult.moduleKind)); + } + catch (e) { + return undefined; + } + }); + }); + } + }); + + + it('SourceMapRecord for (' + moduleNameToString(moduleKind) + '): ' + testCaseFileName, () => { + if (compilerResult.sourceMapData) { + Harness.Baseline.runBaseline('SourceMapRecord for (' + moduleNameToString(compilerResult.moduleKind) + '): ' + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + testCaseJustName + '.sourcemap.txt', () => { + return Harness.SourceMapRecoder.getSourceMapRecord(compilerResult.sourceMapData, compilerResult.program, + ts.filter(compilerResult.outputFiles, outputFile => Harness.Compiler.isJS(outputFile.emittedFileName))); + }); + } + }); + + // Verify that all the generated .d.ts files compile + + it('Errors in generated Dts files for (' + moduleNameToString(moduleKind) + '): ' + testCaseFileName, () => { + if (!compilerResult.errors.length && testCase.declaration) { + let dTsCompileResult = compileCompileDTsFiles(compilerResult); + if (dTsCompileResult.errors.length) { + Harness.Baseline.runBaseline('Errors in generated Dts files for (' + moduleNameToString(compilerResult.moduleKind) + '): ' + testCaseFileName, getBaselineFolder(compilerResult.moduleKind) + testCaseJustName + '.dts.errors.txt', () => { + return getErrorsBaseline(dTsCompileResult); + }); + } + } + }); + after(() => { + compilerResult = undefined; + }); + } + + verifyCompilerResults(ts.ModuleKind.CommonJS); + verifyCompilerResults(ts.ModuleKind.AMD); + after(() => { - compilerResult = undefined; + // Mocha holds onto the closure environment of the describe callback even after the test is done. + // Therefore we have to clean out large objects after the test is done. + testCase = undefined; + testFileText = undefined; + testCaseJustName = undefined; }); - } - - verifyCompilerResults(ts.ModuleKind.CommonJS); - verifyCompilerResults(ts.ModuleKind.AMD); - - after(() => { - // Mocha holds onto the closure environment of the describe callback even after the test is done. - // Therefore we have to clean out large objects after the test is done. - testCase = undefined; - testFileText = undefined; - testCaseJustName = undefined; }); }); } -} \ No newline at end of file +} diff --git a/src/harness/runner.ts b/src/harness/runner.ts index 13d93302f18..e4ed604e980 100644 --- a/src/harness/runner.ts +++ b/src/harness/runner.ts @@ -1,6 +1,6 @@ // // Copyright (c) Microsoft Corporation. All rights reserved. -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -20,26 +20,26 @@ /// /// +let runners: RunnerBase[] = []; +let iterations: number = 1; + function runTests(runners: RunnerBase[]) { - for (var i = iterations; i > 0; i--) { - for (var j = 0; j < runners.length; j++) { + for (let i = iterations; i > 0; i--) { + for (let j = 0; j < runners.length; j++) { runners[j].initializeTests(); } } } -var runners: RunnerBase[] = []; -var iterations: number = 1; - // users can define tests to run in mytest.config that will override cmd line args, otherwise use cmd line args (test.config), otherwise no options -var mytestconfig = 'mytest.config'; -var testconfig = 'test.config'; -var testConfigFile = +let mytestconfig = 'mytest.config'; +let testconfig = 'test.config'; +let testConfigFile = Harness.IO.fileExists(mytestconfig) ? Harness.IO.readFile(mytestconfig) : (Harness.IO.fileExists(testconfig) ? Harness.IO.readFile(testconfig) : ''); if (testConfigFile !== '') { - var testConfig = JSON.parse(testConfigFile); + let testConfig = JSON.parse(testConfigFile); if (testConfig.light) { Harness.lightMode = true; } @@ -99,7 +99,7 @@ if (runners.length === 0) { runners.push(new FourSlashRunner(FourSlashTestType.Native)); runners.push(new FourSlashRunner(FourSlashTestType.Shims)); runners.push(new FourSlashRunner(FourSlashTestType.Server)); - //runners.push(new GeneratedFourslashRunner()); + // runners.push(new GeneratedFourslashRunner()); } ts.sys.newLine = '\r\n'; diff --git a/src/harness/runnerbase.ts b/src/harness/runnerbase.ts index fa8d9d2c597..66438d938dd 100644 --- a/src/harness/runnerbase.ts +++ b/src/harness/runnerbase.ts @@ -24,17 +24,17 @@ class RunnerBase { /** Replaces instances of full paths with fileNames only */ static removeFullPaths(path: string) { - var fixedPath = path; + let fixedPath = path; // full paths either start with a drive letter or / for *nix, shouldn't have \ in the path at this point - var fullPath = /(\w+:|\/)?([\w+\-\.]|\/)*\.tsx?/g; - var fullPathList = fixedPath.match(fullPath); + let fullPath = /(\w+:|\/)?([\w+\-\.]|\/)*\.tsx?/g; + let fullPathList = fixedPath.match(fullPath); if (fullPathList) { fullPathList.forEach((match: string) => fixedPath = fixedPath.replace(match, Harness.Path.getFileName(match))); } // when running in the browser the 'full path' is the host name, shows up in error baselines - var localHost = /http:\/localhost:\d+/g; + let localHost = /http:\/localhost:\d+/g; fixedPath = fixedPath.replace(localHost, ''); return fixedPath; } diff --git a/src/harness/rwcRunner.ts b/src/harness/rwcRunner.ts index 43a118b6aec..bbe80abc887 100644 --- a/src/harness/rwcRunner.ts +++ b/src/harness/rwcRunner.ts @@ -5,9 +5,9 @@ module RWC { function runWithIOLog(ioLog: IOLog, fn: () => void) { - var oldSys = ts.sys; + let oldSys = ts.sys; - var wrappedSys = Playback.wrapSystem(ts.sys); + let wrappedSys = Playback.wrapSystem(ts.sys); wrappedSys.startReplayFromData(ioLog); ts.sys = wrappedSys; @@ -21,17 +21,17 @@ module RWC { export function runRWCTest(jsonPath: string) { describe("Testing a RWC project: " + jsonPath, () => { - var inputFiles: { unitName: string; content: string; }[] = []; - var otherFiles: { unitName: string; content: string; }[] = []; - var compilerResult: Harness.Compiler.CompilerResult; - var compilerOptions: ts.CompilerOptions; - var baselineOpts: Harness.Baseline.BaselineOptions = { + let inputFiles: { unitName: string; content: string; }[] = []; + let otherFiles: { unitName: string; content: string; }[] = []; + let compilerResult: Harness.Compiler.CompilerResult; + let compilerOptions: ts.CompilerOptions; + let baselineOpts: Harness.Baseline.BaselineOptions = { Subfolder: 'rwc', Baselinefolder: 'internal/baselines' }; - var baseName = /(.*)\/(.*).json/.exec(ts.normalizeSlashes(jsonPath))[2]; - var currentDirectory: string; - var useCustomLibraryFile: boolean; + let baseName = /(.*)\/(.*).json/.exec(ts.normalizeSlashes(jsonPath))[2]; + let currentDirectory: string; + let useCustomLibraryFile: boolean; after(() => { // Mocha holds onto the closure environment of the describe callback even after the test is done. @@ -50,10 +50,10 @@ module RWC { }); it('can compile', () => { - var harnessCompiler = Harness.Compiler.getCompiler(); - var opts: ts.ParsedCommandLine; + let harnessCompiler = Harness.Compiler.getCompiler(); + let opts: ts.ParsedCommandLine; - var ioLog: IOLog = JSON.parse(Harness.IO.readFile(jsonPath)); + let ioLog: IOLog = JSON.parse(Harness.IO.readFile(jsonPath)); currentDirectory = ioLog.currentDirectory; useCustomLibraryFile = ioLog.useCustomLibraryFile; runWithIOLog(ioLog, () => { @@ -77,7 +77,7 @@ module RWC { for (let fileRead of ioLog.filesRead) { // Check if the file is already added into the set of input files. var resolvedPath = ts.normalizeSlashes(ts.sys.resolvePath(fileRead.path)); - var inInputList = ts.forEach(inputFiles, inputFile => inputFile.unitName === resolvedPath); + let inInputList = ts.forEach(inputFiles, inputFile => inputFile.unitName === resolvedPath); if (!Harness.isLibraryFile(fileRead.path)) { if (inInputList) { @@ -117,9 +117,10 @@ module RWC { }); function getHarnessCompilerInputUnit(fileName: string) { - var unitName = ts.normalizeSlashes(ts.sys.resolvePath(fileName)); + let unitName = ts.normalizeSlashes(ts.sys.resolvePath(fileName)); + let content: string = null; try { - var content = ts.sys.readFile(unitName); + content = ts.sys.readFile(unitName); } catch (e) { // Leave content undefined. @@ -155,13 +156,13 @@ module RWC { }, false, baselineOpts); }); - //it('has correct source map record', () => { - // if (compilerOptions.sourceMap) { - // Harness.Baseline.runBaseline('has correct source map record', baseName + '.sourcemap.txt', () => { - // return compilerResult.getSourceMapRecord(); - // }, false, baselineOpts); - // } - //}); + /*it('has correct source map record', () => { + if (compilerOptions.sourceMap) { + Harness.Baseline.runBaseline('has correct source map record', baseName + '.sourcemap.txt', () => { + return compilerResult.getSourceMapRecord(); + }, false, baselineOpts); + } + });*/ it('has the expected errors', () => { Harness.Baseline.runBaseline('has the expected errors', baseName + '.errors.txt', () => { @@ -178,7 +179,7 @@ module RWC { it('has the expected errors in generated declaration files', () => { if (compilerOptions.declaration && !compilerResult.errors.length) { Harness.Baseline.runBaseline('has the expected errors in generated declaration files', baseName + '.dts.errors.txt', () => { - var declFileCompilationResult = Harness.Compiler.getCompiler().compileDeclarationFiles(inputFiles, otherFiles, compilerResult, + let declFileCompilationResult = Harness.Compiler.getCompiler().compileDeclarationFiles(inputFiles, otherFiles, compilerResult, /*settingscallback*/ undefined, compilerOptions, currentDirectory); if (declFileCompilationResult.declResult.errors.length === 0) { return null; @@ -204,8 +205,8 @@ class RWCRunner extends RunnerBase { */ public initializeTests(): void { // Read in and evaluate the test list - var testList = Harness.IO.listFiles(RWCRunner.sourcePath, /.+\.json$/); - for (var i = 0; i < testList.length; i++) { + let testList = Harness.IO.listFiles(RWCRunner.sourcePath, /.+\.json$/); + for (let i = 0; i < testList.length; i++) { this.runTest(testList[i]); } } diff --git a/src/harness/sourceMapRecorder.ts b/src/harness/sourceMapRecorder.ts index ed079774d94..767dd37949f 100644 --- a/src/harness/sourceMapRecorder.ts +++ b/src/harness/sourceMapRecorder.ts @@ -1,6 +1,6 @@ // // Copyright (c) Microsoft Corporation. All rights reserved. -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -23,12 +23,12 @@ module Harness.SourceMapRecoder { } module SourceMapDecoder { - var sourceMapMappings: string; - var sourceMapNames: string[]; - var decodingIndex: number; - var prevNameIndex: number; - var decodeOfEncodedMapping: ts.SourceMapSpan; - var errorDecodeOfEncodedMapping: string; + let sourceMapMappings: string; + let sourceMapNames: string[]; + let decodingIndex: number; + let prevNameIndex: number; + let decodeOfEncodedMapping: ts.SourceMapSpan; + let errorDecodeOfEncodedMapping: string; export function initializeSourceMapDecoding(sourceMapData: ts.SourceMapData) { sourceMapMappings = sourceMapData.sourceMapMappings; @@ -82,9 +82,9 @@ module Harness.SourceMapRecoder { return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".indexOf(sourceMapMappings.charAt(decodingIndex)); } - var moreDigits = true; - var shiftCount = 0; - var value = 0; + let moreDigits = true; + let shiftCount = 0; + let value = 0; for (; moreDigits; decodingIndex++) { if (createErrorIfCondition(decodingIndex >= sourceMapMappings.length, "Error in decoding base64VLQFormatDecode, past the mapping string")) { @@ -92,7 +92,7 @@ module Harness.SourceMapRecoder { } // 6 digit number - var currentByte = base64FormatDecode(); + let currentByte = base64FormatDecode(); // If msb is set, we still have more bits to continue moreDigits = (currentByte & 32) !== 0; @@ -143,7 +143,7 @@ module Harness.SourceMapRecoder { return { error: errorDecodeOfEncodedMapping, sourceMapSpan: decodeOfEncodedMapping }; } - // 2. Relative sourceIndex + // 2. Relative sourceIndex decodeOfEncodedMapping.sourceIndex += base64VLQFormatDecode(); // Incorrect sourceIndex dont support this map if (createErrorIfCondition(decodeOfEncodedMapping.sourceIndex < 0, "Invalid sourceIndex found")) { @@ -165,7 +165,7 @@ module Harness.SourceMapRecoder { return { error: errorDecodeOfEncodedMapping, sourceMapSpan: decodeOfEncodedMapping }; } - // 4. Relative sourceColumn 0 based + // 4. Relative sourceColumn 0 based decodeOfEncodedMapping.sourceColumn += base64VLQFormatDecode(); // Incorrect sourceColumn dont support this map if (createErrorIfCondition(decodeOfEncodedMapping.sourceColumn < 1, "Invalid sourceLine found")) { @@ -203,19 +203,19 @@ module Harness.SourceMapRecoder { } module SourceMapSpanWriter { - var sourceMapRecoder: Compiler.WriterAggregator; - var sourceMapSources: string[]; - var sourceMapNames: string[]; + let sourceMapRecoder: Compiler.WriterAggregator; + let sourceMapSources: string[]; + let sourceMapNames: string[]; - var jsFile: Compiler.GeneratedFile; - var jsLineMap: number[]; - var tsCode: string; - var tsLineMap: number[]; + let jsFile: Compiler.GeneratedFile; + let jsLineMap: number[]; + let tsCode: string; + let tsLineMap: number[]; - var spansOnSingleLine: SourceMapSpanWithDecodeErrors[]; - var prevWrittenSourcePos: number; - var prevWrittenJsLine: number; - var spanMarkerContinues: boolean; + let spansOnSingleLine: SourceMapSpanWithDecodeErrors[]; + let prevWrittenSourcePos: number; + let prevWrittenJsLine: number; + let spanMarkerContinues: boolean; export function intializeSourceMapSpanWriter(sourceMapRecordWriter: Compiler.WriterAggregator, sourceMapData: ts.SourceMapData, currentJsFile: Compiler.GeneratedFile) { sourceMapRecoder = sourceMapRecordWriter; @@ -244,7 +244,7 @@ module Harness.SourceMapRecoder { } function getSourceMapSpanString(mapEntry: ts.SourceMapSpan, getAbsentNameIndex?: boolean) { - var mapString = "Emitted(" + mapEntry.emittedLine + ", " + mapEntry.emittedColumn + ") Source(" + mapEntry.sourceLine + ", " + mapEntry.sourceColumn + ") + SourceIndex(" + mapEntry.sourceIndex + ")"; + let mapString = "Emitted(" + mapEntry.emittedLine + ", " + mapEntry.emittedColumn + ") Source(" + mapEntry.sourceLine + ", " + mapEntry.sourceColumn + ") + SourceIndex(" + mapEntry.sourceIndex + ")"; if (mapEntry.nameIndex >= 0 && mapEntry.nameIndex < sourceMapNames.length) { mapString += " name (" + sourceMapNames[mapEntry.nameIndex] + ")"; } @@ -259,8 +259,8 @@ module Harness.SourceMapRecoder { export function recordSourceMapSpan(sourceMapSpan: ts.SourceMapSpan) { // verify the decoded span is same as the new span - var decodeResult = SourceMapDecoder.decodeNextEncodedSourceMapSpan(); - var decodedErrors: string[]; + let decodeResult = SourceMapDecoder.decodeNextEncodedSourceMapSpan(); + let decodedErrors: string[]; if (decodeResult.error || decodeResult.sourceMapSpan.emittedLine !== sourceMapSpan.emittedLine || decodeResult.sourceMapSpan.emittedColumn !== sourceMapSpan.emittedColumn @@ -278,7 +278,7 @@ module Harness.SourceMapRecoder { } if (spansOnSingleLine.length && spansOnSingleLine[0].sourceMapSpan.emittedLine !== sourceMapSpan.emittedLine) { - // On different line from the one that we have been recording till now, + // On different line from the one that we have been recording till now, writeRecordedSpans(); spansOnSingleLine = [{ sourceMapSpan: sourceMapSpan, decodeErrors: decodedErrors }]; } @@ -317,8 +317,8 @@ module Harness.SourceMapRecoder { } function getTextOfLine(line: number, lineMap: number[], code: string) { - var startPos = lineMap[line]; - var endPos = lineMap[line + 1]; + let startPos = lineMap[line]; + let endPos = lineMap[line + 1]; return code.substring(startPos, endPos); } @@ -329,14 +329,16 @@ module Harness.SourceMapRecoder { } function writeRecordedSpans() { + let markerIds: string[] = []; + function getMarkerId(markerIndex: number) { - var markerId = ""; + let markerId = ""; if (spanMarkerContinues) { assert.isTrue(markerIndex === 0); markerId = "1->"; } else { - var markerId = "" + (markerIndex + 1); + markerId = "" + (markerIndex + 1); if (markerId.length < 2) { markerId = markerId + " "; } @@ -345,10 +347,10 @@ module Harness.SourceMapRecoder { return markerId; } - var prevEmittedCol: number; + let prevEmittedCol: number; function iterateSpans(fn: (currentSpan: SourceMapSpanWithDecodeErrors, index: number) => void) { prevEmittedCol = 1; - for (var i = 0; i < spansOnSingleLine.length; i++) { + for (let i = 0; i < spansOnSingleLine.length; i++) { fn(spansOnSingleLine[i], i); prevEmittedCol = spansOnSingleLine[i].sourceMapSpan.emittedColumn; } @@ -356,18 +358,18 @@ module Harness.SourceMapRecoder { function writeSourceMapIndent(indentLength: number, indentPrefix: string) { sourceMapRecoder.Write(indentPrefix); - for (var i = 1; i < indentLength; i++) { + for (let i = 1; i < indentLength; i++) { sourceMapRecoder.Write(" "); } } function writeSourceMapMarker(currentSpan: SourceMapSpanWithDecodeErrors, index: number, endColumn = currentSpan.sourceMapSpan.emittedColumn, endContinues?: boolean) { - var markerId = getMarkerId(index); + let markerId = getMarkerId(index); markerIds.push(markerId); writeSourceMapIndent(prevEmittedCol, markerId); - for (var i = prevEmittedCol; i < endColumn; i++) { + for (let i = prevEmittedCol; i < endColumn; i++) { sourceMapRecoder.Write("^"); } if (endContinues) { @@ -378,8 +380,8 @@ module Harness.SourceMapRecoder { } function writeSourceMapSourceText(currentSpan: SourceMapSpanWithDecodeErrors, index: number) { - var sourcePos = tsLineMap[currentSpan.sourceMapSpan.sourceLine - 1] + (currentSpan.sourceMapSpan.sourceColumn - 1); - var sourceText = ""; + let sourcePos = tsLineMap[currentSpan.sourceMapSpan.sourceLine - 1] + (currentSpan.sourceMapSpan.sourceColumn - 1); + let sourceText = ""; if (prevWrittenSourcePos < sourcePos) { // Position that goes forward, get text sourceText = tsCode.substring(prevWrittenSourcePos, sourcePos); @@ -387,14 +389,14 @@ module Harness.SourceMapRecoder { if (currentSpan.decodeErrors) { // If there are decode errors, write - for (var i = 0; i < currentSpan.decodeErrors.length; i++) { + for (let i = 0; i < currentSpan.decodeErrors.length; i++) { writeSourceMapIndent(prevEmittedCol, markerIds[index]); sourceMapRecoder.WriteLine(currentSpan.decodeErrors[i]); } } - var tsCodeLineMap = ts.computeLineStarts(sourceText); - for (var i = 0; i < tsCodeLineMap.length; i++) { + let tsCodeLineMap = ts.computeLineStarts(sourceText); + for (let i = 0; i < tsCodeLineMap.length; i++) { writeSourceMapIndent(prevEmittedCol, i === 0 ? markerIds[index] : " >"); sourceMapRecoder.Write(getTextOfLine(i, tsCodeLineMap, sourceText)); if (i === tsCodeLineMap.length - 1) { @@ -410,16 +412,15 @@ module Harness.SourceMapRecoder { } if (spansOnSingleLine.length) { - var currentJsLine = spansOnSingleLine[0].sourceMapSpan.emittedLine; + let currentJsLine = spansOnSingleLine[0].sourceMapSpan.emittedLine; // Write js line writeJsFileLines(currentJsLine); // Emit markers - var markerIds: string[] = []; iterateSpans(writeSourceMapMarker); - var jsFileText = getTextOfLine(currentJsLine, jsLineMap, jsFile.code); + let jsFileText = getTextOfLine(currentJsLine, jsLineMap, jsFile.code); if (prevEmittedCol < jsFileText.length) { // There is remaining text on this line that will be part of next source span so write marker that continues writeSourceMapMarker(undefined, spansOnSingleLine.length, /*endColumn*/ jsFileText.length, /*endContinues*/ true); @@ -437,16 +438,16 @@ module Harness.SourceMapRecoder { } export function getSourceMapRecord(sourceMapDataList: ts.SourceMapData[], program: ts.Program, jsFiles: Compiler.GeneratedFile[]) { - var sourceMapRecoder = new Compiler.WriterAggregator(); + let sourceMapRecoder = new Compiler.WriterAggregator(); - for (var i = 0; i < sourceMapDataList.length; i++) { - var sourceMapData = sourceMapDataList[i]; - var prevSourceFile: ts.SourceFile = null; + for (let i = 0; i < sourceMapDataList.length; i++) { + let sourceMapData = sourceMapDataList[i]; + let prevSourceFile: ts.SourceFile = null; SourceMapSpanWriter.intializeSourceMapSpanWriter(sourceMapRecoder, sourceMapData, jsFiles[i]); - for (var j = 0; j < sourceMapData.sourceMapDecodedMappings.length; j++) { - var decodedSourceMapping = sourceMapData.sourceMapDecodedMappings[j]; - var currentSourceFile = program.getSourceFile(sourceMapData.inputSourceFileNames[decodedSourceMapping.sourceIndex]); + for (let j = 0; j < sourceMapData.sourceMapDecodedMappings.length; j++) { + let decodedSourceMapping = sourceMapData.sourceMapDecodedMappings[j]; + let currentSourceFile = program.getSourceFile(sourceMapData.inputSourceFileNames[decodedSourceMapping.sourceIndex]); if (currentSourceFile !== prevSourceFile) { SourceMapSpanWriter.recordNewSourceFileSpan(decodedSourceMapping, currentSourceFile.text); prevSourceFile = currentSourceFile; @@ -455,7 +456,7 @@ module Harness.SourceMapRecoder { SourceMapSpanWriter.recordSourceMapSpan(decodedSourceMapping); } } - SourceMapSpanWriter.close();// If the last spans werent emitted, emit them + SourceMapSpanWriter.close(); // If the last spans werent emitted, emit them } sourceMapRecoder.Close(); return sourceMapRecoder.lines.join('\r\n'); diff --git a/src/harness/test262Runner.ts b/src/harness/test262Runner.ts index 5f8250c5e23..e34e58844ac 100644 --- a/src/harness/test262Runner.ts +++ b/src/harness/test262Runner.ts @@ -27,7 +27,7 @@ class Test262BaselineRunner extends RunnerBase { describe('test262 test for ' + filePath, () => { // Mocha holds onto the closure environment of the describe callback even after the test is done. // Everything declared here should be cleared out in the "after" callback. - var testState: { + let testState: { filename: string; compilerResult: Harness.Compiler.CompilerResult; inputFiles: { unitName: string; content: string }[]; @@ -35,11 +35,11 @@ class Test262BaselineRunner extends RunnerBase { }; before(() => { - var content = Harness.IO.readFile(filePath); - var testFilename = ts.removeFileExtension(filePath).replace(/\//g, '_') + ".test"; - var testCaseContent = Harness.TestCaseParser.makeUnitsFromTest(content, testFilename); + let content = Harness.IO.readFile(filePath); + let testFilename = ts.removeFileExtension(filePath).replace(/\//g, '_') + ".test"; + let testCaseContent = Harness.TestCaseParser.makeUnitsFromTest(content, testFilename); - var inputFiles = testCaseContent.testUnitData.map(unit => { + let inputFiles = testCaseContent.testUnitData.map(unit => { return { unitName: Test262BaselineRunner.getTestFilePath(unit.name), content: unit.content }; }); @@ -63,14 +63,14 @@ class Test262BaselineRunner extends RunnerBase { it('has the expected emitted code', () => { Harness.Baseline.runBaseline('has the expected emitted code', testState.filename + '.output.js', () => { - var files = testState.compilerResult.files.filter(f=> f.fileName !== Test262BaselineRunner.helpersFilePath); + let files = testState.compilerResult.files.filter(f => f.fileName !== Test262BaselineRunner.helpersFilePath); return Harness.Compiler.collateOutputs(files); }, false, Test262BaselineRunner.baselineOptions); }); it('has the expected errors', () => { Harness.Baseline.runBaseline('has the expected errors', testState.filename + '.errors.txt', () => { - var errors = testState.compilerResult.errors; + let errors = testState.compilerResult.errors; if (errors.length === 0) { return null; } @@ -79,14 +79,14 @@ class Test262BaselineRunner extends RunnerBase { }, false, Test262BaselineRunner.baselineOptions); }); - it('satisfies invariants', () => { - var sourceFile = testState.program.getSourceFile(Test262BaselineRunner.getTestFilePath(testState.filename)); + it('satisfies inletiants', () => { + let sourceFile = testState.program.getSourceFile(Test262BaselineRunner.getTestFilePath(testState.filename)); Utils.assertInvariants(sourceFile, /*parent:*/ undefined); }); - it('has the expected AST',() => { - Harness.Baseline.runBaseline('has the expected AST', testState.filename + '.AST.txt',() => { - var sourceFile = testState.program.getSourceFile(Test262BaselineRunner.getTestFilePath(testState.filename)); + it('has the expected AST', () => { + Harness.Baseline.runBaseline('has the expected AST', testState.filename + '.AST.txt', () => { + let sourceFile = testState.program.getSourceFile(Test262BaselineRunner.getTestFilePath(testState.filename)); return Utils.sourceFileToJSON(sourceFile); }, false, Test262BaselineRunner.baselineOptions); }); @@ -96,7 +96,7 @@ class Test262BaselineRunner extends RunnerBase { public initializeTests() { // this will set up a series of describe/it blocks to run between the setup and cleanup phases if (this.tests.length === 0) { - var testFiles = this.enumerateFiles(Test262BaselineRunner.basePath, Test262BaselineRunner.testFileExtensionRegex, { recursive: true }); + let testFiles = this.enumerateFiles(Test262BaselineRunner.basePath, Test262BaselineRunner.testFileExtensionRegex, { recursive: true }); testFiles.forEach(fn => { this.runTest(ts.normalizePath(fn)); }); @@ -105,4 +105,4 @@ class Test262BaselineRunner extends RunnerBase { this.tests.forEach(test => this.runTest(test)); } } -} \ No newline at end of file +} diff --git a/src/harness/typeWriter.ts b/src/harness/typeWriter.ts index b68e606c79d..27cb3574473 100644 --- a/src/harness/typeWriter.ts +++ b/src/harness/typeWriter.ts @@ -13,7 +13,7 @@ class TypeWriterWalker { private checker: ts.TypeChecker; constructor(private program: ts.Program, fullTypeCheck: boolean) { - // Consider getting both the diagnostics checker and the non-diagnostics checker to verify + // Consider getting both the diagnostics checker and the non-diagnostics checker to verify // they are consistent. this.checker = fullTypeCheck ? program.getDiagnosticsProducingTypeChecker() @@ -21,7 +21,7 @@ class TypeWriterWalker { } public getTypeAndSymbols(fileName: string): TypeWriterResult[] { - var sourceFile = this.program.getSourceFile(fileName); + let sourceFile = this.program.getSourceFile(fileName); this.currentSourceFile = sourceFile; this.results = []; this.visitNode(sourceFile); @@ -37,19 +37,19 @@ class TypeWriterWalker { } private logTypeAndSymbol(node: ts.Node): void { - var actualPos = ts.skipTrivia(this.currentSourceFile.text, node.pos); - var lineAndCharacter = this.currentSourceFile.getLineAndCharacterOfPosition(actualPos); - var sourceText = ts.getTextOfNodeFromSourceText(this.currentSourceFile.text, node); + let actualPos = ts.skipTrivia(this.currentSourceFile.text, node.pos); + let lineAndCharacter = this.currentSourceFile.getLineAndCharacterOfPosition(actualPos); + let sourceText = ts.getTextOfNodeFromSourceText(this.currentSourceFile.text, node); // Workaround to ensure we output 'C' instead of 'typeof C' for base class expressions - // var type = this.checker.getTypeAtLocation(node); - var type = node.parent && ts.isExpressionWithTypeArgumentsInClassExtendsClause(node.parent) && this.checker.getTypeAtLocation(node.parent) || this.checker.getTypeAtLocation(node); + // let type = this.checker.getTypeAtLocation(node); + let type = node.parent && ts.isExpressionWithTypeArgumentsInClassExtendsClause(node.parent) && this.checker.getTypeAtLocation(node.parent) || this.checker.getTypeAtLocation(node); ts.Debug.assert(type !== undefined, "type doesn't exist"); - var symbol = this.checker.getSymbolAtLocation(node); + let symbol = this.checker.getSymbolAtLocation(node); - var typeString = this.checker.typeToString(type, node.parent, ts.TypeFormatFlags.NoTruncation); - var symbolString: string; + let typeString = this.checker.typeToString(type, node.parent, ts.TypeFormatFlags.NoTruncation); + let symbolString: string; if (symbol) { symbolString = "Symbol(" + this.checker.symbolToString(symbol, node.parent); if (symbol.declarations) { @@ -57,7 +57,7 @@ class TypeWriterWalker { symbolString += ", "; let declSourceFile = declaration.getSourceFile(); let declLineAndCharacter = declSourceFile.getLineAndCharacterOfPosition(declaration.pos); - symbolString += `Decl(${ ts.getBaseFileName(declSourceFile.fileName) }, ${ declLineAndCharacter.line }, ${ declLineAndCharacter.character })` + symbolString += `Decl(${ ts.getBaseFileName(declSourceFile.fileName) }, ${ declLineAndCharacter.line }, ${ declLineAndCharacter.character })`; } } symbolString += ")"; diff --git a/src/server/session.ts b/src/server/session.ts index 3eea095d9d5..ff6f97139cb 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -887,53 +887,53 @@ namespace ts.server { private handlers : Map<(request: protocol.Request) => {response?: any, responseRequired?: boolean}> = { [CommandNames.Exit]: () => { this.exit(); - return {}; + return { responseRequired: false}; }, [CommandNames.Definition]: (request: protocol.Request) => { var defArgs = request.arguments; - return {response: this.getDefinition(defArgs.line, defArgs.offset, defArgs.file)}; + return {response: this.getDefinition(defArgs.line, defArgs.offset, defArgs.file), responseRequired: true}; }, [CommandNames.TypeDefinition]: (request: protocol.Request) => { var defArgs = request.arguments; - return {response: this.getTypeDefinition(defArgs.line, defArgs.offset, defArgs.file)}; + return {response: this.getTypeDefinition(defArgs.line, defArgs.offset, defArgs.file), responseRequired: true}; }, [CommandNames.References]: (request: protocol.Request) => { var defArgs = request.arguments; - return {response: this.getReferences(defArgs.line, defArgs.offset, defArgs.file)}; + return {response: this.getReferences(defArgs.line, defArgs.offset, defArgs.file), responseRequired: true}; }, [CommandNames.Rename]: (request: protocol.Request) => { var renameArgs = request.arguments; - return {response: this.getRenameLocations(renameArgs.line, renameArgs.offset, renameArgs.file, renameArgs.findInComments, renameArgs.findInStrings)} + return {response: this.getRenameLocations(renameArgs.line, renameArgs.offset, renameArgs.file, renameArgs.findInComments, renameArgs.findInStrings), responseRequired: true} }, [CommandNames.Open]: (request: protocol.Request) => { var openArgs = request.arguments; this.openClientFile(openArgs.file); - return {} + return {responseRequired: false} }, [CommandNames.Quickinfo]: (request: protocol.Request) => { var quickinfoArgs = request.arguments; - return {response: this.getQuickInfo(quickinfoArgs.line, quickinfoArgs.offset, quickinfoArgs.file)}; + return {response: this.getQuickInfo(quickinfoArgs.line, quickinfoArgs.offset, quickinfoArgs.file), responseRequired: true}; }, [CommandNames.Format]: (request: protocol.Request) => { var formatArgs = request.arguments; - return {response: this.getFormattingEditsForRange(formatArgs.line, formatArgs.offset, formatArgs.endLine, formatArgs.endOffset, formatArgs.file)}; + return {response: this.getFormattingEditsForRange(formatArgs.line, formatArgs.offset, formatArgs.endLine, formatArgs.endOffset, formatArgs.file), responseRequired: true}; }, [CommandNames.Formatonkey]: (request: protocol.Request) => { var formatOnKeyArgs = request.arguments; - return {response: this.getFormattingEditsAfterKeystroke(formatOnKeyArgs.line, formatOnKeyArgs.offset, formatOnKeyArgs.key, formatOnKeyArgs.file)}; + return {response: this.getFormattingEditsAfterKeystroke(formatOnKeyArgs.line, formatOnKeyArgs.offset, formatOnKeyArgs.key, formatOnKeyArgs.file), responseRequired: true}; }, [CommandNames.Completions]: (request: protocol.Request) => { var completionsArgs = request.arguments; - return {response: this.getCompletions(completionsArgs.line, completionsArgs.offset, completionsArgs.prefix, completionsArgs.file)} + return {response: this.getCompletions(completionsArgs.line, completionsArgs.offset, completionsArgs.prefix, completionsArgs.file), responseRequired: true} }, [CommandNames.CompletionDetails]: (request: protocol.Request) => { var completionDetailsArgs = request.arguments; return {response: this.getCompletionEntryDetails(completionDetailsArgs.line,completionDetailsArgs.offset, - completionDetailsArgs.entryNames,completionDetailsArgs.file)} + completionDetailsArgs.entryNames,completionDetailsArgs.file), responseRequired: true} }, [CommandNames.SignatureHelp]: (request: protocol.Request) => { var signatureHelpArgs = request.arguments; - return {response: this.getSignatureHelpItems(signatureHelpArgs.line, signatureHelpArgs.offset, signatureHelpArgs.file)} + return {response: this.getSignatureHelpItems(signatureHelpArgs.line, signatureHelpArgs.offset, signatureHelpArgs.file), responseRequired: true} }, [CommandNames.Geterr]: (request: protocol.Request) => { var geterrArgs = request.arguments; @@ -972,23 +972,23 @@ namespace ts.server { }, [CommandNames.Navto]: (request: protocol.Request) => { var navtoArgs = request.arguments; - return {response: this.getNavigateToItems(navtoArgs.searchValue, navtoArgs.file, navtoArgs.maxResultCount)}; + return {response: this.getNavigateToItems(navtoArgs.searchValue, navtoArgs.file, navtoArgs.maxResultCount), responseRequired: true}; }, [CommandNames.Brace]: (request: protocol.Request) => { var braceArguments = request.arguments; - return {response: this.getBraceMatching(braceArguments.line, braceArguments.offset, braceArguments.file)}; + return {response: this.getBraceMatching(braceArguments.line, braceArguments.offset, braceArguments.file), responseRequired: true}; }, [CommandNames.NavBar]: (request: protocol.Request) => { var navBarArgs = request.arguments; - return {response: this.getNavigationBarItems(navBarArgs.file)}; + return {response: this.getNavigationBarItems(navBarArgs.file), responseRequired: true}; }, [CommandNames.Occurrences]: (request: protocol.Request) => { var { line, offset, file: fileName } = request.arguments; - return {response: this.getOccurrences(line, offset, fileName)}; + return {response: this.getOccurrences(line, offset, fileName), responseRequired: true}; }, [CommandNames.ProjectInfo]: (request: protocol.Request) => { var { file, needFileNameList } = request.arguments; - return {response: this.getProjectInfo(file, needFileNameList)}; + return {response: this.getProjectInfo(file, needFileNameList), responseRequired: true}; }, }; addProtocolHandler(command: string, handler: (request: protocol.Request) => {response?: any, responseRequired: boolean}) { diff --git a/src/services/services.ts b/src/services/services.ts index c85c10dc411..c2432816f24 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -91,6 +91,9 @@ namespace ts { * not happen and the entire document will be re - parsed. */ getChangeRange(oldSnapshot: IScriptSnapshot): TextChangeRange; + + /** Releases all resources held by this script snapshot */ + dispose?(): void; } export module ScriptSnapshot { @@ -1863,6 +1866,16 @@ namespace ts { // after incremental parsing nameTable might not be up-to-date // drop it so it can be lazily recreated later newSourceFile.nameTable = undefined; + + // dispose all resources held by old script snapshot + if (sourceFile !== newSourceFile && sourceFile.scriptSnapshot) { + if (sourceFile.scriptSnapshot.dispose) { + sourceFile.scriptSnapshot.dispose(); + } + + sourceFile.scriptSnapshot = undefined; + } + return newSourceFile; } } @@ -3015,17 +3028,17 @@ namespace ts { function tryGetGlobalSymbols(): boolean { let objectLikeContainer: ObjectLiteralExpression | BindingPattern; - let importClause: ImportClause; + let namedImportsOrExports: NamedImportsOrExports; let jsxContainer: JsxOpeningLikeElement; if (objectLikeContainer = tryGetObjectLikeCompletionContainer(contextToken)) { return tryGetObjectLikeCompletionSymbols(objectLikeContainer); } - if (importClause = getAncestor(contextToken, SyntaxKind.ImportClause)) { + if (namedImportsOrExports = tryGetNamedImportsOrExportsForCompletion(contextToken)) { // cursor is in an import clause // try to show exported member for imported module - return tryGetImportClauseCompletionSymbols(importClause); + return tryGetImportOrExportClauseCompletionSymbols(namedImportsOrExports); } if (jsxContainer = tryGetContainingJsxElement(contextToken)) { @@ -3035,7 +3048,7 @@ namespace ts { attrsType = typeChecker.getJsxElementAttributesType(jsxContainer); if (attrsType) { - symbols = filterJsxAttributes((jsxContainer).attributes, typeChecker.getPropertiesOfType(attrsType)); + symbols = filterJsxAttributes(typeChecker.getPropertiesOfType(attrsType), (jsxContainer).attributes); isMemberCompletion = true; isNewIdentifierLocation = false; return true; @@ -3104,24 +3117,12 @@ namespace ts { function isCompletionListBlocker(contextToken: Node): boolean { let start = new Date().getTime(); let result = isInStringOrRegularExpressionOrTemplateLiteral(contextToken) || - isIdentifierDefinitionLocation(contextToken) || + isSolelyIdentifierDefinitionLocation(contextToken) || isDotOfNumericLiteral(contextToken); log("getCompletionsAtPosition: isCompletionListBlocker: " + (new Date().getTime() - start)); return result; } - function shouldShowCompletionsInImportsClause(node: Node): boolean { - if (node) { - // import {| - // import {a,| - if (node.kind === SyntaxKind.OpenBraceToken || node.kind === SyntaxKind.CommaToken) { - return node.parent.kind === SyntaxKind.NamedImports; - } - } - - return false; - } - function isNewIdentifierDefinitionLocation(previousToken: Node): boolean { if (previousToken) { let containingNodeKind = previousToken.parent.kind; @@ -3233,8 +3234,19 @@ namespace ts { // We are *only* completing on properties from the type being destructured. isNewIdentifierLocation = false; - typeForObject = typeChecker.getTypeAtLocation(objectLikeContainer); - existingMembers = (objectLikeContainer).elements; + let rootDeclaration = getRootDeclaration(objectLikeContainer.parent); + if (isVariableLike(rootDeclaration)) { + // We don't want to complete using the type acquired by the shape + // of the binding pattern; we are only interested in types acquired + // through type declaration or inference. + if (rootDeclaration.initializer || rootDeclaration.type) { + typeForObject = typeChecker.getTypeAtLocation(objectLikeContainer); + existingMembers = (objectLikeContainer).elements; + } + } + else { + Debug.fail("Root declaration is not variable-like.") + } } else { Debug.fail("Expected object literal or binding pattern, got " + objectLikeContainer.kind); @@ -3253,38 +3265,42 @@ namespace ts { } /** - * Aggregates relevant symbols for completion in import clauses; for instance, + * Aggregates relevant symbols for completion in import clauses and export clauses + * whose declarations have a module specifier; for instance, symbols will be aggregated for * - * import { $ } from "moduleName"; + * import { | } from "moduleName"; + * export { a as foo, | } from "moduleName"; + * + * but not for + * + * export { | }; * * Relevant symbols are stored in the captured 'symbols' variable. * * @returns true if 'symbols' was successfully populated; false otherwise. */ - function tryGetImportClauseCompletionSymbols(importClause: ImportClause): boolean { - // cursor is in import clause - // try to show exported member for imported module - if (shouldShowCompletionsInImportsClause(contextToken)) { - isMemberCompletion = true; - isNewIdentifierLocation = false; + function tryGetImportOrExportClauseCompletionSymbols(namedImportsOrExports: NamedImportsOrExports): boolean { + let declarationKind = namedImportsOrExports.kind === SyntaxKind.NamedImports ? + SyntaxKind.ImportDeclaration : + SyntaxKind.ExportDeclaration; + let importOrExportDeclaration = getAncestor(namedImportsOrExports, declarationKind); + let moduleSpecifier = importOrExportDeclaration.moduleSpecifier; - let importDeclaration = importClause.parent; - Debug.assert(importDeclaration !== undefined && importDeclaration.kind === SyntaxKind.ImportDeclaration); - - let exports: Symbol[]; - let moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(importDeclaration.moduleSpecifier); - if (moduleSpecifierSymbol) { - exports = typeChecker.getExportsOfModule(moduleSpecifierSymbol); - } - - //let exports = typeInfoResolver.getExportsOfImportDeclaration(importDeclaration); - symbols = exports ? filterModuleExports(exports, importDeclaration) : emptyArray; + if (!moduleSpecifier) { + return false; } - else { - isMemberCompletion = false; - isNewIdentifierLocation = true; + + isMemberCompletion = true; + isNewIdentifierLocation = false; + + let exports: Symbol[]; + let moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(importOrExportDeclaration.moduleSpecifier); + if (moduleSpecifierSymbol) { + exports = typeChecker.getExportsOfModule(moduleSpecifierSymbol); } + symbols = exports ? filterNamedImportOrExportCompletionItems(exports, namedImportsOrExports.elements) : emptyArray; + return true; } @@ -3308,6 +3324,26 @@ namespace ts { return undefined; } + /** + * Returns the containing list of named imports or exports of a context token, + * on the condition that one exists and that the context implies completion should be given. + */ + function tryGetNamedImportsOrExportsForCompletion(contextToken: Node): NamedImportsOrExports { + if (contextToken) { + switch (contextToken.kind) { + case SyntaxKind.OpenBraceToken: // import { | + case SyntaxKind.CommaToken: // import { a as 0, | + switch (contextToken.parent.kind) { + case SyntaxKind.NamedImports: + case SyntaxKind.NamedExports: + return contextToken.parent; + } + } + } + + return undefined; + } + function tryGetContainingJsxElement(contextToken: Node): JsxOpeningLikeElement { if (contextToken) { let parent = contextToken.parent; @@ -3355,7 +3391,10 @@ namespace ts { return false; } - function isIdentifierDefinitionLocation(contextToken: Node): boolean { + /** + * @returns true if we are certain that the currently edited location must define a new location; false otherwise. + */ + function isSolelyIdentifierDefinitionLocation(contextToken: Node): boolean { let containingNodeKind = contextToken.parent.kind; switch (contextToken.kind) { case SyntaxKind.CommaToken: @@ -3412,6 +3451,11 @@ namespace ts { case SyntaxKind.ProtectedKeyword: return containingNodeKind === SyntaxKind.Parameter; + case SyntaxKind.AsKeyword: + containingNodeKind === SyntaxKind.ImportSpecifier || + containingNodeKind === SyntaxKind.ExportSpecifier || + containingNodeKind === SyntaxKind.NamespaceImport; + case SyntaxKind.ClassKeyword: case SyntaxKind.EnumKeyword: case SyntaxKind.InterfaceKeyword: @@ -3453,33 +3497,41 @@ namespace ts { return false; } - function filterModuleExports(exports: Symbol[], importDeclaration: ImportDeclaration): Symbol[] { - let exisingImports: Map = {}; + /** + * Filters out completion suggestions for named imports or exports. + * + * @param exportsOfModule The list of symbols which a module exposes. + * @param namedImportsOrExports The list of existing import/export specifiers in the import/export clause. + * + * @returns Symbols to be suggested at an import/export clause, barring those whose named imports/exports + * do not occur at the current position and have not otherwise been typed. + */ + function filterNamedImportOrExportCompletionItems(exportsOfModule: Symbol[], namedImportsOrExports: ImportOrExportSpecifier[]): Symbol[] { + let exisingImportsOrExports: Map = {}; - if (!importDeclaration.importClause) { - return exports; + for (let element of namedImportsOrExports) { + // If this is the current item we are editing right now, do not filter it out + if (element.getStart() <= position && position <= element.getEnd()) { + continue; + } + + let name = element.propertyName || element.name; + exisingImportsOrExports[name.text] = true; } - if (importDeclaration.importClause.namedBindings && - importDeclaration.importClause.namedBindings.kind === SyntaxKind.NamedImports) { - - forEach((importDeclaration.importClause.namedBindings).elements, el => { - // If this is the current item we are editing right now, do not filter it out - if (el.getStart() <= position && position <= el.getEnd()) { - return; - } - - let name = el.propertyName || el.name; - exisingImports[name.text] = true; - }); + if (isEmpty(exisingImportsOrExports)) { + return exportsOfModule; } - if (isEmpty(exisingImports)) { - return exports; - } - return filter(exports, e => !lookUp(exisingImports, e.name)); + return filter(exportsOfModule, e => !lookUp(exisingImportsOrExports, e.name)); } + /** + * Filters out completion suggestions for named imports or exports. + * + * @returns Symbols to be suggested in an object binding pattern or object literal expression, barring those whose declarations + * do not occur at the current position and have not otherwise been typed. + */ function filterObjectMembersList(contextualMemberSymbols: Symbol[], existingMembers: Declaration[]): Symbol[] { if (!existingMembers || existingMembers.length === 0) { return contextualMemberSymbols; @@ -3514,17 +3566,16 @@ namespace ts { existingMemberNames[existingName] = true; } - let filteredMembers: Symbol[] = []; - forEach(contextualMemberSymbols, s => { - if (!existingMemberNames[s.name]) { - filteredMembers.push(s); - } - }); - - return filteredMembers; + return filter(contextualMemberSymbols, m => !lookUp(existingMemberNames, m.name)); } - function filterJsxAttributes(attributes: NodeArray, symbols: Symbol[]): Symbol[] { + /** + * Filters out completion suggestions from 'symbols' according to existing JSX attributes. + * + * @returns Symbols to be suggested in a JSX element, barring those whose attributes + * do not occur at the current position and have not otherwise been typed. + */ + function filterJsxAttributes(symbols: Symbol[], attributes: NodeArray): Symbol[] { let seenNames: Map = {}; for (let attr of attributes) { // If this is the current item we are editing right now, do not filter it out @@ -3536,13 +3587,8 @@ namespace ts { seenNames[(attr).name.text] = true; } } - let result: Symbol[] = []; - for (let sym of symbols) { - if (!seenNames[sym.name]) { - result.push(sym); - } - } - return result; + + return filter(symbols, a => !lookUp(seenNames, a.name)); } } @@ -4682,12 +4728,13 @@ namespace ts { // Make sure we only highlight the keyword when it makes sense to do so. if (isAccessibilityModifier(modifier)) { if (!(container.kind === SyntaxKind.ClassDeclaration || + container.kind === SyntaxKind.ClassExpression || (declaration.kind === SyntaxKind.Parameter && hasKind(container, SyntaxKind.Constructor)))) { return undefined; } } else if (modifier === SyntaxKind.StaticKeyword) { - if (container.kind !== SyntaxKind.ClassDeclaration) { + if (!(container.kind === SyntaxKind.ClassDeclaration || container.kind === SyntaxKind.ClassExpression)) { return undefined; } } @@ -4696,6 +4743,11 @@ namespace ts { return undefined; } } + else if (modifier === SyntaxKind.AbstractKeyword) { + if (!(container.kind === SyntaxKind.ClassDeclaration || declaration.kind === SyntaxKind.ClassDeclaration)) { + return undefined; + } + } else { // unsupported modifier return undefined; @@ -4708,19 +4760,26 @@ namespace ts { switch (container.kind) { case SyntaxKind.ModuleBlock: case SyntaxKind.SourceFile: - nodes = (container).statements; + // Container is either a class declaration or the declaration is a classDeclaration + if (modifierFlag & NodeFlags.Abstract) { + nodes = ((declaration).members).concat(declaration); + } + else { + nodes = (container).statements; + } break; case SyntaxKind.Constructor: nodes = ((container).parameters).concat( (container.parent).members); break; case SyntaxKind.ClassDeclaration: - nodes = (container).members; + case SyntaxKind.ClassExpression: + nodes = (container).members; // If we're an accessibility modifier, we're in an instance member and should search // the constructor's parameter list for instance members as well. if (modifierFlag & NodeFlags.AccessibilityModifier) { - let constructor = forEach((container).members, member => { + let constructor = forEach((container).members, member => { return member.kind === SyntaxKind.Constructor && member; }); @@ -4728,6 +4787,9 @@ namespace ts { nodes = nodes.concat(constructor.parameters); } } + else if (modifierFlag & NodeFlags.Abstract) { + nodes = nodes.concat(container); + } break; default: Debug.fail("Invalid container kind.") @@ -4755,6 +4817,8 @@ namespace ts { return NodeFlags.Export; case SyntaxKind.DeclareKeyword: return NodeFlags.Ambient; + case SyntaxKind.AbstractKeyword: + return NodeFlags.Abstract; default: Debug.fail(); } @@ -6575,7 +6639,7 @@ namespace ts { } } - return ClassificationType.text; + return ClassificationType.identifier; } } diff --git a/src/services/shims.ts b/src/services/shims.ts index 6e765eff499..e2055b3de77 100644 --- a/src/services/shims.ts +++ b/src/services/shims.ts @@ -34,6 +34,9 @@ namespace ts { * Or undefined value if there was no change. */ getChangeRange(oldSnapshot: ScriptSnapshotShim): string; + + /** Releases all resources held by this script snapshot */ + dispose?(): void; } export interface Logger { @@ -61,8 +64,13 @@ namespace ts { /** Public interface of the the of a config service shim instance.*/ export interface CoreServicesShimHost extends Logger { - /** Returns a JSON-encoded value of the type: string[] */ - readDirectory(rootDir: string, extension: string): string; + /** + * Returns a JSON-encoded value of the type: string[] + * + * @param exclude A JSON encoded string[] containing the paths to exclude + * when enumerating the directory. + */ + readDirectory(rootDir: string, extension: string, exclude?: string): string; } /// @@ -243,6 +251,14 @@ namespace ts { return createTextChangeRange( createTextSpan(decoded.span.start, decoded.span.length), decoded.newLength); } + + public dispose(): void { + // if scriptSnapshotShim is a COM object then property check becomes method call with no arguments + // 'in' does not have this effect + if ("dispose" in this.scriptSnapshotShim) { + this.scriptSnapshotShim.dispose(); + } + } } export class LanguageServiceShimHostAdapter implements LanguageServiceHost { @@ -375,8 +391,18 @@ namespace ts { constructor(private shimHost: CoreServicesShimHost) { } - public readDirectory(rootDir: string, extension: string): string[] { - var encoded = this.shimHost.readDirectory(rootDir, extension); + public readDirectory(rootDir: string, extension: string, exclude: string[]): string[] { + // Wrap the API changes for 1.5 release. This try/catch + // should be removed once TypeScript 1.5 has shipped. + // Also consider removing the optional designation for + // the exclude param at this time. + var encoded: string; + try { + encoded = this.shimHost.readDirectory(rootDir, extension, JSON.stringify(exclude)); + } + catch (e) { + encoded = this.shimHost.readDirectory(rootDir, extension); + } return JSON.parse(encoded); } } diff --git a/tests/baselines/reference/arrowFunctionExpressions.symbols b/tests/baselines/reference/arrowFunctionExpressions.symbols index 28945e1179f..61c575933da 100644 --- a/tests/baselines/reference/arrowFunctionExpressions.symbols +++ b/tests/baselines/reference/arrowFunctionExpressions.symbols @@ -70,6 +70,7 @@ var p6 = ({ a }) => { }; var p7 = ({ a: { b } }) => { }; >p7 : Symbol(p7, Decl(arrowFunctionExpressions.ts, 21, 3)) +>a : Symbol(a) >b : Symbol(b, Decl(arrowFunctionExpressions.ts, 21, 16)) var p8 = ({ a = 1 }) => { }; @@ -78,6 +79,7 @@ var p8 = ({ a = 1 }) => { }; var p9 = ({ a: { b = 1 } = { b: 1 } }) => { }; >p9 : Symbol(p9, Decl(arrowFunctionExpressions.ts, 23, 3)) +>a : Symbol(a) >b : Symbol(b, Decl(arrowFunctionExpressions.ts, 23, 16)) >b : Symbol(b, Decl(arrowFunctionExpressions.ts, 23, 28)) diff --git a/tests/baselines/reference/declarationEmitDestructuring1.symbols b/tests/baselines/reference/declarationEmitDestructuring1.symbols index 10920128eee..32755fdef35 100644 --- a/tests/baselines/reference/declarationEmitDestructuring1.symbols +++ b/tests/baselines/reference/declarationEmitDestructuring1.symbols @@ -23,6 +23,7 @@ function bar({a1, b1, c1}: { a1: number, b1: boolean, c1: string }): void { } function baz({a2, b2: {b1, c1}}: { a2: number, b2: { b1: boolean, c1: string } }): void { } >baz : Symbol(baz, Decl(declarationEmitDestructuring1.ts, 2, 77)) >a2 : Symbol(a2, Decl(declarationEmitDestructuring1.ts, 3, 14)) +>b2 : Symbol(b2, Decl(declarationEmitDestructuring1.ts, 3, 46)) >b1 : Symbol(b1, Decl(declarationEmitDestructuring1.ts, 3, 23)) >c1 : Symbol(c1, Decl(declarationEmitDestructuring1.ts, 3, 26)) >a2 : Symbol(a2, Decl(declarationEmitDestructuring1.ts, 3, 34)) diff --git a/tests/baselines/reference/declarationEmitDestructuringArrayPattern2.symbols b/tests/baselines/reference/declarationEmitDestructuringArrayPattern2.symbols index 9e0e48f89e8..0a3c6f4044d 100644 --- a/tests/baselines/reference/declarationEmitDestructuringArrayPattern2.symbols +++ b/tests/baselines/reference/declarationEmitDestructuringArrayPattern2.symbols @@ -17,6 +17,7 @@ var [a2, [b2, { x12, y12: c2 }]=["abc", { x12: 10, y12: false }]] = [1, ["hello" >a2 : Symbol(a2, Decl(declarationEmitDestructuringArrayPattern2.ts, 5, 5)) >b2 : Symbol(b2, Decl(declarationEmitDestructuringArrayPattern2.ts, 5, 10)) >x12 : Symbol(x12, Decl(declarationEmitDestructuringArrayPattern2.ts, 5, 15)) +>y12 : Symbol(y12, Decl(declarationEmitDestructuringArrayPattern2.ts, 5, 91)) >c2 : Symbol(c2, Decl(declarationEmitDestructuringArrayPattern2.ts, 5, 20)) >x12 : Symbol(x12, Decl(declarationEmitDestructuringArrayPattern2.ts, 5, 41)) >y12 : Symbol(y12, Decl(declarationEmitDestructuringArrayPattern2.ts, 5, 50)) diff --git a/tests/baselines/reference/declarationEmitDestructuringObjectLiteralPattern.symbols b/tests/baselines/reference/declarationEmitDestructuringObjectLiteralPattern.symbols index 3cb4ef28c2b..0a57a93f3d0 100644 --- a/tests/baselines/reference/declarationEmitDestructuringObjectLiteralPattern.symbols +++ b/tests/baselines/reference/declarationEmitDestructuringObjectLiteralPattern.symbols @@ -21,24 +21,33 @@ var { x6, y6 } = { x6: 5, y6: "hello" }; >y6 : Symbol(y6, Decl(declarationEmitDestructuringObjectLiteralPattern.ts, 4, 25)) var { x7: a1 } = { x7: 5, y7: "hello" }; +>x7 : Symbol(x7, Decl(declarationEmitDestructuringObjectLiteralPattern.ts, 5, 18)) >a1 : Symbol(a1, Decl(declarationEmitDestructuringObjectLiteralPattern.ts, 5, 5)) >x7 : Symbol(x7, Decl(declarationEmitDestructuringObjectLiteralPattern.ts, 5, 18)) >y7 : Symbol(y7, Decl(declarationEmitDestructuringObjectLiteralPattern.ts, 5, 25)) var { y8: b1 } = { x8: 5, y8: "hello" }; +>y8 : Symbol(y8, Decl(declarationEmitDestructuringObjectLiteralPattern.ts, 6, 25)) >b1 : Symbol(b1, Decl(declarationEmitDestructuringObjectLiteralPattern.ts, 6, 5)) >x8 : Symbol(x8, Decl(declarationEmitDestructuringObjectLiteralPattern.ts, 6, 18)) >y8 : Symbol(y8, Decl(declarationEmitDestructuringObjectLiteralPattern.ts, 6, 25)) var { x9: a2, y9: b2 } = { x9: 5, y9: "hello" }; +>x9 : Symbol(x9, Decl(declarationEmitDestructuringObjectLiteralPattern.ts, 7, 26)) >a2 : Symbol(a2, Decl(declarationEmitDestructuringObjectLiteralPattern.ts, 7, 5)) +>y9 : Symbol(y9, Decl(declarationEmitDestructuringObjectLiteralPattern.ts, 7, 33)) >b2 : Symbol(b2, Decl(declarationEmitDestructuringObjectLiteralPattern.ts, 7, 13)) >x9 : Symbol(x9, Decl(declarationEmitDestructuringObjectLiteralPattern.ts, 7, 26)) >y9 : Symbol(y9, Decl(declarationEmitDestructuringObjectLiteralPattern.ts, 7, 33)) var { a: x11, b: { a: y11, b: { a: z11 }}} = { a: 1, b: { a: "hello", b: { a: true } } }; +>a : Symbol(a, Decl(declarationEmitDestructuringObjectLiteralPattern.ts, 9, 46)) >x11 : Symbol(x11, Decl(declarationEmitDestructuringObjectLiteralPattern.ts, 9, 5)) +>b : Symbol(b, Decl(declarationEmitDestructuringObjectLiteralPattern.ts, 9, 52)) +>a : Symbol(a, Decl(declarationEmitDestructuringObjectLiteralPattern.ts, 9, 57)) >y11 : Symbol(y11, Decl(declarationEmitDestructuringObjectLiteralPattern.ts, 9, 18)) +>b : Symbol(b, Decl(declarationEmitDestructuringObjectLiteralPattern.ts, 9, 69)) +>a : Symbol(a, Decl(declarationEmitDestructuringObjectLiteralPattern.ts, 9, 74)) >z11 : Symbol(z11, Decl(declarationEmitDestructuringObjectLiteralPattern.ts, 9, 31)) >a : Symbol(a, Decl(declarationEmitDestructuringObjectLiteralPattern.ts, 9, 46)) >b : Symbol(b, Decl(declarationEmitDestructuringObjectLiteralPattern.ts, 9, 52)) diff --git a/tests/baselines/reference/declarationEmitDestructuringObjectLiteralPattern1.symbols b/tests/baselines/reference/declarationEmitDestructuringObjectLiteralPattern1.symbols index a4c43a07bc8..cac2431411e 100644 --- a/tests/baselines/reference/declarationEmitDestructuringObjectLiteralPattern1.symbols +++ b/tests/baselines/reference/declarationEmitDestructuringObjectLiteralPattern1.symbols @@ -21,17 +21,21 @@ var { x6, y6 } = { x6: 5, y6: "hello" }; >y6 : Symbol(y6, Decl(declarationEmitDestructuringObjectLiteralPattern1.ts, 4, 25)) var { x7: a1 } = { x7: 5, y7: "hello" }; +>x7 : Symbol(x7, Decl(declarationEmitDestructuringObjectLiteralPattern1.ts, 5, 18)) >a1 : Symbol(a1, Decl(declarationEmitDestructuringObjectLiteralPattern1.ts, 5, 5)) >x7 : Symbol(x7, Decl(declarationEmitDestructuringObjectLiteralPattern1.ts, 5, 18)) >y7 : Symbol(y7, Decl(declarationEmitDestructuringObjectLiteralPattern1.ts, 5, 25)) var { y8: b1 } = { x8: 5, y8: "hello" }; +>y8 : Symbol(y8, Decl(declarationEmitDestructuringObjectLiteralPattern1.ts, 6, 25)) >b1 : Symbol(b1, Decl(declarationEmitDestructuringObjectLiteralPattern1.ts, 6, 5)) >x8 : Symbol(x8, Decl(declarationEmitDestructuringObjectLiteralPattern1.ts, 6, 18)) >y8 : Symbol(y8, Decl(declarationEmitDestructuringObjectLiteralPattern1.ts, 6, 25)) var { x9: a2, y9: b2 } = { x9: 5, y9: "hello" }; +>x9 : Symbol(x9, Decl(declarationEmitDestructuringObjectLiteralPattern1.ts, 7, 26)) >a2 : Symbol(a2, Decl(declarationEmitDestructuringObjectLiteralPattern1.ts, 7, 5)) +>y9 : Symbol(y9, Decl(declarationEmitDestructuringObjectLiteralPattern1.ts, 7, 33)) >b2 : Symbol(b2, Decl(declarationEmitDestructuringObjectLiteralPattern1.ts, 7, 13)) >x9 : Symbol(x9, Decl(declarationEmitDestructuringObjectLiteralPattern1.ts, 7, 26)) >y9 : Symbol(y9, Decl(declarationEmitDestructuringObjectLiteralPattern1.ts, 7, 33)) diff --git a/tests/baselines/reference/declarationEmitDestructuringObjectLiteralPattern2.symbols b/tests/baselines/reference/declarationEmitDestructuringObjectLiteralPattern2.symbols index 76440b60038..77e26e2c9b7 100644 --- a/tests/baselines/reference/declarationEmitDestructuringObjectLiteralPattern2.symbols +++ b/tests/baselines/reference/declarationEmitDestructuringObjectLiteralPattern2.symbols @@ -1,8 +1,13 @@ === tests/cases/compiler/declarationEmitDestructuringObjectLiteralPattern2.ts === var { a: x11, b: { a: y11, b: { a: z11 }}} = { a: 1, b: { a: "hello", b: { a: true } } }; +>a : Symbol(a, Decl(declarationEmitDestructuringObjectLiteralPattern2.ts, 1, 46)) >x11 : Symbol(x11, Decl(declarationEmitDestructuringObjectLiteralPattern2.ts, 1, 5)) +>b : Symbol(b, Decl(declarationEmitDestructuringObjectLiteralPattern2.ts, 1, 52)) +>a : Symbol(a, Decl(declarationEmitDestructuringObjectLiteralPattern2.ts, 1, 57)) >y11 : Symbol(y11, Decl(declarationEmitDestructuringObjectLiteralPattern2.ts, 1, 18)) +>b : Symbol(b, Decl(declarationEmitDestructuringObjectLiteralPattern2.ts, 1, 69)) +>a : Symbol(a, Decl(declarationEmitDestructuringObjectLiteralPattern2.ts, 1, 74)) >z11 : Symbol(z11, Decl(declarationEmitDestructuringObjectLiteralPattern2.ts, 1, 31)) >a : Symbol(a, Decl(declarationEmitDestructuringObjectLiteralPattern2.ts, 1, 46)) >b : Symbol(b, Decl(declarationEmitDestructuringObjectLiteralPattern2.ts, 1, 52)) diff --git a/tests/baselines/reference/destructuringObjectBindingPatternAndAssignment1ES5.symbols b/tests/baselines/reference/destructuringObjectBindingPatternAndAssignment1ES5.symbols index 017a7f71e61..718af66047d 100644 --- a/tests/baselines/reference/destructuringObjectBindingPatternAndAssignment1ES5.symbols +++ b/tests/baselines/reference/destructuringObjectBindingPatternAndAssignment1ES5.symbols @@ -19,6 +19,7 @@ var { b1, } = { b1:1, }; >b1 : Symbol(b1, Decl(destructuringObjectBindingPatternAndAssignment1ES5.ts, 11, 15)) var { b2: { b21 } = { b21: "string" } } = { b2: { b21: "world" } }; +>b2 : Symbol(b2, Decl(destructuringObjectBindingPatternAndAssignment1ES5.ts, 12, 44)) >b21 : Symbol(b21, Decl(destructuringObjectBindingPatternAndAssignment1ES5.ts, 12, 11)) >b21 : Symbol(b21, Decl(destructuringObjectBindingPatternAndAssignment1ES5.ts, 12, 21)) >b2 : Symbol(b2, Decl(destructuringObjectBindingPatternAndAssignment1ES5.ts, 12, 44)) @@ -32,6 +33,7 @@ var {b4 = 1}: any = { b4: 100000 }; >b4 : Symbol(b4, Decl(destructuringObjectBindingPatternAndAssignment1ES5.ts, 14, 21)) var {b5: { b52 } } = { b5: { b52 } }; +>b5 : Symbol(b5, Decl(destructuringObjectBindingPatternAndAssignment1ES5.ts, 15, 23)) >b52 : Symbol(b52, Decl(destructuringObjectBindingPatternAndAssignment1ES5.ts, 15, 10)) >b5 : Symbol(b5, Decl(destructuringObjectBindingPatternAndAssignment1ES5.ts, 15, 23)) >b52 : Symbol(b52, Decl(destructuringObjectBindingPatternAndAssignment1ES5.ts, 15, 29)) diff --git a/tests/baselines/reference/destructuringObjectBindingPatternAndAssignment1ES6.symbols b/tests/baselines/reference/destructuringObjectBindingPatternAndAssignment1ES6.symbols index 11289210ee4..57d739cbbfc 100644 --- a/tests/baselines/reference/destructuringObjectBindingPatternAndAssignment1ES6.symbols +++ b/tests/baselines/reference/destructuringObjectBindingPatternAndAssignment1ES6.symbols @@ -19,6 +19,7 @@ var { b1, } = { b1:1, }; >b1 : Symbol(b1, Decl(destructuringObjectBindingPatternAndAssignment1ES6.ts, 11, 15)) var { b2: { b21 } = { b21: "string" } } = { b2: { b21: "world" } }; +>b2 : Symbol(b2, Decl(destructuringObjectBindingPatternAndAssignment1ES6.ts, 12, 44)) >b21 : Symbol(b21, Decl(destructuringObjectBindingPatternAndAssignment1ES6.ts, 12, 11)) >b21 : Symbol(b21, Decl(destructuringObjectBindingPatternAndAssignment1ES6.ts, 12, 21)) >b2 : Symbol(b2, Decl(destructuringObjectBindingPatternAndAssignment1ES6.ts, 12, 44)) @@ -32,6 +33,7 @@ var {b4 = 1}: any = { b4: 100000 }; >b4 : Symbol(b4, Decl(destructuringObjectBindingPatternAndAssignment1ES6.ts, 14, 21)) var {b5: { b52 } } = { b5: { b52 } }; +>b5 : Symbol(b5, Decl(destructuringObjectBindingPatternAndAssignment1ES6.ts, 15, 23)) >b52 : Symbol(b52, Decl(destructuringObjectBindingPatternAndAssignment1ES6.ts, 15, 10)) >b5 : Symbol(b5, Decl(destructuringObjectBindingPatternAndAssignment1ES6.ts, 15, 23)) >b52 : Symbol(b52, Decl(destructuringObjectBindingPatternAndAssignment1ES6.ts, 15, 29)) diff --git a/tests/baselines/reference/destructuringParameterDeclaration1ES5.errors.txt b/tests/baselines/reference/destructuringParameterDeclaration1ES5.errors.txt index 269d2b5640d..8e51c2b6111 100644 --- a/tests/baselines/reference/destructuringParameterDeclaration1ES5.errors.txt +++ b/tests/baselines/reference/destructuringParameterDeclaration1ES5.errors.txt @@ -1,16 +1,8 @@ -tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration1ES5.ts(32,4): error TS2345: Argument of type '[string, number, number]' is not assignable to parameter of type '[undefined, null, undefined]'. - Types of property '0' are incompatible. - Type 'string' is not assignable to type 'undefined'. -tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration1ES5.ts(33,4): error TS2345: Argument of type '[[string], number, [[boolean, boolean]]]' is not assignable to parameter of type '[[undefined], undefined, [[undefined, undefined]]]'. - Types of property '0' are incompatible. - Type '[string]' is not assignable to type '[undefined]'. - Types of property '0' are incompatible. - Type 'string' is not assignable to type 'undefined'. tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration1ES5.ts(62,10): error TS2393: Duplicate function implementation. tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration1ES5.ts(63,10): error TS2393: Duplicate function implementation. -==== tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration1ES5.ts (4 errors) ==== +==== tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration1ES5.ts (2 errors) ==== // A parameter declaration may specify either an identifier or a binding pattern. // The identifiers specified in parameter declarations and binding patterns // in a parameter list must be unique within that parameter list. @@ -43,17 +35,7 @@ tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration1ES5. b2("string", { x: 200, y: "string" }); b2("string", { x: 200, y: true }); b6(["string", 1, 2]); // Shouldn't be an error - ~~~~~~~~~~~~~~~~ -!!! error TS2345: Argument of type '[string, number, number]' is not assignable to parameter of type '[undefined, null, undefined]'. -!!! error TS2345: Types of property '0' are incompatible. -!!! error TS2345: Type 'string' is not assignable to type 'undefined'. b7([["string"], 1, [[true, false]]]); // Shouldn't be an error - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2345: Argument of type '[[string], number, [[boolean, boolean]]]' is not assignable to parameter of type '[[undefined], undefined, [[undefined, undefined]]]'. -!!! error TS2345: Types of property '0' are incompatible. -!!! error TS2345: Type '[string]' is not assignable to type '[undefined]'. -!!! error TS2345: Types of property '0' are incompatible. -!!! error TS2345: Type 'string' is not assignable to type 'undefined'. // If the declaration specifies a binding pattern, the parameter type is the implied type of that binding pattern (section 5.1.3) diff --git a/tests/baselines/reference/destructuringVariableDeclaration1ES5.symbols b/tests/baselines/reference/destructuringVariableDeclaration1ES5.symbols index 2a2f2a358ca..924527bf1b4 100644 --- a/tests/baselines/reference/destructuringVariableDeclaration1ES5.symbols +++ b/tests/baselines/reference/destructuringVariableDeclaration1ES5.symbols @@ -17,6 +17,7 @@ var [a3, [[a4]], a5]: [number, [[string]], boolean] = [1, [["hello"]], true]; // The type T associated with a destructuring variable declaration is determined as follows: // Otherwise, if the declaration includes an initializer expression, T is the type of that initializer expression. var { b1: { b11 } = { b11: "string" } } = { b1: { b11: "world" } }; +>b1 : Symbol(b1, Decl(destructuringVariableDeclaration1ES5.ts, 7, 44)) >b11 : Symbol(b11, Decl(destructuringVariableDeclaration1ES5.ts, 7, 11)) >b11 : Symbol(b11, Decl(destructuringVariableDeclaration1ES5.ts, 7, 21)) >b1 : Symbol(b1, Decl(destructuringVariableDeclaration1ES5.ts, 7, 44)) @@ -74,6 +75,7 @@ var [d3, d4] = [1, "string", ...temp1]; // Combining both forms of destructuring, var {e: [e1, e2, e3 = { b1: 1000, b4: 200 }]} = { e: [1, 2, { b1: 4, b4: 0 }] }; +>e : Symbol(e, Decl(destructuringVariableDeclaration1ES5.ts, 31, 49)) >e1 : Symbol(e1, Decl(destructuringVariableDeclaration1ES5.ts, 31, 9)) >e2 : Symbol(e2, Decl(destructuringVariableDeclaration1ES5.ts, 31, 12)) >e3 : Symbol(e3, Decl(destructuringVariableDeclaration1ES5.ts, 31, 16)) @@ -84,8 +86,10 @@ var {e: [e1, e2, e3 = { b1: 1000, b4: 200 }]} = { e: [1, 2, { b1: 4, b4: 0 }] }; >b4 : Symbol(b4, Decl(destructuringVariableDeclaration1ES5.ts, 31, 68)) var {f: [f1, f2, { f3: f4, f5 }, , ]} = { f: [1, 2, { f3: 4, f5: 0 }] }; +>f : Symbol(f, Decl(destructuringVariableDeclaration1ES5.ts, 32, 41)) >f1 : Symbol(f1, Decl(destructuringVariableDeclaration1ES5.ts, 32, 9)) >f2 : Symbol(f2, Decl(destructuringVariableDeclaration1ES5.ts, 32, 12)) +>f3 : Symbol(f3, Decl(destructuringVariableDeclaration1ES5.ts, 32, 53)) >f4 : Symbol(f4, Decl(destructuringVariableDeclaration1ES5.ts, 32, 18)) >f5 : Symbol(f5, Decl(destructuringVariableDeclaration1ES5.ts, 32, 26)) >f : Symbol(f, Decl(destructuringVariableDeclaration1ES5.ts, 32, 41)) @@ -96,6 +100,7 @@ var {f: [f1, f2, { f3: f4, f5 }, , ]} = { f: [1, 2, { f3: 4, f5: 0 }] }; // an initializer expression, the type of the initializer expression is required to be assignable // to the widened form of the type associated with the destructuring variable declaration, binding property, or binding element. var {g: {g1 = [undefined, null]}}: { g: { g1: any[] } } = { g: { g1: [1, 2] } }; +>g : Symbol(g, Decl(destructuringVariableDeclaration1ES5.ts, 37, 36)) >g1 : Symbol(g1, Decl(destructuringVariableDeclaration1ES5.ts, 37, 9)) >undefined : Symbol(undefined) >g : Symbol(g, Decl(destructuringVariableDeclaration1ES5.ts, 37, 36)) @@ -104,6 +109,7 @@ var {g: {g1 = [undefined, null]}}: { g: { g1: any[] } } = { g: { g1: [1, 2] } }; >g1 : Symbol(g1, Decl(destructuringVariableDeclaration1ES5.ts, 37, 64)) var {h: {h1 = [undefined, null]}}: { h: { h1: number[] } } = { h: { h1: [1, 2] } }; +>h : Symbol(h, Decl(destructuringVariableDeclaration1ES5.ts, 38, 36)) >h1 : Symbol(h1, Decl(destructuringVariableDeclaration1ES5.ts, 38, 9)) >undefined : Symbol(undefined) >h : Symbol(h, Decl(destructuringVariableDeclaration1ES5.ts, 38, 36)) diff --git a/tests/baselines/reference/destructuringVariableDeclaration1ES6.symbols b/tests/baselines/reference/destructuringVariableDeclaration1ES6.symbols index 0350ff35251..ee4f391eb7a 100644 --- a/tests/baselines/reference/destructuringVariableDeclaration1ES6.symbols +++ b/tests/baselines/reference/destructuringVariableDeclaration1ES6.symbols @@ -17,6 +17,7 @@ var [a3, [[a4]], a5]: [number, [[string]], boolean] = [1, [["hello"]], true]; // The type T associated with a destructuring variable declaration is determined as follows: // Otherwise, if the declaration includes an initializer expression, T is the type of that initializer expression. var { b1: { b11 } = { b11: "string" } } = { b1: { b11: "world" } }; +>b1 : Symbol(b1, Decl(destructuringVariableDeclaration1ES6.ts, 7, 44)) >b11 : Symbol(b11, Decl(destructuringVariableDeclaration1ES6.ts, 7, 11)) >b11 : Symbol(b11, Decl(destructuringVariableDeclaration1ES6.ts, 7, 21)) >b1 : Symbol(b1, Decl(destructuringVariableDeclaration1ES6.ts, 7, 44)) @@ -74,6 +75,7 @@ var [d3, d4] = [1, "string", ...temp1]; // Combining both forms of destructuring, var {e: [e1, e2, e3 = { b1: 1000, b4: 200 }]} = { e: [1, 2, { b1: 4, b4: 0 }] }; +>e : Symbol(e, Decl(destructuringVariableDeclaration1ES6.ts, 31, 49)) >e1 : Symbol(e1, Decl(destructuringVariableDeclaration1ES6.ts, 31, 9)) >e2 : Symbol(e2, Decl(destructuringVariableDeclaration1ES6.ts, 31, 12)) >e3 : Symbol(e3, Decl(destructuringVariableDeclaration1ES6.ts, 31, 16)) @@ -84,8 +86,10 @@ var {e: [e1, e2, e3 = { b1: 1000, b4: 200 }]} = { e: [1, 2, { b1: 4, b4: 0 }] }; >b4 : Symbol(b4, Decl(destructuringVariableDeclaration1ES6.ts, 31, 68)) var {f: [f1, f2, { f3: f4, f5 }, , ]} = { f: [1, 2, { f3: 4, f5: 0 }] }; +>f : Symbol(f, Decl(destructuringVariableDeclaration1ES6.ts, 32, 41)) >f1 : Symbol(f1, Decl(destructuringVariableDeclaration1ES6.ts, 32, 9)) >f2 : Symbol(f2, Decl(destructuringVariableDeclaration1ES6.ts, 32, 12)) +>f3 : Symbol(f3, Decl(destructuringVariableDeclaration1ES6.ts, 32, 53)) >f4 : Symbol(f4, Decl(destructuringVariableDeclaration1ES6.ts, 32, 18)) >f5 : Symbol(f5, Decl(destructuringVariableDeclaration1ES6.ts, 32, 26)) >f : Symbol(f, Decl(destructuringVariableDeclaration1ES6.ts, 32, 41)) @@ -96,6 +100,7 @@ var {f: [f1, f2, { f3: f4, f5 }, , ]} = { f: [1, 2, { f3: 4, f5: 0 }] }; // an initializer expression, the type of the initializer expression is required to be assignable // to the widened form of the type associated with the destructuring variable declaration, binding property, or binding element. var {g: {g1 = [undefined, null]}}: { g: { g1: any[] } } = { g: { g1: [1, 2] } }; +>g : Symbol(g, Decl(destructuringVariableDeclaration1ES6.ts, 37, 36)) >g1 : Symbol(g1, Decl(destructuringVariableDeclaration1ES6.ts, 37, 9)) >undefined : Symbol(undefined) >g : Symbol(g, Decl(destructuringVariableDeclaration1ES6.ts, 37, 36)) @@ -104,6 +109,7 @@ var {g: {g1 = [undefined, null]}}: { g: { g1: any[] } } = { g: { g1: [1, 2] } }; >g1 : Symbol(g1, Decl(destructuringVariableDeclaration1ES6.ts, 37, 64)) var {h: {h1 = [undefined, null]}}: { h: { h1: number[] } } = { h: { h1: [1, 2] } }; +>h : Symbol(h, Decl(destructuringVariableDeclaration1ES6.ts, 38, 36)) >h1 : Symbol(h1, Decl(destructuringVariableDeclaration1ES6.ts, 38, 9)) >undefined : Symbol(undefined) >h : Symbol(h, Decl(destructuringVariableDeclaration1ES6.ts, 38, 36)) diff --git a/tests/baselines/reference/downlevelLetConst12.symbols b/tests/baselines/reference/downlevelLetConst12.symbols index d1c7fe3ea5b..97d6d5eebf8 100644 --- a/tests/baselines/reference/downlevelLetConst12.symbols +++ b/tests/baselines/reference/downlevelLetConst12.symbols @@ -12,6 +12,7 @@ let [baz] = []; >baz : Symbol(baz, Decl(downlevelLetConst12.ts, 6, 5)) let {a: baz2} = { a: 1 }; +>a : Symbol(a, Decl(downlevelLetConst12.ts, 7, 17)) >baz2 : Symbol(baz2, Decl(downlevelLetConst12.ts, 7, 5)) >a : Symbol(a, Decl(downlevelLetConst12.ts, 7, 17)) @@ -19,6 +20,7 @@ const [baz3] = [] >baz3 : Symbol(baz3, Decl(downlevelLetConst12.ts, 9, 7)) const {a: baz4} = { a: 1 }; +>a : Symbol(a, Decl(downlevelLetConst12.ts, 10, 19)) >baz4 : Symbol(baz4, Decl(downlevelLetConst12.ts, 10, 7)) >a : Symbol(a, Decl(downlevelLetConst12.ts, 10, 19)) diff --git a/tests/baselines/reference/downlevelLetConst13.symbols b/tests/baselines/reference/downlevelLetConst13.symbols index 1b06184f2b3..f8cd2e548a9 100644 --- a/tests/baselines/reference/downlevelLetConst13.symbols +++ b/tests/baselines/reference/downlevelLetConst13.symbols @@ -16,10 +16,12 @@ export const [bar2] = [2]; >bar2 : Symbol(bar2, Decl(downlevelLetConst13.ts, 7, 14)) export let {a: bar3} = { a: 1 }; +>a : Symbol(a, Decl(downlevelLetConst13.ts, 8, 24)) >bar3 : Symbol(bar3, Decl(downlevelLetConst13.ts, 8, 12)) >a : Symbol(a, Decl(downlevelLetConst13.ts, 8, 24)) export const {a: bar4} = { a: 1 }; +>a : Symbol(a, Decl(downlevelLetConst13.ts, 9, 26)) >bar4 : Symbol(bar4, Decl(downlevelLetConst13.ts, 9, 14)) >a : Symbol(a, Decl(downlevelLetConst13.ts, 9, 26)) @@ -39,10 +41,12 @@ export module M { >bar6 : Symbol(bar6, Decl(downlevelLetConst13.ts, 15, 18)) export let {a: bar7} = { a: 1 }; +>a : Symbol(a, Decl(downlevelLetConst13.ts, 16, 28)) >bar7 : Symbol(bar7, Decl(downlevelLetConst13.ts, 16, 16)) >a : Symbol(a, Decl(downlevelLetConst13.ts, 16, 28)) export const {a: bar8} = { a: 1 }; +>a : Symbol(a, Decl(downlevelLetConst13.ts, 17, 30)) >bar8 : Symbol(bar8, Decl(downlevelLetConst13.ts, 17, 18)) >a : Symbol(a, Decl(downlevelLetConst13.ts, 17, 30)) } diff --git a/tests/baselines/reference/downlevelLetConst14.symbols b/tests/baselines/reference/downlevelLetConst14.symbols index bf3450af71c..135f3c1417d 100644 --- a/tests/baselines/reference/downlevelLetConst14.symbols +++ b/tests/baselines/reference/downlevelLetConst14.symbols @@ -35,6 +35,7 @@ var z0, z1, z2, z3; >z1 : Symbol(z1, Decl(downlevelLetConst14.ts, 11, 9)) let {a: z2} = { a: 1 }; +>a : Symbol(a, Decl(downlevelLetConst14.ts, 13, 19)) >z2 : Symbol(z2, Decl(downlevelLetConst14.ts, 13, 9)) >a : Symbol(a, Decl(downlevelLetConst14.ts, 13, 19)) @@ -43,6 +44,7 @@ var z0, z1, z2, z3; >z2 : Symbol(z2, Decl(downlevelLetConst14.ts, 13, 9)) let {a: z3} = { a: 1 }; +>a : Symbol(a, Decl(downlevelLetConst14.ts, 15, 19)) >z3 : Symbol(z3, Decl(downlevelLetConst14.ts, 15, 9)) >a : Symbol(a, Decl(downlevelLetConst14.ts, 15, 19)) @@ -86,6 +88,7 @@ var y = true; >y : Symbol(y, Decl(downlevelLetConst14.ts, 29, 11)) let {a: z6} = {a: 1} +>a : Symbol(a, Decl(downlevelLetConst14.ts, 30, 23)) >z6 : Symbol(z6, Decl(downlevelLetConst14.ts, 30, 13)) >a : Symbol(a, Decl(downlevelLetConst14.ts, 30, 23)) @@ -129,6 +132,7 @@ var z5 = 1; >_z : Symbol(_z, Decl(downlevelLetConst14.ts, 46, 11)) let {a: _z5} = { a: 1 }; +>a : Symbol(a, Decl(downlevelLetConst14.ts, 47, 24)) >_z5 : Symbol(_z5, Decl(downlevelLetConst14.ts, 47, 13)) >a : Symbol(a, Decl(downlevelLetConst14.ts, 47, 24)) diff --git a/tests/baselines/reference/downlevelLetConst15.symbols b/tests/baselines/reference/downlevelLetConst15.symbols index 159e5a6d676..00c7e122eb2 100644 --- a/tests/baselines/reference/downlevelLetConst15.symbols +++ b/tests/baselines/reference/downlevelLetConst15.symbols @@ -28,6 +28,7 @@ var z0, z1, z2, z3; >z0 : Symbol(z0, Decl(downlevelLetConst15.ts, 9, 11)) const [{a: z1}] = [{a: 1}] +>a : Symbol(a, Decl(downlevelLetConst15.ts, 11, 24)) >z1 : Symbol(z1, Decl(downlevelLetConst15.ts, 11, 12)) >a : Symbol(a, Decl(downlevelLetConst15.ts, 11, 24)) @@ -36,6 +37,7 @@ var z0, z1, z2, z3; >z1 : Symbol(z1, Decl(downlevelLetConst15.ts, 11, 12)) const {a: z2} = { a: 1 }; +>a : Symbol(a, Decl(downlevelLetConst15.ts, 13, 21)) >z2 : Symbol(z2, Decl(downlevelLetConst15.ts, 13, 11)) >a : Symbol(a, Decl(downlevelLetConst15.ts, 13, 21)) @@ -44,6 +46,8 @@ var z0, z1, z2, z3; >z2 : Symbol(z2, Decl(downlevelLetConst15.ts, 13, 11)) const {a: {b: z3}} = { a: {b: 1} }; +>a : Symbol(a, Decl(downlevelLetConst15.ts, 15, 26)) +>b : Symbol(b, Decl(downlevelLetConst15.ts, 15, 31)) >z3 : Symbol(z3, Decl(downlevelLetConst15.ts, 15, 15)) >a : Symbol(a, Decl(downlevelLetConst15.ts, 15, 26)) >b : Symbol(b, Decl(downlevelLetConst15.ts, 15, 31)) @@ -88,6 +92,7 @@ var y = true; >y : Symbol(y, Decl(downlevelLetConst15.ts, 29, 13)) const {a: z6} = { a: 1 } +>a : Symbol(a, Decl(downlevelLetConst15.ts, 30, 25)) >z6 : Symbol(z6, Decl(downlevelLetConst15.ts, 30, 15)) >a : Symbol(a, Decl(downlevelLetConst15.ts, 30, 25)) @@ -131,6 +136,7 @@ var z5 = 1; >_z : Symbol(_z, Decl(downlevelLetConst15.ts, 46, 13)) const {a: _z5} = { a: 1 }; +>a : Symbol(a, Decl(downlevelLetConst15.ts, 47, 26)) >_z5 : Symbol(_z5, Decl(downlevelLetConst15.ts, 47, 15)) >a : Symbol(a, Decl(downlevelLetConst15.ts, 47, 26)) diff --git a/tests/baselines/reference/emitArrowFunctionES6.symbols b/tests/baselines/reference/emitArrowFunctionES6.symbols index 06f83f7f6f0..8d1603cfd82 100644 --- a/tests/baselines/reference/emitArrowFunctionES6.symbols +++ b/tests/baselines/reference/emitArrowFunctionES6.symbols @@ -56,6 +56,7 @@ var p6 = ({ a }) => { }; var p7 = ({ a: { b } }) => { }; >p7 : Symbol(p7, Decl(emitArrowFunctionES6.ts, 15, 3)) +>a : Symbol(a) >b : Symbol(b, Decl(emitArrowFunctionES6.ts, 15, 16)) var p8 = ({ a = 1 }) => { }; @@ -64,6 +65,7 @@ var p8 = ({ a = 1 }) => { }; var p9 = ({ a: { b = 1 } = { b: 1 } }) => { }; >p9 : Symbol(p9, Decl(emitArrowFunctionES6.ts, 17, 3)) +>a : Symbol(a) >b : Symbol(b, Decl(emitArrowFunctionES6.ts, 17, 16)) >b : Symbol(b, Decl(emitArrowFunctionES6.ts, 17, 28)) diff --git a/tests/baselines/reference/emitArrowFunctionWhenUsingArguments18_ES6.symbols b/tests/baselines/reference/emitArrowFunctionWhenUsingArguments18_ES6.symbols index 4ac60f9b429..707b99c82c1 100644 --- a/tests/baselines/reference/emitArrowFunctionWhenUsingArguments18_ES6.symbols +++ b/tests/baselines/reference/emitArrowFunctionWhenUsingArguments18_ES6.symbols @@ -4,6 +4,7 @@ function f() { >f : Symbol(f, Decl(emitArrowFunctionWhenUsingArguments18_ES6.ts, 0, 0)) var { arguments: args } = { arguments }; +>arguments : Symbol(arguments, Decl(emitArrowFunctionWhenUsingArguments18_ES6.ts, 2, 31)) >args : Symbol(args, Decl(emitArrowFunctionWhenUsingArguments18_ES6.ts, 2, 9)) >arguments : Symbol(arguments, Decl(emitArrowFunctionWhenUsingArguments18_ES6.ts, 2, 31)) diff --git a/tests/baselines/reference/exportDeclarationWithModuleSpecifierNameOnNextLine1.js b/tests/baselines/reference/exportDeclarationWithModuleSpecifierNameOnNextLine1.js new file mode 100644 index 00000000000..a6700fb5e59 --- /dev/null +++ b/tests/baselines/reference/exportDeclarationWithModuleSpecifierNameOnNextLine1.js @@ -0,0 +1,34 @@ +//// [tests/cases/compiler/exportDeclarationWithModuleSpecifierNameOnNextLine1.ts] //// + +//// [t1.ts] + +export var x = "x"; + +//// [t2.ts] +export { x } from + "./t1"; + +//// [t3.ts] +export { } from + "./t1"; + +//// [t4.ts] +export { x as a } from + "./t1"; + +//// [t5.ts] +export { x as a, } from + "./t1"; + +//// [t1.js] +exports.x = "x"; +//// [t2.js] +var t1_1 = require("./t1"); +exports.x = t1_1.x; +//// [t3.js] +//// [t4.js] +var t1_1 = require("./t1"); +exports.a = t1_1.x; +//// [t5.js] +var t1_1 = require("./t1"); +exports.a = t1_1.x; diff --git a/tests/baselines/reference/exportDeclarationWithModuleSpecifierNameOnNextLine1.symbols b/tests/baselines/reference/exportDeclarationWithModuleSpecifierNameOnNextLine1.symbols new file mode 100644 index 00000000000..331766f7712 --- /dev/null +++ b/tests/baselines/reference/exportDeclarationWithModuleSpecifierNameOnNextLine1.symbols @@ -0,0 +1,28 @@ +=== tests/cases/compiler/t1.ts === + +export var x = "x"; +>x : Symbol(x, Decl(t1.ts, 1, 10)) + +=== tests/cases/compiler/t2.ts === +export { x } from +>x : Symbol(x, Decl(t2.ts, 0, 8)) + + "./t1"; + +=== tests/cases/compiler/t3.ts === +export { } from +No type information for this code. "./t1"; +No type information for this code. +No type information for this code.=== tests/cases/compiler/t4.ts === +export { x as a } from +>x : Symbol(a, Decl(t4.ts, 0, 8)) +>a : Symbol(a, Decl(t4.ts, 0, 8)) + + "./t1"; + +=== tests/cases/compiler/t5.ts === +export { x as a, } from +>x : Symbol(a, Decl(t5.ts, 0, 8)) +>a : Symbol(a, Decl(t5.ts, 0, 8)) + + "./t1"; diff --git a/tests/baselines/reference/exportDeclarationWithModuleSpecifierNameOnNextLine1.types b/tests/baselines/reference/exportDeclarationWithModuleSpecifierNameOnNextLine1.types new file mode 100644 index 00000000000..1ad841fe947 --- /dev/null +++ b/tests/baselines/reference/exportDeclarationWithModuleSpecifierNameOnNextLine1.types @@ -0,0 +1,29 @@ +=== tests/cases/compiler/t1.ts === + +export var x = "x"; +>x : string +>"x" : string + +=== tests/cases/compiler/t2.ts === +export { x } from +>x : string + + "./t1"; + +=== tests/cases/compiler/t3.ts === +export { } from +No type information for this code. "./t1"; +No type information for this code. +No type information for this code.=== tests/cases/compiler/t4.ts === +export { x as a } from +>x : string +>a : string + + "./t1"; + +=== tests/cases/compiler/t5.ts === +export { x as a, } from +>x : string +>a : string + + "./t1"; diff --git a/tests/baselines/reference/for-of41.symbols b/tests/baselines/reference/for-of41.symbols index cf8db913919..046361653bb 100644 --- a/tests/baselines/reference/for-of41.symbols +++ b/tests/baselines/reference/for-of41.symbols @@ -6,7 +6,9 @@ var array = [{x: [0], y: {p: ""}}] >p : Symbol(p, Decl(for-of41.ts, 0, 26)) for (var {x: [a], y: {p}} of array) { +>x : Symbol(x, Decl(for-of41.ts, 0, 14)) >a : Symbol(a, Decl(for-of41.ts, 1, 14)) +>y : Symbol(y, Decl(for-of41.ts, 0, 21)) >p : Symbol(p, Decl(for-of41.ts, 1, 22)) >array : Symbol(array, Decl(for-of41.ts, 0, 3)) diff --git a/tests/baselines/reference/for-of42.symbols b/tests/baselines/reference/for-of42.symbols index b310fb1044f..5310f4970b9 100644 --- a/tests/baselines/reference/for-of42.symbols +++ b/tests/baselines/reference/for-of42.symbols @@ -5,7 +5,9 @@ var array = [{ x: "", y: 0 }] >y : Symbol(y, Decl(for-of42.ts, 0, 21)) for (var {x: a, y: b} of array) { +>x : Symbol(x, Decl(for-of42.ts, 0, 14)) >a : Symbol(a, Decl(for-of42.ts, 1, 10)) +>y : Symbol(y, Decl(for-of42.ts, 0, 21)) >b : Symbol(b, Decl(for-of42.ts, 1, 15)) >array : Symbol(array, Decl(for-of42.ts, 0, 3)) diff --git a/tests/baselines/reference/initializePropertiesWithRenamedLet.symbols b/tests/baselines/reference/initializePropertiesWithRenamedLet.symbols index 203508ddf98..f16d8cfc9e0 100644 --- a/tests/baselines/reference/initializePropertiesWithRenamedLet.symbols +++ b/tests/baselines/reference/initializePropertiesWithRenamedLet.symbols @@ -24,6 +24,7 @@ var x, y, z; if (true) { let { x: x } = { x: 0 }; +>x : Symbol(x, Decl(initializePropertiesWithRenamedLet.ts, 10, 20)) >x : Symbol(x, Decl(initializePropertiesWithRenamedLet.ts, 10, 9)) >x : Symbol(x, Decl(initializePropertiesWithRenamedLet.ts, 10, 20)) diff --git a/tests/baselines/reference/letInNonStrictMode.symbols b/tests/baselines/reference/letInNonStrictMode.symbols index 2b854a8c03f..47ba4465d1b 100644 --- a/tests/baselines/reference/letInNonStrictMode.symbols +++ b/tests/baselines/reference/letInNonStrictMode.symbols @@ -3,6 +3,7 @@ let [x] = [1]; >x : Symbol(x, Decl(letInNonStrictMode.ts, 0, 5)) let {a: y} = {a: 1}; +>a : Symbol(a, Decl(letInNonStrictMode.ts, 1, 14)) >y : Symbol(y, Decl(letInNonStrictMode.ts, 1, 5)) >a : Symbol(a, Decl(letInNonStrictMode.ts, 1, 14)) diff --git a/tests/baselines/reference/objectBindingPatternKeywordIdentifiers06.symbols b/tests/baselines/reference/objectBindingPatternKeywordIdentifiers06.symbols index 7cee5f3009b..f0546012498 100644 --- a/tests/baselines/reference/objectBindingPatternKeywordIdentifiers06.symbols +++ b/tests/baselines/reference/objectBindingPatternKeywordIdentifiers06.symbols @@ -1,6 +1,7 @@ === tests/cases/conformance/es6/destructuring/objectBindingPatternKeywordIdentifiers06.ts === var { as: as } = { as: 1 } +>as : Symbol(as, Decl(objectBindingPatternKeywordIdentifiers06.ts, 1, 18)) >as : Symbol(as, Decl(objectBindingPatternKeywordIdentifiers06.ts, 1, 5)) >as : Symbol(as, Decl(objectBindingPatternKeywordIdentifiers06.ts, 1, 18)) diff --git a/tests/baselines/reference/strictModeInConstructor.js b/tests/baselines/reference/strictModeInConstructor.js index 7fd74aa108f..7d1adc48fa0 100644 --- a/tests/baselines/reference/strictModeInConstructor.js +++ b/tests/baselines/reference/strictModeInConstructor.js @@ -74,8 +74,8 @@ var A = (function () { var B = (function (_super) { __extends(B, _super); function B() { - this.s = 9; "use strict"; // No error + this.s = 9; _super.call(this); } return B; diff --git a/tests/baselines/reference/superSymbolIndexedAccess1.js b/tests/baselines/reference/superSymbolIndexedAccess1.js new file mode 100644 index 00000000000..411158bcc7d --- /dev/null +++ b/tests/baselines/reference/superSymbolIndexedAccess1.js @@ -0,0 +1,27 @@ +//// [superSymbolIndexedAccess1.ts] +var symbol = Symbol.for('myThing'); + +class Foo { + [symbol]() { + return 0; + } +} + +class Bar extends Foo { + [symbol]() { + return super[symbol](); + } +} + +//// [superSymbolIndexedAccess1.js] +var symbol = Symbol.for('myThing'); +class Foo { + [symbol]() { + return 0; + } +} +class Bar extends Foo { + [symbol]() { + return super[symbol](); + } +} diff --git a/tests/baselines/reference/superSymbolIndexedAccess1.symbols b/tests/baselines/reference/superSymbolIndexedAccess1.symbols new file mode 100644 index 00000000000..818d0ac52af --- /dev/null +++ b/tests/baselines/reference/superSymbolIndexedAccess1.symbols @@ -0,0 +1,29 @@ +=== tests/cases/conformance/expressions/superPropertyAccess/superSymbolIndexedAccess1.ts === +var symbol = Symbol.for('myThing'); +>symbol : Symbol(symbol, Decl(superSymbolIndexedAccess1.ts, 0, 3)) +>Symbol.for : Symbol(SymbolConstructor.for, Decl(lib.d.ts, 1221, 42)) +>Symbol : Symbol(Symbol, Decl(lib.d.ts, 1199, 52), Decl(lib.d.ts, 1305, 11)) +>for : Symbol(SymbolConstructor.for, Decl(lib.d.ts, 1221, 42)) + +class Foo { +>Foo : Symbol(Foo, Decl(superSymbolIndexedAccess1.ts, 0, 35)) + + [symbol]() { +>symbol : Symbol(symbol, Decl(superSymbolIndexedAccess1.ts, 0, 3)) + + return 0; + } +} + +class Bar extends Foo { +>Bar : Symbol(Bar, Decl(superSymbolIndexedAccess1.ts, 6, 1)) +>Foo : Symbol(Foo, Decl(superSymbolIndexedAccess1.ts, 0, 35)) + + [symbol]() { +>symbol : Symbol(symbol, Decl(superSymbolIndexedAccess1.ts, 0, 3)) + + return super[symbol](); +>super : Symbol(Foo, Decl(superSymbolIndexedAccess1.ts, 0, 35)) +>symbol : Symbol(symbol, Decl(superSymbolIndexedAccess1.ts, 0, 3)) + } +} diff --git a/tests/baselines/reference/superSymbolIndexedAccess1.types b/tests/baselines/reference/superSymbolIndexedAccess1.types new file mode 100644 index 00000000000..af2c6cab156 --- /dev/null +++ b/tests/baselines/reference/superSymbolIndexedAccess1.types @@ -0,0 +1,34 @@ +=== tests/cases/conformance/expressions/superPropertyAccess/superSymbolIndexedAccess1.ts === +var symbol = Symbol.for('myThing'); +>symbol : symbol +>Symbol.for('myThing') : symbol +>Symbol.for : (key: string) => symbol +>Symbol : SymbolConstructor +>for : (key: string) => symbol +>'myThing' : string + +class Foo { +>Foo : Foo + + [symbol]() { +>symbol : symbol + + return 0; +>0 : number + } +} + +class Bar extends Foo { +>Bar : Bar +>Foo : Foo + + [symbol]() { +>symbol : symbol + + return super[symbol](); +>super[symbol]() : any +>super[symbol] : any +>super : Foo +>symbol : symbol + } +} diff --git a/tests/baselines/reference/superSymbolIndexedAccess2.js b/tests/baselines/reference/superSymbolIndexedAccess2.js new file mode 100644 index 00000000000..bc42addc41f --- /dev/null +++ b/tests/baselines/reference/superSymbolIndexedAccess2.js @@ -0,0 +1,25 @@ +//// [superSymbolIndexedAccess2.ts] + +class Foo { + [Symbol.isConcatSpreadable]() { + return 0; + } +} + +class Bar extends Foo { + [Symbol.isConcatSpreadable]() { + return super[Symbol.isConcatSpreadable](); + } +} + +//// [superSymbolIndexedAccess2.js] +class Foo { + [Symbol.isConcatSpreadable]() { + return 0; + } +} +class Bar extends Foo { + [Symbol.isConcatSpreadable]() { + return super[Symbol.isConcatSpreadable](); + } +} diff --git a/tests/baselines/reference/superSymbolIndexedAccess2.symbols b/tests/baselines/reference/superSymbolIndexedAccess2.symbols new file mode 100644 index 00000000000..3865b920647 --- /dev/null +++ b/tests/baselines/reference/superSymbolIndexedAccess2.symbols @@ -0,0 +1,30 @@ +=== tests/cases/conformance/expressions/superPropertyAccess/superSymbolIndexedAccess2.ts === + +class Foo { +>Foo : Symbol(Foo, Decl(superSymbolIndexedAccess2.ts, 0, 0)) + + [Symbol.isConcatSpreadable]() { +>Symbol.isConcatSpreadable : Symbol(SymbolConstructor.isConcatSpreadable, Decl(lib.d.ts, 1243, 24)) +>Symbol : Symbol(Symbol, Decl(lib.d.ts, 1199, 52), Decl(lib.d.ts, 1305, 11)) +>isConcatSpreadable : Symbol(SymbolConstructor.isConcatSpreadable, Decl(lib.d.ts, 1243, 24)) + + return 0; + } +} + +class Bar extends Foo { +>Bar : Symbol(Bar, Decl(superSymbolIndexedAccess2.ts, 5, 1)) +>Foo : Symbol(Foo, Decl(superSymbolIndexedAccess2.ts, 0, 0)) + + [Symbol.isConcatSpreadable]() { +>Symbol.isConcatSpreadable : Symbol(SymbolConstructor.isConcatSpreadable, Decl(lib.d.ts, 1243, 24)) +>Symbol : Symbol(Symbol, Decl(lib.d.ts, 1199, 52), Decl(lib.d.ts, 1305, 11)) +>isConcatSpreadable : Symbol(SymbolConstructor.isConcatSpreadable, Decl(lib.d.ts, 1243, 24)) + + return super[Symbol.isConcatSpreadable](); +>super : Symbol(Foo, Decl(superSymbolIndexedAccess2.ts, 0, 0)) +>Symbol.isConcatSpreadable : Symbol(SymbolConstructor.isConcatSpreadable, Decl(lib.d.ts, 1243, 24)) +>Symbol : Symbol(Symbol, Decl(lib.d.ts, 1199, 52), Decl(lib.d.ts, 1305, 11)) +>isConcatSpreadable : Symbol(SymbolConstructor.isConcatSpreadable, Decl(lib.d.ts, 1243, 24)) + } +} diff --git a/tests/baselines/reference/superSymbolIndexedAccess2.types b/tests/baselines/reference/superSymbolIndexedAccess2.types new file mode 100644 index 00000000000..72bb6914d3e --- /dev/null +++ b/tests/baselines/reference/superSymbolIndexedAccess2.types @@ -0,0 +1,33 @@ +=== tests/cases/conformance/expressions/superPropertyAccess/superSymbolIndexedAccess2.ts === + +class Foo { +>Foo : Foo + + [Symbol.isConcatSpreadable]() { +>Symbol.isConcatSpreadable : symbol +>Symbol : SymbolConstructor +>isConcatSpreadable : symbol + + return 0; +>0 : number + } +} + +class Bar extends Foo { +>Bar : Bar +>Foo : Foo + + [Symbol.isConcatSpreadable]() { +>Symbol.isConcatSpreadable : symbol +>Symbol : SymbolConstructor +>isConcatSpreadable : symbol + + return super[Symbol.isConcatSpreadable](); +>super[Symbol.isConcatSpreadable]() : number +>super[Symbol.isConcatSpreadable] : () => number +>super : Foo +>Symbol.isConcatSpreadable : symbol +>Symbol : SymbolConstructor +>isConcatSpreadable : symbol + } +} diff --git a/tests/baselines/reference/superSymbolIndexedAccess3.errors.txt b/tests/baselines/reference/superSymbolIndexedAccess3.errors.txt new file mode 100644 index 00000000000..7f25510e00b --- /dev/null +++ b/tests/baselines/reference/superSymbolIndexedAccess3.errors.txt @@ -0,0 +1,19 @@ +tests/cases/conformance/expressions/superPropertyAccess/superSymbolIndexedAccess3.ts(11,16): error TS2342: An index expression argument must be of type 'string', 'number', 'symbol, or 'any'. + + +==== tests/cases/conformance/expressions/superPropertyAccess/superSymbolIndexedAccess3.ts (1 errors) ==== + var symbol = Symbol.for('myThing'); + + class Foo { + [symbol]() { + return 0; + } + } + + class Bar extends Foo { + [symbol]() { + return super[Bar](); + ~~~~~~~~~~ +!!! error TS2342: An index expression argument must be of type 'string', 'number', 'symbol, or 'any'. + } + } \ No newline at end of file diff --git a/tests/baselines/reference/superSymbolIndexedAccess3.js b/tests/baselines/reference/superSymbolIndexedAccess3.js new file mode 100644 index 00000000000..439a13c6e6e --- /dev/null +++ b/tests/baselines/reference/superSymbolIndexedAccess3.js @@ -0,0 +1,27 @@ +//// [superSymbolIndexedAccess3.ts] +var symbol = Symbol.for('myThing'); + +class Foo { + [symbol]() { + return 0; + } +} + +class Bar extends Foo { + [symbol]() { + return super[Bar](); + } +} + +//// [superSymbolIndexedAccess3.js] +var symbol = Symbol.for('myThing'); +class Foo { + [symbol]() { + return 0; + } +} +class Bar extends Foo { + [symbol]() { + return super[Bar](); + } +} diff --git a/tests/baselines/reference/superSymbolIndexedAccess4.errors.txt b/tests/baselines/reference/superSymbolIndexedAccess4.errors.txt new file mode 100644 index 00000000000..dbf18c3d00d --- /dev/null +++ b/tests/baselines/reference/superSymbolIndexedAccess4.errors.txt @@ -0,0 +1,13 @@ +tests/cases/conformance/expressions/superPropertyAccess/superSymbolIndexedAccess4.ts(5,16): error TS2335: 'super' can only be referenced in a derived class. + + +==== tests/cases/conformance/expressions/superPropertyAccess/superSymbolIndexedAccess4.ts (1 errors) ==== + var symbol = Symbol.for('myThing'); + + class Bar { + [symbol]() { + return super[symbol](); + ~~~~~ +!!! error TS2335: 'super' can only be referenced in a derived class. + } + } \ No newline at end of file diff --git a/tests/baselines/reference/superSymbolIndexedAccess4.js b/tests/baselines/reference/superSymbolIndexedAccess4.js new file mode 100644 index 00000000000..8d966511fc6 --- /dev/null +++ b/tests/baselines/reference/superSymbolIndexedAccess4.js @@ -0,0 +1,16 @@ +//// [superSymbolIndexedAccess4.ts] +var symbol = Symbol.for('myThing'); + +class Bar { + [symbol]() { + return super[symbol](); + } +} + +//// [superSymbolIndexedAccess4.js] +var symbol = Symbol.for('myThing'); +class Bar { + [symbol]() { + return super[symbol](); + } +} diff --git a/tests/baselines/reference/superSymbolIndexedAccess5.js b/tests/baselines/reference/superSymbolIndexedAccess5.js new file mode 100644 index 00000000000..64a8ac5094c --- /dev/null +++ b/tests/baselines/reference/superSymbolIndexedAccess5.js @@ -0,0 +1,40 @@ +//// [superSymbolIndexedAccess5.ts] +var symbol: any; + +class Foo { + [symbol]() { + return 0; + } +} + +class Bar extends Foo { + [symbol]() { + return super[symbol](); + } +} + +//// [superSymbolIndexedAccess5.js] +var __extends = (this && this.__extends) || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +}; +var symbol; +var Foo = (function () { + function Foo() { + } + Foo.prototype[symbol] = function () { + return 0; + }; + return Foo; +})(); +var Bar = (function (_super) { + __extends(Bar, _super); + function Bar() { + _super.apply(this, arguments); + } + Bar.prototype[symbol] = function () { + return _super.prototype[symbol](); + }; + return Bar; +})(Foo); diff --git a/tests/baselines/reference/superSymbolIndexedAccess5.symbols b/tests/baselines/reference/superSymbolIndexedAccess5.symbols new file mode 100644 index 00000000000..98ff04a25cd --- /dev/null +++ b/tests/baselines/reference/superSymbolIndexedAccess5.symbols @@ -0,0 +1,26 @@ +=== tests/cases/conformance/expressions/superPropertyAccess/superSymbolIndexedAccess5.ts === +var symbol: any; +>symbol : Symbol(symbol, Decl(superSymbolIndexedAccess5.ts, 0, 3)) + +class Foo { +>Foo : Symbol(Foo, Decl(superSymbolIndexedAccess5.ts, 0, 16)) + + [symbol]() { +>symbol : Symbol(symbol, Decl(superSymbolIndexedAccess5.ts, 0, 3)) + + return 0; + } +} + +class Bar extends Foo { +>Bar : Symbol(Bar, Decl(superSymbolIndexedAccess5.ts, 6, 1)) +>Foo : Symbol(Foo, Decl(superSymbolIndexedAccess5.ts, 0, 16)) + + [symbol]() { +>symbol : Symbol(symbol, Decl(superSymbolIndexedAccess5.ts, 0, 3)) + + return super[symbol](); +>super : Symbol(Foo, Decl(superSymbolIndexedAccess5.ts, 0, 16)) +>symbol : Symbol(symbol, Decl(superSymbolIndexedAccess5.ts, 0, 3)) + } +} diff --git a/tests/baselines/reference/superSymbolIndexedAccess5.types b/tests/baselines/reference/superSymbolIndexedAccess5.types new file mode 100644 index 00000000000..abc3ba364b0 --- /dev/null +++ b/tests/baselines/reference/superSymbolIndexedAccess5.types @@ -0,0 +1,29 @@ +=== tests/cases/conformance/expressions/superPropertyAccess/superSymbolIndexedAccess5.ts === +var symbol: any; +>symbol : any + +class Foo { +>Foo : Foo + + [symbol]() { +>symbol : any + + return 0; +>0 : number + } +} + +class Bar extends Foo { +>Bar : Bar +>Foo : Foo + + [symbol]() { +>symbol : any + + return super[symbol](); +>super[symbol]() : any +>super[symbol] : any +>super : Foo +>symbol : any + } +} diff --git a/tests/baselines/reference/superSymbolIndexedAccess6.js b/tests/baselines/reference/superSymbolIndexedAccess6.js new file mode 100644 index 00000000000..e014cf47c1a --- /dev/null +++ b/tests/baselines/reference/superSymbolIndexedAccess6.js @@ -0,0 +1,40 @@ +//// [superSymbolIndexedAccess6.ts] +var symbol: any; + +class Foo { + static [symbol]() { + return 0; + } +} + +class Bar extends Foo { + static [symbol]() { + return super[symbol](); + } +} + +//// [superSymbolIndexedAccess6.js] +var __extends = (this && this.__extends) || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +}; +var symbol; +var Foo = (function () { + function Foo() { + } + Foo[symbol] = function () { + return 0; + }; + return Foo; +})(); +var Bar = (function (_super) { + __extends(Bar, _super); + function Bar() { + _super.apply(this, arguments); + } + Bar[symbol] = function () { + return _super[symbol](); + }; + return Bar; +})(Foo); diff --git a/tests/baselines/reference/superSymbolIndexedAccess6.symbols b/tests/baselines/reference/superSymbolIndexedAccess6.symbols new file mode 100644 index 00000000000..a79a6552674 --- /dev/null +++ b/tests/baselines/reference/superSymbolIndexedAccess6.symbols @@ -0,0 +1,26 @@ +=== tests/cases/conformance/expressions/superPropertyAccess/superSymbolIndexedAccess6.ts === +var symbol: any; +>symbol : Symbol(symbol, Decl(superSymbolIndexedAccess6.ts, 0, 3)) + +class Foo { +>Foo : Symbol(Foo, Decl(superSymbolIndexedAccess6.ts, 0, 16)) + + static [symbol]() { +>symbol : Symbol(symbol, Decl(superSymbolIndexedAccess6.ts, 0, 3)) + + return 0; + } +} + +class Bar extends Foo { +>Bar : Symbol(Bar, Decl(superSymbolIndexedAccess6.ts, 6, 1)) +>Foo : Symbol(Foo, Decl(superSymbolIndexedAccess6.ts, 0, 16)) + + static [symbol]() { +>symbol : Symbol(symbol, Decl(superSymbolIndexedAccess6.ts, 0, 3)) + + return super[symbol](); +>super : Symbol(Foo, Decl(superSymbolIndexedAccess6.ts, 0, 16)) +>symbol : Symbol(symbol, Decl(superSymbolIndexedAccess6.ts, 0, 3)) + } +} diff --git a/tests/baselines/reference/superSymbolIndexedAccess6.types b/tests/baselines/reference/superSymbolIndexedAccess6.types new file mode 100644 index 00000000000..830ade0c685 --- /dev/null +++ b/tests/baselines/reference/superSymbolIndexedAccess6.types @@ -0,0 +1,29 @@ +=== tests/cases/conformance/expressions/superPropertyAccess/superSymbolIndexedAccess6.ts === +var symbol: any; +>symbol : any + +class Foo { +>Foo : Foo + + static [symbol]() { +>symbol : any + + return 0; +>0 : number + } +} + +class Bar extends Foo { +>Bar : Bar +>Foo : Foo + + static [symbol]() { +>symbol : any + + return super[symbol](); +>super[symbol]() : any +>super[symbol] : any +>super : typeof Foo +>symbol : any + } +} diff --git a/tests/baselines/reference/systemModule13.symbols b/tests/baselines/reference/systemModule13.symbols index d9e64335c2b..8245029e006 100644 --- a/tests/baselines/reference/systemModule13.symbols +++ b/tests/baselines/reference/systemModule13.symbols @@ -6,7 +6,10 @@ export let [x,y,z] = [1, 2, 3]; >z : Symbol(z, Decl(systemModule13.ts, 1, 16)) export const {a: z0, b: {c: z1}} = {a: true, b: {c: "123"}}; +>a : Symbol(a, Decl(systemModule13.ts, 2, 36)) >z0 : Symbol(z0, Decl(systemModule13.ts, 2, 14)) +>b : Symbol(b, Decl(systemModule13.ts, 2, 44)) +>c : Symbol(c, Decl(systemModule13.ts, 2, 49)) >z1 : Symbol(z1, Decl(systemModule13.ts, 2, 25)) >a : Symbol(a, Decl(systemModule13.ts, 2, 36)) >b : Symbol(b, Decl(systemModule13.ts, 2, 44)) diff --git a/tests/baselines/reference/systemModule8.symbols b/tests/baselines/reference/systemModule8.symbols index 3365ce7e37d..719d48e4592 100644 --- a/tests/baselines/reference/systemModule8.symbols +++ b/tests/baselines/reference/systemModule8.symbols @@ -78,7 +78,10 @@ export let [y] = [1]; >y : Symbol(y, Decl(systemModule8.ts, 27, 12)) export const {a: z0, b: {c: z1}} = {a: true, b: {c: "123"}}; +>a : Symbol(a, Decl(systemModule8.ts, 28, 36)) >z0 : Symbol(z0, Decl(systemModule8.ts, 28, 14)) +>b : Symbol(b, Decl(systemModule8.ts, 28, 44)) +>c : Symbol(c, Decl(systemModule8.ts, 28, 49)) >z1 : Symbol(z1, Decl(systemModule8.ts, 28, 25)) >a : Symbol(a, Decl(systemModule8.ts, 28, 36)) >b : Symbol(b, Decl(systemModule8.ts, 28, 44)) diff --git a/tests/baselines/reference/typeArgumentInferenceApparentType1.js b/tests/baselines/reference/typeArgumentInferenceApparentType1.js new file mode 100644 index 00000000000..7a4f1ea19f5 --- /dev/null +++ b/tests/baselines/reference/typeArgumentInferenceApparentType1.js @@ -0,0 +1,12 @@ +//// [typeArgumentInferenceApparentType1.ts] +function method(iterable: Iterable): T { + return; +} + +var res: string = method("test"); + +//// [typeArgumentInferenceApparentType1.js] +function method(iterable) { + return; +} +var res = method("test"); diff --git a/tests/baselines/reference/typeArgumentInferenceApparentType1.symbols b/tests/baselines/reference/typeArgumentInferenceApparentType1.symbols new file mode 100644 index 00000000000..abcb8fdfc68 --- /dev/null +++ b/tests/baselines/reference/typeArgumentInferenceApparentType1.symbols @@ -0,0 +1,16 @@ +=== tests/cases/compiler/typeArgumentInferenceApparentType1.ts === +function method(iterable: Iterable): T { +>method : Symbol(method, Decl(typeArgumentInferenceApparentType1.ts, 0, 0)) +>T : Symbol(T, Decl(typeArgumentInferenceApparentType1.ts, 0, 16)) +>iterable : Symbol(iterable, Decl(typeArgumentInferenceApparentType1.ts, 0, 19)) +>Iterable : Symbol(Iterable, Decl(lib.d.ts, 1681, 1)) +>T : Symbol(T, Decl(typeArgumentInferenceApparentType1.ts, 0, 16)) +>T : Symbol(T, Decl(typeArgumentInferenceApparentType1.ts, 0, 16)) + + return; +} + +var res: string = method("test"); +>res : Symbol(res, Decl(typeArgumentInferenceApparentType1.ts, 4, 3)) +>method : Symbol(method, Decl(typeArgumentInferenceApparentType1.ts, 0, 0)) + diff --git a/tests/baselines/reference/typeArgumentInferenceApparentType1.types b/tests/baselines/reference/typeArgumentInferenceApparentType1.types new file mode 100644 index 00000000000..29fd1aeca18 --- /dev/null +++ b/tests/baselines/reference/typeArgumentInferenceApparentType1.types @@ -0,0 +1,18 @@ +=== tests/cases/compiler/typeArgumentInferenceApparentType1.ts === +function method(iterable: Iterable): T { +>method : (iterable: Iterable) => T +>T : T +>iterable : Iterable +>Iterable : Iterable +>T : T +>T : T + + return; +} + +var res: string = method("test"); +>res : string +>method("test") : string +>method : (iterable: Iterable) => T +>"test" : string + diff --git a/tests/baselines/reference/typeArgumentInferenceApparentType2.js b/tests/baselines/reference/typeArgumentInferenceApparentType2.js new file mode 100644 index 00000000000..cf9f3bca00e --- /dev/null +++ b/tests/baselines/reference/typeArgumentInferenceApparentType2.js @@ -0,0 +1,17 @@ +//// [typeArgumentInferenceApparentType2.ts] +function method(iterable: Iterable): T { + function inner>() { + var u: U; + var res: T = method(u); + } + return; +} + +//// [typeArgumentInferenceApparentType2.js] +function method(iterable) { + function inner() { + var u; + var res = method(u); + } + return; +} diff --git a/tests/baselines/reference/typeArgumentInferenceApparentType2.symbols b/tests/baselines/reference/typeArgumentInferenceApparentType2.symbols new file mode 100644 index 00000000000..86cf8e7cdcd --- /dev/null +++ b/tests/baselines/reference/typeArgumentInferenceApparentType2.symbols @@ -0,0 +1,27 @@ +=== tests/cases/compiler/typeArgumentInferenceApparentType2.ts === +function method(iterable: Iterable): T { +>method : Symbol(method, Decl(typeArgumentInferenceApparentType2.ts, 0, 0)) +>T : Symbol(T, Decl(typeArgumentInferenceApparentType2.ts, 0, 16)) +>iterable : Symbol(iterable, Decl(typeArgumentInferenceApparentType2.ts, 0, 19)) +>Iterable : Symbol(Iterable, Decl(lib.d.ts, 1681, 1)) +>T : Symbol(T, Decl(typeArgumentInferenceApparentType2.ts, 0, 16)) +>T : Symbol(T, Decl(typeArgumentInferenceApparentType2.ts, 0, 16)) + + function inner>() { +>inner : Symbol(inner, Decl(typeArgumentInferenceApparentType2.ts, 0, 46)) +>U : Symbol(U, Decl(typeArgumentInferenceApparentType2.ts, 1, 19)) +>Iterable : Symbol(Iterable, Decl(lib.d.ts, 1681, 1)) +>T : Symbol(T, Decl(typeArgumentInferenceApparentType2.ts, 0, 16)) + + var u: U; +>u : Symbol(u, Decl(typeArgumentInferenceApparentType2.ts, 2, 11)) +>U : Symbol(U, Decl(typeArgumentInferenceApparentType2.ts, 1, 19)) + + var res: T = method(u); +>res : Symbol(res, Decl(typeArgumentInferenceApparentType2.ts, 3, 11)) +>T : Symbol(T, Decl(typeArgumentInferenceApparentType2.ts, 0, 16)) +>method : Symbol(method, Decl(typeArgumentInferenceApparentType2.ts, 0, 0)) +>u : Symbol(u, Decl(typeArgumentInferenceApparentType2.ts, 2, 11)) + } + return; +} diff --git a/tests/baselines/reference/typeArgumentInferenceApparentType2.types b/tests/baselines/reference/typeArgumentInferenceApparentType2.types new file mode 100644 index 00000000000..6a0e6ae6454 --- /dev/null +++ b/tests/baselines/reference/typeArgumentInferenceApparentType2.types @@ -0,0 +1,28 @@ +=== tests/cases/compiler/typeArgumentInferenceApparentType2.ts === +function method(iterable: Iterable): T { +>method : (iterable: Iterable) => T +>T : T +>iterable : Iterable +>Iterable : Iterable +>T : T +>T : T + + function inner>() { +>inner : >() => void +>U : U +>Iterable : Iterable +>T : T + + var u: U; +>u : U +>U : U + + var res: T = method(u); +>res : T +>T : T +>method(u) : T +>method : (iterable: Iterable) => T +>u : U + } + return; +} diff --git a/tests/baselines/reference/unclosedExportClause01.errors.txt b/tests/baselines/reference/unclosedExportClause01.errors.txt new file mode 100644 index 00000000000..6590bc5cfed --- /dev/null +++ b/tests/baselines/reference/unclosedExportClause01.errors.txt @@ -0,0 +1,44 @@ +tests/cases/compiler/t2.ts(1,13): error TS2305: Module '"tests/cases/compiler/t1"' has no exported member 'from'. +tests/cases/compiler/t2.ts(1,18): error TS1005: ',' expected. +tests/cases/compiler/t3.ts(1,10): error TS2305: Module '"tests/cases/compiler/t1"' has no exported member 'from'. +tests/cases/compiler/t3.ts(1,15): error TS1005: ',' expected. +tests/cases/compiler/t4.ts(1,17): error TS1005: ',' expected. +tests/cases/compiler/t4.ts(1,17): error TS2305: Module '"tests/cases/compiler/t1"' has no exported member 'from'. +tests/cases/compiler/t4.ts(1,22): error TS1005: ',' expected. +tests/cases/compiler/t5.ts(1,18): error TS2305: Module '"tests/cases/compiler/t1"' has no exported member 'from'. +tests/cases/compiler/t5.ts(1,23): error TS1005: ',' expected. + + +==== tests/cases/compiler/t1.ts (0 errors) ==== + + export var x = "x"; + +==== tests/cases/compiler/t2.ts (2 errors) ==== + export { x, from "./t1" + ~~~~ +!!! error TS2305: Module '"tests/cases/compiler/t1"' has no exported member 'from'. + ~~~~~~ +!!! error TS1005: ',' expected. + +==== tests/cases/compiler/t3.ts (2 errors) ==== + export { from "./t1" + ~~~~ +!!! error TS2305: Module '"tests/cases/compiler/t1"' has no exported member 'from'. + ~~~~~~ +!!! error TS1005: ',' expected. + +==== tests/cases/compiler/t4.ts (3 errors) ==== + export { x as a from "./t1" + ~~~~ +!!! error TS1005: ',' expected. + ~~~~ +!!! error TS2305: Module '"tests/cases/compiler/t1"' has no exported member 'from'. + ~~~~~~ +!!! error TS1005: ',' expected. + +==== tests/cases/compiler/t5.ts (2 errors) ==== + export { x as a, from "./t1" + ~~~~ +!!! error TS2305: Module '"tests/cases/compiler/t1"' has no exported member 'from'. + ~~~~~~ +!!! error TS1005: ',' expected. \ No newline at end of file diff --git a/tests/baselines/reference/unclosedExportClause01.js b/tests/baselines/reference/unclosedExportClause01.js new file mode 100644 index 00000000000..a683f8d987d --- /dev/null +++ b/tests/baselines/reference/unclosedExportClause01.js @@ -0,0 +1,30 @@ +//// [tests/cases/compiler/unclosedExportClause01.ts] //// + +//// [t1.ts] + +export var x = "x"; + +//// [t2.ts] +export { x, from "./t1" + +//// [t3.ts] +export { from "./t1" + +//// [t4.ts] +export { x as a from "./t1" + +//// [t5.ts] +export { x as a, from "./t1" + +//// [t1.js] +exports.x = "x"; +//// [t2.js] +var t1_1 = require("./t1"); +exports.x = t1_1.x; +//// [t3.js] +//// [t4.js] +var t1_1 = require("./t1"); +exports.a = t1_1.x; +//// [t5.js] +var t1_1 = require("./t1"); +exports.a = t1_1.x; diff --git a/tests/baselines/reference/unclosedExportClause02.errors.txt b/tests/baselines/reference/unclosedExportClause02.errors.txt new file mode 100644 index 00000000000..a4809e2c0c3 --- /dev/null +++ b/tests/baselines/reference/unclosedExportClause02.errors.txt @@ -0,0 +1,57 @@ +tests/cases/compiler/t2.ts(1,10): error TS2304: Cannot find name 'x'. +tests/cases/compiler/t2.ts(1,13): error TS2304: Cannot find name 'from'. +tests/cases/compiler/t2.ts(2,5): error TS1005: ',' expected. +tests/cases/compiler/t3.ts(1,10): error TS2304: Cannot find name 'from'. +tests/cases/compiler/t3.ts(2,5): error TS1005: ',' expected. +tests/cases/compiler/t4.ts(1,10): error TS2304: Cannot find name 'x'. +tests/cases/compiler/t4.ts(1,17): error TS1005: ',' expected. +tests/cases/compiler/t4.ts(1,17): error TS2304: Cannot find name 'from'. +tests/cases/compiler/t4.ts(2,5): error TS1005: ',' expected. +tests/cases/compiler/t5.ts(1,10): error TS2304: Cannot find name 'x'. +tests/cases/compiler/t5.ts(1,18): error TS2304: Cannot find name 'from'. +tests/cases/compiler/t5.ts(2,5): error TS1005: ',' expected. + + +==== tests/cases/compiler/t1.ts (0 errors) ==== + + export var x = "x"; + +==== tests/cases/compiler/t2.ts (3 errors) ==== + export { x, from + ~ +!!! error TS2304: Cannot find name 'x'. + ~~~~ +!!! error TS2304: Cannot find name 'from'. + "./t1"; + ~~~~~~ +!!! error TS1005: ',' expected. + +==== tests/cases/compiler/t3.ts (2 errors) ==== + export { from + ~~~~ +!!! error TS2304: Cannot find name 'from'. + "./t1"; + ~~~~~~ +!!! error TS1005: ',' expected. + +==== tests/cases/compiler/t4.ts (4 errors) ==== + export { x as a from + ~ +!!! error TS2304: Cannot find name 'x'. + ~~~~ +!!! error TS1005: ',' expected. + ~~~~ +!!! error TS2304: Cannot find name 'from'. + "./t1"; + ~~~~~~ +!!! error TS1005: ',' expected. + +==== tests/cases/compiler/t5.ts (3 errors) ==== + export { x as a, from + ~ +!!! error TS2304: Cannot find name 'x'. + ~~~~ +!!! error TS2304: Cannot find name 'from'. + "./t1"; + ~~~~~~ +!!! error TS1005: ',' expected. \ No newline at end of file diff --git a/tests/baselines/reference/unclosedExportClause02.js b/tests/baselines/reference/unclosedExportClause02.js new file mode 100644 index 00000000000..964cc29899c --- /dev/null +++ b/tests/baselines/reference/unclosedExportClause02.js @@ -0,0 +1,32 @@ +//// [tests/cases/compiler/unclosedExportClause02.ts] //// + +//// [t1.ts] + +export var x = "x"; + +//// [t2.ts] +export { x, from + "./t1"; + +//// [t3.ts] +export { from + "./t1"; + +//// [t4.ts] +export { x as a from + "./t1"; + +//// [t5.ts] +export { x as a, from + "./t1"; + +//// [t1.js] +exports.x = "x"; +//// [t2.js] +"./t1"; +//// [t3.js] +"./t1"; +//// [t4.js] +"./t1"; +//// [t5.js] +"./t1"; diff --git a/tests/baselines/reference/wideningTuples1.js b/tests/baselines/reference/wideningTuples1.js new file mode 100644 index 00000000000..ed39a735bfe --- /dev/null +++ b/tests/baselines/reference/wideningTuples1.js @@ -0,0 +1,9 @@ +//// [wideningTuples1.ts] +declare function foo(x: T): T; + +var y = foo([undefined]); +y = [""]; + +//// [wideningTuples1.js] +var y = foo([undefined]); +y = [""]; diff --git a/tests/baselines/reference/wideningTuples1.symbols b/tests/baselines/reference/wideningTuples1.symbols new file mode 100644 index 00000000000..819510b7319 --- /dev/null +++ b/tests/baselines/reference/wideningTuples1.symbols @@ -0,0 +1,16 @@ +=== tests/cases/conformance/types/tuple/wideningTuples1.ts === +declare function foo(x: T): T; +>foo : Symbol(foo, Decl(wideningTuples1.ts, 0, 0)) +>T : Symbol(T, Decl(wideningTuples1.ts, 0, 21)) +>x : Symbol(x, Decl(wideningTuples1.ts, 0, 38)) +>T : Symbol(T, Decl(wideningTuples1.ts, 0, 21)) +>T : Symbol(T, Decl(wideningTuples1.ts, 0, 21)) + +var y = foo([undefined]); +>y : Symbol(y, Decl(wideningTuples1.ts, 2, 3)) +>foo : Symbol(foo, Decl(wideningTuples1.ts, 0, 0)) +>undefined : Symbol(undefined) + +y = [""]; +>y : Symbol(y, Decl(wideningTuples1.ts, 2, 3)) + diff --git a/tests/baselines/reference/wideningTuples1.types b/tests/baselines/reference/wideningTuples1.types new file mode 100644 index 00000000000..1fdd4a6cb53 --- /dev/null +++ b/tests/baselines/reference/wideningTuples1.types @@ -0,0 +1,21 @@ +=== tests/cases/conformance/types/tuple/wideningTuples1.ts === +declare function foo(x: T): T; +>foo : (x: T) => T +>T : T +>x : T +>T : T +>T : T + +var y = foo([undefined]); +>y : [any] +>foo([undefined]) : [any] +>foo : (x: T) => T +>[undefined] : [undefined] +>undefined : undefined + +y = [""]; +>y = [""] : [string] +>y : [any] +>[""] : [string] +>"" : string + diff --git a/tests/baselines/reference/wideningTuples2.js b/tests/baselines/reference/wideningTuples2.js new file mode 100644 index 00000000000..fa74e089961 --- /dev/null +++ b/tests/baselines/reference/wideningTuples2.js @@ -0,0 +1,13 @@ +//// [wideningTuples2.ts] +var foo: () => [any] = function bar() { + let intermediate = bar(); + intermediate = [""]; + return [undefined]; +}; + +//// [wideningTuples2.js] +var foo = function bar() { + var intermediate = bar(); + intermediate = [""]; + return [undefined]; +}; diff --git a/tests/baselines/reference/wideningTuples2.symbols b/tests/baselines/reference/wideningTuples2.symbols new file mode 100644 index 00000000000..74186045e90 --- /dev/null +++ b/tests/baselines/reference/wideningTuples2.symbols @@ -0,0 +1,16 @@ +=== tests/cases/conformance/types/tuple/wideningTuples2.ts === +var foo: () => [any] = function bar() { +>foo : Symbol(foo, Decl(wideningTuples2.ts, 0, 3)) +>bar : Symbol(bar, Decl(wideningTuples2.ts, 0, 22)) + + let intermediate = bar(); +>intermediate : Symbol(intermediate, Decl(wideningTuples2.ts, 1, 7)) +>bar : Symbol(bar, Decl(wideningTuples2.ts, 0, 22)) + + intermediate = [""]; +>intermediate : Symbol(intermediate, Decl(wideningTuples2.ts, 1, 7)) + + return [undefined]; +>undefined : Symbol(undefined) + +}; diff --git a/tests/baselines/reference/wideningTuples2.types b/tests/baselines/reference/wideningTuples2.types new file mode 100644 index 00000000000..c07166c53f0 --- /dev/null +++ b/tests/baselines/reference/wideningTuples2.types @@ -0,0 +1,22 @@ +=== tests/cases/conformance/types/tuple/wideningTuples2.ts === +var foo: () => [any] = function bar() { +>foo : () => [any] +>function bar() { let intermediate = bar(); intermediate = [""]; return [undefined];} : () => [any] +>bar : () => [any] + + let intermediate = bar(); +>intermediate : [any] +>bar() : [any] +>bar : () => [any] + + intermediate = [""]; +>intermediate = [""] : [string] +>intermediate : [any] +>[""] : [string] +>"" : string + + return [undefined]; +>[undefined] : [undefined] +>undefined : undefined + +}; diff --git a/tests/baselines/reference/wideningTuples3.errors.txt b/tests/baselines/reference/wideningTuples3.errors.txt new file mode 100644 index 00000000000..43c7e349a0c --- /dev/null +++ b/tests/baselines/reference/wideningTuples3.errors.txt @@ -0,0 +1,9 @@ +tests/cases/conformance/types/tuple/wideningTuples3.ts(3,5): error TS7005: Variable 'b' implicitly has an '[any, any]' type. + + +==== tests/cases/conformance/types/tuple/wideningTuples3.ts (1 errors) ==== + var a: [any]; + + var b = a = [undefined, null]; + ~ +!!! error TS7005: Variable 'b' implicitly has an '[any, any]' type. \ No newline at end of file diff --git a/tests/baselines/reference/wideningTuples3.js b/tests/baselines/reference/wideningTuples3.js new file mode 100644 index 00000000000..dfeaae745d4 --- /dev/null +++ b/tests/baselines/reference/wideningTuples3.js @@ -0,0 +1,8 @@ +//// [wideningTuples3.ts] +var a: [any]; + +var b = a = [undefined, null]; + +//// [wideningTuples3.js] +var a; +var b = a = [undefined, null]; diff --git a/tests/baselines/reference/wideningTuples4.js b/tests/baselines/reference/wideningTuples4.js new file mode 100644 index 00000000000..b4d16a3058b --- /dev/null +++ b/tests/baselines/reference/wideningTuples4.js @@ -0,0 +1,10 @@ +//// [wideningTuples4.ts] +var a: [any]; + +var b = a = [undefined, null]; +b = ["", ""]; + +//// [wideningTuples4.js] +var a; +var b = a = [undefined, null]; +b = ["", ""]; diff --git a/tests/baselines/reference/wideningTuples4.symbols b/tests/baselines/reference/wideningTuples4.symbols new file mode 100644 index 00000000000..95e7cc3cff8 --- /dev/null +++ b/tests/baselines/reference/wideningTuples4.symbols @@ -0,0 +1,12 @@ +=== tests/cases/conformance/types/tuple/wideningTuples4.ts === +var a: [any]; +>a : Symbol(a, Decl(wideningTuples4.ts, 0, 3)) + +var b = a = [undefined, null]; +>b : Symbol(b, Decl(wideningTuples4.ts, 2, 3)) +>a : Symbol(a, Decl(wideningTuples4.ts, 0, 3)) +>undefined : Symbol(undefined) + +b = ["", ""]; +>b : Symbol(b, Decl(wideningTuples4.ts, 2, 3)) + diff --git a/tests/baselines/reference/wideningTuples4.types b/tests/baselines/reference/wideningTuples4.types new file mode 100644 index 00000000000..6d101dd1e01 --- /dev/null +++ b/tests/baselines/reference/wideningTuples4.types @@ -0,0 +1,19 @@ +=== tests/cases/conformance/types/tuple/wideningTuples4.ts === +var a: [any]; +>a : [any] + +var b = a = [undefined, null]; +>b : [any, any] +>a = [undefined, null] : [undefined, null] +>a : [any] +>[undefined, null] : [undefined, null] +>undefined : undefined +>null : null + +b = ["", ""]; +>b = ["", ""] : [string, string] +>b : [any, any] +>["", ""] : [string, string] +>"" : string +>"" : string + diff --git a/tests/baselines/reference/wideningTuples5.errors.txt b/tests/baselines/reference/wideningTuples5.errors.txt new file mode 100644 index 00000000000..bfd72079f55 --- /dev/null +++ b/tests/baselines/reference/wideningTuples5.errors.txt @@ -0,0 +1,10 @@ +tests/cases/conformance/types/tuple/wideningTuples5.ts(1,6): error TS7005: Variable 'a' implicitly has an 'any' type. +tests/cases/conformance/types/tuple/wideningTuples5.ts(1,9): error TS7005: Variable 'b' implicitly has an 'any' type. + + +==== tests/cases/conformance/types/tuple/wideningTuples5.ts (2 errors) ==== + var [a, b] = [undefined, null]; + ~ +!!! error TS7005: Variable 'a' implicitly has an 'any' type. + ~ +!!! error TS7005: Variable 'b' implicitly has an 'any' type. \ No newline at end of file diff --git a/tests/baselines/reference/wideningTuples5.js b/tests/baselines/reference/wideningTuples5.js new file mode 100644 index 00000000000..5763fb3340f --- /dev/null +++ b/tests/baselines/reference/wideningTuples5.js @@ -0,0 +1,5 @@ +//// [wideningTuples5.ts] +var [a, b] = [undefined, null]; + +//// [wideningTuples5.js] +var _a = [undefined, null], a = _a[0], b = _a[1]; diff --git a/tests/baselines/reference/wideningTuples6.js b/tests/baselines/reference/wideningTuples6.js new file mode 100644 index 00000000000..b1d5e8ec0bd --- /dev/null +++ b/tests/baselines/reference/wideningTuples6.js @@ -0,0 +1,9 @@ +//// [wideningTuples6.ts] +var [a, b] = [undefined, null]; +a = ""; +b = ""; + +//// [wideningTuples6.js] +var _a = [undefined, null], a = _a[0], b = _a[1]; +a = ""; +b = ""; diff --git a/tests/baselines/reference/wideningTuples6.symbols b/tests/baselines/reference/wideningTuples6.symbols new file mode 100644 index 00000000000..88de6a7b9b7 --- /dev/null +++ b/tests/baselines/reference/wideningTuples6.symbols @@ -0,0 +1,12 @@ +=== tests/cases/conformance/types/tuple/wideningTuples6.ts === +var [a, b] = [undefined, null]; +>a : Symbol(a, Decl(wideningTuples6.ts, 0, 5)) +>b : Symbol(b, Decl(wideningTuples6.ts, 0, 7)) +>undefined : Symbol(undefined) + +a = ""; +>a : Symbol(a, Decl(wideningTuples6.ts, 0, 5)) + +b = ""; +>b : Symbol(b, Decl(wideningTuples6.ts, 0, 7)) + diff --git a/tests/baselines/reference/wideningTuples6.types b/tests/baselines/reference/wideningTuples6.types new file mode 100644 index 00000000000..d75c0b49e9e --- /dev/null +++ b/tests/baselines/reference/wideningTuples6.types @@ -0,0 +1,18 @@ +=== tests/cases/conformance/types/tuple/wideningTuples6.ts === +var [a, b] = [undefined, null]; +>a : any +>b : any +>[undefined, null] : [undefined, null] +>undefined : undefined +>null : null + +a = ""; +>a = "" : string +>a : any +>"" : string + +b = ""; +>b = "" : string +>b : any +>"" : string + diff --git a/tests/baselines/reference/wideningTuples7.errors.txt b/tests/baselines/reference/wideningTuples7.errors.txt new file mode 100644 index 00000000000..25fd1f58e64 --- /dev/null +++ b/tests/baselines/reference/wideningTuples7.errors.txt @@ -0,0 +1,10 @@ +tests/cases/conformance/types/tuple/wideningTuples7.ts(1,20): error TS7010: 'bar', which lacks return-type annotation, implicitly has an '[any]' return type. + + +==== tests/cases/conformance/types/tuple/wideningTuples7.ts (1 errors) ==== + var foo = function bar() { + ~~~ +!!! error TS7010: 'bar', which lacks return-type annotation, implicitly has an '[any]' return type. + let intermediate: [string]; + return intermediate = [undefined]; + }; \ No newline at end of file diff --git a/tests/baselines/reference/wideningTuples7.js b/tests/baselines/reference/wideningTuples7.js new file mode 100644 index 00000000000..4d94a1909ad --- /dev/null +++ b/tests/baselines/reference/wideningTuples7.js @@ -0,0 +1,11 @@ +//// [wideningTuples7.ts] +var foo = function bar() { + let intermediate: [string]; + return intermediate = [undefined]; +}; + +//// [wideningTuples7.js] +var foo = function bar() { + var intermediate; + return intermediate = [undefined]; +}; diff --git a/tests/cases/compiler/exportDeclarationWithModuleSpecifierNameOnNextLine1.ts b/tests/cases/compiler/exportDeclarationWithModuleSpecifierNameOnNextLine1.ts new file mode 100644 index 00000000000..ea3f55db16b --- /dev/null +++ b/tests/cases/compiler/exportDeclarationWithModuleSpecifierNameOnNextLine1.ts @@ -0,0 +1,20 @@ +// @module: commonjs + +// @filename: t1.ts +export var x = "x"; + +// @filename: t2.ts +export { x } from + "./t1"; + +// @filename: t3.ts +export { } from + "./t1"; + +// @filename: t4.ts +export { x as a } from + "./t1"; + +// @filename: t5.ts +export { x as a, } from + "./t1"; \ No newline at end of file diff --git a/tests/cases/compiler/typeArgumentInferenceApparentType1.ts b/tests/cases/compiler/typeArgumentInferenceApparentType1.ts new file mode 100644 index 00000000000..4cc4a0dd4e5 --- /dev/null +++ b/tests/cases/compiler/typeArgumentInferenceApparentType1.ts @@ -0,0 +1,6 @@ +//@target: ES6 +function method(iterable: Iterable): T { + return; +} + +var res: string = method("test"); \ No newline at end of file diff --git a/tests/cases/compiler/typeArgumentInferenceApparentType2.ts b/tests/cases/compiler/typeArgumentInferenceApparentType2.ts new file mode 100644 index 00000000000..88ae4df8c4c --- /dev/null +++ b/tests/cases/compiler/typeArgumentInferenceApparentType2.ts @@ -0,0 +1,8 @@ +//@target: ES6 +function method(iterable: Iterable): T { + function inner>() { + var u: U; + var res: T = method(u); + } + return; +} \ No newline at end of file diff --git a/tests/cases/compiler/unclosedExportClause01.ts b/tests/cases/compiler/unclosedExportClause01.ts new file mode 100644 index 00000000000..3bcbc713d61 --- /dev/null +++ b/tests/cases/compiler/unclosedExportClause01.ts @@ -0,0 +1,16 @@ +// @module: commonjs + +// @filename: t1.ts +export var x = "x"; + +// @filename: t2.ts +export { x, from "./t1" + +// @filename: t3.ts +export { from "./t1" + +// @filename: t4.ts +export { x as a from "./t1" + +// @filename: t5.ts +export { x as a, from "./t1" \ No newline at end of file diff --git a/tests/cases/compiler/unclosedExportClause02.ts b/tests/cases/compiler/unclosedExportClause02.ts new file mode 100644 index 00000000000..45dcb65a4cb --- /dev/null +++ b/tests/cases/compiler/unclosedExportClause02.ts @@ -0,0 +1,20 @@ +// @module: commonjs + +// @filename: t1.ts +export var x = "x"; + +// @filename: t2.ts +export { x, from + "./t1"; + +// @filename: t3.ts +export { from + "./t1"; + +// @filename: t4.ts +export { x as a from + "./t1"; + +// @filename: t5.ts +export { x as a, from + "./t1"; \ No newline at end of file diff --git a/tests/cases/conformance/expressions/superPropertyAccess/superSymbolIndexedAccess1.ts b/tests/cases/conformance/expressions/superPropertyAccess/superSymbolIndexedAccess1.ts new file mode 100644 index 00000000000..160a76f5c61 --- /dev/null +++ b/tests/cases/conformance/expressions/superPropertyAccess/superSymbolIndexedAccess1.ts @@ -0,0 +1,14 @@ +//@target: ES6 +var symbol = Symbol.for('myThing'); + +class Foo { + [symbol]() { + return 0; + } +} + +class Bar extends Foo { + [symbol]() { + return super[symbol](); + } +} \ No newline at end of file diff --git a/tests/cases/conformance/expressions/superPropertyAccess/superSymbolIndexedAccess2.ts b/tests/cases/conformance/expressions/superPropertyAccess/superSymbolIndexedAccess2.ts new file mode 100644 index 00000000000..3f399d41629 --- /dev/null +++ b/tests/cases/conformance/expressions/superPropertyAccess/superSymbolIndexedAccess2.ts @@ -0,0 +1,13 @@ +//@target: ES6 + +class Foo { + [Symbol.isConcatSpreadable]() { + return 0; + } +} + +class Bar extends Foo { + [Symbol.isConcatSpreadable]() { + return super[Symbol.isConcatSpreadable](); + } +} \ No newline at end of file diff --git a/tests/cases/conformance/expressions/superPropertyAccess/superSymbolIndexedAccess3.ts b/tests/cases/conformance/expressions/superPropertyAccess/superSymbolIndexedAccess3.ts new file mode 100644 index 00000000000..2fbbbdc63e6 --- /dev/null +++ b/tests/cases/conformance/expressions/superPropertyAccess/superSymbolIndexedAccess3.ts @@ -0,0 +1,14 @@ +//@target: ES6 +var symbol = Symbol.for('myThing'); + +class Foo { + [symbol]() { + return 0; + } +} + +class Bar extends Foo { + [symbol]() { + return super[Bar](); + } +} \ No newline at end of file diff --git a/tests/cases/conformance/expressions/superPropertyAccess/superSymbolIndexedAccess4.ts b/tests/cases/conformance/expressions/superPropertyAccess/superSymbolIndexedAccess4.ts new file mode 100644 index 00000000000..095fcc1dbb7 --- /dev/null +++ b/tests/cases/conformance/expressions/superPropertyAccess/superSymbolIndexedAccess4.ts @@ -0,0 +1,8 @@ +//@target: ES6 +var symbol = Symbol.for('myThing'); + +class Bar { + [symbol]() { + return super[symbol](); + } +} \ No newline at end of file diff --git a/tests/cases/conformance/expressions/superPropertyAccess/superSymbolIndexedAccess5.ts b/tests/cases/conformance/expressions/superPropertyAccess/superSymbolIndexedAccess5.ts new file mode 100644 index 00000000000..3c1a376eab6 --- /dev/null +++ b/tests/cases/conformance/expressions/superPropertyAccess/superSymbolIndexedAccess5.ts @@ -0,0 +1,14 @@ +//@target: ES5 +var symbol: any; + +class Foo { + [symbol]() { + return 0; + } +} + +class Bar extends Foo { + [symbol]() { + return super[symbol](); + } +} \ No newline at end of file diff --git a/tests/cases/conformance/expressions/superPropertyAccess/superSymbolIndexedAccess6.ts b/tests/cases/conformance/expressions/superPropertyAccess/superSymbolIndexedAccess6.ts new file mode 100644 index 00000000000..3850821e9f3 --- /dev/null +++ b/tests/cases/conformance/expressions/superPropertyAccess/superSymbolIndexedAccess6.ts @@ -0,0 +1,14 @@ +//@target: ES5 +var symbol: any; + +class Foo { + static [symbol]() { + return 0; + } +} + +class Bar extends Foo { + static [symbol]() { + return super[symbol](); + } +} \ No newline at end of file diff --git a/tests/cases/conformance/types/tuple/wideningTuples1.ts b/tests/cases/conformance/types/tuple/wideningTuples1.ts new file mode 100644 index 00000000000..f4885435dcf --- /dev/null +++ b/tests/cases/conformance/types/tuple/wideningTuples1.ts @@ -0,0 +1,5 @@ +//@noImplicitAny: true +declare function foo(x: T): T; + +var y = foo([undefined]); +y = [""]; \ No newline at end of file diff --git a/tests/cases/conformance/types/tuple/wideningTuples2.ts b/tests/cases/conformance/types/tuple/wideningTuples2.ts new file mode 100644 index 00000000000..d8bf1248546 --- /dev/null +++ b/tests/cases/conformance/types/tuple/wideningTuples2.ts @@ -0,0 +1,6 @@ +//@noImplicitAny: true +var foo: () => [any] = function bar() { + let intermediate = bar(); + intermediate = [""]; + return [undefined]; +}; \ No newline at end of file diff --git a/tests/cases/conformance/types/tuple/wideningTuples3.ts b/tests/cases/conformance/types/tuple/wideningTuples3.ts new file mode 100644 index 00000000000..a6837be2a0f --- /dev/null +++ b/tests/cases/conformance/types/tuple/wideningTuples3.ts @@ -0,0 +1,4 @@ +//@noImplicitAny: true +var a: [any]; + +var b = a = [undefined, null]; \ No newline at end of file diff --git a/tests/cases/conformance/types/tuple/wideningTuples4.ts b/tests/cases/conformance/types/tuple/wideningTuples4.ts new file mode 100644 index 00000000000..550ba07f600 --- /dev/null +++ b/tests/cases/conformance/types/tuple/wideningTuples4.ts @@ -0,0 +1,4 @@ +var a: [any]; + +var b = a = [undefined, null]; +b = ["", ""]; \ No newline at end of file diff --git a/tests/cases/conformance/types/tuple/wideningTuples5.ts b/tests/cases/conformance/types/tuple/wideningTuples5.ts new file mode 100644 index 00000000000..36434c6eafe --- /dev/null +++ b/tests/cases/conformance/types/tuple/wideningTuples5.ts @@ -0,0 +1,2 @@ +//@noImplicitAny: true +var [a, b] = [undefined, null]; \ No newline at end of file diff --git a/tests/cases/conformance/types/tuple/wideningTuples6.ts b/tests/cases/conformance/types/tuple/wideningTuples6.ts new file mode 100644 index 00000000000..cac228ecb4d --- /dev/null +++ b/tests/cases/conformance/types/tuple/wideningTuples6.ts @@ -0,0 +1,3 @@ +var [a, b] = [undefined, null]; +a = ""; +b = ""; \ No newline at end of file diff --git a/tests/cases/conformance/types/tuple/wideningTuples7.ts b/tests/cases/conformance/types/tuple/wideningTuples7.ts new file mode 100644 index 00000000000..1a4d212d362 --- /dev/null +++ b/tests/cases/conformance/types/tuple/wideningTuples7.ts @@ -0,0 +1,5 @@ +//@noImplicitAny: true +var foo = function bar() { + let intermediate: [string]; + return intermediate = [undefined]; +}; \ No newline at end of file diff --git a/tests/cases/fourslash/completionListAtIdentifierDefinitionLocations_destructuring.ts b/tests/cases/fourslash/completionListAtIdentifierDefinitionLocations_destructuring.ts index 0812cb138d2..7f8ef32e1ad 100644 --- a/tests/cases/fourslash/completionListAtIdentifierDefinitionLocations_destructuring.ts +++ b/tests/cases/fourslash/completionListAtIdentifierDefinitionLocations_destructuring.ts @@ -16,7 +16,7 @@ //// function func2({ a, b/*parameter2*/ -test.markers().forEach((m) => { +test.markers().forEach(m => { goTo.position(m.position, m.fileName); verify.completionListIsEmpty(); }); diff --git a/tests/cases/fourslash/completionListInExportClause01.ts b/tests/cases/fourslash/completionListInExportClause01.ts new file mode 100644 index 00000000000..12726444bd2 --- /dev/null +++ b/tests/cases/fourslash/completionListInExportClause01.ts @@ -0,0 +1,40 @@ +/// + +// @Filename: m1.ts +////export var foo: number = 1; +////export function bar() { return 10; } +////export function baz() { return 10; } + +// @Filename: m2.ts +////export {/*1*/, /*2*/ from "m1" +////export {/*3*/} from "m1" +////export {foo,/*4*/ from "m1" +////export {bar as /*5*/, /*6*/ from "m1" +////export {foo, bar, baz as b,/*7*/} from "m1" + +function verifyCompletionAtMarker(marker: string, showBuilder: boolean, ...completions: string[]) { + goTo.marker(marker); + if (completions.length) { + for (let completion of completions) { + verify.completionListContains(completion); + } + } + else { + verify.completionListIsEmpty(); + } + + if (showBuilder) { + verify.completionListAllowsNewIdentifier(); + } + else { + verify.not.completionListAllowsNewIdentifier(); + } +} + +verifyCompletionAtMarker("1", /*showBuilder*/ false, "foo", "bar", "baz"); +verifyCompletionAtMarker("2", /*showBuilder*/ false, "foo", "bar", "baz"); +verifyCompletionAtMarker("3", /*showBuilder*/ false, "foo", "bar", "baz"); +verifyCompletionAtMarker("4", /*showBuilder*/ false, "bar", "baz"); +verifyCompletionAtMarker("5", /*showBuilder*/ true); +verifyCompletionAtMarker("6", /*showBuilder*/ false, "foo", "baz"); +verifyCompletionAtMarker("7", /*showBuilder*/ false); \ No newline at end of file diff --git a/tests/cases/fourslash/completionListInExportClause02.ts b/tests/cases/fourslash/completionListInExportClause02.ts new file mode 100644 index 00000000000..4b40976f521 --- /dev/null +++ b/tests/cases/fourslash/completionListInExportClause02.ts @@ -0,0 +1,14 @@ +/// + +////declare module "M1" { +//// export var V; +////} +////var W; +////declare module "M2" { +//// export { /**/ } from "M1" +////} + +goTo.marker(); +verify.completionListContains("V"); +verify.not.completionListContains("W"); +verify.not.completionListAllowsNewIdentifier(); \ No newline at end of file diff --git a/tests/cases/fourslash/completionListInExportClause03.ts b/tests/cases/fourslash/completionListInExportClause03.ts new file mode 100644 index 00000000000..426c85d02ea --- /dev/null +++ b/tests/cases/fourslash/completionListInExportClause03.ts @@ -0,0 +1,16 @@ +/// + +////declare module "M1" { +//// export var abc: number; +//// export var def: string; +////} +//// +////declare module "M2" { +//// export { abc/**/ } from "M1"; +////} + +// Ensure we don't filter out the current item. +goTo.marker(); +verify.completionListContains("abc"); +verify.completionListContains("def"); +verify.not.completionListAllowsNewIdentifier(); \ No newline at end of file diff --git a/tests/cases/fourslash/completionListInImportClause01.ts b/tests/cases/fourslash/completionListInImportClause01.ts index 1191216baf1..2b679ffe550 100644 --- a/tests/cases/fourslash/completionListInImportClause01.ts +++ b/tests/cases/fourslash/completionListInImportClause01.ts @@ -11,6 +11,7 @@ ////import {foo,/*4*/ from "m1" ////import {bar as /*5*/, /*6*/ from "m1" ////import {foo, bar, baz as b,/*7*/} from "m1" + function verifyCompletionAtMarker(marker: string, showBuilder: boolean, ...completions: string[]) { goTo.marker(marker); if (completions.length) { diff --git a/tests/cases/fourslash/completionListInNamespaceImportName01.ts b/tests/cases/fourslash/completionListInNamespaceImportName01.ts new file mode 100644 index 00000000000..ac1c0e13e07 --- /dev/null +++ b/tests/cases/fourslash/completionListInNamespaceImportName01.ts @@ -0,0 +1,11 @@ +/// + +// @Filename: m1.ts +////export var foo: number = 1; + +// @Filename: m2.ts +////import * as /**/ from "m1" + +goTo.marker(); +verify.completionListIsEmpty(); +verify.completionListAllowsNewIdentifier(); \ No newline at end of file diff --git a/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName01.ts b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName01.ts new file mode 100644 index 00000000000..0d03561515d --- /dev/null +++ b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName01.ts @@ -0,0 +1,19 @@ +/// + +////interface I { +//// [|property1|]: number; +//// property2: string; +////} +//// +////var foo: I; +////var { [|property1|]: prop1 } = foo; + +let ranges = test.ranges(); +for (let range of ranges) { + goTo.position(range.start); + + verify.referencesCountIs(ranges.length); + for (let expectedRange of ranges) { + verify.referencesAtPositionContains(expectedRange); + } +} \ No newline at end of file diff --git a/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName02.ts b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName02.ts new file mode 100644 index 00000000000..86514051557 --- /dev/null +++ b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName02.ts @@ -0,0 +1,19 @@ +/// + +////interface I { +//// [|property1|]: number; +//// property2: string; +////} +//// +////var foo: I; +////var { [|property1|]: {} } = foo; + +let ranges = test.ranges(); +for (let range of ranges) { + goTo.position(range.start); + + verify.referencesCountIs(ranges.length); + for (let expectedRange of ranges) { + verify.referencesAtPositionContains(expectedRange); + } +} \ No newline at end of file diff --git a/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName03.ts b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName03.ts new file mode 100644 index 00000000000..304fa9e42e9 --- /dev/null +++ b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName03.ts @@ -0,0 +1,19 @@ +/// + +////interface I { +//// [|property1|]: number; +//// property2: string; +////} +//// +////var foo: I; +////var [{ [|property1|]: prop1 }, { property1, property2 } ] = [foo, foo]; + +let ranges = test.ranges(); +for (let range of ranges) { + goTo.position(range.start); + + verify.referencesCountIs(ranges.length); + for (let expectedRange of ranges) { + verify.referencesAtPositionContains(expectedRange); + } +} \ No newline at end of file diff --git a/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName04.ts b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName04.ts new file mode 100644 index 00000000000..bdb37525f71 --- /dev/null +++ b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName04.ts @@ -0,0 +1,23 @@ +/// + +////interface I { +//// [|property1|]: number; +//// property2: string; +////} +//// +////function f({ /**/[|property1|]: p1 }: I, +//// { /*SHOULD_BE_A_REFERENCE*/property1 }: I, +//// { property1: p2 }) { +//// +//// return property1 + 1; +////} + +// NOTE: In the future, the identifier at +// SHOULD_BE_A_REFERENCE should be in the set of ranges. +goTo.marker(); + +let ranges = test.ranges(); +verify.referencesCountIs(ranges.length); +for (let expectedRange of ranges) { + verify.referencesAtPositionContains(expectedRange); +} \ No newline at end of file diff --git a/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName05.ts b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName05.ts new file mode 100644 index 00000000000..f7e3b80fe45 --- /dev/null +++ b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName05.ts @@ -0,0 +1,13 @@ +/// + +////interface I { +//// property1: number; +//// property2: string; +////} +//// +////function f({ /**/property1: p }, { property1 }) { +//// let x = property1; +////} + +goTo.marker(); +verify.referencesCountIs(0); \ No newline at end of file diff --git a/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName06.ts b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName06.ts new file mode 100644 index 00000000000..67c7029861e --- /dev/null +++ b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName06.ts @@ -0,0 +1,30 @@ +/// + +////interface I { +//// [|property1|]: number; +//// property2: string; +////} +//// +////var elems: I[]; +////for (let { [|property1|]: p } of elems) { +////} +////for (let { property1 } of elems) { +////} +////for (var { [|property1|]: p1 } of elems) { +////} +////var p2; +////for ({ property1 : p2 } of elems) { +////} + +// Note: if this test ever changes, consider updating +// 'quickInfoForObjectBindingElementPropertyName05.ts' + +let ranges = test.ranges(); +for (let range of ranges) { + goTo.position(range.start); + + verify.referencesCountIs(ranges.length); + for (let expectedRange of ranges) { + verify.referencesAtPositionContains(expectedRange); + } +} \ No newline at end of file diff --git a/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName07.ts b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName07.ts new file mode 100644 index 00000000000..6448d2396b3 --- /dev/null +++ b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName07.ts @@ -0,0 +1,15 @@ +/// + +////let p, b; +//// +////p, [{ [|a|]: p, b }] = [{ [|a|]: 10, b: true }]; + +let ranges = test.ranges(); +for (let range of ranges) { + goTo.position(range.start); + + verify.referencesCountIs(ranges.length); + for (let expectedRange of ranges) { + verify.referencesAtPositionContains(expectedRange); + } +} \ No newline at end of file diff --git a/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName09.ts b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName09.ts new file mode 100644 index 00000000000..e45359bcf1c --- /dev/null +++ b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName09.ts @@ -0,0 +1,23 @@ +/// + +////interface I { +//// /*SHOULD_BE_A_REFERENCE1*/property1: number; +//// property2: string; +////} +//// +////function f({ /*SHOULD_BE_A_REFERENCE2*/property1: p1 }: I, +//// { /**/[|property1|] }: I, +//// { property1: p2 }) { +//// +//// return [|property1|] + 1; +////} + +// NOTE: In the future, the identifiers at +// SHOULD_BE_A_REFERENCE[1/2] should be in the set of ranges. +goTo.marker(); + +let ranges = test.ranges(); +verify.referencesCountIs(ranges.length); +for (let expectedRange of ranges) { + verify.referencesAtPositionContains(expectedRange); +} \ No newline at end of file diff --git a/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName10.ts b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName10.ts new file mode 100644 index 00000000000..7b8be1aa91c --- /dev/null +++ b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName10.ts @@ -0,0 +1,19 @@ +/// + +////interface Recursive { +//// [|next|]?: Recursive; +//// value: any; +////} +//// +////function f ({ [|next|]: { [|next|]: x} }: Recursive) { +////} + +let ranges = test.ranges(); +for (let range of ranges) { + goTo.position(range.start); + + verify.referencesCountIs(ranges.length); + for (let expectedRange of ranges) { + verify.referencesAtPositionContains(expectedRange); + } +} \ No newline at end of file diff --git a/tests/cases/fourslash/getOccurrencesAbstract01.ts b/tests/cases/fourslash/getOccurrencesAbstract01.ts new file mode 100644 index 00000000000..3e48ba4841a --- /dev/null +++ b/tests/cases/fourslash/getOccurrencesAbstract01.ts @@ -0,0 +1,24 @@ +/// + +////[|abstract|] class Animal { +//// [|abstract|] prop1; // Does not compile +//// [|abstract|] abstract(); +//// [|abstract|] walk(): void; +//// [|abstract|] makeSound(): void; +////} +////// Abstract class below should not get highlighted +////abstract class Foo { +//// abstract foo(): void; +//// abstract bar(): void; +////} + +const ranges = test.ranges(); + +for (let r of ranges) { + goTo.position(r.start); + verify.occurrencesAtPositionCount(ranges.length); + + for (let range of ranges) { + verify.occurrencesAtPositionContains(range, false); + } +} diff --git a/tests/cases/fourslash/getOccurrencesAbstract02.ts b/tests/cases/fourslash/getOccurrencesAbstract02.ts new file mode 100644 index 00000000000..8daafdbdc8e --- /dev/null +++ b/tests/cases/fourslash/getOccurrencesAbstract02.ts @@ -0,0 +1,29 @@ +/// + +////// Not valid TS (abstract methods can only appear in abstract classes) +////class Animal { +//// [|abstract|] walk(): void; +//// [|abstract|] makeSound(): void; +////} +////// abstract cannot appear here, won't get highlighted +////let c = /*1*/abstract class Foo { +//// /*2*/abstract foo(): void; +//// abstract bar(): void; +////} + +const ranges = test.ranges(); + +for (let r of ranges) { + goTo.position(r.start); + verify.occurrencesAtPositionCount(ranges.length); + + for (let range of ranges) { + verify.occurrencesAtPositionContains(range, false); + } +} + +goTo.marker("1"); +verify.occurrencesAtPositionCount(0); + +goTo.marker("2"); +verify.occurrencesAtPositionCount(2); diff --git a/tests/cases/fourslash/getOccurrencesClassExpressionConstructor.ts b/tests/cases/fourslash/getOccurrencesClassExpressionConstructor.ts new file mode 100644 index 00000000000..5fa778ef8cd --- /dev/null +++ b/tests/cases/fourslash/getOccurrencesClassExpressionConstructor.ts @@ -0,0 +1,23 @@ +/// + +////let A = class Foo { +//// [|constructor|](); +//// [|constructor|](x: number); +//// [|constructor|](y: string); +//// [|constructor|](a?: any) { +//// } +////} +//// +////let B = class D { +//// constructor(x: number) { +//// } +////} + +const ranges = test.ranges(); +for (let r of ranges) { + goTo.position(r.start); + + for (let range of ranges) { + verify.occurrencesAtPositionContains(range, false); + } +} diff --git a/tests/cases/fourslash/getOccurrencesClassExpressionPrivate.ts b/tests/cases/fourslash/getOccurrencesClassExpressionPrivate.ts new file mode 100644 index 00000000000..b008ec237b8 --- /dev/null +++ b/tests/cases/fourslash/getOccurrencesClassExpressionPrivate.ts @@ -0,0 +1,27 @@ +/// + +////let A = class Foo { +//// [|private|] foo; +//// [|private|] private; +//// constructor([|private|] y: string, public x: string) { +//// } +//// [|private|] method() { } +//// public method2() { } +//// [|private|] static static() { } +////} +//// +////let B = class D { +//// constructor(private x: number) { +//// } +//// private test() {} +//// public test2() {} +////} + +const ranges = test.ranges(); +for (let r of ranges) { + goTo.position(r.start); + + for (let range of ranges) { + verify.occurrencesAtPositionContains(range, false); + } +} diff --git a/tests/cases/fourslash/getOccurrencesClassExpressionPublic.ts b/tests/cases/fourslash/getOccurrencesClassExpressionPublic.ts new file mode 100644 index 00000000000..3070fd4f6ca --- /dev/null +++ b/tests/cases/fourslash/getOccurrencesClassExpressionPublic.ts @@ -0,0 +1,27 @@ +/// + +////let A = class Foo { +//// [|public|] foo; +//// [|public|] public; +//// constructor([|public|] y: string, private x: string) { +//// } +//// [|public|] method() { } +//// private method2() {} +//// [|public|] static static() { } +////} +//// +////let B = class D { +//// constructor(private x: number) { +//// } +//// private test() {} +//// public test2() {} +////} + +const ranges = test.ranges(); +for (let r of ranges) { + goTo.position(r.start); + + for (let range of ranges) { + verify.occurrencesAtPositionContains(range, false); + } +} diff --git a/tests/cases/fourslash/getOccurrencesClassExpressionStatic.ts b/tests/cases/fourslash/getOccurrencesClassExpressionStatic.ts new file mode 100644 index 00000000000..567c0c4eccd --- /dev/null +++ b/tests/cases/fourslash/getOccurrencesClassExpressionStatic.ts @@ -0,0 +1,29 @@ +/// + +////let A = class Foo { +//// public static foo; +//// [|static|] a; +//// constructor(public y: string, private x: string) { +//// } +//// public method() { } +//// private method2() {} +//// public [|static|] static() { } +//// private [|static|] static2() { } +////} +//// +////let B = class D { +//// static a; +//// constructor(private x: number) { +//// } +//// private static test() {} +//// public static test2() {} +////} + +const ranges = test.ranges(); +for (let r of ranges) { + goTo.position(r.start); + + for (let range of ranges) { + verify.occurrencesAtPositionContains(range, false); + } +} diff --git a/tests/cases/fourslash/goToDefinitionObjectBindingElementPropertyName01.ts b/tests/cases/fourslash/goToDefinitionObjectBindingElementPropertyName01.ts new file mode 100644 index 00000000000..9348ba05678 --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionObjectBindingElementPropertyName01.ts @@ -0,0 +1,14 @@ +/// + +////interface I { +//// /*def*/property1: number; +//// property2: string; +////} +//// +////var foo: I; +////var { /*use*/property1: prop1 } = foo; + +goTo.marker("use"); +verify.definitionLocationExists(); +goTo.definition(); +verify.caretAtMarker("def"); \ No newline at end of file diff --git a/tests/cases/fourslash/quickInfoForObjectBindingElementName01.ts b/tests/cases/fourslash/quickInfoForObjectBindingElementName01.ts new file mode 100644 index 00000000000..5cba9554b80 --- /dev/null +++ b/tests/cases/fourslash/quickInfoForObjectBindingElementName01.ts @@ -0,0 +1,12 @@ +/// + +////interface I { +//// property1: number; +//// property2: string; +////} +//// +////var foo: I; +////var { /**/property1 } = foo; + +goTo.marker(); +verify.quickInfoIs("var property1: number"); \ No newline at end of file diff --git a/tests/cases/fourslash/quickInfoForObjectBindingElementName02.ts b/tests/cases/fourslash/quickInfoForObjectBindingElementName02.ts new file mode 100644 index 00000000000..e861d3db8fb --- /dev/null +++ b/tests/cases/fourslash/quickInfoForObjectBindingElementName02.ts @@ -0,0 +1,12 @@ +/// + +////interface I { +//// property1: number; +//// property2: string; +////} +//// +////var foo: I; +////var { property1: /**/prop1 } = foo; + +goTo.marker(); +verify.quickInfoIs("var prop1: number"); \ No newline at end of file diff --git a/tests/cases/fourslash/quickInfoForObjectBindingElementPropertyName01.ts b/tests/cases/fourslash/quickInfoForObjectBindingElementPropertyName01.ts new file mode 100644 index 00000000000..52a9af258b3 --- /dev/null +++ b/tests/cases/fourslash/quickInfoForObjectBindingElementPropertyName01.ts @@ -0,0 +1,12 @@ +/// + +////interface I { +//// property1: number; +//// property2: string; +////} +//// +////var foo: I; +////var { /**/property1: prop1 } = foo; + +goTo.marker(); +verify.quickInfoIs("(property) I.property1: number"); \ No newline at end of file diff --git a/tests/cases/fourslash/quickInfoForObjectBindingElementPropertyName02.ts b/tests/cases/fourslash/quickInfoForObjectBindingElementPropertyName02.ts new file mode 100644 index 00000000000..5a166037f1c --- /dev/null +++ b/tests/cases/fourslash/quickInfoForObjectBindingElementPropertyName02.ts @@ -0,0 +1,12 @@ +/// + +////interface I { +//// property1: number; +//// property2: string; +////} +//// +////var foo: I; +////var { /**/property1: {} } = foo; + +goTo.marker(); +verify.quickInfoIs("(property) I.property1: number"); \ No newline at end of file diff --git a/tests/cases/fourslash/quickInfoForObjectBindingElementPropertyName03.ts b/tests/cases/fourslash/quickInfoForObjectBindingElementPropertyName03.ts new file mode 100644 index 00000000000..cfdeef111dc --- /dev/null +++ b/tests/cases/fourslash/quickInfoForObjectBindingElementPropertyName03.ts @@ -0,0 +1,14 @@ +/// + +////interface Recursive { +//// next?: Recursive; +//// value: any; +////} +//// +////function f ({ /*1*/next: { /*2*/next: x} }: Recursive) { +////} + +for (let { position } of test.markers()) { + goTo.position(position) + verify.quickInfoIs("(property) Recursive.next: Recursive"); +} \ No newline at end of file diff --git a/tests/cases/fourslash/quickInfoForObjectBindingElementPropertyName04.ts b/tests/cases/fourslash/quickInfoForObjectBindingElementPropertyName04.ts new file mode 100644 index 00000000000..8b152740861 --- /dev/null +++ b/tests/cases/fourslash/quickInfoForObjectBindingElementPropertyName04.ts @@ -0,0 +1,17 @@ +/// + +////interface Recursive { +//// next?: Recursive; +//// value: any; +////} +//// +////function f ({ /*1*/next: { /*2*/next: x} }) { +////} + +goTo.marker("1"); +verify.quickInfoIs(`(property) next: { + next: any; +}`); + +goTo.marker("2"); +verify.quickInfoIs("(property) next: any"); \ No newline at end of file diff --git a/tests/cases/fourslash/renameObjectBindingElementPropertyName01.ts b/tests/cases/fourslash/renameObjectBindingElementPropertyName01.ts new file mode 100644 index 00000000000..535dbd3d5a3 --- /dev/null +++ b/tests/cases/fourslash/renameObjectBindingElementPropertyName01.ts @@ -0,0 +1,14 @@ +/// + +////interface I { +//// [|property1|]: number; +//// property2: string; +////} +//// +////var foo: I; +////var { [|property1|]: prop1 } = foo; + +for (let range of test.ranges()) { + goTo.position(range.start); + verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false); +} \ No newline at end of file diff --git a/tests/cases/fourslash/shims/getSyntacticClassifications.ts b/tests/cases/fourslash/shims/getSyntacticClassifications.ts index 88f655683a3..1dbe2944b8a 100644 --- a/tests/cases/fourslash/shims/getSyntacticClassifications.ts +++ b/tests/cases/fourslash/shims/getSyntacticClassifications.ts @@ -22,8 +22,8 @@ var c = classification; verify.syntacticClassificationsAre( c.comment("// comment"), c.keyword("module"), c.moduleName("M"), c.punctuation("{"), - c.keyword("var"), c.text("v"), c.operator("="), c.numericLiteral("0"), c.operator("+"), c.numericLiteral("1"), c.punctuation(";"), - c.keyword("var"), c.text("s"), c.operator("="), c.stringLiteral('"string"'), c.punctuation(";"), + c.keyword("var"), c.identifier("v"), c.operator("="), c.numericLiteral("0"), c.operator("+"), c.numericLiteral("1"), c.punctuation(";"), + c.keyword("var"), c.identifier("s"), c.operator("="), c.stringLiteral('"string"'), c.punctuation(";"), c.keyword("class"), c.className("C"), c.punctuation("<"), c.typeParameterName("T"), c.punctuation(">"), c.punctuation("{"), c.punctuation("}"), c.keyword("enum"), c.enumName("E"), c.punctuation("{"), diff --git a/tests/cases/fourslash/syntacticClassificationWithErrors.ts b/tests/cases/fourslash/syntacticClassificationWithErrors.ts index b4572d3e620..166a22a1a51 100644 --- a/tests/cases/fourslash/syntacticClassificationWithErrors.ts +++ b/tests/cases/fourslash/syntacticClassificationWithErrors.ts @@ -8,7 +8,7 @@ let c = classification verify.syntacticClassificationsAre( c.keyword("class"), c.className("A"), c.punctuation("{"), - c.text("a"), c.punctuation(":"), + c.identifier("a"), c.punctuation(":"), c.punctuation("}"), - c.text("c"), c.operator("=") + c.identifier("c"), c.operator("=") ); \ No newline at end of file diff --git a/tests/cases/fourslash/syntacticClassifications1.ts b/tests/cases/fourslash/syntacticClassifications1.ts index 88f655683a3..1dbe2944b8a 100644 --- a/tests/cases/fourslash/syntacticClassifications1.ts +++ b/tests/cases/fourslash/syntacticClassifications1.ts @@ -22,8 +22,8 @@ var c = classification; verify.syntacticClassificationsAre( c.comment("// comment"), c.keyword("module"), c.moduleName("M"), c.punctuation("{"), - c.keyword("var"), c.text("v"), c.operator("="), c.numericLiteral("0"), c.operator("+"), c.numericLiteral("1"), c.punctuation(";"), - c.keyword("var"), c.text("s"), c.operator("="), c.stringLiteral('"string"'), c.punctuation(";"), + c.keyword("var"), c.identifier("v"), c.operator("="), c.numericLiteral("0"), c.operator("+"), c.numericLiteral("1"), c.punctuation(";"), + c.keyword("var"), c.identifier("s"), c.operator("="), c.stringLiteral('"string"'), c.punctuation(";"), c.keyword("class"), c.className("C"), c.punctuation("<"), c.typeParameterName("T"), c.punctuation(">"), c.punctuation("{"), c.punctuation("}"), c.keyword("enum"), c.enumName("E"), c.punctuation("{"), diff --git a/tests/cases/fourslash/syntacticClassificationsConflictMarkers1.ts b/tests/cases/fourslash/syntacticClassificationsConflictMarkers1.ts index 7f26038c33e..99db7443a4c 100644 --- a/tests/cases/fourslash/syntacticClassificationsConflictMarkers1.ts +++ b/tests/cases/fourslash/syntacticClassificationsConflictMarkers1.ts @@ -12,8 +12,8 @@ var c = classification; verify.syntacticClassificationsAre( c.keyword("class"), c.className("C"), c.punctuation("{"), c.comment("<<<<<<< HEAD"), - c.text("v"), c.operator("="), c.numericLiteral("1"), c.punctuation(";"), + c.identifier("v"), c.operator("="), c.numericLiteral("1"), c.punctuation(";"), c.comment("======="), - c.text("v"), c.punctuation("="), c.numericLiteral("2"), c.punctuation(";"), + c.identifier("v"), c.punctuation("="), c.numericLiteral("2"), c.punctuation(";"), c.comment(">>>>>>> Branch - a"), c.punctuation("}")); \ No newline at end of file diff --git a/tests/cases/fourslash/syntacticClassificationsConflictMarkers2.ts b/tests/cases/fourslash/syntacticClassificationsConflictMarkers2.ts index 92ede0d104b..18363c0389e 100644 --- a/tests/cases/fourslash/syntacticClassificationsConflictMarkers2.ts +++ b/tests/cases/fourslash/syntacticClassificationsConflictMarkers2.ts @@ -11,5 +11,5 @@ verify.syntacticClassificationsAre( c.comment("<<<<<<< HEAD"), c.keyword("class"), c.className("C"), c.punctuation("{"), c.punctuation("}"), c.comment("======="), - c.keyword("class"), c.text("D"), c.punctuation("{"), c.punctuation("}"), + c.keyword("class"), c.identifier("D"), c.punctuation("{"), c.punctuation("}"), c.comment(">>>>>>> Branch - a")); \ No newline at end of file diff --git a/tests/cases/fourslash/syntacticClassificationsDocComment1.ts b/tests/cases/fourslash/syntacticClassificationsDocComment1.ts index fe812b4c780..1ea3bf9684a 100644 --- a/tests/cases/fourslash/syntacticClassificationsDocComment1.ts +++ b/tests/cases/fourslash/syntacticClassificationsDocComment1.ts @@ -13,5 +13,5 @@ verify.syntacticClassificationsAre( c.punctuation("}"), c.comment(" */"), c.keyword("var"), - c.text("v"), + c.identifier("v"), c.punctuation(";")); diff --git a/tests/cases/fourslash/syntacticClassificationsDocComment2.ts b/tests/cases/fourslash/syntacticClassificationsDocComment2.ts index 201251dde6d..38dca4edcf2 100644 --- a/tests/cases/fourslash/syntacticClassificationsDocComment2.ts +++ b/tests/cases/fourslash/syntacticClassificationsDocComment2.ts @@ -15,12 +15,12 @@ verify.syntacticClassificationsAre( c.punctuation("{"), c.keyword("function"), c.punctuation("("), - c.text("x"), + c.identifier("x"), c.punctuation(")"), c.punctuation(":"), c.keyword("string"), c.punctuation("}"), c.comment(" */"), c.keyword("var"), - c.text("v"), + c.identifier("v"), c.punctuation(";")); diff --git a/tests/cases/fourslash/syntacticClassificationsDocComment3.ts b/tests/cases/fourslash/syntacticClassificationsDocComment3.ts index 6aca8cc415f..d7996fbbc54 100644 --- a/tests/cases/fourslash/syntacticClassificationsDocComment3.ts +++ b/tests/cases/fourslash/syntacticClassificationsDocComment3.ts @@ -15,5 +15,5 @@ verify.syntacticClassificationsAre( c.keyword("number"), c.comment(" /* } */"), c.keyword("var"), - c.text("v"), + c.identifier("v"), c.punctuation(";")); diff --git a/tests/cases/fourslash/syntacticClassificationsForOfKeyword.ts b/tests/cases/fourslash/syntacticClassificationsForOfKeyword.ts index a7a8c704ce6..22d7aa8ba94 100644 --- a/tests/cases/fourslash/syntacticClassificationsForOfKeyword.ts +++ b/tests/cases/fourslash/syntacticClassificationsForOfKeyword.ts @@ -7,9 +7,9 @@ verify.syntacticClassificationsAre( c.keyword("for"), c.punctuation("("), c.keyword("var"), - c.text("of"), + c.identifier("of"), c.keyword("of"), - c.text("of"), + c.identifier("of"), c.punctuation(")"), c.punctuation("{"), c.punctuation("}") diff --git a/tests/cases/fourslash/syntacticClassificationsForOfKeyword2.ts b/tests/cases/fourslash/syntacticClassificationsForOfKeyword2.ts index 30cfaea51e0..190663caa99 100644 --- a/tests/cases/fourslash/syntacticClassificationsForOfKeyword2.ts +++ b/tests/cases/fourslash/syntacticClassificationsForOfKeyword2.ts @@ -7,9 +7,9 @@ verify.syntacticClassificationsAre( c.keyword("for"), c.punctuation("("), c.keyword("var"), - c.text("of"), + c.identifier("of"), c.keyword("in"), - c.text("of"), + c.identifier("of"), c.punctuation(")"), c.punctuation("{"), c.punctuation("}") diff --git a/tests/cases/fourslash/syntacticClassificationsForOfKeyword3.ts b/tests/cases/fourslash/syntacticClassificationsForOfKeyword3.ts index 3af4733f3b2..ef96c99fed4 100644 --- a/tests/cases/fourslash/syntacticClassificationsForOfKeyword3.ts +++ b/tests/cases/fourslash/syntacticClassificationsForOfKeyword3.ts @@ -7,11 +7,11 @@ verify.syntacticClassificationsAre( c.keyword("for"), c.punctuation("("), c.keyword("var"), - c.text("of"), + c.identifier("of"), c.punctuation(";"), - c.text("of"), + c.identifier("of"), c.punctuation(";"), - c.text("of"), + c.identifier("of"), c.punctuation(")"), c.punctuation("{"), c.punctuation("}") diff --git a/tests/cases/fourslash/syntacticClassificationsFunctionWithComments.ts b/tests/cases/fourslash/syntacticClassificationsFunctionWithComments.ts index f7e5b7355a7..05a5aaa173e 100644 --- a/tests/cases/fourslash/syntacticClassificationsFunctionWithComments.ts +++ b/tests/cases/fourslash/syntacticClassificationsFunctionWithComments.ts @@ -19,7 +19,7 @@ var firstCommentText = var c = classification; verify.syntacticClassificationsAre( c.comment(firstCommentText), - c.keyword("function"), c.text("myFunction"), c.punctuation("("), c.comment("/* x */"), c.parameterName("x"), c.punctuation(":"), c.keyword("any"), c.punctuation(")"), c.punctuation("{"), - c.keyword("var"), c.text("y"), c.operator("="), c.text("x"), c.operator("?"), c.text("x"), c.operator("++"), c.operator(":"), c.operator("++"), c.text("x"), c.punctuation(";"), + c.keyword("function"), c.identifier("myFunction"), c.punctuation("("), c.comment("/* x */"), c.parameterName("x"), c.punctuation(":"), c.keyword("any"), c.punctuation(")"), c.punctuation("{"), + c.keyword("var"), c.identifier("y"), c.operator("="), c.identifier("x"), c.operator("?"), c.identifier("x"), c.operator("++"), c.operator(":"), c.operator("++"), c.identifier("x"), c.punctuation(";"), c.punctuation("}"), c.comment("// end of file")); \ No newline at end of file diff --git a/tests/cases/fourslash/syntacticClassificationsObjectLiteral.ts b/tests/cases/fourslash/syntacticClassificationsObjectLiteral.ts index 59642468ce9..c5bab5181a3 100644 --- a/tests/cases/fourslash/syntacticClassificationsObjectLiteral.ts +++ b/tests/cases/fourslash/syntacticClassificationsObjectLiteral.ts @@ -13,13 +13,13 @@ var c = classification; verify.syntacticClassificationsAre( - c.keyword("var"), c.text("v"), c.operator("="), c.numericLiteral("10e0"), c.punctuation(";"), - c.keyword("var"), c.text("x"), c.operator("="), c.punctuation("{"), - c.text("p1"), c.punctuation(":"), c.numericLiteral("1"), c.punctuation(","), - c.text("p2"), c.punctuation(":"), c.numericLiteral("2"), c.punctuation(","), - c.text("any"), c.punctuation(":"), c.numericLiteral("3"), c.punctuation(","), - c.text("function"), c.punctuation(":"), c.numericLiteral("4"), c.punctuation(","), - c.text("var"), c.punctuation(":"), c.numericLiteral("5"), c.punctuation(","), - c.text("void"), c.punctuation(":"), c.keyword("void"), c.numericLiteral("0"), c.punctuation(","), - c.text("v"), c.punctuation(":"), c.text("v"), c.operator("+="), c.text("v"), c.punctuation(","), + c.keyword("var"), c.identifier("v"), c.operator("="), c.numericLiteral("10e0"), c.punctuation(";"), + c.keyword("var"), c.identifier("x"), c.operator("="), c.punctuation("{"), + c.identifier("p1"), c.punctuation(":"), c.numericLiteral("1"), c.punctuation(","), + c.identifier("p2"), c.punctuation(":"), c.numericLiteral("2"), c.punctuation(","), + c.identifier("any"), c.punctuation(":"), c.numericLiteral("3"), c.punctuation(","), + c.identifier("function"), c.punctuation(":"), c.numericLiteral("4"), c.punctuation(","), + c.identifier("var"), c.punctuation(":"), c.numericLiteral("5"), c.punctuation(","), + c.identifier("void"), c.punctuation(":"), c.keyword("void"), c.numericLiteral("0"), c.punctuation(","), + c.identifier("v"), c.punctuation(":"), c.identifier("v"), c.operator("+="), c.identifier("v"), c.punctuation(","), c.punctuation("}"), c.punctuation(";")); \ No newline at end of file diff --git a/tests/cases/fourslash/syntacticClassificationsTemplates1.ts b/tests/cases/fourslash/syntacticClassificationsTemplates1.ts index 8ee48fb8a11..6c27aab3f40 100644 --- a/tests/cases/fourslash/syntacticClassificationsTemplates1.ts +++ b/tests/cases/fourslash/syntacticClassificationsTemplates1.ts @@ -8,8 +8,8 @@ var c = classification; verify.syntacticClassificationsAre( - c.keyword("var"), c.text("v"), c.operator("="), c.numericLiteral("10e0"), c.punctuation(";"), - c.keyword("var"), c.text("x"), c.operator("="), c.punctuation("{"), - c.text("p1"), c.punctuation(":"), c.stringLiteral("`hello world`"), c.punctuation(","), - c.text("p2"), c.punctuation(":"), c.stringLiteral("`goodbye ${"), c.numericLiteral("0"), c.stringLiteral("} cruel ${"), c.numericLiteral("0"), c.stringLiteral("} world`"), c.punctuation(","), + c.keyword("var"), c.identifier("v"), c.operator("="), c.numericLiteral("10e0"), c.punctuation(";"), + c.keyword("var"), c.identifier("x"), c.operator("="), c.punctuation("{"), + c.identifier("p1"), c.punctuation(":"), c.stringLiteral("`hello world`"), c.punctuation(","), + c.identifier("p2"), c.punctuation(":"), c.stringLiteral("`goodbye ${"), c.numericLiteral("0"), c.stringLiteral("} cruel ${"), c.numericLiteral("0"), c.stringLiteral("} world`"), c.punctuation(","), c.punctuation("}"), c.punctuation(";")); \ No newline at end of file diff --git a/tests/cases/fourslash/syntacticClassificationsTemplates2.ts b/tests/cases/fourslash/syntacticClassificationsTemplates2.ts index 913dc039012..25bb64e78ba 100644 --- a/tests/cases/fourslash/syntacticClassificationsTemplates2.ts +++ b/tests/cases/fourslash/syntacticClassificationsTemplates2.ts @@ -6,6 +6,6 @@ var c = classification; verify.syntacticClassificationsAre( - c.keyword("var"), c.text("tiredOfCanonicalExamples"), c.operator("="), + c.keyword("var"), c.identifier("tiredOfCanonicalExamples"), c.operator("="), c.stringLiteral("`goodbye \"${"), c.stringLiteral("`hello world`"), c.stringLiteral("}\" \nand ${"), c.stringLiteral("`good${"), c.stringLiteral("\" \""), c.stringLiteral("}riddance`"), c.stringLiteral("}`"), c.punctuation(";")); \ No newline at end of file From 2dd71e063a78692e4a20c630847cd873fddf271c Mon Sep 17 00:00:00 2001 From: zhengbli Date: Thu, 16 Jul 2015 16:42:25 -0700 Subject: [PATCH 14/93] Fix fourslash test --- src/harness/fourslash.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 5c8e6bc8981..68a154b4cd4 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -1884,7 +1884,7 @@ module FourSlash { ); assert.equal( expected.join(","), - actual.fileNameList.map( file => { + actual.fileNames.map( file => { return file.replace(this.basePath + "/", ""); }).join(",") ); From bf7c073e633ccffc60872799ab0a4334f6730268 Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Thu, 16 Jul 2015 18:28:58 -0700 Subject: [PATCH 15/93] refactored isInComment, isInString --- src/services/services.ts | 33 ++++++++------------------------- src/services/utilities.ts | 29 +++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 25 deletions(-) diff --git a/src/services/services.ts b/src/services/services.ts index a4a848479f7..d7bcb6c0629 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -5434,7 +5434,7 @@ namespace ts { symbolToIndex: number[]): void { let sourceFile = container.getSourceFile(); - let tripleSlashDirectivePrefixRegex = /^\/\/\/\s* token.getStart(); - } + function isInNonReferenceComment(sourceFile: SourceFile, position: number): boolean { + return isInCommentHelper(sourceFile, position, isNonReferenceComment); - function isInComment(position: number) { - let token = getTokenAtPosition(sourceFile, position); - if (token && position < token.getStart()) { - // First, we have to see if this position actually landed in a comment. - let commentRanges = getLeadingCommentRanges(sourceFile.text, token.pos); - - // Then we want to make sure that it wasn't in a "///<" directive comment - // We don't want to unintentionally update a file name. - return forEach(commentRanges, c => { - if (c.pos < position && position < c.end) { - let commentText = sourceFile.text.substring(c.pos, c.end); - if (!tripleSlashDirectivePrefixRegex.test(commentText)) { - return true; - } - } - }); + function isNonReferenceComment(c: CommentRange): boolean { + let commentText = sourceFile.text.substring(c.pos, c.end); + return !tripleSlashDirectivePrefixRegex.test(commentText); } - - return false; } } diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 5f8859c815e..98d5c2efec4 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -414,6 +414,35 @@ namespace ts { } } } + + export function isInString(sourceFile: SourceFile, position: number) { + let token = getTokenAtPosition(sourceFile, position); + return token && token.kind === SyntaxKind.StringLiteral && position > token.getStart(); + } + + export function isInComment(sourceFile: SourceFile, position: number) { + return isInCommentHelper(sourceFile, position, c => true); + } + + /** + * Returns true if the cursor at position in sourceFile is within a comment that additionally + * satisfies extraCheck, and false otherwise. + */ + export function isInCommentHelper(sourceFile: SourceFile, position: number, + extraCheck: (c: CommentRange) => boolean): boolean { + let token = getTokenAtPosition(sourceFile, position); + + if (token && position < token.getStart()) { + // First, we have to see if this position actually landed in a comment. + let commentRanges = getLeadingCommentRanges(sourceFile.text, token.pos); + + // Then we want to make sure that it wasn't in a "///<" directive comment + // We don't want to unintentionally update a file name. + return forEach(commentRanges, c => c.pos < position && position < c.end && extraCheck(c)); + } + + return false; + } function nodeHasTokens(n: Node): boolean { // If we have a token or node that has a non-zero width, it must have tokens. From aa45967b795387a3e24e89ffafad2097e12e18db Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Fri, 17 Jul 2015 09:12:59 -0700 Subject: [PATCH 16/93] refactored isInComment, isInString --- src/compiler/binder.ts | 4 ++++ src/services/services.ts | 10 ++++++---- src/services/utilities.ts | 13 ++++++++++++- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 336be9d1eda..66b5a0b894d 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -9,7 +9,11 @@ namespace ts { Instantiated = 1, ConstEnumOnly = 2 } + + "/**" + /* /** */ + // /** getDocCommentScaffoldingAtPosition -- TS side! */ export function getModuleInstanceState(node: Node): ModuleInstanceState { // A module is uninstantiated if it contains only // 1. interface declarations, type alias declarations diff --git a/src/services/services.ts b/src/services/services.ts index d7bcb6c0629..876d5646a13 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -6756,19 +6756,21 @@ namespace ts { * be performed. */ function getDocCommentScaffoldingAtPosition(fileName: string, position: number): string { - const nullResult = "/** */"; + const nullResult = "/**"; + const emptyCompletion = "/** */"; let start = new Date().getTime(); let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); log("getDocCommentScaffoldingAtPosition: getCurrentSourceFile: " + (new Date().getTime() - start)); // Check if in comment context - var nodeAtPos = getTokenAtPosition(sourceFile, position); - - return "/** token is : daniel cant copy/paste " + tokenToString(nodeAtPos.kind) + " */"; + if(isInString(sourceFile, position) || isInComment(sourceFile,position)) { return nullResult; } // Get the next non-comment token + var nodeAtPos = getTokenAtPosition(sourceFile, position); + var containingFunction = getAncestor(nodeAtPos, SyntaxKind.FunctionDeclaration); // check if token is a function keyword + if(!containingFunction) { return emptyCompletion; } // Get the parsed object corresponding to the token diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 98d5c2efec4..4c0ce77c522 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -438,7 +438,18 @@ namespace ts { // Then we want to make sure that it wasn't in a "///<" directive comment // We don't want to unintentionally update a file name. - return forEach(commentRanges, c => c.pos < position && position < c.end && extraCheck(c)); + return forEach(commentRanges, c => c.pos < position && + // The end marker of a single-line comment does not include the newline character. + // In the following case, we are inside a comment (^ denotes the cursor position): + // + // // asdf ^\n + // + // But for multi-line comments, we don't want to be inside the comment in the following case: + // /* asdf */^ + // + // Internally, we represent the end of the comment at the newline and closing '/', respectively. + (c.kind == SyntaxKind.SingleLineCommentTrivia ? position <= c.end : position < c.end) && + extraCheck(c)); } return false; From 6d670704a10b65183e2f874db92b510aff88386c Mon Sep 17 00:00:00 2001 From: zhengbli Date: Fri, 17 Jul 2015 15:44:03 -0700 Subject: [PATCH 17/93] fix issue 3884 --- src/lib/dom.generated.d.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib/dom.generated.d.ts b/src/lib/dom.generated.d.ts index 32e8fb45ce4..a8c2334f35d 100644 --- a/src/lib/dom.generated.d.ts +++ b/src/lib/dom.generated.d.ts @@ -11962,7 +11962,7 @@ interface Window extends EventTarget, WindowTimers, WindowSessionStorage, Window onvolumechange: (ev: Event) => any; onwaiting: (ev: Event) => any; opener: Window; - orientation: string; + orientation: number; outerHeight: number; outerWidth: number; pageXOffset: number; @@ -12777,7 +12777,7 @@ declare var onunload: (ev: Event) => any; declare var onvolumechange: (ev: Event) => any; declare var onwaiting: (ev: Event) => any; declare var opener: Window; -declare var orientation: string; +declare var orientation: number; declare var outerHeight: number; declare var outerWidth: number; declare var pageXOffset: number; @@ -12952,4 +12952,4 @@ declare function addEventListener(type: "unload", listener: (ev: Event) => any, declare function addEventListener(type: "volumechange", listener: (ev: Event) => any, useCapture?: boolean): void; declare function addEventListener(type: "waiting", listener: (ev: Event) => any, useCapture?: boolean): void; declare function addEventListener(type: "wheel", listener: (ev: WheelEvent) => any, useCapture?: boolean): void; -declare function addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; \ No newline at end of file +declare function addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; From efd274df38a37ae12da0e07a5c1ce0cea34969ca Mon Sep 17 00:00:00 2001 From: zhengbli Date: Fri, 17 Jul 2015 16:27:13 -0700 Subject: [PATCH 18/93] cr feedback --- src/lib/dom.generated.d.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/dom.generated.d.ts b/src/lib/dom.generated.d.ts index a8c2334f35d..8eec72f1a4c 100644 --- a/src/lib/dom.generated.d.ts +++ b/src/lib/dom.generated.d.ts @@ -11962,7 +11962,7 @@ interface Window extends EventTarget, WindowTimers, WindowSessionStorage, Window onvolumechange: (ev: Event) => any; onwaiting: (ev: Event) => any; opener: Window; - orientation: number; + orientation: string | number; outerHeight: number; outerWidth: number; pageXOffset: number; @@ -12777,7 +12777,7 @@ declare var onunload: (ev: Event) => any; declare var onvolumechange: (ev: Event) => any; declare var onwaiting: (ev: Event) => any; declare var opener: Window; -declare var orientation: number; +declare var orientation: string | number; declare var outerHeight: number; declare var outerWidth: number; declare var pageXOffset: number; From 558f1e34cabd3c537e4267464709ae1ac39c0c4f Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Fri, 17 Jul 2015 16:30:20 -0700 Subject: [PATCH 19/93] Remove Garbage --- src/compiler/binder.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 66b5a0b894d..336be9d1eda 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -9,11 +9,7 @@ namespace ts { Instantiated = 1, ConstEnumOnly = 2 } - - "/**" - /* /** */ - // /** getDocCommentScaffoldingAtPosition -- TS side! */ export function getModuleInstanceState(node: Node): ModuleInstanceState { // A module is uninstantiated if it contains only // 1. interface declarations, type alias declarations From ab340756bc5a54bf61a9179206403d358ecba207 Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Fri, 17 Jul 2015 16:32:29 -0700 Subject: [PATCH 20/93] Get Scaffolding --- src/services/services.ts | 47 +++++++++++++++++++-------------------- src/services/utilities.ts | 14 +++++++++--- 2 files changed, 34 insertions(+), 27 deletions(-) diff --git a/src/services/services.ts b/src/services/services.ts index 876d5646a13..058029af9f4 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -6762,31 +6762,30 @@ namespace ts { let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); log("getDocCommentScaffoldingAtPosition: getCurrentSourceFile: " + (new Date().getTime() - start)); - // Check if in comment context - if(isInString(sourceFile, position) || isInComment(sourceFile,position)) { return nullResult; } + // Check if in a context where we don't want to perform any insertion + if (isInString(sourceFile, position) || isInComment(sourceFile, position)) { + return nullResult; + } - // Get the next non-comment token - var nodeAtPos = getTokenAtPosition(sourceFile, position); - var containingFunction = getAncestor(nodeAtPos, SyntaxKind.FunctionDeclaration); - - // check if token is a function keyword - if(!containingFunction) { return emptyCompletion; } - - // Get the parsed object corresponding to the token - - // get the function's param list - - // map the params to JSDoc declarations. ie: - // foo: T -> '* @param foo ' - - // Get the indentation level - // * perhaps just use the carat's indentation? - - // Recall that the in-comment have one extra whitespace character - - // Create the JSDoc comment string from the parts - - return "/** getDocCommentScaffoldingAtPosition -- TS side! */"; + let nodeAtPos = getTokenAtPosition(sourceFile, position); + let containingFunction = getAncestor(nodeAtPos, SyntaxKind.FunctionDeclaration); + + if (hasDocComment(sourceFile, position) || !containingFunction) { + return emptyCompletion; + } + + let parameters = containingFunction.parameters; + let posLineAndChar = sourceFile.getLineAndCharacterOfPosition(position); + let lineStart = sourceFile.getLineStarts()[posLineAndChar.line]; + + let indentationStr = sourceFile.text.substr(lineStart, posLineAndChar.character).match(/\s*/).toString(); + + let docParams = parameters.map((p, index) => + indentationStr + " * @param " + (p.name.kind === SyntaxKind.Identifier ? (p.name).text : "param" + index.toString()) + "\n"); + + let result = "/**\n" + docParams.reduce((prev, cur) => prev + cur, "") + indentationStr + " */"; + + return result; } function getTodoComments(fileName: string, descriptors: TodoCommentDescriptor[]): TodoComment[] { diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 4c0ce77c522..999b3d30427 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -433,11 +433,8 @@ namespace ts { let token = getTokenAtPosition(sourceFile, position); if (token && position < token.getStart()) { - // First, we have to see if this position actually landed in a comment. let commentRanges = getLeadingCommentRanges(sourceFile.text, token.pos); - // Then we want to make sure that it wasn't in a "///<" directive comment - // We don't want to unintentionally update a file name. return forEach(commentRanges, c => c.pos < position && // The end marker of a single-line comment does not include the newline character. // In the following case, we are inside a comment (^ denotes the cursor position): @@ -455,6 +452,17 @@ namespace ts { return false; } + export function hasDocComment(sourceFile: SourceFile, position: number) { + let token = getTokenAtPosition(sourceFile, position); + + let JSDocPrefixRegex = /^\/\*\*\s*/; + + // First, we have to see if this position actually landed in a comment. + let commentRanges = getLeadingCommentRanges(sourceFile.text, token.pos); + + return forEach(commentRanges, c => JSDocPrefixRegex.test(sourceFile.text.substring(c.pos, c.end))); + } + function nodeHasTokens(n: Node): boolean { // If we have a token or node that has a non-zero width, it must have tokens. // Note, that getWidth() does not take trivia into account. From 784fc89adc76a8f8f5281835ca2d1fcc2d36fb0b Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Fri, 17 Jul 2015 16:32:53 -0700 Subject: [PATCH 21/93] Added Comments and assertions --- src/compiler/core.ts | 9 ++++++++- src/compiler/scanner.ts | 11 +++++++++-- src/compiler/types.ts | 10 +++++----- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index ec171d4aee2..db16975b0fe 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -193,6 +193,13 @@ namespace ts { return array[array.length - 1]; } + /** + * Performs a binary search, finding the index at which 'value' occurs in 'array'. + * If no such index is found, returns the 2's-complement of first index at which + * number[index] exceeds number. + * @param array A sorted array whose first element must be no larger than number + * @param number The value to be searched for in the array. + */ export function binarySearch(array: number[], value: number): number { let low = 0; let high = array.length - 1; @@ -805,4 +812,4 @@ namespace ts { Debug.assert(false, message); } } -} +} diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index 9122cadc287..2e692470cc5 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -320,13 +320,20 @@ namespace ts { /* @internal */ export function computeLineAndCharacterOfPosition(lineStarts: number[], position: number) { + Debug.assert(lineStarts.length && lineStarts[0] === 0, "the first line should start at position 0"); + Debug.assert(0 <= position, "position should be positive"); + let lineNumber = binarySearch(lineStarts, position); if (lineNumber < 0) { // If the actual position was not found, - // the binary search returns the negative value of the next line start + // the binary search returns the 2's-complement of the next line start // e.g. if the line starts at [5, 10, 23, 80] and the position requested was 20 - // then the search will return -2 + // then the search will return -2. + // + // We want the index of the previous line start, so we subtract 1. + // Review 2's-complement if this is confusing. lineNumber = ~lineNumber - 1; + Debug.assert(lineNumber !== -1, "position cannot precede the beginning of the file"); } return { line: lineNumber, diff --git a/src/compiler/types.ts b/src/compiler/types.ts index e0f16a00c2b..cdd814065c5 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -583,9 +583,9 @@ namespace ts { * Several node kinds share function-like features such as a signature, * a name, and a body. These nodes should extend FunctionLikeDeclaration. * Examples: - * FunctionDeclaration - * MethodDeclaration - * AccessorDeclaration + * * FunctionDeclaration + * * MethodDeclaration + * * AccessorDeclaration */ export interface FunctionLikeDeclaration extends SignatureDeclaration { _functionLikeDeclarationBrand: any; @@ -1774,10 +1774,10 @@ namespace ts { StringLike = String | StringLiteral, NumberLike = Number | Enum, ObjectType = Class | Interface | Reference | Tuple | Anonymous, - UnionOrIntersection = Union | Intersection, + UnionOrIntersection = Union | Intersection, StructuredType = ObjectType | Union | Intersection, /* @internal */ - RequiresWidening = ContainsUndefinedOrNull | ContainsObjectLiteral + RequiresWidening = ContainsUndefinedOrNull | ContainsObjectLiteral } // Properties common to all types From 6d174a0f18d6406e16dd527fa24481296f610c71 Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Mon, 20 Jul 2015 18:31:17 -0700 Subject: [PATCH 22/93] Adjust carat after insertion --- src/harness/harnessLanguageService.ts | 2 +- src/services/services.ts | 23 +++++++++++++++++------ src/services/shims.ts | 11 +++++------ 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index c6b472e79e5..bb87fb43609 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -381,7 +381,7 @@ module Harness.LanguageService { getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: ts.FormatCodeOptions): ts.TextChange[] { return unwrapJSONCallResult(this.shim.getFormattingEditsAfterKeystroke(fileName, position, key, JSON.stringify(options))); } - getDocCommentScaffoldingAtPosition(fileName: string, position: number): string { + getDocCommentScaffoldingAtPosition(fileName: string, position: number): ts.TextInsertion { return unwrapJSONCallResult(this.shim.getDocCommentScaffoldingAtPosition(fileName, position)); } getEmitOutput(fileName: string): ts.EmitOutput { diff --git a/src/services/services.ts b/src/services/services.ts index 058029af9f4..f91cfa10f1b 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1035,7 +1035,7 @@ namespace ts { getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions): TextChange[]; getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions): TextChange[]; - getDocCommentScaffoldingAtPosition(fileName: string, position: number): string; + getDocCommentScaffoldingAtPosition(fileName: string, position: number): TextInsertion; getEmitOutput(fileName: string): EmitOutput; @@ -1083,6 +1083,11 @@ namespace ts { newText: string; } + export interface TextInsertion { + newText: string; + cursorOffset: number; + } + export interface RenameLocation { textSpan: TextSpan; fileName: string; @@ -6755,9 +6760,9 @@ namespace ts { * @param position The (character-indexed) position in the file where the check should * be performed. */ - function getDocCommentScaffoldingAtPosition(fileName: string, position: number): string { - const nullResult = "/**"; - const emptyCompletion = "/** */"; + function getDocCommentScaffoldingAtPosition(fileName: string, position: number): TextInsertion { + const nullResult = { newText: "/**", cursorOffset: 3 }; + const emptyCompletion = { newText: "/** */", cursorOffset: 3 }; let start = new Date().getTime(); let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); log("getDocCommentScaffoldingAtPosition: getCurrentSourceFile: " + (new Date().getTime() - start)); @@ -6783,9 +6788,15 @@ namespace ts { let docParams = parameters.map((p, index) => indentationStr + " * @param " + (p.name.kind === SyntaxKind.Identifier ? (p.name).text : "param" + index.toString()) + "\n"); - let result = "/**\n" + docParams.reduce((prev, cur) => prev + cur, "") + indentationStr + " */"; + let result = + /* opening comment */ "/**\n" + + /* first line for function info */ indentationStr + " * \n" + + /* paramters */ docParams.reduce((prev, cur) => prev + cur, "") + + /* closing comment */ indentationStr + " */"; + + let cursorOffset = /* "/**\n" */ 4 + indentationStr.length + /* " * " */ 3; - return result; + return {newText: result, cursorOffset: cursorOffset }; } function getTodoComments(fileName: string, descriptors: TodoCommentDescriptor[]): TodoComment[] { diff --git a/src/services/shims.ts b/src/services/shims.ts index 523ca00056c..0a783a256d2 100644 --- a/src/services/shims.ts +++ b/src/services/shims.ts @@ -205,6 +205,9 @@ namespace ts { getFormattingEditsForDocument(fileName: string, options: string/*Services.FormatCodeOptions*/): string; getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: string/*Services.FormatCodeOptions*/): string; + /** + * Returns JSON-encoded value of the type TextInsertion. + */ getDocCommentScaffoldingAtPosition(fileName: string, position: number): string; getEmitOutput(fileName: string): string; @@ -816,12 +819,8 @@ namespace ts { public getDocCommentScaffoldingAtPosition(fileName: string, position: number): string { return this.forwardJSONCall( "getDocCommentScaffoldingAtPosition('" + fileName + "', " + position + ")", - () => { - var commentText = this.languageService.getDocCommentScaffoldingAtPosition(fileName, position); - return commentText; - } - - ) + () => this.languageService.getDocCommentScaffoldingAtPosition(fileName, position) + ); } /// NAVIGATE TO From 38005e7174b442105ba65b50209dbf6b459c2e17 Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Tue, 21 Jul 2015 14:15:39 -0700 Subject: [PATCH 23/93] Add test harnesses --- src/harness/fourslash.ts | 12 ++++++++++++ src/server/client.ts | 2 +- tests/cases/fourslash/fourslash.ts | 13 +++++++++---- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 5c8e6bc8981..9ba15d4f8a0 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -1942,6 +1942,18 @@ module FourSlash { } } + public verfiyDocCommentScaffolding(position: number, expected: ts.TextInsertion) { + let actual = this.languageService.getDocCommentScaffoldingAtPosition(this.activeFile.fileName, position); + + if (actual.newText !== expected.newText) { + this.raiseError('verfiyDocCommentScaffolding failed - expected insertion:\n' + expected.newText + 'actual insertion:\n' + actual.newText); + } + + if (actual.cursorOffset !== expected.cursorOffset) { + this.raiseError('verfiyDocCommentScaffolding failed - expected cursorOffset: ' + expected.cursorOffset + ',\tactual cursorOffset:' + actual.cursorOffset); + } + } + public verifyMatchingBracePosition(bracePosition: number, expectedMatchPosition: number) { this.taoInvalidReason = 'verifyMatchingBracePosition NYI'; diff --git a/src/server/client.ts b/src/server/client.ts index 3f6770d7144..59e3d6e8f2e 100644 --- a/src/server/client.ts +++ b/src/server/client.ts @@ -541,7 +541,7 @@ namespace ts.server { throw new Error("Not Implemented Yet."); } - getDocCommentScaffoldingAtPosition(fileName: string, position: number): string { + getDocCommentScaffoldingAtPosition(fileName: string, position: number): TextInsertion { throw new Error("Not Implemented Yet."); } diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index a0463073d8c..4edd46bf824 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -269,10 +269,10 @@ module FourSlashInterface { } /** - Compiles the current file and evaluates 'expr' in a context containing - the emitted output, then compares (using ===) the result of that expression - to 'value'. Do not use this function with external modules as it is not supported. - */ + * Compiles the current file and evaluates 'expr' in a context containing + * the emitted output, then compares (using ===) the result of that expression + * to 'value'. Do not use this function with external modules as it is not supported. + */ public eval(expr: string, value: any) { FourSlash.currentTestState.verifyEval(expr, value); } @@ -365,6 +365,11 @@ module FourSlashInterface { FourSlash.currentTestState.setVerifyDocComments(val); } + // Will fix in fourslash-referencing + public DocCommentScaffolding(position: number, expected: ts.TextInsertion) { + FourSlash.currentTestState.verifyDocCommentScaffolding(position, expected); + } + public getScriptLexicalStructureListCount(count: number) { FourSlash.currentTestState.verifyGetScriptLexicalStructureListCount(count); } From 2bdd874a00494853b240db265b22a419454d9c9a Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Tue, 21 Jul 2015 14:18:27 -0700 Subject: [PATCH 24/93] A test --- tests/cases/fourslash/docCommentScaffoldingEmptyFile.ts | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 tests/cases/fourslash/docCommentScaffoldingEmptyFile.ts diff --git a/tests/cases/fourslash/docCommentScaffoldingEmptyFile.ts b/tests/cases/fourslash/docCommentScaffoldingEmptyFile.ts new file mode 100644 index 00000000000..0d8cb1f28de --- /dev/null +++ b/tests/cases/fourslash/docCommentScaffoldingEmptyFile.ts @@ -0,0 +1,6 @@ +/// + +// @Filename: emptyFile.ts +/////*0*/ + +verify.DocCommentScaffolding(0, { newText: "/** */", cursorOffset: 3}); \ No newline at end of file From acb940134532c4f58e64200f2c02e3732b1f746f Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Thu, 23 Jul 2015 11:20:16 -0700 Subject: [PATCH 25/93] Fixed spelling error --- src/harness/fourslash.ts | 10 +++++----- tests/cases/fourslash/fourslash.ts | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 464cb3e1444..1668fcedc62 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -1941,15 +1941,15 @@ module FourSlash { } } - public verfiyDocCommentScaffolding(position: number, expected: ts.TextInsertion) { - let actual = this.languageService.getDocCommentScaffoldingAtPosition(this.activeFile.fileName, position); + public verifyDocCommentScaffolding(expected: ts.TextInsertion) { + let actual = this.languageService.getDocCommentScaffoldingAtPosition(this.activeFile.fileName, this.currentCaretPosition); if (actual.newText !== expected.newText) { - this.raiseError('verfiyDocCommentScaffolding failed - expected insertion:\n' + expected.newText + 'actual insertion:\n' + actual.newText); + this.raiseError('verifyDocCommentScaffolding failed - expected insertion:\n' + expected.newText + 'actual insertion:\n' + actual.newText); } if (actual.cursorOffset !== expected.cursorOffset) { - this.raiseError('verfiyDocCommentScaffolding failed - expected cursorOffset: ' + expected.cursorOffset + ',\tactual cursorOffset:' + actual.cursorOffset); + this.raiseError('verifyDocCommentScaffolding failed - expected cursorOffset: ' + expected.cursorOffset + ',\tactual cursorOffset:' + actual.cursorOffset); } } @@ -2747,4 +2747,4 @@ module FourSlash { fileName: fileName }; } -} +} diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index 5840b1bbf09..d673acba671 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -380,7 +380,7 @@ module FourSlashInterface { // Will fix in fourslash-referencing public DocCommentScaffolding(position: number, expectedText: string, expectedOffset: number) { - FourSlash.currentTestState.verifyDocCommentScaffolding(position, { newText: expectedText, cursorOffset: expectedOffset }); + FourSlash.currentTestState.verifyDocCommentScaffolding({ newText: expectedText, cursorOffset: expectedOffset }); } public getScriptLexicalStructureListCount(count: number) { From 24b29f1fb7adc6f0a70e512ad95bb8ca2ab199e5 Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Thu, 23 Jul 2015 14:03:52 -0700 Subject: [PATCH 26/93] Check if inside the declaration --- src/harness/fourslash.ts | 2 +- src/services/services.ts | 2 +- src/services/utilities.ts | 3 ++- tests/cases/fourslash/fourslash.ts | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 1668fcedc62..82f24279a87 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -1945,7 +1945,7 @@ module FourSlash { let actual = this.languageService.getDocCommentScaffoldingAtPosition(this.activeFile.fileName, this.currentCaretPosition); if (actual.newText !== expected.newText) { - this.raiseError('verifyDocCommentScaffolding failed - expected insertion:\n' + expected.newText + 'actual insertion:\n' + actual.newText); + this.raiseError('verifyDocCommentScaffolding failed - expected insertion:\n' + expected.newText + '\nactual insertion:\n' + actual.newText); } if (actual.cursorOffset !== expected.cursorOffset) { diff --git a/src/services/services.ts b/src/services/services.ts index 23621f133b8..2a0516b2d34 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -6778,7 +6778,7 @@ namespace ts { let nodeAtPos = getTokenAtPosition(sourceFile, position); let containingFunction = getAncestor(nodeAtPos, SyntaxKind.FunctionDeclaration); - if (hasDocComment(sourceFile, position) || !containingFunction) { + if (hasDocComment(sourceFile, position) || !containingFunction || containingFunction.getStart() < position) { return emptyCompletion; } diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 999b3d30427..6007fcdbaf4 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -432,7 +432,7 @@ namespace ts { extraCheck: (c: CommentRange) => boolean): boolean { let token = getTokenAtPosition(sourceFile, position); - if (token && position < token.getStart()) { + if (token && position <= token.getStart()) { let commentRanges = getLeadingCommentRanges(sourceFile.text, token.pos); return forEach(commentRanges, c => c.pos < position && @@ -442,6 +442,7 @@ namespace ts { // // asdf ^\n // // But for multi-line comments, we don't want to be inside the comment in the following case: + // // /* asdf */^ // // Internally, we represent the end of the comment at the newline and closing '/', respectively. diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index d673acba671..c5446ef4148 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -379,7 +379,7 @@ module FourSlashInterface { } // Will fix in fourslash-referencing - public DocCommentScaffolding(position: number, expectedText: string, expectedOffset: number) { + public DocCommentScaffolding(expectedText: string, expectedOffset: number) { FourSlash.currentTestState.verifyDocCommentScaffolding({ newText: expectedText, cursorOffset: expectedOffset }); } From fff2f7be228cbb3b9056e14fe1efd8f920e9865a Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Thu, 23 Jul 2015 14:04:03 -0700 Subject: [PATCH 27/93] Add Tests --- .../docCommentScaffoldingEmptyFile.ts | 2 +- ...ommentScaffoldingFunctionWithParameters.ts | 11 ++++++++ ...docCommentScaffoldingInMultiLineComment.ts | 6 +++++ ...ocCommentScaffoldingInSingleLineComment.ts | 22 ++++++++++++++++ .../docCommentScaffoldingIndentation.ts | 22 ++++++++++++++++ ...entScaffoldingInsideFunctionDeclaration.ts | 25 +++++++++++++++++++ 6 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 tests/cases/fourslash/docCommentScaffoldingFunctionWithParameters.ts create mode 100644 tests/cases/fourslash/docCommentScaffoldingInMultiLineComment.ts create mode 100644 tests/cases/fourslash/docCommentScaffoldingInSingleLineComment.ts create mode 100644 tests/cases/fourslash/docCommentScaffoldingIndentation.ts create mode 100644 tests/cases/fourslash/docCommentScaffoldingInsideFunctionDeclaration.ts diff --git a/tests/cases/fourslash/docCommentScaffoldingEmptyFile.ts b/tests/cases/fourslash/docCommentScaffoldingEmptyFile.ts index 0d8cb1f28de..733c7673579 100644 --- a/tests/cases/fourslash/docCommentScaffoldingEmptyFile.ts +++ b/tests/cases/fourslash/docCommentScaffoldingEmptyFile.ts @@ -3,4 +3,4 @@ // @Filename: emptyFile.ts /////*0*/ -verify.DocCommentScaffolding(0, { newText: "/** */", cursorOffset: 3}); \ No newline at end of file +verify.DocCommentScaffolding("/** */", 3); \ No newline at end of file diff --git a/tests/cases/fourslash/docCommentScaffoldingFunctionWithParameters.ts b/tests/cases/fourslash/docCommentScaffoldingFunctionWithParameters.ts new file mode 100644 index 00000000000..11eb8495fe7 --- /dev/null +++ b/tests/cases/fourslash/docCommentScaffoldingFunctionWithParameters.ts @@ -0,0 +1,11 @@ +/// + +// @Filename: emptyFile.ts +/////*0*/ +//// /*1*/ +//// function foo(x: number, y: string): boolean {} + +const noIndentEmptyScaffolding = "/**\n * \n * @param x \n * @param y\n */"; +const oneIndentEmptyScaffolding = "/**\n * \n * @param x \n * @param y\n */"; +const noIndentOffset = 7; +const oneIndentOffset = noIndentOffset + 4; \ No newline at end of file diff --git a/tests/cases/fourslash/docCommentScaffoldingInMultiLineComment.ts b/tests/cases/fourslash/docCommentScaffoldingInMultiLineComment.ts new file mode 100644 index 00000000000..7055cc376cd --- /dev/null +++ b/tests/cases/fourslash/docCommentScaffoldingInMultiLineComment.ts @@ -0,0 +1,6 @@ +/// + +// @Filename: emptyFile.ts +//// /* /*0*/ */ +goTo.marker("0"); +verify.DocCommentScaffolding("/**", 3); \ No newline at end of file diff --git a/tests/cases/fourslash/docCommentScaffoldingInSingleLineComment.ts b/tests/cases/fourslash/docCommentScaffoldingInSingleLineComment.ts new file mode 100644 index 00000000000..2c8e7afc397 --- /dev/null +++ b/tests/cases/fourslash/docCommentScaffoldingInSingleLineComment.ts @@ -0,0 +1,22 @@ +/// + +// @Filename: emptyFile.ts +//// // We want to check off-by-one errors in assessing the end of the comment, so we check twice, +//// // first with a trailing space and then without. +//// // /*0*/ +//// // /*1*/ +/////*2*/ +//// // We also want to check EOF handling at the end of a comment +//// // /*3*/ + +goTo.marker("0"); +verify.DocCommentScaffolding("/**", 3); + +goTo.marker("1"); +verify.DocCommentScaffolding("/**", 3); + +goTo.marker("2"); +verify.DocCommentScaffolding("/** */", 3); + +goTo.marker("3"); +verify.DocCommentScaffolding("/**", 3); \ No newline at end of file diff --git a/tests/cases/fourslash/docCommentScaffoldingIndentation.ts b/tests/cases/fourslash/docCommentScaffoldingIndentation.ts new file mode 100644 index 00000000000..77031ad14e1 --- /dev/null +++ b/tests/cases/fourslash/docCommentScaffoldingIndentation.ts @@ -0,0 +1,22 @@ +/// + +// @Filename: emptyFile.ts +/////*0*/ +//// /*1*/ +//// /*2*/function /*3*/foo/*4*/(/*5*/) /*6*/{ /*7*/}/*8*/ + +const noIndentEmptyScaffolding = "/**\n * \n */"; +const oneIndentEmptyScaffolding = "/**\n * \n */"; +const twoIndentEmptyScaffolding = "/**\n * \n */"; +const noIndentOffset = 7; +const oneIndentOffset = noIndentOffset + 4; +const twoIndentOffset = oneIndentOffset + 4; + +goTo.marker("0"); +verify.DocCommentScaffolding(noIndentEmptyScaffolding, noIndentOffset); + +goTo.marker("1"); +verify.DocCommentScaffolding(oneIndentEmptyScaffolding, oneIndentOffset); + +goTo.marker("2"); +verify.DocCommentScaffolding(twoIndentEmptyScaffolding, twoIndentOffset); \ No newline at end of file diff --git a/tests/cases/fourslash/docCommentScaffoldingInsideFunctionDeclaration.ts b/tests/cases/fourslash/docCommentScaffoldingInsideFunctionDeclaration.ts new file mode 100644 index 00000000000..dd154042dab --- /dev/null +++ b/tests/cases/fourslash/docCommentScaffoldingInsideFunctionDeclaration.ts @@ -0,0 +1,25 @@ +/// + +// @Filename: emptyFile.ts +////function /*0*/foo/*1*/(/*2*/) /*3*/{ /*4*/}/*5*/ + +const emptyCompletion = "/** */"; +const emptyIndent = 3; + +goTo.marker("0"); +verify.DocCommentScaffolding(emptyCompletion, emptyIndent); + +goTo.marker("1"); +verify.DocCommentScaffolding(emptyCompletion, emptyIndent); + +goTo.marker("2"); +verify.DocCommentScaffolding(emptyCompletion, emptyIndent); + +goTo.marker("3"); +verify.DocCommentScaffolding(emptyCompletion, emptyIndent); + +goTo.marker("4"); +verify.DocCommentScaffolding(emptyCompletion, emptyIndent); + +goTo.marker("5"); +verify.DocCommentScaffolding(emptyCompletion, emptyIndent); From e6809c30f175dc3d391121dd9ad16d44f2140b46 Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Fri, 24 Jul 2015 15:27:28 -0700 Subject: [PATCH 28/93] Simplfied Return Values --- src/harness/typeWriter.ts | 2 +- src/services/services.ts | 24 +++++++++++++++++++----- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/harness/typeWriter.ts b/src/harness/typeWriter.ts index 27cb3574473..0fef0779965 100644 --- a/src/harness/typeWriter.ts +++ b/src/harness/typeWriter.ts @@ -71,4 +71,4 @@ class TypeWriterWalker { symbol: symbolString }); } -} +} \ No newline at end of file diff --git a/src/services/services.ts b/src/services/services.ts index 7769e9b2fc0..37b57b3336d 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -6764,14 +6764,23 @@ namespace ts { /** * Checks if position points to a valid position to add JSDoc comments, and if so, - * returns the appropriate scaffolding. Otherwise returns a default string. - * @param fileName The file in which to perofrm the check + * returns the appropriate scaffolding. Otherwise returns an empty string. + * Valid positions are + * * outside of comments, statements, and expressions, and + * * preceding a function declaration. + * + * In VS, we additionally check that: + * * The line is all whitespace up to 'position' before performing the insertion. + * * If the keystroke sequence "/\*\*" induced the call, we also check that the next + * non-whitespace character is '*', which (approximately) indicates whether we added + * the second '*' to complete an existing (JSDoc) comment. + * @param fileName The file in which to perform the check. * @param position The (character-indexed) position in the file where the check should * be performed. */ function getDocCommentScaffoldingAtPosition(fileName: string, position: number): TextInsertion { - const nullResult = { newText: "/**", cursorOffset: 3 }; - const emptyCompletion = { newText: "/** */", cursorOffset: 3 }; + // Indicates the position is not appropriate to insert a comment (eg: a string or a regex). + const nullResult: TextInsertion = { newText: "", cursorOffset: 0 }; let start = new Date().getTime(); let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); log("getDocCommentScaffoldingAtPosition: getCurrentSourceFile: " + (new Date().getTime() - start)); @@ -6782,10 +6791,15 @@ namespace ts { } let nodeAtPos = getTokenAtPosition(sourceFile, position); + + if (!nodeAtPos || nodeAtPos.getStart() < position) { + return nullResult; + } + let containingFunction = getAncestor(nodeAtPos, SyntaxKind.FunctionDeclaration); if (hasDocComment(sourceFile, position) || !containingFunction || containingFunction.getStart() < position) { - return emptyCompletion; + return nullResult; } let parameters = containingFunction.parameters; From 45ddfa7c757e2996ae870f709ded6e304aa9a081 Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Fri, 24 Jul 2015 15:28:28 -0700 Subject: [PATCH 29/93] Simplified Tests --- .../docCommentScaffoldingEmptyFile.ts | 3 +- ...ommentScaffoldingFunctionWithParameters.ts | 14 +++++++--- ...docCommentScaffoldingInMultiLineComment.ts | 5 ++-- ...ocCommentScaffoldingInSingleLineComment.ts | 20 ++++--------- .../docCommentScaffoldingIndentation.ts | 4 +-- ...entScaffoldingInsideFunctionDeclaration.ts | 28 ++++--------------- .../fourslash/docCommentScaffoldingRegex.ts | 9 ++++++ tests/cases/fourslash/fourslash.ts | 12 ++++++++ 8 files changed, 50 insertions(+), 45 deletions(-) create mode 100644 tests/cases/fourslash/docCommentScaffoldingRegex.ts diff --git a/tests/cases/fourslash/docCommentScaffoldingEmptyFile.ts b/tests/cases/fourslash/docCommentScaffoldingEmptyFile.ts index 733c7673579..35d427a0001 100644 --- a/tests/cases/fourslash/docCommentScaffoldingEmptyFile.ts +++ b/tests/cases/fourslash/docCommentScaffoldingEmptyFile.ts @@ -3,4 +3,5 @@ // @Filename: emptyFile.ts /////*0*/ -verify.DocCommentScaffolding("/** */", 3); \ No newline at end of file +goTo.marker("0"); +verify.noDocCommentScaffolding(); \ No newline at end of file diff --git a/tests/cases/fourslash/docCommentScaffoldingFunctionWithParameters.ts b/tests/cases/fourslash/docCommentScaffoldingFunctionWithParameters.ts index 11eb8495fe7..d127f60f47e 100644 --- a/tests/cases/fourslash/docCommentScaffoldingFunctionWithParameters.ts +++ b/tests/cases/fourslash/docCommentScaffoldingFunctionWithParameters.ts @@ -1,11 +1,17 @@ /// -// @Filename: emptyFile.ts +// @Filename: functionWithParams.ts /////*0*/ //// /*1*/ //// function foo(x: number, y: string): boolean {} -const noIndentEmptyScaffolding = "/**\n * \n * @param x \n * @param y\n */"; -const oneIndentEmptyScaffolding = "/**\n * \n * @param x \n * @param y\n */"; +const noIndentScaffolding = "/**\n * \n * @param x\n * @param y\n */"; +const oneIndentScaffolding = "/**\n * \n * @param x\n * @param y\n */"; const noIndentOffset = 7; -const oneIndentOffset = noIndentOffset + 4; \ No newline at end of file +const oneIndentOffset = noIndentOffset + 4; + +goTo.marker("0"); +verify.DocCommentScaffolding(noIndentScaffolding, noIndentOffset); + +goTo.marker("1"); +verify.DocCommentScaffolding(oneIndentScaffolding, oneIndentOffset); \ No newline at end of file diff --git a/tests/cases/fourslash/docCommentScaffoldingInMultiLineComment.ts b/tests/cases/fourslash/docCommentScaffoldingInMultiLineComment.ts index 7055cc376cd..cff57a68305 100644 --- a/tests/cases/fourslash/docCommentScaffoldingInMultiLineComment.ts +++ b/tests/cases/fourslash/docCommentScaffoldingInMultiLineComment.ts @@ -1,6 +1,7 @@ /// -// @Filename: emptyFile.ts +// @Filename: justAComment.ts //// /* /*0*/ */ + goTo.marker("0"); -verify.DocCommentScaffolding("/**", 3); \ No newline at end of file +verify.noDocCommentScaffolding(); \ No newline at end of file diff --git a/tests/cases/fourslash/docCommentScaffoldingInSingleLineComment.ts b/tests/cases/fourslash/docCommentScaffoldingInSingleLineComment.ts index 2c8e7afc397..99d0a539d52 100644 --- a/tests/cases/fourslash/docCommentScaffoldingInSingleLineComment.ts +++ b/tests/cases/fourslash/docCommentScaffoldingInSingleLineComment.ts @@ -1,22 +1,14 @@ /// -// @Filename: emptyFile.ts +// @Filename: justAComment.ts //// // We want to check off-by-one errors in assessing the end of the comment, so we check twice, //// // first with a trailing space and then without. //// // /*0*/ //// // /*1*/ -/////*2*/ //// // We also want to check EOF handling at the end of a comment -//// // /*3*/ +//// // /*2*/ -goTo.marker("0"); -verify.DocCommentScaffolding("/**", 3); - -goTo.marker("1"); -verify.DocCommentScaffolding("/**", 3); - -goTo.marker("2"); -verify.DocCommentScaffolding("/** */", 3); - -goTo.marker("3"); -verify.DocCommentScaffolding("/**", 3); \ No newline at end of file +test.markers().forEach((marker) => { + goTo.position(marker.position); + verify.noDocCommentScaffolding(); +}); \ No newline at end of file diff --git a/tests/cases/fourslash/docCommentScaffoldingIndentation.ts b/tests/cases/fourslash/docCommentScaffoldingIndentation.ts index 77031ad14e1..53119aae138 100644 --- a/tests/cases/fourslash/docCommentScaffoldingIndentation.ts +++ b/tests/cases/fourslash/docCommentScaffoldingIndentation.ts @@ -1,9 +1,9 @@ /// -// @Filename: emptyFile.ts +// @Filename: indents.ts /////*0*/ //// /*1*/ -//// /*2*/function /*3*/foo/*4*/(/*5*/) /*6*/{ /*7*/}/*8*/ +//// /*2*/function foo() { } const noIndentEmptyScaffolding = "/**\n * \n */"; const oneIndentEmptyScaffolding = "/**\n * \n */"; diff --git a/tests/cases/fourslash/docCommentScaffoldingInsideFunctionDeclaration.ts b/tests/cases/fourslash/docCommentScaffoldingInsideFunctionDeclaration.ts index dd154042dab..6a7881339ad 100644 --- a/tests/cases/fourslash/docCommentScaffoldingInsideFunctionDeclaration.ts +++ b/tests/cases/fourslash/docCommentScaffoldingInsideFunctionDeclaration.ts @@ -1,25 +1,9 @@ /// -// @Filename: emptyFile.ts -////function /*0*/foo/*1*/(/*2*/) /*3*/{ /*4*/}/*5*/ +// @Filename: functionDecl.ts +////function /*0*/foo/*1*/(/*2*/) /*3*/{ /*4*/} -const emptyCompletion = "/** */"; -const emptyIndent = 3; - -goTo.marker("0"); -verify.DocCommentScaffolding(emptyCompletion, emptyIndent); - -goTo.marker("1"); -verify.DocCommentScaffolding(emptyCompletion, emptyIndent); - -goTo.marker("2"); -verify.DocCommentScaffolding(emptyCompletion, emptyIndent); - -goTo.marker("3"); -verify.DocCommentScaffolding(emptyCompletion, emptyIndent); - -goTo.marker("4"); -verify.DocCommentScaffolding(emptyCompletion, emptyIndent); - -goTo.marker("5"); -verify.DocCommentScaffolding(emptyCompletion, emptyIndent); +test.markers().forEach((marker) => { + goTo.position(marker.position); + verify.noDocCommentScaffolding(); +}); diff --git a/tests/cases/fourslash/docCommentScaffoldingRegex.ts b/tests/cases/fourslash/docCommentScaffoldingRegex.ts new file mode 100644 index 00000000000..374bc94ef5e --- /dev/null +++ b/tests/cases/fourslash/docCommentScaffoldingRegex.ts @@ -0,0 +1,9 @@ +/// + +// @Filename: regex.ts +////var regex = /*0*///*1*/asdf/*2*/ /*3*///*4*/; + +test.markers().forEach((marker) => { + goTo.position(marker.position); + verify.noDocCommentScaffolding(); +}); \ No newline at end of file diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index c5446ef4148..9c4b4be5d7a 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -382,6 +382,18 @@ module FourSlashInterface { public DocCommentScaffolding(expectedText: string, expectedOffset: number) { FourSlash.currentTestState.verifyDocCommentScaffolding({ newText: expectedText, cursorOffset: expectedOffset }); } + + public noDocCommentScaffolding() { + const expectedText = ""; + const expectedOffset = 0; + this.DocCommentScaffolding(expectedText, expectedOffset); + } + + public emptyTemplateDocCommentScaffolding() { + const expectedText = "/** */"; + const expectedOffset = 3; + this.DocCommentScaffolding(expectedText, expectedOffset); + } public getScriptLexicalStructureListCount(count: number) { FourSlash.currentTestState.verifyGetScriptLexicalStructureListCount(count); From 80db03efaa0d4c2fd4256a2bd3f86146688968fb Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Fri, 24 Jul 2015 15:28:48 -0700 Subject: [PATCH 30/93] Added a regex test --- ...ularExpressionMixedWithComments.errors.txt | 27 +++++++++++++++++++ ...parseRegularExpressionMixedWithComments.js | 14 ++++++++++ ...parseRegularExpressionMixedWithComments.ts | 6 +++++ 3 files changed, 47 insertions(+) create mode 100644 tests/baselines/reference/parseRegularExpressionMixedWithComments.errors.txt create mode 100644 tests/baselines/reference/parseRegularExpressionMixedWithComments.js create mode 100644 tests/cases/conformance/parser/ecmascript5/RegularExpressions/parseRegularExpressionMixedWithComments.ts diff --git a/tests/baselines/reference/parseRegularExpressionMixedWithComments.errors.txt b/tests/baselines/reference/parseRegularExpressionMixedWithComments.errors.txt new file mode 100644 index 00000000000..a6d63ce1754 --- /dev/null +++ b/tests/baselines/reference/parseRegularExpressionMixedWithComments.errors.txt @@ -0,0 +1,27 @@ +tests/cases/conformance/parser/ecmascript5/RegularExpressions/parseRegularExpressionMixedWithComments.ts(5,18): error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type. +tests/cases/conformance/parser/ecmascript5/RegularExpressions/parseRegularExpressionMixedWithComments.ts(5,22): error TS1109: Expression expected. +tests/cases/conformance/parser/ecmascript5/RegularExpressions/parseRegularExpressionMixedWithComments.ts(5,23): error TS2363: The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type. +tests/cases/conformance/parser/ecmascript5/RegularExpressions/parseRegularExpressionMixedWithComments.ts(6,18): error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type. +tests/cases/conformance/parser/ecmascript5/RegularExpressions/parseRegularExpressionMixedWithComments.ts(6,26): error TS1109: Expression expected. +tests/cases/conformance/parser/ecmascript5/RegularExpressions/parseRegularExpressionMixedWithComments.ts(6,27): error TS2363: The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type. + + +==== tests/cases/conformance/parser/ecmascript5/RegularExpressions/parseRegularExpressionMixedWithComments.ts (6 errors) ==== + var regex1 = / asdf /; + var regex2 = /**// asdf /; + var regex3 = /**///**/ asdf / // should be a comment line + 1; + var regex4 = /**// /**/asdf /; + ~~~ +!!! error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type. + ~ +!!! error TS1109: Expression expected. + ~~~~~~~ +!!! error TS2363: The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type. + var regex5 = /**// asdf/**/ /; + ~~~~~~~ +!!! error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type. + ~ +!!! error TS1109: Expression expected. + ~~~ +!!! error TS2363: The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type. \ No newline at end of file diff --git a/tests/baselines/reference/parseRegularExpressionMixedWithComments.js b/tests/baselines/reference/parseRegularExpressionMixedWithComments.js new file mode 100644 index 00000000000..c7aded33697 --- /dev/null +++ b/tests/baselines/reference/parseRegularExpressionMixedWithComments.js @@ -0,0 +1,14 @@ +//// [parseRegularExpressionMixedWithComments.ts] +var regex1 = / asdf /; +var regex2 = /**// asdf /; +var regex3 = /**///**/ asdf / // should be a comment line +1; +var regex4 = /**// /**/asdf /; +var regex5 = /**// asdf/**/ /; + +//// [parseRegularExpressionMixedWithComments.js] +var regex1 = / asdf /; +var regex2 = / asdf /; +var regex3 = 1; +var regex4 = / / * * /asdf /; +var regex5 = / asdf/ * * / /; diff --git a/tests/cases/conformance/parser/ecmascript5/RegularExpressions/parseRegularExpressionMixedWithComments.ts b/tests/cases/conformance/parser/ecmascript5/RegularExpressions/parseRegularExpressionMixedWithComments.ts new file mode 100644 index 00000000000..5e5c2e85485 --- /dev/null +++ b/tests/cases/conformance/parser/ecmascript5/RegularExpressions/parseRegularExpressionMixedWithComments.ts @@ -0,0 +1,6 @@ +var regex1 = / asdf /; +var regex2 = /**// asdf /; +var regex3 = /**///**/ asdf / // should be a comment line +1; +var regex4 = /**// /**/asdf /; +var regex5 = /**// asdf/**/ /; \ No newline at end of file From 98d2bcbf88243eff0e5405921cec89351c86a143 Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Fri, 24 Jul 2015 16:25:32 -0700 Subject: [PATCH 31/93] add newline if we directly precede the declaration --- src/services/services.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/services/services.ts b/src/services/services.ts index 37b57b3336d..fc0b14722e1 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -6786,19 +6786,19 @@ namespace ts { log("getDocCommentScaffoldingAtPosition: getCurrentSourceFile: " + (new Date().getTime() - start)); // Check if in a context where we don't want to perform any insertion - if (isInString(sourceFile, position) || isInComment(sourceFile, position)) { + if (isInString(sourceFile, position) || isInComment(sourceFile, position) || hasDocComment(sourceFile, position)) { return nullResult; } let nodeAtPos = getTokenAtPosition(sourceFile, position); - - if (!nodeAtPos || nodeAtPos.getStart() < position) { + let nodeStart = nodeAtPos.getStart() + if (!nodeAtPos || nodeStart < position) { return nullResult; } let containingFunction = getAncestor(nodeAtPos, SyntaxKind.FunctionDeclaration); - if (hasDocComment(sourceFile, position) || !containingFunction || containingFunction.getStart() < position) { + if (!containingFunction || containingFunction.getStart() < position) { return nullResult; } @@ -6815,7 +6815,8 @@ namespace ts { /* opening comment */ "/**\n" + /* first line for function info */ indentationStr + " * \n" + /* paramters */ docParams.reduce((prev, cur) => prev + cur, "") + - /* closing comment */ indentationStr + " */"; + /* closing comment */ indentationStr + " */" + + /* newline if at decl start */ (nodeStart === position ? "\n" + indentationStr : ""); let cursorOffset = /* "/**\n" */ 4 + indentationStr.length + /* " * " */ 3; From 3b6fb32cd6307a8304be9cf527dd417bab473a9d Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Fri, 24 Jul 2015 17:55:32 -0700 Subject: [PATCH 32/93] fixed a test --- tests/cases/fourslash/docCommentScaffoldingIndentation.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cases/fourslash/docCommentScaffoldingIndentation.ts b/tests/cases/fourslash/docCommentScaffoldingIndentation.ts index 53119aae138..7769480426e 100644 --- a/tests/cases/fourslash/docCommentScaffoldingIndentation.ts +++ b/tests/cases/fourslash/docCommentScaffoldingIndentation.ts @@ -7,7 +7,7 @@ const noIndentEmptyScaffolding = "/**\n * \n */"; const oneIndentEmptyScaffolding = "/**\n * \n */"; -const twoIndentEmptyScaffolding = "/**\n * \n */"; +const twoIndentEmptyScaffolding = "/**\n * \n */\n "; const noIndentOffset = 7; const oneIndentOffset = noIndentOffset + 4; const twoIndentOffset = oneIndentOffset + 4; From 92b42ee42d1a50eedcc9c7c0133c9e29de70862d Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Fri, 24 Jul 2015 17:56:53 -0700 Subject: [PATCH 33/93] added an annotation --- src/services/utilities.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 6007fcdbaf4..8b8cadfc7fe 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -421,7 +421,7 @@ namespace ts { } export function isInComment(sourceFile: SourceFile, position: number) { - return isInCommentHelper(sourceFile, position, c => true); + return isInCommentHelper(sourceFile, position, /*extraCheck*/ c => true); } /** From 2540905075043bd1d97b81ac228f85938ac3d04e Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Fri, 31 Jul 2015 11:58:52 -0700 Subject: [PATCH 34/93] refactoring --- src/harness/fourslash.ts | 16 ++++++++++++-- src/services/services.ts | 34 +++++++++++++++--------------- tests/cases/fourslash/fourslash.ts | 16 ++++---------- 3 files changed, 35 insertions(+), 31 deletions(-) diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index b3c91c94d1f..c787f8fa5d3 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -1944,12 +1944,24 @@ module FourSlash { public verifyDocCommentScaffolding(expected: ts.TextInsertion) { let actual = this.languageService.getDocCommentScaffoldingAtPosition(this.activeFile.fileName, this.currentCaretPosition); + if (expected === undefined) { + if (actual === undefined) { + return; + } + else { + this.raiseError('verifyDocCommentScaffolding failed - expected no scaffolding but got {newText: \"' + actual.newText + '\" offsetInNewText: ' + actual.offsetInNewText + '}'); + } + } + if (expected !== undefined && actual === undefined) { + this.raiseError('verifyDocCommentScaffolding failed - expected the scaffolding {newText: \"' + actual.newText + '\" offsetInNewText: ' + actual.offsetInNewText + '} but got nothin instead'); + } + if (actual.newText !== expected.newText) { this.raiseError('verifyDocCommentScaffolding failed - expected insertion:\n' + expected.newText + '\nactual insertion:\n' + actual.newText); } - if (actual.cursorOffset !== expected.cursorOffset) { - this.raiseError('verifyDocCommentScaffolding failed - expected cursorOffset: ' + expected.cursorOffset + ',\tactual cursorOffset:' + actual.cursorOffset); + if (actual.offsetInNewText !== expected.offsetInNewText) { + this.raiseError('verifyDocCommentScaffolding failed - expected cursorOffset: ' + expected.offsetInNewText + ',\tactual cursorOffset:' + actual.offsetInNewText); } } diff --git a/src/services/services.ts b/src/services/services.ts index 75951cacb93..c0551f5681b 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1090,7 +1090,7 @@ namespace ts { export interface TextInsertion { newText: string; - cursorOffset: number; + offsetInNewText: number; } export interface RenameLocation { @@ -6801,7 +6801,7 @@ namespace ts { * * outside of comments, statements, and expressions, and * * preceding a function declaration. * - * In VS, we additionally check that: + * Hosts should ideally check that: * * The line is all whitespace up to 'position' before performing the insertion. * * If the keystroke sequence "/\*\*" induced the call, we also check that the next * non-whitespace character is '*', which (approximately) indicates whether we added @@ -6811,27 +6811,25 @@ namespace ts { * be performed. */ function getDocCommentScaffoldingAtPosition(fileName: string, position: number): TextInsertion { - // Indicates the position is not appropriate to insert a comment (eg: a string or a regex). - const nullResult: TextInsertion = { newText: "", cursorOffset: 0 }; let start = new Date().getTime(); let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); log("getDocCommentScaffoldingAtPosition: getCurrentSourceFile: " + (new Date().getTime() - start)); // Check if in a context where we don't want to perform any insertion if (isInString(sourceFile, position) || isInComment(sourceFile, position) || hasDocComment(sourceFile, position)) { - return nullResult; + return undefined; } - let nodeAtPos = getTokenAtPosition(sourceFile, position); - let nodeStart = nodeAtPos.getStart() - if (!nodeAtPos || nodeStart < position) { - return nullResult; + let tokenAtPos = getTokenAtPosition(sourceFile, position); + let tokenStart = tokenAtPos.getStart() + if (!tokenAtPos || tokenStart < position) { + return undefined; } - let containingFunction = getAncestor(nodeAtPos, SyntaxKind.FunctionDeclaration); + let containingFunction = getAncestor(tokenAtPos, SyntaxKind.FunctionDeclaration); if (!containingFunction || containingFunction.getStart() < position) { - return nullResult; + return undefined; } let parameters = containingFunction.parameters; @@ -6840,19 +6838,21 @@ namespace ts { let indentationStr = sourceFile.text.substr(lineStart, posLineAndChar.character).match(/\s*/).toString(); + const newLine = host.getNewLine(); + let docParams = parameters.map((p, index) => - indentationStr + " * @param " + (p.name.kind === SyntaxKind.Identifier ? (p.name).text : "param" + index.toString()) + "\n"); + indentationStr + " * @param " + (p.name.kind === SyntaxKind.Identifier ? (p.name).text : "param" + index.toString()) + newLine); let result = - /* opening comment */ "/**\n" + - /* first line for function info */ indentationStr + " * \n" + + /* opening comment */ "/**" + newLine + + /* first line for function info */ indentationStr + " * " + newLine + /* paramters */ docParams.reduce((prev, cur) => prev + cur, "") + /* closing comment */ indentationStr + " */" + - /* newline if at decl start */ (nodeStart === position ? "\n" + indentationStr : ""); + /* newline if at decl start */ (tokenStart === position ? newLine + indentationStr : ""); - let cursorOffset = /* "/**\n" */ 4 + indentationStr.length + /* " * " */ 3; + let cursorOffset = /* "/**" */ 3 + /* newLine */ + newLine.length + indentationStr.length + /* " * " */ 3; - return {newText: result, cursorOffset: cursorOffset }; + return {newText: result, offsetInNewText: cursorOffset }; } function getTodoComments(fileName: string, descriptors: TodoCommentDescriptor[]): TodoComment[] { diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index 9c4b4be5d7a..0be9ba4a5fc 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -379,20 +379,12 @@ module FourSlashInterface { } // Will fix in fourslash-referencing - public DocCommentScaffolding(expectedText: string, expectedOffset: number) { - FourSlash.currentTestState.verifyDocCommentScaffolding({ newText: expectedText, cursorOffset: expectedOffset }); + public DocCommentScaffolding(expectedText: string, expectedOffset: number, empty?: boolean) { + FourSlash.currentTestState.verifyDocCommentScaffolding(empty ? undefined : { newText: expectedText, cursorOffset: expectedOffset }); } - + public noDocCommentScaffolding() { - const expectedText = ""; - const expectedOffset = 0; - this.DocCommentScaffolding(expectedText, expectedOffset); - } - - public emptyTemplateDocCommentScaffolding() { - const expectedText = "/** */"; - const expectedOffset = 3; - this.DocCommentScaffolding(expectedText, expectedOffset); + this.DocCommentScaffolding(/*expectedText*/ undefined, /*expectedOffset*/ undefined, true); } public getScriptLexicalStructureListCount(count: number) { From 8e13c0a3ad1a63708b0421db9162f694af29b760 Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Mon, 3 Aug 2015 11:09:58 -0700 Subject: [PATCH 35/93] Fixed a comment --- src/compiler/scanner.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index 2e692470cc5..55e58bb4d46 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -536,10 +536,10 @@ namespace ts { } /** - * Extract comments from the given source text starting at the given position. + * Extract comments from text prefixing the token closest following `pos`. * The return value is an array containing a TextRange for each comment. * Single-line comment ranges include the beginning '//' characters but not the ending line break. - * Multi - line comment ranges include the beginning '/* and ending '/' characters. + * Multi - line comment ranges include the beginning '/* and ending '/' characters. * The return value is undefined if no comments were found. * @param trailing * If false, whitespace is skipped until the first line break and comments between that location From a759f9f0b526c42f9b92d1ec99ccb61a38c7470c Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Mon, 3 Aug 2015 13:38:45 -0700 Subject: [PATCH 36/93] added helper --- src/compiler/core.ts | 4 ++-- src/compiler/utilities.ts | 8 ++++++++ src/services/services.ts | 9 +-------- src/services/shims.ts | 6 +----- 4 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index ec171d4aee2..8cca7b1f4f6 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -794,7 +794,7 @@ namespace ts { if (!expression) { let verboseDebugString = ""; if (verboseDebugInfo) { - verboseDebugString = "\r\nVerbose Debug Information: " + verboseDebugInfo(); + verboseDebugString = getNewLineOrDefault() + "Verbose Debug Information: " + verboseDebugInfo(); } throw new Error("Debug Failure. False expression: " + (message || "") + verboseDebugString); @@ -805,4 +805,4 @@ namespace ts { Debug.assert(false, message); } } -} +} diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 312a3666757..88a5322977d 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2092,6 +2092,14 @@ namespace ts { } return carriageReturnLineFeed; } + + /** + * The default is CRLF. + */ + export function getNewLineOrDefault(getNewLine?: () => string): string { + return getNewLine ? getNewLine() : carriageReturnLineFeed; + var x: number; + } } namespace ts { diff --git a/src/services/services.ts b/src/services/services.ts index 8e670268498..bf777a9d653 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1560,13 +1560,6 @@ namespace ts { /// Language Service - interface FormattingOptions { - useTabs: boolean; - spacesPerTab: number; - indentSpaces: number; - newLineCharacter: string; - } - // Information about a specific host file. interface HostFileInformation { hostFileName: string; @@ -2535,7 +2528,7 @@ namespace ts { getCancellationToken: () => cancellationToken, getCanonicalFileName, useCaseSensitiveFileNames: () => useCaseSensitivefileNames, - getNewLine: () => host.getNewLine ? host.getNewLine() : "\r\n", + getNewLine: () => getNewLineOrDefault(host.getNewLine), getDefaultLibFileName: (options) => host.getDefaultLibFileName(options), writeFile: (fileName, data, writeByteOrderMark) => { }, getCurrentDirectory: () => host.getCurrentDirectory() diff --git a/src/services/shims.ts b/src/services/shims.ts index ae853e1c72a..42247c31ece 100644 --- a/src/services/shims.ts +++ b/src/services/shims.ts @@ -529,7 +529,7 @@ namespace ts { } private realizeDiagnostics(diagnostics: Diagnostic[]): { message: string; start: number; length: number; category: string; }[]{ - var newLine = this.getNewLine(); + var newLine = getNewLineOrDefault(this.host.getNewLine); return ts.realizeDiagnostics(diagnostics, newLine); } @@ -571,10 +571,6 @@ namespace ts { }); } - private getNewLine(): string { - return this.host.getNewLine ? this.host.getNewLine() : "\r\n"; - } - public getSyntacticDiagnostics(fileName: string): string { return this.forwardJSONCall( "getSyntacticDiagnostics('" + fileName + "')", From f3395a9484d266a15b101127815bba7d987b64d5 Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Mon, 3 Aug 2015 13:54:49 -0700 Subject: [PATCH 37/93] reverted a hard-coded '\r\n' --- src/compiler/core.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 8cca7b1f4f6..3cd7c17e622 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -794,7 +794,7 @@ namespace ts { if (!expression) { let verboseDebugString = ""; if (verboseDebugInfo) { - verboseDebugString = getNewLineOrDefault() + "Verbose Debug Information: " + verboseDebugInfo(); + verboseDebugString = "\r\nVerbose Debug Information: " + verboseDebugInfo(); } throw new Error("Debug Failure. False expression: " + (message || "") + verboseDebugString); From 8d07c6929a2f8947d2986f72adf3082d81ac23fb Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Mon, 3 Aug 2015 14:28:21 -0700 Subject: [PATCH 38/93] rename feature --- src/harness/fourslash.ts | 13 +++++++------ src/harness/harnessLanguageService.ts | 4 ++-- src/server/client.ts | 2 +- src/services/services.ts | 10 +++++----- src/services/shims.ts | 8 ++++---- ...gEmptyFile.ts => docCommentTemplateEmptyFile.ts} | 2 +- ... => docCommentTemplateFunctionWithParameters.ts} | 4 ++-- ...t.ts => docCommentTemplateInMultiLineComment.ts} | 2 +- ....ts => docCommentTemplateInSingleLineComment.ts} | 2 +- ...entation.ts => docCommentTemplateIndentation.ts} | 6 +++--- ... docCommentTemplateInsideFunctionDeclaration.ts} | 4 ++-- ...affoldingRegex.ts => docCommentTemplateRegex.ts} | 2 +- tests/cases/fourslash/fourslash.ts | 8 ++++---- 13 files changed, 34 insertions(+), 33 deletions(-) rename tests/cases/fourslash/{docCommentScaffoldingEmptyFile.ts => docCommentTemplateEmptyFile.ts} (70%) rename tests/cases/fourslash/{docCommentScaffoldingFunctionWithParameters.ts => docCommentTemplateFunctionWithParameters.ts} (73%) rename tests/cases/fourslash/{docCommentScaffoldingInMultiLineComment.ts => docCommentTemplateInMultiLineComment.ts} (72%) rename tests/cases/fourslash/{docCommentScaffoldingInSingleLineComment.ts => docCommentTemplateInSingleLineComment.ts} (88%) rename tests/cases/fourslash/{docCommentScaffoldingIndentation.ts => docCommentTemplateIndentation.ts} (66%) rename tests/cases/fourslash/{docCommentScaffoldingInsideFunctionDeclaration.ts => docCommentTemplateInsideFunctionDeclaration.ts} (60%) rename tests/cases/fourslash/{docCommentScaffoldingRegex.ts => docCommentTemplateRegex.ts} (79%) diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index c787f8fa5d3..e8048ab82d7 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -1941,27 +1941,28 @@ module FourSlash { } } - public verifyDocCommentScaffolding(expected: ts.TextInsertion) { - let actual = this.languageService.getDocCommentScaffoldingAtPosition(this.activeFile.fileName, this.currentCaretPosition); + public verifyDocCommentTemplate(expected: ts.TextInsertion) { + const name = "verifyDocCommentTemplate"; + let actual = this.languageService.getDocCommentTemplateAtPosition(this.activeFile.fileName, this.currentCaretPosition); if (expected === undefined) { if (actual === undefined) { return; } else { - this.raiseError('verifyDocCommentScaffolding failed - expected no scaffolding but got {newText: \"' + actual.newText + '\" offsetInNewText: ' + actual.offsetInNewText + '}'); + this.raiseError(name + ' failed - expected no template but got {newText: \"' + actual.newText + '\" offsetInNewText: ' + actual.offsetInNewText + '}'); } } if (expected !== undefined && actual === undefined) { - this.raiseError('verifyDocCommentScaffolding failed - expected the scaffolding {newText: \"' + actual.newText + '\" offsetInNewText: ' + actual.offsetInNewText + '} but got nothin instead'); + this.raiseError(name + ' failed - expected the template {newText: \"' + actual.newText + '\" offsetInNewText: ' + actual.offsetInNewText + '} but got nothing instead'); } if (actual.newText !== expected.newText) { - this.raiseError('verifyDocCommentScaffolding failed - expected insertion:\n' + expected.newText + '\nactual insertion:\n' + actual.newText); + this.raiseError(name + ' failed - expected insertion:\n' + expected.newText + '\nactual insertion:\n' + actual.newText); } if (actual.offsetInNewText !== expected.offsetInNewText) { - this.raiseError('verifyDocCommentScaffolding failed - expected cursorOffset: ' + expected.offsetInNewText + ',\tactual cursorOffset:' + actual.offsetInNewText); + this.raiseError(name + ' failed - expected offsetInNewText: ' + expected.offsetInNewText + ',\nactual offsetInNewText:' + actual.offsetInNewText); } } diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index bb87fb43609..237606c1fa7 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -381,8 +381,8 @@ module Harness.LanguageService { getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: ts.FormatCodeOptions): ts.TextChange[] { return unwrapJSONCallResult(this.shim.getFormattingEditsAfterKeystroke(fileName, position, key, JSON.stringify(options))); } - getDocCommentScaffoldingAtPosition(fileName: string, position: number): ts.TextInsertion { - return unwrapJSONCallResult(this.shim.getDocCommentScaffoldingAtPosition(fileName, position)); + getDocCommentTemplateAtPosition(fileName: string, position: number): ts.TextInsertion { + return unwrapJSONCallResult(this.shim.getDocCommentTemplateAtPosition(fileName, position)); } getEmitOutput(fileName: string): ts.EmitOutput { return unwrapJSONCallResult(this.shim.getEmitOutput(fileName)); diff --git a/src/server/client.ts b/src/server/client.ts index b3ed05ecfc7..09a70456c25 100644 --- a/src/server/client.ts +++ b/src/server/client.ts @@ -539,7 +539,7 @@ namespace ts.server { throw new Error("Not Implemented Yet."); } - getDocCommentScaffoldingAtPosition(fileName: string, position: number): TextInsertion { + getDocCommentTemplateAtPosition(fileName: string, position: number): TextInsertion { throw new Error("Not Implemented Yet."); } diff --git a/src/services/services.ts b/src/services/services.ts index c0551f5681b..a9992cbe231 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1040,7 +1040,7 @@ namespace ts { getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions): TextChange[]; getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions): TextChange[]; - getDocCommentScaffoldingAtPosition(fileName: string, position: number): TextInsertion; + getDocCommentTemplateAtPosition(fileName: string, position: number): TextInsertion; getEmitOutput(fileName: string): EmitOutput; @@ -6796,7 +6796,7 @@ namespace ts { /** * Checks if position points to a valid position to add JSDoc comments, and if so, - * returns the appropriate scaffolding. Otherwise returns an empty string. + * returns the appropriate template. Otherwise returns an empty string. * Valid positions are * * outside of comments, statements, and expressions, and * * preceding a function declaration. @@ -6810,10 +6810,10 @@ namespace ts { * @param position The (character-indexed) position in the file where the check should * be performed. */ - function getDocCommentScaffoldingAtPosition(fileName: string, position: number): TextInsertion { + function getDocCommentTemplateAtPosition(fileName: string, position: number): TextInsertion { let start = new Date().getTime(); let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); - log("getDocCommentScaffoldingAtPosition: getCurrentSourceFile: " + (new Date().getTime() - start)); + log("getDocCommentTemplateAtPosition: getCurrentSourceFile: " + (new Date().getTime() - start)); // Check if in a context where we don't want to perform any insertion if (isInString(sourceFile, position) || isInComment(sourceFile, position) || hasDocComment(sourceFile, position)) { @@ -7096,7 +7096,7 @@ namespace ts { getFormattingEditsForRange, getFormattingEditsForDocument, getFormattingEditsAfterKeystroke, - getDocCommentScaffoldingAtPosition, + getDocCommentTemplateAtPosition, getEmitOutput, getSourceFile, getProgram diff --git a/src/services/shims.ts b/src/services/shims.ts index 486c0c4d7d3..912cbcb58c7 100644 --- a/src/services/shims.ts +++ b/src/services/shims.ts @@ -208,7 +208,7 @@ namespace ts { /** * Returns JSON-encoded value of the type TextInsertion. */ - getDocCommentScaffoldingAtPosition(fileName: string, position: number): string; + getDocCommentTemplateAtPosition(fileName: string, position: number): string; getEmitOutput(fileName: string): string; } @@ -816,10 +816,10 @@ namespace ts { }); } - public getDocCommentScaffoldingAtPosition(fileName: string, position: number): string { + public getDocCommentTemplateAtPosition(fileName: string, position: number): string { return this.forwardJSONCall( - "getDocCommentScaffoldingAtPosition('" + fileName + "', " + position + ")", - () => this.languageService.getDocCommentScaffoldingAtPosition(fileName, position) + "getDocCommentTemplateAtPosition('" + fileName + "', " + position + ")", + () => this.languageService.getDocCommentTemplateAtPosition(fileName, position) ); } diff --git a/tests/cases/fourslash/docCommentScaffoldingEmptyFile.ts b/tests/cases/fourslash/docCommentTemplateEmptyFile.ts similarity index 70% rename from tests/cases/fourslash/docCommentScaffoldingEmptyFile.ts rename to tests/cases/fourslash/docCommentTemplateEmptyFile.ts index 35d427a0001..76e888ea2cb 100644 --- a/tests/cases/fourslash/docCommentScaffoldingEmptyFile.ts +++ b/tests/cases/fourslash/docCommentTemplateEmptyFile.ts @@ -4,4 +4,4 @@ /////*0*/ goTo.marker("0"); -verify.noDocCommentScaffolding(); \ No newline at end of file +verify.noDocCommentTemplate(); \ No newline at end of file diff --git a/tests/cases/fourslash/docCommentScaffoldingFunctionWithParameters.ts b/tests/cases/fourslash/docCommentTemplateFunctionWithParameters.ts similarity index 73% rename from tests/cases/fourslash/docCommentScaffoldingFunctionWithParameters.ts rename to tests/cases/fourslash/docCommentTemplateFunctionWithParameters.ts index d127f60f47e..00a98cfe72c 100644 --- a/tests/cases/fourslash/docCommentScaffoldingFunctionWithParameters.ts +++ b/tests/cases/fourslash/docCommentTemplateFunctionWithParameters.ts @@ -11,7 +11,7 @@ const noIndentOffset = 7; const oneIndentOffset = noIndentOffset + 4; goTo.marker("0"); -verify.DocCommentScaffolding(noIndentScaffolding, noIndentOffset); +verify.DocCommentTemplate(noIndentScaffolding, noIndentOffset); goTo.marker("1"); -verify.DocCommentScaffolding(oneIndentScaffolding, oneIndentOffset); \ No newline at end of file +verify.DocCommentTemplate(oneIndentScaffolding, oneIndentOffset); \ No newline at end of file diff --git a/tests/cases/fourslash/docCommentScaffoldingInMultiLineComment.ts b/tests/cases/fourslash/docCommentTemplateInMultiLineComment.ts similarity index 72% rename from tests/cases/fourslash/docCommentScaffoldingInMultiLineComment.ts rename to tests/cases/fourslash/docCommentTemplateInMultiLineComment.ts index cff57a68305..131f722a9af 100644 --- a/tests/cases/fourslash/docCommentScaffoldingInMultiLineComment.ts +++ b/tests/cases/fourslash/docCommentTemplateInMultiLineComment.ts @@ -4,4 +4,4 @@ //// /* /*0*/ */ goTo.marker("0"); -verify.noDocCommentScaffolding(); \ No newline at end of file +verify.noDocCommentTemplate(); \ No newline at end of file diff --git a/tests/cases/fourslash/docCommentScaffoldingInSingleLineComment.ts b/tests/cases/fourslash/docCommentTemplateInSingleLineComment.ts similarity index 88% rename from tests/cases/fourslash/docCommentScaffoldingInSingleLineComment.ts rename to tests/cases/fourslash/docCommentTemplateInSingleLineComment.ts index 99d0a539d52..52925870a66 100644 --- a/tests/cases/fourslash/docCommentScaffoldingInSingleLineComment.ts +++ b/tests/cases/fourslash/docCommentTemplateInSingleLineComment.ts @@ -10,5 +10,5 @@ test.markers().forEach((marker) => { goTo.position(marker.position); - verify.noDocCommentScaffolding(); + verify.noDocCommentTemplate(); }); \ No newline at end of file diff --git a/tests/cases/fourslash/docCommentScaffoldingIndentation.ts b/tests/cases/fourslash/docCommentTemplateIndentation.ts similarity index 66% rename from tests/cases/fourslash/docCommentScaffoldingIndentation.ts rename to tests/cases/fourslash/docCommentTemplateIndentation.ts index 7769480426e..f35e3b42cd3 100644 --- a/tests/cases/fourslash/docCommentScaffoldingIndentation.ts +++ b/tests/cases/fourslash/docCommentTemplateIndentation.ts @@ -13,10 +13,10 @@ const oneIndentOffset = noIndentOffset + 4; const twoIndentOffset = oneIndentOffset + 4; goTo.marker("0"); -verify.DocCommentScaffolding(noIndentEmptyScaffolding, noIndentOffset); +verify.DocCommentTemplate(noIndentEmptyScaffolding, noIndentOffset); goTo.marker("1"); -verify.DocCommentScaffolding(oneIndentEmptyScaffolding, oneIndentOffset); +verify.DocCommentTemplate(oneIndentEmptyScaffolding, oneIndentOffset); goTo.marker("2"); -verify.DocCommentScaffolding(twoIndentEmptyScaffolding, twoIndentOffset); \ No newline at end of file +verify.DocCommentTemplate(twoIndentEmptyScaffolding, twoIndentOffset); \ No newline at end of file diff --git a/tests/cases/fourslash/docCommentScaffoldingInsideFunctionDeclaration.ts b/tests/cases/fourslash/docCommentTemplateInsideFunctionDeclaration.ts similarity index 60% rename from tests/cases/fourslash/docCommentScaffoldingInsideFunctionDeclaration.ts rename to tests/cases/fourslash/docCommentTemplateInsideFunctionDeclaration.ts index 6a7881339ad..9c803301526 100644 --- a/tests/cases/fourslash/docCommentScaffoldingInsideFunctionDeclaration.ts +++ b/tests/cases/fourslash/docCommentTemplateInsideFunctionDeclaration.ts @@ -1,9 +1,9 @@ /// // @Filename: functionDecl.ts -////function /*0*/foo/*1*/(/*2*/) /*3*/{ /*4*/} +////f/*0*/unction /*1*/foo/*2*/(/*3*/) /*4*/{ /*5*/} test.markers().forEach((marker) => { goTo.position(marker.position); - verify.noDocCommentScaffolding(); + verify.noDocCommentTemplate(); }); diff --git a/tests/cases/fourslash/docCommentScaffoldingRegex.ts b/tests/cases/fourslash/docCommentTemplateRegex.ts similarity index 79% rename from tests/cases/fourslash/docCommentScaffoldingRegex.ts rename to tests/cases/fourslash/docCommentTemplateRegex.ts index 374bc94ef5e..0bf50f5e85a 100644 --- a/tests/cases/fourslash/docCommentScaffoldingRegex.ts +++ b/tests/cases/fourslash/docCommentTemplateRegex.ts @@ -5,5 +5,5 @@ test.markers().forEach((marker) => { goTo.position(marker.position); - verify.noDocCommentScaffolding(); + verify.noDocCommentTemplate(); }); \ No newline at end of file diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index 0be9ba4a5fc..10c49777a6d 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -379,12 +379,12 @@ module FourSlashInterface { } // Will fix in fourslash-referencing - public DocCommentScaffolding(expectedText: string, expectedOffset: number, empty?: boolean) { - FourSlash.currentTestState.verifyDocCommentScaffolding(empty ? undefined : { newText: expectedText, cursorOffset: expectedOffset }); + public DocCommentTemplate(expectedText: string, expectedOffset: number, empty?: boolean) { + FourSlash.currentTestState.verifyDocCommentTemplate(empty ? undefined : { newText: expectedText, cursorOffset: expectedOffset }); } - public noDocCommentScaffolding() { - this.DocCommentScaffolding(/*expectedText*/ undefined, /*expectedOffset*/ undefined, true); + public noDocCommentTemplate() { + this.DocCommentTemplate(/*expectedText*/ undefined, /*expectedOffset*/ undefined, true); } public getScriptLexicalStructureListCount(count: number) { From 9d26b4eb4178cc59ae27f1e1f3d68e9cbd799b34 Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Mon, 3 Aug 2015 15:09:49 -0700 Subject: [PATCH 39/93] Fixed newline handling --- src/harness/fourslash.ts | 20 ++++++++++--------- src/services/services.ts | 4 ++-- ...ocCommentTemplateFunctionWithParameters.ts | 6 +++--- .../docCommentTemplateIndentation.ts | 8 ++++---- tests/cases/fourslash/fourslash.ts | 3 +-- 5 files changed, 21 insertions(+), 20 deletions(-) diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index e8048ab82d7..a65a6b21e38 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -1941,7 +1941,7 @@ module FourSlash { } } - public verifyDocCommentTemplate(expected: ts.TextInsertion) { + public verifyDocCommentTemplate(expected?: ts.TextInsertion) { const name = "verifyDocCommentTemplate"; let actual = this.languageService.getDocCommentTemplateAtPosition(this.activeFile.fileName, this.currentCaretPosition); @@ -1953,16 +1953,18 @@ module FourSlash { this.raiseError(name + ' failed - expected no template but got {newText: \"' + actual.newText + '\" offsetInNewText: ' + actual.offsetInNewText + '}'); } } - if (expected !== undefined && actual === undefined) { - this.raiseError(name + ' failed - expected the template {newText: \"' + actual.newText + '\" offsetInNewText: ' + actual.offsetInNewText + '} but got nothing instead'); - } + else { + if (actual === undefined) { + this.raiseError(name + ' failed - expected the template {newText: \"' + actual.newText + '\" offsetInNewText: ' + actual.offsetInNewText + '} but got nothing instead'); + } - if (actual.newText !== expected.newText) { - this.raiseError(name + ' failed - expected insertion:\n' + expected.newText + '\nactual insertion:\n' + actual.newText); - } + if (actual.newText !== expected.newText) { + this.raiseError(name + ' failed - expected insertion:\n' + expected.newText + '\nactual insertion:\n' + actual.newText); + } - if (actual.offsetInNewText !== expected.offsetInNewText) { - this.raiseError(name + ' failed - expected offsetInNewText: ' + expected.offsetInNewText + ',\nactual offsetInNewText:' + actual.offsetInNewText); + if (actual.offsetInNewText !== expected.offsetInNewText) { + this.raiseError(name + ' failed - expected offsetInNewText: ' + expected.offsetInNewText + ',\nactual offsetInNewText:' + actual.offsetInNewText); + } } } diff --git a/src/services/services.ts b/src/services/services.ts index a9992cbe231..260f18e4630 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -6838,7 +6838,7 @@ namespace ts { let indentationStr = sourceFile.text.substr(lineStart, posLineAndChar.character).match(/\s*/).toString(); - const newLine = host.getNewLine(); + const newLine = host.getNewLine ? host.getNewLine() : "\r\n"; let docParams = parameters.map((p, index) => indentationStr + " * @param " + (p.name.kind === SyntaxKind.Identifier ? (p.name).text : "param" + index.toString()) + newLine); @@ -6850,7 +6850,7 @@ namespace ts { /* closing comment */ indentationStr + " */" + /* newline if at decl start */ (tokenStart === position ? newLine + indentationStr : ""); - let cursorOffset = /* "/**" */ 3 + /* newLine */ + newLine.length + indentationStr.length + /* " * " */ 3; + let cursorOffset = /* "/**" */ 3 + /* newLine */ newLine.length + indentationStr.length + /* " * " */ 3; return {newText: result, offsetInNewText: cursorOffset }; } diff --git a/tests/cases/fourslash/docCommentTemplateFunctionWithParameters.ts b/tests/cases/fourslash/docCommentTemplateFunctionWithParameters.ts index 00a98cfe72c..f4410d5d454 100644 --- a/tests/cases/fourslash/docCommentTemplateFunctionWithParameters.ts +++ b/tests/cases/fourslash/docCommentTemplateFunctionWithParameters.ts @@ -5,9 +5,9 @@ //// /*1*/ //// function foo(x: number, y: string): boolean {} -const noIndentScaffolding = "/**\n * \n * @param x\n * @param y\n */"; -const oneIndentScaffolding = "/**\n * \n * @param x\n * @param y\n */"; -const noIndentOffset = 7; +const noIndentScaffolding = "/**\r\n * \r\n * @param x\r\n * @param y\r\n */"; +const oneIndentScaffolding = "/**\r\n * \r\n * @param x\r\n * @param y\r\n */"; +const noIndentOffset = 8; const oneIndentOffset = noIndentOffset + 4; goTo.marker("0"); diff --git a/tests/cases/fourslash/docCommentTemplateIndentation.ts b/tests/cases/fourslash/docCommentTemplateIndentation.ts index f35e3b42cd3..db7e48dab2e 100644 --- a/tests/cases/fourslash/docCommentTemplateIndentation.ts +++ b/tests/cases/fourslash/docCommentTemplateIndentation.ts @@ -5,10 +5,10 @@ //// /*1*/ //// /*2*/function foo() { } -const noIndentEmptyScaffolding = "/**\n * \n */"; -const oneIndentEmptyScaffolding = "/**\n * \n */"; -const twoIndentEmptyScaffolding = "/**\n * \n */\n "; -const noIndentOffset = 7; +const noIndentEmptyScaffolding = "/**\r\n * \r\n */"; +const oneIndentEmptyScaffolding = "/**\r\n * \r\n */"; +const twoIndentEmptyScaffolding = "/**\r\n * \r\n */\r\n "; +const noIndentOffset = 8; const oneIndentOffset = noIndentOffset + 4; const twoIndentOffset = oneIndentOffset + 4; diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index 10c49777a6d..b778fb3fc24 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -378,9 +378,8 @@ module FourSlashInterface { FourSlash.currentTestState.verifyNoMatchingBracePosition(bracePosition); } - // Will fix in fourslash-referencing public DocCommentTemplate(expectedText: string, expectedOffset: number, empty?: boolean) { - FourSlash.currentTestState.verifyDocCommentTemplate(empty ? undefined : { newText: expectedText, cursorOffset: expectedOffset }); + FourSlash.currentTestState.verifyDocCommentTemplate(empty ? undefined : { newText: expectedText, offsetInNewText: expectedOffset }); } public noDocCommentTemplate() { From ae721d3a6f49224ff11ea739ca58d92dfa024772 Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Mon, 3 Aug 2015 16:03:15 -0700 Subject: [PATCH 40/93] respond to cyrus --- src/harness/fourslash.ts | 8 +++--- src/services/services.ts | 34 +++++++++++++++---------- src/services/utilities.ts | 40 ++++++++++++++++-------------- tests/cases/fourslash/fourslash.ts | 2 +- 4 files changed, 47 insertions(+), 37 deletions(-) diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index a65a6b21e38..c44fa9dbc09 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -1950,20 +1950,20 @@ module FourSlash { return; } else { - this.raiseError(name + ' failed - expected no template but got {newText: \"' + actual.newText + '\" offsetInNewText: ' + actual.offsetInNewText + '}'); + this.raiseError(name + ' failed - expected no template but got {newText: \"' + actual.newText + '\" caretOffset: ' + actual.caretOffset + '}'); } } else { if (actual === undefined) { - this.raiseError(name + ' failed - expected the template {newText: \"' + actual.newText + '\" offsetInNewText: ' + actual.offsetInNewText + '} but got nothing instead'); + this.raiseError(name + ' failed - expected the template {newText: \"' + actual.newText + '\" caretOffset: ' + actual.caretOffset + '} but got nothing instead'); } if (actual.newText !== expected.newText) { this.raiseError(name + ' failed - expected insertion:\n' + expected.newText + '\nactual insertion:\n' + actual.newText); } - if (actual.offsetInNewText !== expected.offsetInNewText) { - this.raiseError(name + ' failed - expected offsetInNewText: ' + expected.offsetInNewText + ',\nactual offsetInNewText:' + actual.offsetInNewText); + if (actual.caretOffset !== expected.caretOffset) { + this.raiseError(name + ' failed - expected caretOffset: ' + expected.caretOffset + ',\nactual caretOffset:' + actual.caretOffset); } } } diff --git a/src/services/services.ts b/src/services/services.ts index 260f18e4630..b72ef7ca111 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1090,7 +1090,8 @@ namespace ts { export interface TextInsertion { newText: string; - offsetInNewText: number; + /** The position in newText the caret should point to after the insertion. */ + caretOffset: number; } export interface RenameLocation { @@ -6758,7 +6759,6 @@ namespace ts { function getIndentationAtPosition(fileName: string, position: number, editorOptions: EditorOptions) { let start = new Date().getTime(); let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); - log("getIndentationAtPosition: getCurrentSourceFile: " + (new Date().getTime() - start)); start = new Date().getTime(); @@ -6800,11 +6800,11 @@ namespace ts { * Valid positions are * * outside of comments, statements, and expressions, and * * preceding a function declaration. - * + * * Hosts should ideally check that: * * The line is all whitespace up to 'position' before performing the insertion. * * If the keystroke sequence "/\*\*" induced the call, we also check that the next - * non-whitespace character is '*', which (approximately) indicates whether we added + * non-whitespace character is '*', which (approximately) indicates whether we added * the second '*' to complete an existing (JSDoc) comment. * @param fileName The file in which to perform the check. * @param position The (character-indexed) position in the file where the check should @@ -6843,16 +6843,24 @@ namespace ts { let docParams = parameters.map((p, index) => indentationStr + " * @param " + (p.name.kind === SyntaxKind.Identifier ? (p.name).text : "param" + index.toString()) + newLine); - let result = - /* opening comment */ "/**" + newLine + - /* first line for function info */ indentationStr + " * " + newLine + - /* paramters */ docParams.reduce((prev, cur) => prev + cur, "") + - /* closing comment */ indentationStr + " */" + - /* newline if at decl start */ (tokenStart === position ? newLine + indentationStr : ""); - - let cursorOffset = /* "/**" */ 3 + /* newLine */ newLine.length + indentationStr.length + /* " * " */ 3; - return {newText: result, offsetInNewText: cursorOffset }; + // A doc comment consists of the following + // * The opening comment line + // * the first line (without a param) for the object's untagged info (this is also where the caret ends up) + // * the '@param'-tagged lines + // * TODO: other tags. + // * the closing comment line + // * if the caret was directly in front of the object, then we add an extra line and indentation. + let result = + "/**" + newLine + + indentationStr + " * " + newLine + + docParams.reduce((prev, cur) => prev + cur, "") + + indentationStr + " */" + + (tokenStart === position ? newLine + indentationStr : ""); + + let cursorOffset = "/**".length + newLine.length + indentationStr.length + " * ".length; + + return { newText: result, caretOffset: cursorOffset }; } function getTodoComments(fileName: string, descriptors: TodoCommentDescriptor[]): TodoComment[] { diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 8b8cadfc7fe..36ae22ca46a 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -421,33 +421,32 @@ namespace ts { } export function isInComment(sourceFile: SourceFile, position: number) { - return isInCommentHelper(sourceFile, position, /*extraCheck*/ c => true); + return isInCommentHelper(sourceFile, position, /*predicate*/ c => true); } /** * Returns true if the cursor at position in sourceFile is within a comment that additionally - * satisfies extraCheck, and false otherwise. + * satisfies predicate, and false otherwise. */ - export function isInCommentHelper(sourceFile: SourceFile, position: number, - extraCheck: (c: CommentRange) => boolean): boolean { + export function isInCommentHelper(sourceFile: SourceFile, position: number, predicate: (c: CommentRange) => boolean): boolean { let token = getTokenAtPosition(sourceFile, position); if (token && position <= token.getStart()) { let commentRanges = getLeadingCommentRanges(sourceFile.text, token.pos); - + + // The end marker of a single-line comment does not include the newline character. + // In the following case, we are inside a comment (^ denotes the cursor position): + // + // // asdf ^\n + // + // But for multi-line comments, we don't want to be inside the comment in the following case: + // + // /* asdf */^ + // + // Internally, we represent the end of the comment at the newline and closing '/', respectively. return forEach(commentRanges, c => c.pos < position && - // The end marker of a single-line comment does not include the newline character. - // In the following case, we are inside a comment (^ denotes the cursor position): - // - // // asdf ^\n - // - // But for multi-line comments, we don't want to be inside the comment in the following case: - // - // /* asdf */^ - // - // Internally, we represent the end of the comment at the newline and closing '/', respectively. (c.kind == SyntaxKind.SingleLineCommentTrivia ? position <= c.end : position < c.end) && - extraCheck(c)); + predicate(c)); } return false; @@ -456,12 +455,15 @@ namespace ts { export function hasDocComment(sourceFile: SourceFile, position: number) { let token = getTokenAtPosition(sourceFile, position); - let JSDocPrefixRegex = /^\/\*\*\s*/; - // First, we have to see if this position actually landed in a comment. let commentRanges = getLeadingCommentRanges(sourceFile.text, token.pos); - return forEach(commentRanges, c => JSDocPrefixRegex.test(sourceFile.text.substring(c.pos, c.end))); + return forEach(commentRanges, c => jsDocPrefix); + + function jsDocPrefix(c: CommentRange): boolean { + var text = sourceFile.text; + return text.length >= c.pos + 3 && text[c.pos] === '/' && text[c.pos + 1] === '*' && text[c.pos + 2] === '*'; + } } function nodeHasTokens(n: Node): boolean { diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index b778fb3fc24..465d84cb0da 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -379,7 +379,7 @@ module FourSlashInterface { } public DocCommentTemplate(expectedText: string, expectedOffset: number, empty?: boolean) { - FourSlash.currentTestState.verifyDocCommentTemplate(empty ? undefined : { newText: expectedText, offsetInNewText: expectedOffset }); + FourSlash.currentTestState.verifyDocCommentTemplate(empty ? undefined : { newText: expectedText, caretOffset: expectedOffset }); } public noDocCommentTemplate() { From 5c8e3518e93f3d00dd0178a3ca8eadbb32c2aaad Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Mon, 3 Aug 2015 16:17:59 -0700 Subject: [PATCH 41/93] fixed logging --- src/services/services.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/services.ts b/src/services/services.ts index b72ef7ca111..0a4f60d916d 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -6759,6 +6759,7 @@ namespace ts { function getIndentationAtPosition(fileName: string, position: number, editorOptions: EditorOptions) { let start = new Date().getTime(); let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); + log("getIndentationAtPosition: getCurrentSourceFile: " + (new Date().getTime() - start)); start = new Date().getTime(); @@ -6813,7 +6814,6 @@ namespace ts { function getDocCommentTemplateAtPosition(fileName: string, position: number): TextInsertion { let start = new Date().getTime(); let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); - log("getDocCommentTemplateAtPosition: getCurrentSourceFile: " + (new Date().getTime() - start)); // Check if in a context where we don't want to perform any insertion if (isInString(sourceFile, position) || isInComment(sourceFile, position) || hasDocComment(sourceFile, position)) { From 24753c48858cec8193d65631b741e3feeda3d040 Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Tue, 4 Aug 2015 17:53:01 -0700 Subject: [PATCH 42/93] remove asserts --- src/compiler/scanner.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index 55e58bb4d46..8aaed566671 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -319,10 +319,10 @@ namespace ts { } /* @internal */ + /** + * We assume the first line starts at position 0 and 'position' is non-negative. + */ export function computeLineAndCharacterOfPosition(lineStarts: number[], position: number) { - Debug.assert(lineStarts.length && lineStarts[0] === 0, "the first line should start at position 0"); - Debug.assert(0 <= position, "position should be positive"); - let lineNumber = binarySearch(lineStarts, position); if (lineNumber < 0) { // If the actual position was not found, From 4ea3bb6485a14515da46053ea119ea6eb8f14ade Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Wed, 5 Aug 2015 16:22:27 -0700 Subject: [PATCH 43/93] Make 'predicate' optional and DRY --- src/services/services.ts | 20 ++++++++++++-------- src/services/utilities.ts | 15 +++++++++------ 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/src/services/services.ts b/src/services/services.ts index 0a4f60d916d..ad158192cf6 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -6826,6 +6826,10 @@ namespace ts { return undefined; } + // TODO: add support for: + // * methods + // * constructors + // * class decls let containingFunction = getAncestor(tokenAtPos, SyntaxKind.FunctionDeclaration); if (!containingFunction || containingFunction.getStart() < position) { @@ -6836,12 +6840,13 @@ namespace ts { let posLineAndChar = sourceFile.getLineAndCharacterOfPosition(position); let lineStart = sourceFile.getLineStarts()[posLineAndChar.line]; - let indentationStr = sourceFile.text.substr(lineStart, posLineAndChar.character).match(/\s*/).toString(); + let indentationStr = sourceFile.text.substr(lineStart, posLineAndChar.character); + // TODO: call a helper method instead once PR #4133 gets merged in. const newLine = host.getNewLine ? host.getNewLine() : "\r\n"; let docParams = parameters.map((p, index) => - indentationStr + " * @param " + (p.name.kind === SyntaxKind.Identifier ? (p.name).text : "param" + index.toString()) + newLine); + indentationStr + " * @param " + (p.name.kind === SyntaxKind.Identifier ? (p.name).text : "param" + index) + newLine); // A doc comment consists of the following @@ -6851,16 +6856,15 @@ namespace ts { // * TODO: other tags. // * the closing comment line // * if the caret was directly in front of the object, then we add an extra line and indentation. + const preamble = "/**" + newLine + + indentationStr + " * "; let result = - "/**" + newLine + - indentationStr + " * " + newLine + - docParams.reduce((prev, cur) => prev + cur, "") + + preamble + newLine + + docParams.join("") + indentationStr + " */" + (tokenStart === position ? newLine + indentationStr : ""); - let cursorOffset = "/**".length + newLine.length + indentationStr.length + " * ".length; - - return { newText: result, caretOffset: cursorOffset }; + return { newText: result, caretOffset: preamble.length }; } function getTodoComments(fileName: string, descriptors: TodoCommentDescriptor[]): TodoComment[] { diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 36ae22ca46a..a5230e7eb08 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -421,14 +421,14 @@ namespace ts { } export function isInComment(sourceFile: SourceFile, position: number) { - return isInCommentHelper(sourceFile, position, /*predicate*/ c => true); + return isInCommentHelper(sourceFile, position, /*predicate*/ undefined); } /** * Returns true if the cursor at position in sourceFile is within a comment that additionally * satisfies predicate, and false otherwise. */ - export function isInCommentHelper(sourceFile: SourceFile, position: number, predicate: (c: CommentRange) => boolean): boolean { + export function isInCommentHelper(sourceFile: SourceFile, position: number, predicate?: (c: CommentRange) => boolean): boolean { let token = getTokenAtPosition(sourceFile, position); if (token && position <= token.getStart()) { @@ -444,9 +444,12 @@ namespace ts { // /* asdf */^ // // Internally, we represent the end of the comment at the newline and closing '/', respectively. - return forEach(commentRanges, c => c.pos < position && - (c.kind == SyntaxKind.SingleLineCommentTrivia ? position <= c.end : position < c.end) && - predicate(c)); + return predicate ? + forEach(commentRanges, c => c.pos < position && + (c.kind == SyntaxKind.SingleLineCommentTrivia ? position <= c.end : position < c.end) && + predicate(c)) : + forEach(commentRanges, c => c.pos < position && + (c.kind == SyntaxKind.SingleLineCommentTrivia ? position <= c.end : position < c.end)); } return false; @@ -458,7 +461,7 @@ namespace ts { // First, we have to see if this position actually landed in a comment. let commentRanges = getLeadingCommentRanges(sourceFile.text, token.pos); - return forEach(commentRanges, c => jsDocPrefix); + return forEach(commentRanges, jsDocPrefix); function jsDocPrefix(c: CommentRange): boolean { var text = sourceFile.text; From eab6911bcec8f6d1fc722df3328894f602b06c8a Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Wed, 5 Aug 2015 21:45:04 -0700 Subject: [PATCH 44/93] emit export declarations for system modules as a part of 'execute' method --- src/compiler/emitter.ts | 124 ++++++++---------- tests/baselines/reference/systemModule10.js | 12 +- .../baselines/reference/systemModule10_ES5.js | 12 +- .../reference/systemModule14.errors.txt | 16 +++ tests/baselines/reference/systemModule14.js | 31 +++++ tests/cases/compiler/systemModule14.ts | 12 ++ 6 files changed, 124 insertions(+), 83 deletions(-) create mode 100644 tests/baselines/reference/systemModule14.errors.txt create mode 100644 tests/baselines/reference/systemModule14.js create mode 100644 tests/cases/compiler/systemModule14.ts diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index e5bdb9a2585..da268892ad9 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -3090,32 +3090,39 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi } } - function emitExportMemberAssignments(name: Identifier) { + function emitExportMemberAssignmentsInNonSystemModule(name: Identifier) { + if (compilerOptions.module === ModuleKind.System) { + return; + } + if (!exportEquals && exportSpecifiers && hasProperty(exportSpecifiers, name.text)) { for (let specifier of exportSpecifiers[name.text]) { writeLine(); - if (compilerOptions.module === ModuleKind.System) { - emitStart(specifier.name); - write(`${exportFunctionForFile}("`); - emitNodeWithoutSourceMap(specifier.name); - write(`", `); - emitExpressionIdentifier(name); - write(")"); - emitEnd(specifier.name); - } - else { - emitStart(specifier.name); - emitContainingModuleName(specifier); - write("."); - emitNodeWithoutSourceMap(specifier.name); - emitEnd(specifier.name); - write(" = "); - emitExpressionIdentifier(name); - } + emitStart(specifier.name); + emitContainingModuleName(specifier); + write("."); + emitNodeWithoutSourceMap(specifier.name); + emitEnd(specifier.name); + write(" = "); + emitExpressionIdentifier(name); write(";"); } } } + + function emitExportSpecifierInSystemModule(specifier: ExportSpecifier): void { + Debug.assert(compilerOptions.module === ModuleKind.System); + + writeLine(); + emitStart(specifier.name); + write(`${exportFunctionForFile}("`); + emitNodeWithoutSourceMap(specifier.name); + write(`", `); + emitExpressionIdentifier(specifier.propertyName || specifier.name); + write(")"); + emitEnd(specifier.name); + write(";"); + } function emitDestructuring(root: BinaryExpression | VariableDeclaration | ParameterDeclaration, isAssignmentExpressionStatement: boolean, value?: Expression) { let emitCount = 0; @@ -3405,7 +3412,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi } let name = node.name; if (name.kind === SyntaxKind.Identifier) { - emitExportMemberAssignments(name); + emitExportMemberAssignmentsInNonSystemModule(name); } else if (isBindingPattern(name)) { forEach((name).elements, emitExportVariableAssignments); @@ -3660,7 +3667,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi emitSignatureAndBody(node); if (languageVersion < ScriptTarget.ES6 && node.kind === SyntaxKind.FunctionDeclaration && node.parent === currentSourceFile && node.name) { - emitExportMemberAssignments((node).name); + emitExportMemberAssignmentsInNonSystemModule((node).name); } if (node.kind !== SyntaxKind.MethodDeclaration && node.kind !== SyntaxKind.MethodSignature) { emitTrailingComments(node); @@ -4583,7 +4590,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi } if (languageVersion < ScriptTarget.ES6 && node.parent === currentSourceFile && node.name) { - emitExportMemberAssignments(node.name); + emitExportMemberAssignmentsInNonSystemModule(node.name); } } @@ -5172,7 +5179,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi emitDeclarationName(node); write(");"); } - emitExportMemberAssignments(node.name); + emitExportMemberAssignmentsInNonSystemModule(node.name); } } @@ -5293,7 +5300,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi emitDeclarationName(node); write(");"); } - emitExportMemberAssignments(node.name); + emitExportMemberAssignmentsInNonSystemModule(node.name); } } @@ -5326,7 +5333,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitExportImportAssignments(node: Node) { if (isAliasSymbolDeclaration(node) && resolver.isValueAliasDeclaration(node)) { - emitExportMemberAssignments((node).name); + emitExportMemberAssignmentsInNonSystemModule((node).name); } forEachChild(node, emitExportImportAssignments); } @@ -6134,45 +6141,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi writeLine(); // save import into the local write(`${importVariableName} = ${parameterName};`); - writeLine(); - - let defaultName = - importNode.kind === SyntaxKind.ImportDeclaration - ? (importNode).importClause.name - : (importNode).name; - - if (defaultName) { - // emit re-export for imported default name - // import n1 from 'foo1' - // import n2 = require('foo2') - // export {n1} - // export {n2} - emitExportMemberAssignments(defaultName); - writeLine(); - } - - if (importNode.kind === SyntaxKind.ImportDeclaration && - (importNode).importClause.namedBindings) { - - let namedBindings = (importNode).importClause.namedBindings; - if (namedBindings.kind === SyntaxKind.NamespaceImport) { - // emit re-export for namespace - // import * as n from 'foo' - // export {n} - emitExportMemberAssignments((namedBindings).name); - writeLine(); - } - else { - // emit re-exports for named imports - // import {a, b} from 'foo' - // export {a, b as c} - for (let element of (namedBindings).elements) { - emitExportMemberAssignments(element.name || element.propertyName); - writeLine(); - } - } - } - + writeLine(); decreaseIndent(); break; case SyntaxKind.ExportDeclaration: @@ -6226,26 +6195,39 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi writeLine(); for (let i = startIndex; i < node.statements.length; ++i) { let statement = node.statements[i]; - // - external module related imports/exports are not emitted for system modules - // - function declarations are not emitted because they were already hoisted switch (statement.kind) { + // - function declarations are not emitted because they were already hoisted + // - import declarations are not emitted since they are already handled in setters + // - export declarations with module specifiers are not emitted since they were already written in setters + // - export declarations without module specifiers are emitted preserving the order + case SyntaxKind.FunctionDeclaration: case SyntaxKind.ExportDeclaration: case SyntaxKind.ImportDeclaration: - case SyntaxKind.FunctionDeclaration: + if (statement.kind === SyntaxKind.ExportDeclaration) { + if (!(statement).moduleSpecifier) { + for (let element of (statement).exportClause.elements) { + // write call to exporter function for every export specifier in exports list + emitExportSpecifierInSystemModule(element); + } + } + } continue; case SyntaxKind.ImportEqualsDeclaration: if (!isInternalModuleImportEqualsDeclaration(statement)) { + // - import equals declarations that import external modules are not emitted continue; } - } - writeLine(); - emit(statement); + // fall-though for import declarations that import internal modules + default: + writeLine(); + emit(statement); + } } decreaseIndent(); writeLine(); write("}"); // execute } - + function emitSystemModule(node: SourceFile, startIndex: number): void { collectExternalModuleInfo(node); // System modules has the following shape diff --git a/tests/baselines/reference/systemModule10.js b/tests/baselines/reference/systemModule10.js index c63b3589085..dec185a3063 100644 --- a/tests/baselines/reference/systemModule10.js +++ b/tests/baselines/reference/systemModule10.js @@ -16,17 +16,17 @@ System.register(['file1', 'file2'], function(exports_1) { setters:[ function (_file1_1) { file1_1 = _file1_1; - exports_1("n", file1_1["default"]); - exports_1("n1", file1_1["default"]); - exports_1("x", file1_1.x); - exports_1("y", file1_1.x); }, function (_n2) { n2 = _n2; - exports_1("n2", n2); - exports_1("n3", n2); }], execute: function() { + exports_1("x", file1_1.x); + exports_1("y", file1_1.x); + exports_1("n", file1_1["default"]); + exports_1("n1", file1_1["default"]); + exports_1("n2", n2); + exports_1("n3", n2); } } }); diff --git a/tests/baselines/reference/systemModule10_ES5.js b/tests/baselines/reference/systemModule10_ES5.js index bdb920414de..c080b893513 100644 --- a/tests/baselines/reference/systemModule10_ES5.js +++ b/tests/baselines/reference/systemModule10_ES5.js @@ -16,17 +16,17 @@ System.register(['file1', 'file2'], function(exports_1) { setters:[ function (_file1_1) { file1_1 = _file1_1; - exports_1("n", file1_1.default); - exports_1("n1", file1_1.default); - exports_1("x", file1_1.x); - exports_1("y", file1_1.x); }, function (_n2) { n2 = _n2; - exports_1("n2", n2); - exports_1("n3", n2); }], execute: function() { + exports_1("x", file1_1.x); + exports_1("y", file1_1.x); + exports_1("n", file1_1.default); + exports_1("n1", file1_1.default); + exports_1("n2", n2); + exports_1("n3", n2); } } }); diff --git a/tests/baselines/reference/systemModule14.errors.txt b/tests/baselines/reference/systemModule14.errors.txt new file mode 100644 index 00000000000..6ba64896df8 --- /dev/null +++ b/tests/baselines/reference/systemModule14.errors.txt @@ -0,0 +1,16 @@ +tests/cases/compiler/systemModule14.ts(6,17): error TS2307: Cannot find module 'foo'. + + +==== tests/cases/compiler/systemModule14.ts (1 errors) ==== + + function foo() { + return a; + } + + import {a} from "foo"; + ~~~~~ +!!! error TS2307: Cannot find module 'foo'. + export {foo} + + var x = 1; + export {foo as b} \ No newline at end of file diff --git a/tests/baselines/reference/systemModule14.js b/tests/baselines/reference/systemModule14.js new file mode 100644 index 00000000000..9365754a1e5 --- /dev/null +++ b/tests/baselines/reference/systemModule14.js @@ -0,0 +1,31 @@ +//// [systemModule14.ts] + +function foo() { + return a; +} + +import {a} from "foo"; +export {foo} + +var x = 1; +export {foo as b} + +//// [systemModule14.js] +System.register(["foo"], function(exports_1) { + var foo_1; + var x; + function foo() { + return foo_1.a; + } + return { + setters:[ + function (_foo_1) { + foo_1 = _foo_1; + }], + execute: function() { + exports_1("foo", foo); + x = 1; + exports_1("b", foo); + } + } +}); diff --git a/tests/cases/compiler/systemModule14.ts b/tests/cases/compiler/systemModule14.ts new file mode 100644 index 00000000000..91192cec74a --- /dev/null +++ b/tests/cases/compiler/systemModule14.ts @@ -0,0 +1,12 @@ +// @module: system +// @isolatedModules: true + +function foo() { + return a; +} + +import {a} from "foo"; +export {foo} + +var x = 1; +export {foo as b} \ No newline at end of file From 6b1838caec3688b76da7895925f8087b9bbb6dfc Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Thu, 6 Aug 2015 08:31:29 -0700 Subject: [PATCH 45/93] change '*' to '-' in lists --- src/compiler/types.ts | 6 +++--- src/services/services.ts | 16 ++++++++-------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/compiler/types.ts b/src/compiler/types.ts index eb908d07ec0..658f263ec3d 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -586,9 +586,9 @@ namespace ts { * Several node kinds share function-like features such as a signature, * a name, and a body. These nodes should extend FunctionLikeDeclaration. * Examples: - * * FunctionDeclaration - * * MethodDeclaration - * * AccessorDeclaration + * - FunctionDeclaration + * - MethodDeclaration + * - AccessorDeclaration */ export interface FunctionLikeDeclaration extends SignatureDeclaration { _functionLikeDeclarationBrand: any; diff --git a/src/services/services.ts b/src/services/services.ts index ad158192cf6..4478caae338 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -6759,7 +6759,7 @@ namespace ts { function getIndentationAtPosition(fileName: string, position: number, editorOptions: EditorOptions) { let start = new Date().getTime(); let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); - log("getIndentationAtPosition: getCurrentSourceFile: " + (new Date().getTime() - start)); + log("getIndentationAtPosition: getCurrentSourceFile: " + (new Date().getTime() - start)); start = new Date().getTime(); @@ -6799,12 +6799,12 @@ namespace ts { * Checks if position points to a valid position to add JSDoc comments, and if so, * returns the appropriate template. Otherwise returns an empty string. * Valid positions are - * * outside of comments, statements, and expressions, and - * * preceding a function declaration. + * - outside of comments, statements, and expressions, and + * - preceding a function declaration. * * Hosts should ideally check that: - * * The line is all whitespace up to 'position' before performing the insertion. - * * If the keystroke sequence "/\*\*" induced the call, we also check that the next + * - The line is all whitespace up to 'position' before performing the insertion. + * - If the keystroke sequence "/\*\*" induced the call, we also check that the next * non-whitespace character is '*', which (approximately) indicates whether we added * the second '*' to complete an existing (JSDoc) comment. * @param fileName The file in which to perform the check. @@ -6827,9 +6827,9 @@ namespace ts { } // TODO: add support for: - // * methods - // * constructors - // * class decls + // - methods + // - constructors + // - class decls let containingFunction = getAncestor(tokenAtPos, SyntaxKind.FunctionDeclaration); if (!containingFunction || containingFunction.getStart() < position) { From 400fc30e9d54d8baaaa6745c593625ecb8840e51 Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Thu, 6 Aug 2015 14:31:52 -0700 Subject: [PATCH 46/93] simplified a conditional --- src/compiler/binder.ts | 2 +- src/harness/fourslash.ts | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index beba5f0c656..2ecaf7aac75 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -1062,4 +1062,4 @@ namespace ts { : declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes); } } -} +} \ No newline at end of file diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index c44fa9dbc09..e46469a35d2 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -1946,12 +1946,11 @@ module FourSlash { let actual = this.languageService.getDocCommentTemplateAtPosition(this.activeFile.fileName, this.currentCaretPosition); if (expected === undefined) { - if (actual === undefined) { - return; - } - else { + if (actual) { this.raiseError(name + ' failed - expected no template but got {newText: \"' + actual.newText + '\" caretOffset: ' + actual.caretOffset + '}'); } + + return; } else { if (actual === undefined) { From b3dd18a4630ac9e4ccb24b92bbca40e1b940f3ff Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 6 Aug 2015 15:20:17 -0700 Subject: [PATCH 47/93] Allow partial matches in union type signatures --- src/compiler/checker.ts | 105 +++++++++++++++++++++++----------------- 1 file changed, 60 insertions(+), 45 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e1b7ba42f64..c5c51f88b04 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3131,52 +3131,66 @@ namespace ts { setObjectTypeMembers(type, members, arrayType.callSignatures, arrayType.constructSignatures, arrayType.stringIndexType, arrayType.numberIndexType); } - function findMatchingSignature(signature: Signature, signatureList: Signature[]): Signature { - for (let s of signatureList) { - // Only signatures with no type parameters may differ in return types - if (compareSignatures(signature, s, /*compareReturnTypes*/ !!signature.typeParameters, compareTypes)) { + function findMatchingSignature(signatureList: Signature[], signature: Signature, partialMatch: boolean, ignoreReturnTypes: boolean): Signature { + for (let s of signatureList) { + if (compareSignatures(s, signature, partialMatch, ignoreReturnTypes, compareTypes)) { return s; } } } - function findMatchingSignatures(signature: Signature, signatureLists: Signature[][]): Signature[] { + function findMatchingSignatures(signatureLists: Signature[][], signature: Signature, listIndex: number): Signature[] { + if (signature.typeParameters) { + // We require an exact match for generic signatures, so we only return signatures from the first + // signature list and only if they have exact matches in the other signature lists. + if (listIndex > 0) { + return undefined; + } + for (let i = 1; i < signatureLists.length; i++) { + if (!findMatchingSignature(signatureLists[i], signature, /*partialMatch*/ false, /*ignoreReturnTypes*/ false)) { + return undefined; + } + } + return [signature]; + } let result: Signature[] = undefined; - for (let i = 1; i < signatureLists.length; i++) { - let match = findMatchingSignature(signature, signatureLists[i]); + for (let i = 0; i < signatureLists.length; i++) { + // Allow matching non-generic signatures to have excess parameters and different return types + let match = i === listIndex ? signature : findMatchingSignature(signatureLists[i], signature, /*partialMatch*/ true, /*ignoreReturnTypes*/ true); if (!match) { return undefined; } - if (!result) { - result = [signature]; - } - if (match !== signature) { - result.push(match); + if (!contains(result, match)) { + (result || (result = [])).push(match); } } return result; } - // The signatures of a union type are those signatures that are present and identical in each of the - // constituent types, except that non-generic signatures may differ in return types. When signatures - // differ in return types, the resulting return type is the union of the constituent return types. + // The signatures of a union type are those signatures that are present in each of the constituent types. + // Generic signatures must match exactly, but non-generic signatures are allowed to have extra optional + // parameters and may differ in return types. When signatures differ in return types, the resulting return + // type is the union of the constituent return types. function getUnionSignatures(types: Type[], kind: SignatureKind): Signature[] { let signatureLists = map(types, t => getSignaturesOfType(t, kind)); let result: Signature[] = undefined; - for (let source of signatureLists[0]) { - let unionSignatures = findMatchingSignatures(source, signatureLists); - if (unionSignatures) { - let signature: Signature = undefined; - if (unionSignatures.length === 1 || source.typeParameters) { - signature = source; + for (let i = 0; i < signatureLists.length; i++) { + for (let signature of signatureLists[i]) { + // Only process signatures with parameter lists that aren't already in the result list + if (!result || !findMatchingSignature(result, signature, /*partialMatch*/ false, /*ignoreReturnTypes*/ true)) { + let unionSignatures = findMatchingSignatures(signatureLists, signature, i); + if (unionSignatures) { + let s = signature; + // Union the result types when more than one signature matches + if (unionSignatures.length > 1) { + s = cloneSignature(signature); + // Clear resolved return type we possibly got from cloneSignature + s.resolvedReturnType = undefined; + s.unionSignatures = unionSignatures; + } + (result || (result = [])).push(s); + } } - else { - signature = cloneSignature(source); - // Clear resolved return type we possibly got from cloneSignature - signature.resolvedReturnType = undefined; - signature.unionSignatures = unionSignatures; - } - (result || (result = [])).push(signature); } } return result || emptyArray; @@ -5242,7 +5256,7 @@ namespace ts { } let result = Ternary.True; for (let i = 0, len = sourceSignatures.length; i < len; ++i) { - let related = compareSignatures(sourceSignatures[i], targetSignatures[i], /*compareReturnTypes*/ true, isRelatedTo); + let related = compareSignatures(sourceSignatures[i], targetSignatures[i], /*partialMatch*/ false, /*ignoreReturnTypes*/ false, isRelatedTo); if (!related) { return Ternary.False; } @@ -5372,15 +5386,21 @@ namespace ts { return compareTypes(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp)); } - function compareSignatures(source: Signature, target: Signature, compareReturnTypes: boolean, compareTypes: (s: Type, t: Type) => Ternary): Ternary { + function compareSignatures(source: Signature, target: Signature, partialMatch: boolean, ignoreReturnTypes: boolean, compareTypes: (s: Type, t: Type) => Ternary): Ternary { if (source === target) { return Ternary.True; } - if (source.parameters.length !== target.parameters.length || - source.minArgumentCount !== target.minArgumentCount || - source.hasRestParameter !== target.hasRestParameter) { + if (source.minArgumentCount !== target.minArgumentCount) { return Ternary.False; } + if (source.parameters.length !== target.parameters.length || + source.hasRestParameter !== target.hasRestParameter) { + if (!partialMatch || + source.parameters.length < target.parameters.length || + target.hasRestParameter) { + return Ternary.False; + } + } let result = Ternary.True; if (source.typeParameters && target.typeParameters) { if (source.typeParameters.length !== target.typeParameters.length) { @@ -5401,16 +5421,18 @@ namespace ts { // M and N (the signatures) are instantiated using type Any as the type argument for all type parameters declared by M and N source = getErasedSignature(source); target = getErasedSignature(target); - for (let i = 0, len = source.parameters.length; i < len; i++) { - let s = source.hasRestParameter && i === len - 1 ? getRestTypeOfSignature(source) : getTypeOfSymbol(source.parameters[i]); - let t = target.hasRestParameter && i === len - 1 ? getRestTypeOfSignature(target) : getTypeOfSymbol(target.parameters[i]); + let sourceLen = source.parameters.length; + let targetLen = target.parameters.length; + for (let i = 0; i < targetLen; i++) { + let s = source.hasRestParameter && i === sourceLen - 1 ? getRestTypeOfSignature(source) : getTypeOfSymbol(source.parameters[i]); + let t = target.hasRestParameter && i === targetLen - 1 ? getRestTypeOfSignature(target) : getTypeOfSymbol(target.parameters[i]); let related = compareTypes(s, t); if (!related) { return Ternary.False; } result &= related; } - if (compareReturnTypes) { + if (!ignoreReturnTypes) { result &= compareTypes(getReturnTypeOfSignature(source), getReturnTypeOfSignature(target)); } return result; @@ -6924,20 +6946,13 @@ namespace ts { let signatureList: Signature[]; let types = (type).types; for (let current of types) { - // The signature set of all constituent type with call signatures should match - // So number of signatures allowed is either 0 or 1 - if (signatureList && - getSignaturesOfStructuredType(current, SignatureKind.Call).length > 1) { - return undefined; - } - let signature = getNonGenericSignature(current); if (signature) { if (!signatureList) { // This signature will contribute to contextual union signature signatureList = [signature]; } - else if (!compareSignatures(signatureList[0], signature, /*compareReturnTypes*/ false, compareTypes)) { + else if (!compareSignatures(signatureList[0], signature, /*partialMatch*/ false, /*ignoreReturnTypes*/ true, compareTypes)) { // Signatures aren't identical, do not use return undefined; } From d317bd1340e94d0711058414fe4fd36cb0c08793 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 6 Aug 2015 15:21:30 -0700 Subject: [PATCH 48/93] Adding/fixing tests --- .../types/union/unionTypeCallSignatures.ts | 11 +++++---- .../types/union/unionTypeCallSignatures2.ts | 24 +++++++++++++++++++ 2 files changed, 30 insertions(+), 5 deletions(-) create mode 100644 tests/cases/conformance/types/union/unionTypeCallSignatures2.ts diff --git a/tests/cases/conformance/types/union/unionTypeCallSignatures.ts b/tests/cases/conformance/types/union/unionTypeCallSignatures.ts index 1261de3299e..ca599329743 100644 --- a/tests/cases/conformance/types/union/unionTypeCallSignatures.ts +++ b/tests/cases/conformance/types/union/unionTypeCallSignatures.ts @@ -25,12 +25,12 @@ unionOfDifferentNumberOfSignatures(); // error - no call signatures unionOfDifferentNumberOfSignatures(10); // error - no call signatures unionOfDifferentNumberOfSignatures("hello"); // error - no call signatures - var unionWithDifferentParameterCount: { (a: string): string; } | { (a: string, b: number): number; } ; +var unionWithDifferentParameterCount: { (a: string): string; } | { (a: string, b: number): number; } ; unionWithDifferentParameterCount();// no call signature unionWithDifferentParameterCount("hello");// no call signature unionWithDifferentParameterCount("hello", 10);// no call signature - var unionWithOptionalParameter1: { (a: string, b?: number): string; } | { (a: string, b?: number): number; }; +var unionWithOptionalParameter1: { (a: string, b?: number): string; } | { (a: string, b?: number): number; }; strOrNum = unionWithOptionalParameter1('hello'); strOrNum = unionWithOptionalParameter1('hello', 10); strOrNum = unionWithOptionalParameter1('hello', "hello"); // error in parameter type @@ -43,7 +43,7 @@ strOrNum = unionWithOptionalParameter2('hello', "hello"); // error no call signa strOrNum = unionWithOptionalParameter2(); // error no call signature var unionWithOptionalParameter3: { (a: string, b?: number): string; } | { (a: string): number; }; -strOrNum = unionWithOptionalParameter3('hello'); // error no call signature +strOrNum = unionWithOptionalParameter3('hello'); strOrNum = unionWithOptionalParameter3('hello', 10); // error no call signature strOrNum = unionWithOptionalParameter3('hello', "hello"); // error no call signature strOrNum = unionWithOptionalParameter3(); // error no call signature @@ -63,8 +63,9 @@ strOrNum = unionWithRestParameter2('hello', "hello"); // error no call signature strOrNum = unionWithRestParameter2(); // error no call signature var unionWithRestParameter3: { (a: string, ...b: number[]): string; } | { (a: string): number }; -strOrNum = unionWithRestParameter3('hello'); // error no call signature +strOrNum = unionWithRestParameter3('hello'); strOrNum = unionWithRestParameter3('hello', 10); // error no call signature strOrNum = unionWithRestParameter3('hello', 10, 11); // error no call signature strOrNum = unionWithRestParameter3('hello', "hello"); // error no call signature -strOrNum = unionWithRestParameter3(); // error no call signature \ No newline at end of file +strOrNum = unionWithRestParameter3(); // error no call signature + diff --git a/tests/cases/conformance/types/union/unionTypeCallSignatures2.ts b/tests/cases/conformance/types/union/unionTypeCallSignatures2.ts new file mode 100644 index 00000000000..8095f649330 --- /dev/null +++ b/tests/cases/conformance/types/union/unionTypeCallSignatures2.ts @@ -0,0 +1,24 @@ +interface A { + (x: number): number; + (x: string, y?: string): boolean; + (x: Date): void; + (x: T[]): T[]; +} + +interface B { + (x: number): number; + (x: string): string; + (x: Date): void; + (x: T[]): T[]; +} + +interface C { + (x: string, ...y: string[]): number; + (x: number, s?: string): number; + (x: T[]): T[]; +} + +var f: A | B | C; +var n = f(42); // number +var s = f("abc"); // boolean | string | number +var a = f([true, false]); // boolean[] From e0cb1603e29cd3357f53f139f7557e955c68a3ec Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 6 Aug 2015 15:21:53 -0700 Subject: [PATCH 49/93] Accepting new baselines --- ...ualTypeWithUnionTypeCallSignatures.symbols | 2 + ...xtualTypeWithUnionTypeCallSignatures.types | 12 +- ...citTypeParameterAndArgumentType.errors.txt | 5 +- ...peGuardsInConditionalExpression.errors.txt | 103 ----- .../typeGuardsInConditionalExpression.symbols | 251 +++++++++++ .../typeGuardsInConditionalExpression.types | 388 +++++++++++++++++ .../typeGuardsInIfStatement.errors.txt | 160 ------- .../reference/typeGuardsInIfStatement.symbols | 304 +++++++++++++ .../reference/typeGuardsInIfStatement.types | 405 ++++++++++++++++++ ...sInRightOperandOfAndAndOperator.errors.txt | 64 --- ...ardsInRightOperandOfAndAndOperator.symbols | 143 +++++++ ...GuardsInRightOperandOfAndAndOperator.types | 234 ++++++++++ ...rdsInRightOperandOfOrOrOperator.errors.txt | 64 --- ...GuardsInRightOperandOfOrOrOperator.symbols | 143 +++++++ ...peGuardsInRightOperandOfOrOrOperator.types | 234 ++++++++++ .../unionTypeCallSignatures.errors.txt | 46 +- .../reference/unionTypeCallSignatures.js | 16 +- .../reference/unionTypeCallSignatures2.js | 32 ++ .../unionTypeCallSignatures2.symbols | 78 ++++ .../reference/unionTypeCallSignatures2.types | 86 ++++ .../unionTypeConstructSignatures.errors.txt | 36 +- 21 files changed, 2352 insertions(+), 454 deletions(-) delete mode 100644 tests/baselines/reference/typeGuardsInConditionalExpression.errors.txt create mode 100644 tests/baselines/reference/typeGuardsInConditionalExpression.symbols create mode 100644 tests/baselines/reference/typeGuardsInConditionalExpression.types delete mode 100644 tests/baselines/reference/typeGuardsInIfStatement.errors.txt create mode 100644 tests/baselines/reference/typeGuardsInIfStatement.symbols create mode 100644 tests/baselines/reference/typeGuardsInIfStatement.types delete mode 100644 tests/baselines/reference/typeGuardsInRightOperandOfAndAndOperator.errors.txt create mode 100644 tests/baselines/reference/typeGuardsInRightOperandOfAndAndOperator.symbols create mode 100644 tests/baselines/reference/typeGuardsInRightOperandOfAndAndOperator.types delete mode 100644 tests/baselines/reference/typeGuardsInRightOperandOfOrOrOperator.errors.txt create mode 100644 tests/baselines/reference/typeGuardsInRightOperandOfOrOrOperator.symbols create mode 100644 tests/baselines/reference/typeGuardsInRightOperandOfOrOrOperator.types create mode 100644 tests/baselines/reference/unionTypeCallSignatures2.js create mode 100644 tests/baselines/reference/unionTypeCallSignatures2.symbols create mode 100644 tests/baselines/reference/unionTypeCallSignatures2.types diff --git a/tests/baselines/reference/contextualTypeWithUnionTypeCallSignatures.symbols b/tests/baselines/reference/contextualTypeWithUnionTypeCallSignatures.symbols index 172336603ab..3e23a7812f5 100644 --- a/tests/baselines/reference/contextualTypeWithUnionTypeCallSignatures.symbols +++ b/tests/baselines/reference/contextualTypeWithUnionTypeCallSignatures.symbols @@ -82,5 +82,7 @@ var x4: IWithCallSignatures | IWithCallSignatures4 = a => /*here a should be any >IWithCallSignatures : Symbol(IWithCallSignatures, Decl(contextualTypeWithUnionTypeCallSignatures.ts, 9, 1)) >IWithCallSignatures4 : Symbol(IWithCallSignatures4, Decl(contextualTypeWithUnionTypeCallSignatures.ts, 18, 1)) >a : Symbol(a, Decl(contextualTypeWithUnionTypeCallSignatures.ts, 35, 52)) +>a.toString : Symbol(Number.toString, Decl(lib.d.ts, 458, 18)) >a : Symbol(a, Decl(contextualTypeWithUnionTypeCallSignatures.ts, 35, 52)) +>toString : Symbol(Number.toString, Decl(lib.d.ts, 458, 18)) diff --git a/tests/baselines/reference/contextualTypeWithUnionTypeCallSignatures.types b/tests/baselines/reference/contextualTypeWithUnionTypeCallSignatures.types index 02dfecf5c08..8e1915d4754 100644 --- a/tests/baselines/reference/contextualTypeWithUnionTypeCallSignatures.types +++ b/tests/baselines/reference/contextualTypeWithUnionTypeCallSignatures.types @@ -90,10 +90,10 @@ var x4: IWithCallSignatures | IWithCallSignatures4 = a => /*here a should be any >x4 : IWithCallSignatures | IWithCallSignatures4 >IWithCallSignatures : IWithCallSignatures >IWithCallSignatures4 : IWithCallSignatures4 ->a => /*here a should be any*/ a.toString() : (a: any) => any ->a : any ->a.toString() : any ->a.toString : any ->a : any ->toString : any +>a => /*here a should be any*/ a.toString() : (a: number) => string +>a : number +>a.toString() : string +>a.toString : (radix?: number) => string +>a : number +>toString : (radix?: number) => string diff --git a/tests/baselines/reference/mismatchedExplicitTypeParameterAndArgumentType.errors.txt b/tests/baselines/reference/mismatchedExplicitTypeParameterAndArgumentType.errors.txt index 7445ab85a54..e8649cfb567 100644 --- a/tests/baselines/reference/mismatchedExplicitTypeParameterAndArgumentType.errors.txt +++ b/tests/baselines/reference/mismatchedExplicitTypeParameterAndArgumentType.errors.txt @@ -1,11 +1,10 @@ -tests/cases/compiler/mismatchedExplicitTypeParameterAndArgumentType.ts(7,30): error TS2349: Cannot invoke an expression whose type lacks a call signature. tests/cases/compiler/mismatchedExplicitTypeParameterAndArgumentType.ts(10,30): error TS2345: Argument of type '(number | string)[]' is not assignable to parameter of type 'number[]'. Type 'number | string' is not assignable to type 'number'. Type 'string' is not assignable to type 'number'. tests/cases/compiler/mismatchedExplicitTypeParameterAndArgumentType.ts(11,11): error TS2346: Supplied parameters do not match any signature of call target. -==== tests/cases/compiler/mismatchedExplicitTypeParameterAndArgumentType.ts (3 errors) ==== +==== tests/cases/compiler/mismatchedExplicitTypeParameterAndArgumentType.ts (2 errors) ==== function map(xs: T[], f: (x: T) => U) { var ys: U[] = []; xs.forEach(x => ys.push(f(x))); @@ -13,8 +12,6 @@ tests/cases/compiler/mismatchedExplicitTypeParameterAndArgumentType.ts(11,11): e } var r0 = map([1, ""], (x) => x.toString()); - ~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. var r5 = map([1, ""], (x) => x.toString()); var r6 = map([1, ""], (x) => x.toString()); var r7 = map([1, ""], (x) => x.toString()); // error diff --git a/tests/baselines/reference/typeGuardsInConditionalExpression.errors.txt b/tests/baselines/reference/typeGuardsInConditionalExpression.errors.txt deleted file mode 100644 index 37a662e007c..00000000000 --- a/tests/baselines/reference/typeGuardsInConditionalExpression.errors.txt +++ /dev/null @@ -1,103 +0,0 @@ -tests/cases/conformance/expressions/typeGuards/typeGuardsInConditionalExpression.ts(93,22): error TS2349: Cannot invoke an expression whose type lacks a call signature. - - -==== tests/cases/conformance/expressions/typeGuards/typeGuardsInConditionalExpression.ts (1 errors) ==== - // In the true expression of a conditional expression, - // the type of a variable or parameter is narrowed by any type guard in the condition when true, - // provided the true expression contains no assignments to the variable or parameter. - // In the false expression of a conditional expression, - // the type of a variable or parameter is narrowed by any type guard in the condition when false, - // provided the false expression contains no assignments to the variable or parameter. - - function foo(x: number | string) { - return typeof x === "string" - ? x.length // string - : x++; // number - } - function foo2(x: number | string) { - // x is assigned in the if true branch, the type is not narrowed - return typeof x === "string" - ? (x = 10 && x)// string | number - : x; // string | number - } - function foo3(x: number | string) { - // x is assigned in the if false branch, the type is not narrowed - // even though assigned using same type as narrowed expression - return typeof x === "string" - ? (x = "Hello" && x) // string | number - : x; // string | number - } - function foo4(x: number | string) { - // false branch updates the variable - so here it is not number - // even though assigned using same type as narrowed expression - return typeof x === "string" - ? x // string | number - : (x = 10 && x); // string | number - } - function foo5(x: number | string) { - // false branch updates the variable - so here it is not number - return typeof x === "string" - ? x // string | number - : (x = "hello" && x); // string | number - } - function foo6(x: number | string) { - // Modify in both branches - return typeof x === "string" - ? (x = 10 && x) // string | number - : (x = "hello" && x); // string | number - } - function foo7(x: number | string | boolean) { - return typeof x === "string" - ? x === "hello" // string - : typeof x === "boolean" - ? x // boolean - : x == 10; // number - } - function foo8(x: number | string | boolean) { - var b: number | boolean; - return typeof x === "string" - ? x === "hello" - : ((b = x) && // number | boolean - (typeof x === "boolean" - ? x // boolean - : x == 10)); // number - } - function foo9(x: number | string) { - var y = 10; - // usage of x or assignment to separate variable shouldn't cause narrowing of type to stop - return typeof x === "string" - ? ((y = x.length) && x === "hello") // string - : x === 10; // number - } - function foo10(x: number | string | boolean) { - // Mixing typeguards - var b: boolean | number; - return typeof x === "string" - ? x // string - : ((b = x) // x is number | boolean - && typeof x === "number" - && x.toString()); // x is number - } - function foo11(x: number | string | boolean) { - // Mixing typeguards - // Assigning value to x deep inside another guard stops narrowing of type too - var b: number | boolean | string; - return typeof x === "string" - ? x // number | boolean | string - changed in the false branch - : ((b = x) // x is number | boolean | string - because the assignment changed it - && typeof x === "number" - && (x = 10) // assignment to x - && x); // x is number | boolean | string - } - function foo12(x: number | string | boolean) { - // Mixing typeguards - // Assigning value to x in outer guard shouldn't stop narrowing in the inner expression - var b: number | boolean | string; - return typeof x === "string" - ? (x = 10 && x.toString().length) // number | boolean | string - changed here - ~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. - : ((b = x) // x is number | boolean | string - changed in true branch - && typeof x === "number" - && x); // x is number - } \ No newline at end of file diff --git a/tests/baselines/reference/typeGuardsInConditionalExpression.symbols b/tests/baselines/reference/typeGuardsInConditionalExpression.symbols new file mode 100644 index 00000000000..ac35c1f18b9 --- /dev/null +++ b/tests/baselines/reference/typeGuardsInConditionalExpression.symbols @@ -0,0 +1,251 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardsInConditionalExpression.ts === +// In the true expression of a conditional expression, +// the type of a variable or parameter is narrowed by any type guard in the condition when true, +// provided the true expression contains no assignments to the variable or parameter. +// In the false expression of a conditional expression, +// the type of a variable or parameter is narrowed by any type guard in the condition when false, +// provided the false expression contains no assignments to the variable or parameter. + +function foo(x: number | string) { +>foo : Symbol(foo, Decl(typeGuardsInConditionalExpression.ts, 0, 0)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 7, 13)) + + return typeof x === "string" +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 7, 13)) + + ? x.length // string +>x.length : Symbol(String.length, Decl(lib.d.ts, 414, 19)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 7, 13)) +>length : Symbol(String.length, Decl(lib.d.ts, 414, 19)) + + : x++; // number +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 7, 13)) +} +function foo2(x: number | string) { +>foo2 : Symbol(foo2, Decl(typeGuardsInConditionalExpression.ts, 11, 1)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 12, 14)) + + // x is assigned in the if true branch, the type is not narrowed + return typeof x === "string" +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 12, 14)) + + ? (x = 10 && x)// string | number +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 12, 14)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 12, 14)) + + : x; // string | number +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 12, 14)) +} +function foo3(x: number | string) { +>foo3 : Symbol(foo3, Decl(typeGuardsInConditionalExpression.ts, 17, 1)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 18, 14)) + + // x is assigned in the if false branch, the type is not narrowed + // even though assigned using same type as narrowed expression + return typeof x === "string" +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 18, 14)) + + ? (x = "Hello" && x) // string | number +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 18, 14)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 18, 14)) + + : x; // string | number +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 18, 14)) +} +function foo4(x: number | string) { +>foo4 : Symbol(foo4, Decl(typeGuardsInConditionalExpression.ts, 24, 1)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 25, 14)) + + // false branch updates the variable - so here it is not number + // even though assigned using same type as narrowed expression + return typeof x === "string" +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 25, 14)) + + ? x // string | number +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 25, 14)) + + : (x = 10 && x); // string | number +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 25, 14)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 25, 14)) +} +function foo5(x: number | string) { +>foo5 : Symbol(foo5, Decl(typeGuardsInConditionalExpression.ts, 31, 1)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 32, 14)) + + // false branch updates the variable - so here it is not number + return typeof x === "string" +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 32, 14)) + + ? x // string | number +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 32, 14)) + + : (x = "hello" && x); // string | number +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 32, 14)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 32, 14)) +} +function foo6(x: number | string) { +>foo6 : Symbol(foo6, Decl(typeGuardsInConditionalExpression.ts, 37, 1)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 38, 14)) + + // Modify in both branches + return typeof x === "string" +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 38, 14)) + + ? (x = 10 && x) // string | number +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 38, 14)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 38, 14)) + + : (x = "hello" && x); // string | number +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 38, 14)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 38, 14)) +} +function foo7(x: number | string | boolean) { +>foo7 : Symbol(foo7, Decl(typeGuardsInConditionalExpression.ts, 43, 1)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 44, 14)) + + return typeof x === "string" +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 44, 14)) + + ? x === "hello" // string +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 44, 14)) + + : typeof x === "boolean" +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 44, 14)) + + ? x // boolean +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 44, 14)) + + : x == 10; // number +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 44, 14)) +} +function foo8(x: number | string | boolean) { +>foo8 : Symbol(foo8, Decl(typeGuardsInConditionalExpression.ts, 50, 1)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 51, 14)) + + var b: number | boolean; +>b : Symbol(b, Decl(typeGuardsInConditionalExpression.ts, 52, 7)) + + return typeof x === "string" +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 51, 14)) + + ? x === "hello" +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 51, 14)) + + : ((b = x) && // number | boolean +>b : Symbol(b, Decl(typeGuardsInConditionalExpression.ts, 52, 7)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 51, 14)) + + (typeof x === "boolean" +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 51, 14)) + + ? x // boolean +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 51, 14)) + + : x == 10)); // number +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 51, 14)) +} +function foo9(x: number | string) { +>foo9 : Symbol(foo9, Decl(typeGuardsInConditionalExpression.ts, 59, 1)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 60, 14)) + + var y = 10; +>y : Symbol(y, Decl(typeGuardsInConditionalExpression.ts, 61, 7)) + + // usage of x or assignment to separate variable shouldn't cause narrowing of type to stop + return typeof x === "string" +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 60, 14)) + + ? ((y = x.length) && x === "hello") // string +>y : Symbol(y, Decl(typeGuardsInConditionalExpression.ts, 61, 7)) +>x.length : Symbol(String.length, Decl(lib.d.ts, 414, 19)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 60, 14)) +>length : Symbol(String.length, Decl(lib.d.ts, 414, 19)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 60, 14)) + + : x === 10; // number +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 60, 14)) +} +function foo10(x: number | string | boolean) { +>foo10 : Symbol(foo10, Decl(typeGuardsInConditionalExpression.ts, 66, 1)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 67, 15)) + + // Mixing typeguards + var b: boolean | number; +>b : Symbol(b, Decl(typeGuardsInConditionalExpression.ts, 69, 7)) + + return typeof x === "string" +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 67, 15)) + + ? x // string +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 67, 15)) + + : ((b = x) // x is number | boolean +>b : Symbol(b, Decl(typeGuardsInConditionalExpression.ts, 69, 7)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 67, 15)) + + && typeof x === "number" +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 67, 15)) + + && x.toString()); // x is number +>x.toString : Symbol(Number.toString, Decl(lib.d.ts, 458, 18)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 67, 15)) +>toString : Symbol(Number.toString, Decl(lib.d.ts, 458, 18)) +} +function foo11(x: number | string | boolean) { +>foo11 : Symbol(foo11, Decl(typeGuardsInConditionalExpression.ts, 75, 1)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 76, 15)) + + // Mixing typeguards + // Assigning value to x deep inside another guard stops narrowing of type too + var b: number | boolean | string; +>b : Symbol(b, Decl(typeGuardsInConditionalExpression.ts, 79, 7)) + + return typeof x === "string" +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 76, 15)) + + ? x // number | boolean | string - changed in the false branch +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 76, 15)) + + : ((b = x) // x is number | boolean | string - because the assignment changed it +>b : Symbol(b, Decl(typeGuardsInConditionalExpression.ts, 79, 7)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 76, 15)) + + && typeof x === "number" +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 76, 15)) + + && (x = 10) // assignment to x +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 76, 15)) + + && x); // x is number | boolean | string +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 76, 15)) +} +function foo12(x: number | string | boolean) { +>foo12 : Symbol(foo12, Decl(typeGuardsInConditionalExpression.ts, 86, 1)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 87, 15)) + + // Mixing typeguards + // Assigning value to x in outer guard shouldn't stop narrowing in the inner expression + var b: number | boolean | string; +>b : Symbol(b, Decl(typeGuardsInConditionalExpression.ts, 90, 7)) + + return typeof x === "string" +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 87, 15)) + + ? (x = 10 && x.toString().length) // number | boolean | string - changed here +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 87, 15)) +>x.toString().length : Symbol(String.length, Decl(lib.d.ts, 414, 19)) +>x.toString : Symbol(toString, Decl(lib.d.ts, 458, 18), Decl(lib.d.ts, 277, 18), Decl(lib.d.ts, 96, 26)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 87, 15)) +>toString : Symbol(toString, Decl(lib.d.ts, 458, 18), Decl(lib.d.ts, 277, 18), Decl(lib.d.ts, 96, 26)) +>length : Symbol(String.length, Decl(lib.d.ts, 414, 19)) + + : ((b = x) // x is number | boolean | string - changed in true branch +>b : Symbol(b, Decl(typeGuardsInConditionalExpression.ts, 90, 7)) +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 87, 15)) + + && typeof x === "number" +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 87, 15)) + + && x); // x is number +>x : Symbol(x, Decl(typeGuardsInConditionalExpression.ts, 87, 15)) +} diff --git a/tests/baselines/reference/typeGuardsInConditionalExpression.types b/tests/baselines/reference/typeGuardsInConditionalExpression.types new file mode 100644 index 00000000000..ef048fb8562 --- /dev/null +++ b/tests/baselines/reference/typeGuardsInConditionalExpression.types @@ -0,0 +1,388 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardsInConditionalExpression.ts === +// In the true expression of a conditional expression, +// the type of a variable or parameter is narrowed by any type guard in the condition when true, +// provided the true expression contains no assignments to the variable or parameter. +// In the false expression of a conditional expression, +// the type of a variable or parameter is narrowed by any type guard in the condition when false, +// provided the false expression contains no assignments to the variable or parameter. + +function foo(x: number | string) { +>foo : (x: number | string) => number +>x : number | string + + return typeof x === "string" +>typeof x === "string" ? x.length // string : x++ : number +>typeof x === "string" : boolean +>typeof x : string +>x : number | string +>"string" : string + + ? x.length // string +>x.length : number +>x : string +>length : number + + : x++; // number +>x++ : number +>x : number +} +function foo2(x: number | string) { +>foo2 : (x: number | string) => number | string +>x : number | string + + // x is assigned in the if true branch, the type is not narrowed + return typeof x === "string" +>typeof x === "string" ? (x = 10 && x)// string | number : x : number | string +>typeof x === "string" : boolean +>typeof x : string +>x : number | string +>"string" : string + + ? (x = 10 && x)// string | number +>(x = 10 && x) : number | string +>x = 10 && x : number | string +>x : number | string +>10 && x : number | string +>10 : number +>x : number | string + + : x; // string | number +>x : number | string +} +function foo3(x: number | string) { +>foo3 : (x: number | string) => number | string +>x : number | string + + // x is assigned in the if false branch, the type is not narrowed + // even though assigned using same type as narrowed expression + return typeof x === "string" +>typeof x === "string" ? (x = "Hello" && x) // string | number : x : number | string +>typeof x === "string" : boolean +>typeof x : string +>x : number | string +>"string" : string + + ? (x = "Hello" && x) // string | number +>(x = "Hello" && x) : number | string +>x = "Hello" && x : number | string +>x : number | string +>"Hello" && x : number | string +>"Hello" : string +>x : number | string + + : x; // string | number +>x : number | string +} +function foo4(x: number | string) { +>foo4 : (x: number | string) => number | string +>x : number | string + + // false branch updates the variable - so here it is not number + // even though assigned using same type as narrowed expression + return typeof x === "string" +>typeof x === "string" ? x // string | number : (x = 10 && x) : number | string +>typeof x === "string" : boolean +>typeof x : string +>x : number | string +>"string" : string + + ? x // string | number +>x : number | string + + : (x = 10 && x); // string | number +>(x = 10 && x) : number | string +>x = 10 && x : number | string +>x : number | string +>10 && x : number | string +>10 : number +>x : number | string +} +function foo5(x: number | string) { +>foo5 : (x: number | string) => number | string +>x : number | string + + // false branch updates the variable - so here it is not number + return typeof x === "string" +>typeof x === "string" ? x // string | number : (x = "hello" && x) : number | string +>typeof x === "string" : boolean +>typeof x : string +>x : number | string +>"string" : string + + ? x // string | number +>x : number | string + + : (x = "hello" && x); // string | number +>(x = "hello" && x) : number | string +>x = "hello" && x : number | string +>x : number | string +>"hello" && x : number | string +>"hello" : string +>x : number | string +} +function foo6(x: number | string) { +>foo6 : (x: number | string) => number | string +>x : number | string + + // Modify in both branches + return typeof x === "string" +>typeof x === "string" ? (x = 10 && x) // string | number : (x = "hello" && x) : number | string +>typeof x === "string" : boolean +>typeof x : string +>x : number | string +>"string" : string + + ? (x = 10 && x) // string | number +>(x = 10 && x) : number | string +>x = 10 && x : number | string +>x : number | string +>10 && x : number | string +>10 : number +>x : number | string + + : (x = "hello" && x); // string | number +>(x = "hello" && x) : number | string +>x = "hello" && x : number | string +>x : number | string +>"hello" && x : number | string +>"hello" : string +>x : number | string +} +function foo7(x: number | string | boolean) { +>foo7 : (x: number | string | boolean) => boolean +>x : number | string | boolean + + return typeof x === "string" +>typeof x === "string" ? x === "hello" // string : typeof x === "boolean" ? x // boolean : x == 10 : boolean +>typeof x === "string" : boolean +>typeof x : string +>x : number | string | boolean +>"string" : string + + ? x === "hello" // string +>x === "hello" : boolean +>x : string +>"hello" : string + + : typeof x === "boolean" +>typeof x === "boolean" ? x // boolean : x == 10 : boolean +>typeof x === "boolean" : boolean +>typeof x : string +>x : number | boolean +>"boolean" : string + + ? x // boolean +>x : boolean + + : x == 10; // number +>x == 10 : boolean +>x : number +>10 : number +} +function foo8(x: number | string | boolean) { +>foo8 : (x: number | string | boolean) => boolean +>x : number | string | boolean + + var b: number | boolean; +>b : number | boolean + + return typeof x === "string" +>typeof x === "string" ? x === "hello" : ((b = x) && // number | boolean (typeof x === "boolean" ? x // boolean : x == 10)) : boolean +>typeof x === "string" : boolean +>typeof x : string +>x : number | string | boolean +>"string" : string + + ? x === "hello" +>x === "hello" : boolean +>x : string +>"hello" : string + + : ((b = x) && // number | boolean +>((b = x) && // number | boolean (typeof x === "boolean" ? x // boolean : x == 10)) : boolean +>(b = x) && // number | boolean (typeof x === "boolean" ? x // boolean : x == 10) : boolean +>(b = x) : number | boolean +>b = x : number | boolean +>b : number | boolean +>x : number | boolean + + (typeof x === "boolean" +>(typeof x === "boolean" ? x // boolean : x == 10) : boolean +>typeof x === "boolean" ? x // boolean : x == 10 : boolean +>typeof x === "boolean" : boolean +>typeof x : string +>x : number | boolean +>"boolean" : string + + ? x // boolean +>x : boolean + + : x == 10)); // number +>x == 10 : boolean +>x : number +>10 : number +} +function foo9(x: number | string) { +>foo9 : (x: number | string) => boolean +>x : number | string + + var y = 10; +>y : number +>10 : number + + // usage of x or assignment to separate variable shouldn't cause narrowing of type to stop + return typeof x === "string" +>typeof x === "string" ? ((y = x.length) && x === "hello") // string : x === 10 : boolean +>typeof x === "string" : boolean +>typeof x : string +>x : number | string +>"string" : string + + ? ((y = x.length) && x === "hello") // string +>((y = x.length) && x === "hello") : boolean +>(y = x.length) && x === "hello" : boolean +>(y = x.length) : number +>y = x.length : number +>y : number +>x.length : number +>x : string +>length : number +>x === "hello" : boolean +>x : string +>"hello" : string + + : x === 10; // number +>x === 10 : boolean +>x : number +>10 : number +} +function foo10(x: number | string | boolean) { +>foo10 : (x: number | string | boolean) => string +>x : number | string | boolean + + // Mixing typeguards + var b: boolean | number; +>b : boolean | number + + return typeof x === "string" +>typeof x === "string" ? x // string : ((b = x) // x is number | boolean && typeof x === "number" && x.toString()) : string +>typeof x === "string" : boolean +>typeof x : string +>x : number | string | boolean +>"string" : string + + ? x // string +>x : string + + : ((b = x) // x is number | boolean +>((b = x) // x is number | boolean && typeof x === "number" && x.toString()) : string +>(b = x) // x is number | boolean && typeof x === "number" && x.toString() : string +>(b = x) // x is number | boolean && typeof x === "number" : boolean +>(b = x) : number | boolean +>b = x : number | boolean +>b : boolean | number +>x : number | boolean + + && typeof x === "number" +>typeof x === "number" : boolean +>typeof x : string +>x : number | boolean +>"number" : string + + && x.toString()); // x is number +>x.toString() : string +>x.toString : (radix?: number) => string +>x : number +>toString : (radix?: number) => string +} +function foo11(x: number | string | boolean) { +>foo11 : (x: number | string | boolean) => number | string | boolean +>x : number | string | boolean + + // Mixing typeguards + // Assigning value to x deep inside another guard stops narrowing of type too + var b: number | boolean | string; +>b : number | boolean | string + + return typeof x === "string" +>typeof x === "string" ? x // number | boolean | string - changed in the false branch : ((b = x) // x is number | boolean | string - because the assignment changed it && typeof x === "number" && (x = 10) // assignment to x && x) : number | string | boolean +>typeof x === "string" : boolean +>typeof x : string +>x : number | string | boolean +>"string" : string + + ? x // number | boolean | string - changed in the false branch +>x : number | string | boolean + + : ((b = x) // x is number | boolean | string - because the assignment changed it +>((b = x) // x is number | boolean | string - because the assignment changed it && typeof x === "number" && (x = 10) // assignment to x && x) : number | string | boolean +>(b = x) // x is number | boolean | string - because the assignment changed it && typeof x === "number" && (x = 10) // assignment to x && x : number | string | boolean +>(b = x) // x is number | boolean | string - because the assignment changed it && typeof x === "number" && (x = 10) : number +>(b = x) // x is number | boolean | string - because the assignment changed it && typeof x === "number" : boolean +>(b = x) : number | string | boolean +>b = x : number | string | boolean +>b : number | boolean | string +>x : number | string | boolean + + && typeof x === "number" +>typeof x === "number" : boolean +>typeof x : string +>x : number | string | boolean +>"number" : string + + && (x = 10) // assignment to x +>(x = 10) : number +>x = 10 : number +>x : number | string | boolean +>10 : number + + && x); // x is number | boolean | string +>x : number | string | boolean +} +function foo12(x: number | string | boolean) { +>foo12 : (x: number | string | boolean) => number +>x : number | string | boolean + + // Mixing typeguards + // Assigning value to x in outer guard shouldn't stop narrowing in the inner expression + var b: number | boolean | string; +>b : number | boolean | string + + return typeof x === "string" +>typeof x === "string" ? (x = 10 && x.toString().length) // number | boolean | string - changed here : ((b = x) // x is number | boolean | string - changed in true branch && typeof x === "number" && x) : number +>typeof x === "string" : boolean +>typeof x : string +>x : number | string | boolean +>"string" : string + + ? (x = 10 && x.toString().length) // number | boolean | string - changed here +>(x = 10 && x.toString().length) : number +>x = 10 && x.toString().length : number +>x : number | string | boolean +>10 && x.toString().length : number +>10 : number +>x.toString().length : number +>x.toString() : string +>x.toString : ((radix?: number) => string) | (() => string) +>x : number | string | boolean +>toString : ((radix?: number) => string) | (() => string) +>length : number + + : ((b = x) // x is number | boolean | string - changed in true branch +>((b = x) // x is number | boolean | string - changed in true branch && typeof x === "number" && x) : number +>(b = x) // x is number | boolean | string - changed in true branch && typeof x === "number" && x : number +>(b = x) // x is number | boolean | string - changed in true branch && typeof x === "number" : boolean +>(b = x) : number | string | boolean +>b = x : number | string | boolean +>b : number | boolean | string +>x : number | string | boolean + + && typeof x === "number" +>typeof x === "number" : boolean +>typeof x : string +>x : number | string | boolean +>"number" : string + + && x); // x is number +>x : number +} diff --git a/tests/baselines/reference/typeGuardsInIfStatement.errors.txt b/tests/baselines/reference/typeGuardsInIfStatement.errors.txt deleted file mode 100644 index e675daffd6e..00000000000 --- a/tests/baselines/reference/typeGuardsInIfStatement.errors.txt +++ /dev/null @@ -1,160 +0,0 @@ -tests/cases/conformance/expressions/typeGuards/typeGuardsInIfStatement.ts(127,23): error TS2349: Cannot invoke an expression whose type lacks a call signature. -tests/cases/conformance/expressions/typeGuards/typeGuardsInIfStatement.ts(131,22): error TS2349: Cannot invoke an expression whose type lacks a call signature. -tests/cases/conformance/expressions/typeGuards/typeGuardsInIfStatement.ts(139,16): error TS2349: Cannot invoke an expression whose type lacks a call signature. - - -==== tests/cases/conformance/expressions/typeGuards/typeGuardsInIfStatement.ts (3 errors) ==== - // In the true branch statement of an �if� statement, - // the type of a variable or parameter is narrowed by any type guard in the �if� condition when true, - // provided the true branch statement contains no assignments to the variable or parameter. - // In the false branch statement of an �if� statement, - // the type of a variable or parameter is narrowed by any type guard in the �if� condition when false, - // provided the false branch statement contains no assignments to the variable or parameter - function foo(x: number | string) { - if (typeof x === "string") { - return x.length; // string - } - else { - return x++; // number - } - } - function foo2(x: number | string) { - // x is assigned in the if true branch, the type is not narrowed - if (typeof x === "string") { - x = 10; - return x; // string | number - } - else { - return x; // string | number - } - } - function foo3(x: number | string) { - // x is assigned in the if true branch, the type is not narrowed - if (typeof x === "string") { - x = "Hello"; // even though assigned using same type as narrowed expression - return x; // string | number - } - else { - return x; // string | number - } - } - function foo4(x: number | string) { - // false branch updates the variable - so here it is not number - if (typeof x === "string") { - return x; // string | number - } - else { - x = 10; // even though assigned number - this should result in x to be string | number - return x; // string | number - } - } - function foo5(x: number | string) { - // false branch updates the variable - so here it is not number - if (typeof x === "string") { - return x; // string | number - } - else { - x = "hello"; - return x; // string | number - } - } - function foo6(x: number | string) { - // Modify in both branches - if (typeof x === "string") { - x = 10; - return x; // string | number - } - else { - x = "hello"; - return x; // string | number - } - } - function foo7(x: number | string | boolean) { - if (typeof x === "string") { - return x === "hello"; // string - } - else if (typeof x === "boolean") { - return x; // boolean - } - else { - return x == 10; // number - } - } - function foo8(x: number | string | boolean) { - if (typeof x === "string") { - return x === "hello"; // string - } - else { - var b: number | boolean = x; // number | boolean - if (typeof x === "boolean") { - return x; // boolean - } - else { - return x == 10; // number - } - } - } - function foo9(x: number | string) { - var y = 10; - if (typeof x === "string") { - // usage of x or assignment to separate variable shouldn't cause narrowing of type to stop - y = x.length; - return x === "hello"; // string - } - else { - return x == 10; // number - } - } - function foo10(x: number | string | boolean) { - // Mixing typeguard narrowing in if statement with conditional expression typeguard - if (typeof x === "string") { - return x === "hello"; // string - } - else { - var y: boolean | string; - var b = x; // number | boolean - return typeof x === "number" - ? x === 10 // number - : x; // x should be boolean - } - } - function foo11(x: number | string | boolean) { - // Mixing typeguard narrowing in if statement with conditional expression typeguard - // Assigning value to x deep inside another guard stops narrowing of type too - if (typeof x === "string") { - return x; // string | number | boolean - x changed in else branch - } - else { - var y: number| boolean | string; - var b = x; // number | boolean | string - because below we are changing value of x in if statement - return typeof x === "number" - ? ( - // change value of x - x = 10 && x.toString() // number | boolean | string - ~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. - ) - : ( - // do not change value - y = x && x.toString() // number | boolean | string - ~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. - ); - } - } - function foo12(x: number | string | boolean) { - // Mixing typeguard narrowing in if statement with conditional expression typeguard - // Assigning value to x in outer guard shouldn't stop narrowing in the inner expression - if (typeof x === "string") { - return x.toString(); // string | number | boolean - x changed in else branch - ~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. - } - else { - x = 10; - var b = x; // number | boolean | string - return typeof x === "number" - ? x.toString() // number - : x.toString(); // boolean | string - } - } \ No newline at end of file diff --git a/tests/baselines/reference/typeGuardsInIfStatement.symbols b/tests/baselines/reference/typeGuardsInIfStatement.symbols new file mode 100644 index 00000000000..d940e10e066 --- /dev/null +++ b/tests/baselines/reference/typeGuardsInIfStatement.symbols @@ -0,0 +1,304 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardsInIfStatement.ts === +// In the true branch statement of an �if� statement, +// the type of a variable or parameter is narrowed by any type guard in the �if� condition when true, +// provided the true branch statement contains no assignments to the variable or parameter. +// In the false branch statement of an �if� statement, +// the type of a variable or parameter is narrowed by any type guard in the �if� condition when false, +// provided the false branch statement contains no assignments to the variable or parameter +function foo(x: number | string) { +>foo : Symbol(foo, Decl(typeGuardsInIfStatement.ts, 0, 0)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 6, 13)) + + if (typeof x === "string") { +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 6, 13)) + + return x.length; // string +>x.length : Symbol(String.length, Decl(lib.d.ts, 414, 19)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 6, 13)) +>length : Symbol(String.length, Decl(lib.d.ts, 414, 19)) + } + else { + return x++; // number +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 6, 13)) + } +} +function foo2(x: number | string) { +>foo2 : Symbol(foo2, Decl(typeGuardsInIfStatement.ts, 13, 1)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 14, 14)) + + // x is assigned in the if true branch, the type is not narrowed + if (typeof x === "string") { +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 14, 14)) + + x = 10; +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 14, 14)) + + return x; // string | number +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 14, 14)) + } + else { + return x; // string | number +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 14, 14)) + } +} +function foo3(x: number | string) { +>foo3 : Symbol(foo3, Decl(typeGuardsInIfStatement.ts, 23, 1)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 24, 14)) + + // x is assigned in the if true branch, the type is not narrowed + if (typeof x === "string") { +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 24, 14)) + + x = "Hello"; // even though assigned using same type as narrowed expression +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 24, 14)) + + return x; // string | number +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 24, 14)) + } + else { + return x; // string | number +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 24, 14)) + } +} +function foo4(x: number | string) { +>foo4 : Symbol(foo4, Decl(typeGuardsInIfStatement.ts, 33, 1)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 34, 14)) + + // false branch updates the variable - so here it is not number + if (typeof x === "string") { +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 34, 14)) + + return x; // string | number +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 34, 14)) + } + else { + x = 10; // even though assigned number - this should result in x to be string | number +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 34, 14)) + + return x; // string | number +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 34, 14)) + } +} +function foo5(x: number | string) { +>foo5 : Symbol(foo5, Decl(typeGuardsInIfStatement.ts, 43, 1)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 44, 14)) + + // false branch updates the variable - so here it is not number + if (typeof x === "string") { +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 44, 14)) + + return x; // string | number +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 44, 14)) + } + else { + x = "hello"; +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 44, 14)) + + return x; // string | number +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 44, 14)) + } +} +function foo6(x: number | string) { +>foo6 : Symbol(foo6, Decl(typeGuardsInIfStatement.ts, 53, 1)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 54, 14)) + + // Modify in both branches + if (typeof x === "string") { +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 54, 14)) + + x = 10; +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 54, 14)) + + return x; // string | number +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 54, 14)) + } + else { + x = "hello"; +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 54, 14)) + + return x; // string | number +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 54, 14)) + } +} +function foo7(x: number | string | boolean) { +>foo7 : Symbol(foo7, Decl(typeGuardsInIfStatement.ts, 64, 1)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 65, 14)) + + if (typeof x === "string") { +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 65, 14)) + + return x === "hello"; // string +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 65, 14)) + } + else if (typeof x === "boolean") { +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 65, 14)) + + return x; // boolean +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 65, 14)) + } + else { + return x == 10; // number +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 65, 14)) + } +} +function foo8(x: number | string | boolean) { +>foo8 : Symbol(foo8, Decl(typeGuardsInIfStatement.ts, 75, 1)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 76, 14)) + + if (typeof x === "string") { +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 76, 14)) + + return x === "hello"; // string +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 76, 14)) + } + else { + var b: number | boolean = x; // number | boolean +>b : Symbol(b, Decl(typeGuardsInIfStatement.ts, 81, 11)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 76, 14)) + + if (typeof x === "boolean") { +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 76, 14)) + + return x; // boolean +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 76, 14)) + } + else { + return x == 10; // number +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 76, 14)) + } + } +} +function foo9(x: number | string) { +>foo9 : Symbol(foo9, Decl(typeGuardsInIfStatement.ts, 89, 1)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 90, 14)) + + var y = 10; +>y : Symbol(y, Decl(typeGuardsInIfStatement.ts, 91, 7)) + + if (typeof x === "string") { +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 90, 14)) + + // usage of x or assignment to separate variable shouldn't cause narrowing of type to stop + y = x.length; +>y : Symbol(y, Decl(typeGuardsInIfStatement.ts, 91, 7)) +>x.length : Symbol(String.length, Decl(lib.d.ts, 414, 19)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 90, 14)) +>length : Symbol(String.length, Decl(lib.d.ts, 414, 19)) + + return x === "hello"; // string +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 90, 14)) + } + else { + return x == 10; // number +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 90, 14)) + } +} +function foo10(x: number | string | boolean) { +>foo10 : Symbol(foo10, Decl(typeGuardsInIfStatement.ts, 100, 1)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 101, 15)) + + // Mixing typeguard narrowing in if statement with conditional expression typeguard + if (typeof x === "string") { +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 101, 15)) + + return x === "hello"; // string +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 101, 15)) + } + else { + var y: boolean | string; +>y : Symbol(y, Decl(typeGuardsInIfStatement.ts, 107, 11)) + + var b = x; // number | boolean +>b : Symbol(b, Decl(typeGuardsInIfStatement.ts, 108, 11)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 101, 15)) + + return typeof x === "number" +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 101, 15)) + + ? x === 10 // number +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 101, 15)) + + : x; // x should be boolean +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 101, 15)) + } +} +function foo11(x: number | string | boolean) { +>foo11 : Symbol(foo11, Decl(typeGuardsInIfStatement.ts, 113, 1)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 114, 15)) + + // Mixing typeguard narrowing in if statement with conditional expression typeguard + // Assigning value to x deep inside another guard stops narrowing of type too + if (typeof x === "string") { +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 114, 15)) + + return x; // string | number | boolean - x changed in else branch +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 114, 15)) + } + else { + var y: number| boolean | string; +>y : Symbol(y, Decl(typeGuardsInIfStatement.ts, 121, 11)) + + var b = x; // number | boolean | string - because below we are changing value of x in if statement +>b : Symbol(b, Decl(typeGuardsInIfStatement.ts, 122, 11)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 114, 15)) + + return typeof x === "number" +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 114, 15)) + + ? ( + // change value of x + x = 10 && x.toString() // number | boolean | string +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 114, 15)) +>x.toString : Symbol(toString, Decl(lib.d.ts, 458, 18), Decl(lib.d.ts, 277, 18), Decl(lib.d.ts, 96, 26)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 114, 15)) +>toString : Symbol(toString, Decl(lib.d.ts, 458, 18), Decl(lib.d.ts, 277, 18), Decl(lib.d.ts, 96, 26)) + + ) + : ( + // do not change value + y = x && x.toString() // number | boolean | string +>y : Symbol(y, Decl(typeGuardsInIfStatement.ts, 121, 11)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 114, 15)) +>x.toString : Symbol(toString, Decl(lib.d.ts, 458, 18), Decl(lib.d.ts, 277, 18), Decl(lib.d.ts, 96, 26)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 114, 15)) +>toString : Symbol(toString, Decl(lib.d.ts, 458, 18), Decl(lib.d.ts, 277, 18), Decl(lib.d.ts, 96, 26)) + + ); + } +} +function foo12(x: number | string | boolean) { +>foo12 : Symbol(foo12, Decl(typeGuardsInIfStatement.ts, 133, 1)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 134, 15)) + + // Mixing typeguard narrowing in if statement with conditional expression typeguard + // Assigning value to x in outer guard shouldn't stop narrowing in the inner expression + if (typeof x === "string") { +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 134, 15)) + + return x.toString(); // string | number | boolean - x changed in else branch +>x.toString : Symbol(toString, Decl(lib.d.ts, 458, 18), Decl(lib.d.ts, 277, 18), Decl(lib.d.ts, 96, 26)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 134, 15)) +>toString : Symbol(toString, Decl(lib.d.ts, 458, 18), Decl(lib.d.ts, 277, 18), Decl(lib.d.ts, 96, 26)) + } + else { + x = 10; +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 134, 15)) + + var b = x; // number | boolean | string +>b : Symbol(b, Decl(typeGuardsInIfStatement.ts, 142, 11)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 134, 15)) + + return typeof x === "number" +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 134, 15)) + + ? x.toString() // number +>x.toString : Symbol(Number.toString, Decl(lib.d.ts, 458, 18)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 134, 15)) +>toString : Symbol(Number.toString, Decl(lib.d.ts, 458, 18)) + + : x.toString(); // boolean | string +>x.toString : Symbol(toString, Decl(lib.d.ts, 277, 18), Decl(lib.d.ts, 96, 26)) +>x : Symbol(x, Decl(typeGuardsInIfStatement.ts, 134, 15)) +>toString : Symbol(toString, Decl(lib.d.ts, 277, 18), Decl(lib.d.ts, 96, 26)) + } +} diff --git a/tests/baselines/reference/typeGuardsInIfStatement.types b/tests/baselines/reference/typeGuardsInIfStatement.types new file mode 100644 index 00000000000..e049d318a02 --- /dev/null +++ b/tests/baselines/reference/typeGuardsInIfStatement.types @@ -0,0 +1,405 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardsInIfStatement.ts === +// In the true branch statement of an �if� statement, +// the type of a variable or parameter is narrowed by any type guard in the �if� condition when true, +// provided the true branch statement contains no assignments to the variable or parameter. +// In the false branch statement of an �if� statement, +// the type of a variable or parameter is narrowed by any type guard in the �if� condition when false, +// provided the false branch statement contains no assignments to the variable or parameter +function foo(x: number | string) { +>foo : (x: number | string) => number +>x : number | string + + if (typeof x === "string") { +>typeof x === "string" : boolean +>typeof x : string +>x : number | string +>"string" : string + + return x.length; // string +>x.length : number +>x : string +>length : number + } + else { + return x++; // number +>x++ : number +>x : number + } +} +function foo2(x: number | string) { +>foo2 : (x: number | string) => number | string +>x : number | string + + // x is assigned in the if true branch, the type is not narrowed + if (typeof x === "string") { +>typeof x === "string" : boolean +>typeof x : string +>x : number | string +>"string" : string + + x = 10; +>x = 10 : number +>x : number | string +>10 : number + + return x; // string | number +>x : number | string + } + else { + return x; // string | number +>x : number | string + } +} +function foo3(x: number | string) { +>foo3 : (x: number | string) => number | string +>x : number | string + + // x is assigned in the if true branch, the type is not narrowed + if (typeof x === "string") { +>typeof x === "string" : boolean +>typeof x : string +>x : number | string +>"string" : string + + x = "Hello"; // even though assigned using same type as narrowed expression +>x = "Hello" : string +>x : number | string +>"Hello" : string + + return x; // string | number +>x : number | string + } + else { + return x; // string | number +>x : number | string + } +} +function foo4(x: number | string) { +>foo4 : (x: number | string) => number | string +>x : number | string + + // false branch updates the variable - so here it is not number + if (typeof x === "string") { +>typeof x === "string" : boolean +>typeof x : string +>x : number | string +>"string" : string + + return x; // string | number +>x : number | string + } + else { + x = 10; // even though assigned number - this should result in x to be string | number +>x = 10 : number +>x : number | string +>10 : number + + return x; // string | number +>x : number | string + } +} +function foo5(x: number | string) { +>foo5 : (x: number | string) => number | string +>x : number | string + + // false branch updates the variable - so here it is not number + if (typeof x === "string") { +>typeof x === "string" : boolean +>typeof x : string +>x : number | string +>"string" : string + + return x; // string | number +>x : number | string + } + else { + x = "hello"; +>x = "hello" : string +>x : number | string +>"hello" : string + + return x; // string | number +>x : number | string + } +} +function foo6(x: number | string) { +>foo6 : (x: number | string) => number | string +>x : number | string + + // Modify in both branches + if (typeof x === "string") { +>typeof x === "string" : boolean +>typeof x : string +>x : number | string +>"string" : string + + x = 10; +>x = 10 : number +>x : number | string +>10 : number + + return x; // string | number +>x : number | string + } + else { + x = "hello"; +>x = "hello" : string +>x : number | string +>"hello" : string + + return x; // string | number +>x : number | string + } +} +function foo7(x: number | string | boolean) { +>foo7 : (x: number | string | boolean) => boolean +>x : number | string | boolean + + if (typeof x === "string") { +>typeof x === "string" : boolean +>typeof x : string +>x : number | string | boolean +>"string" : string + + return x === "hello"; // string +>x === "hello" : boolean +>x : string +>"hello" : string + } + else if (typeof x === "boolean") { +>typeof x === "boolean" : boolean +>typeof x : string +>x : number | boolean +>"boolean" : string + + return x; // boolean +>x : boolean + } + else { + return x == 10; // number +>x == 10 : boolean +>x : number +>10 : number + } +} +function foo8(x: number | string | boolean) { +>foo8 : (x: number | string | boolean) => boolean +>x : number | string | boolean + + if (typeof x === "string") { +>typeof x === "string" : boolean +>typeof x : string +>x : number | string | boolean +>"string" : string + + return x === "hello"; // string +>x === "hello" : boolean +>x : string +>"hello" : string + } + else { + var b: number | boolean = x; // number | boolean +>b : number | boolean +>x : number | boolean + + if (typeof x === "boolean") { +>typeof x === "boolean" : boolean +>typeof x : string +>x : number | boolean +>"boolean" : string + + return x; // boolean +>x : boolean + } + else { + return x == 10; // number +>x == 10 : boolean +>x : number +>10 : number + } + } +} +function foo9(x: number | string) { +>foo9 : (x: number | string) => boolean +>x : number | string + + var y = 10; +>y : number +>10 : number + + if (typeof x === "string") { +>typeof x === "string" : boolean +>typeof x : string +>x : number | string +>"string" : string + + // usage of x or assignment to separate variable shouldn't cause narrowing of type to stop + y = x.length; +>y = x.length : number +>y : number +>x.length : number +>x : string +>length : number + + return x === "hello"; // string +>x === "hello" : boolean +>x : string +>"hello" : string + } + else { + return x == 10; // number +>x == 10 : boolean +>x : number +>10 : number + } +} +function foo10(x: number | string | boolean) { +>foo10 : (x: number | string | boolean) => boolean +>x : number | string | boolean + + // Mixing typeguard narrowing in if statement with conditional expression typeguard + if (typeof x === "string") { +>typeof x === "string" : boolean +>typeof x : string +>x : number | string | boolean +>"string" : string + + return x === "hello"; // string +>x === "hello" : boolean +>x : string +>"hello" : string + } + else { + var y: boolean | string; +>y : boolean | string + + var b = x; // number | boolean +>b : number | boolean +>x : number | boolean + + return typeof x === "number" +>typeof x === "number" ? x === 10 // number : x : boolean +>typeof x === "number" : boolean +>typeof x : string +>x : number | boolean +>"number" : string + + ? x === 10 // number +>x === 10 : boolean +>x : number +>10 : number + + : x; // x should be boolean +>x : boolean + } +} +function foo11(x: number | string | boolean) { +>foo11 : (x: number | string | boolean) => number | string | boolean +>x : number | string | boolean + + // Mixing typeguard narrowing in if statement with conditional expression typeguard + // Assigning value to x deep inside another guard stops narrowing of type too + if (typeof x === "string") { +>typeof x === "string" : boolean +>typeof x : string +>x : number | string | boolean +>"string" : string + + return x; // string | number | boolean - x changed in else branch +>x : number | string | boolean + } + else { + var y: number| boolean | string; +>y : number | boolean | string + + var b = x; // number | boolean | string - because below we are changing value of x in if statement +>b : number | string | boolean +>x : number | string | boolean + + return typeof x === "number" +>typeof x === "number" ? ( // change value of x x = 10 && x.toString() // number | boolean | string ) : ( // do not change value y = x && x.toString() // number | boolean | string ) : string +>typeof x === "number" : boolean +>typeof x : string +>x : number | string | boolean +>"number" : string + + ? ( +>( // change value of x x = 10 && x.toString() // number | boolean | string ) : string + + // change value of x + x = 10 && x.toString() // number | boolean | string +>x = 10 && x.toString() : string +>x : number | string | boolean +>10 && x.toString() : string +>10 : number +>x.toString() : string +>x.toString : ((radix?: number) => string) | (() => string) +>x : number | string | boolean +>toString : ((radix?: number) => string) | (() => string) + + ) + : ( +>( // do not change value y = x && x.toString() // number | boolean | string ) : string + + // do not change value + y = x && x.toString() // number | boolean | string +>y = x && x.toString() : string +>y : number | boolean | string +>x && x.toString() : string +>x : number | string | boolean +>x.toString() : string +>x.toString : ((radix?: number) => string) | (() => string) +>x : number | string | boolean +>toString : ((radix?: number) => string) | (() => string) + + ); + } +} +function foo12(x: number | string | boolean) { +>foo12 : (x: number | string | boolean) => string +>x : number | string | boolean + + // Mixing typeguard narrowing in if statement with conditional expression typeguard + // Assigning value to x in outer guard shouldn't stop narrowing in the inner expression + if (typeof x === "string") { +>typeof x === "string" : boolean +>typeof x : string +>x : number | string | boolean +>"string" : string + + return x.toString(); // string | number | boolean - x changed in else branch +>x.toString() : string +>x.toString : ((radix?: number) => string) | (() => string) +>x : number | string | boolean +>toString : ((radix?: number) => string) | (() => string) + } + else { + x = 10; +>x = 10 : number +>x : number | string | boolean +>10 : number + + var b = x; // number | boolean | string +>b : number | string | boolean +>x : number | string | boolean + + return typeof x === "number" +>typeof x === "number" ? x.toString() // number : x.toString() : string +>typeof x === "number" : boolean +>typeof x : string +>x : number | string | boolean +>"number" : string + + ? x.toString() // number +>x.toString() : string +>x.toString : (radix?: number) => string +>x : number +>toString : (radix?: number) => string + + : x.toString(); // boolean | string +>x.toString() : string +>x.toString : () => string +>x : string | boolean +>toString : () => string + } +} diff --git a/tests/baselines/reference/typeGuardsInRightOperandOfAndAndOperator.errors.txt b/tests/baselines/reference/typeGuardsInRightOperandOfAndAndOperator.errors.txt deleted file mode 100644 index f44e433a2c8..00000000000 --- a/tests/baselines/reference/typeGuardsInRightOperandOfAndAndOperator.errors.txt +++ /dev/null @@ -1,64 +0,0 @@ -tests/cases/conformance/expressions/typeGuards/typeGuardsInRightOperandOfAndAndOperator.ts(43,22): error TS2349: Cannot invoke an expression whose type lacks a call signature. -tests/cases/conformance/expressions/typeGuards/typeGuardsInRightOperandOfAndAndOperator.ts(45,21): error TS2349: Cannot invoke an expression whose type lacks a call signature. - - -==== tests/cases/conformance/expressions/typeGuards/typeGuardsInRightOperandOfAndAndOperator.ts (2 errors) ==== - // In the right operand of a && operation, - // the type of a variable or parameter is narrowed by any type guard in the left operand when true, - // provided the right operand contains no assignments to the variable or parameter. - function foo(x: number | string) { - return typeof x === "string" && x.length === 10; // string - } - function foo2(x: number | string) { - // modify x in right hand operand - return typeof x === "string" && ((x = 10) && x); // string | number - } - function foo3(x: number | string) { - // modify x in right hand operand with string type itself - return typeof x === "string" && ((x = "hello") && x); // string | number - } - function foo4(x: number | string | boolean) { - return typeof x !== "string" // string | number | boolean - && typeof x !== "number" // number | boolean - && x; // boolean - } - function foo5(x: number | string | boolean) { - // usage of x or assignment to separate variable shouldn't cause narrowing of type to stop - var b: number | boolean; - return typeof x !== "string" // string | number | boolean - && ((b = x) && (typeof x !== "number" // number | boolean - && x)); // boolean - } - function foo6(x: number | string | boolean) { - // Mixing typeguard narrowing in if statement with conditional expression typeguard - return typeof x !== "string" // string | number | boolean - && (typeof x !== "number" // number | boolean - ? x // boolean - : x === 10) // number - } - function foo7(x: number | string | boolean) { - var y: number| boolean | string; - var z: number| boolean | string; - // Mixing typeguard narrowing - // Assigning value to x deep inside another guard stops narrowing of type too - return typeof x !== "string" - && ((z = x) // string | number | boolean - x changed deeper in conditional expression - && (typeof x === "number" - // change value of x - ? (x = 10 && x.toString()) // number | boolean | string - ~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. - // do not change value - : (y = x && x.toString()))); // number | boolean | string - ~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. - } - function foo8(x: number | string) { - // Mixing typeguard - // Assigning value to x in outer guard shouldn't stop narrowing in the inner expression - return typeof x !== "string" - && (x = 10) // change x - number| string - && (typeof x === "number" - ? x // number - : x.length); // string - } \ No newline at end of file diff --git a/tests/baselines/reference/typeGuardsInRightOperandOfAndAndOperator.symbols b/tests/baselines/reference/typeGuardsInRightOperandOfAndAndOperator.symbols new file mode 100644 index 00000000000..59f51d21e71 --- /dev/null +++ b/tests/baselines/reference/typeGuardsInRightOperandOfAndAndOperator.symbols @@ -0,0 +1,143 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardsInRightOperandOfAndAndOperator.ts === +// In the right operand of a && operation, +// the type of a variable or parameter is narrowed by any type guard in the left operand when true, +// provided the right operand contains no assignments to the variable or parameter. +function foo(x: number | string) { +>foo : Symbol(foo, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 0, 0)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 3, 13)) + + return typeof x === "string" && x.length === 10; // string +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 3, 13)) +>x.length : Symbol(String.length, Decl(lib.d.ts, 414, 19)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 3, 13)) +>length : Symbol(String.length, Decl(lib.d.ts, 414, 19)) +} +function foo2(x: number | string) { +>foo2 : Symbol(foo2, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 5, 1)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 6, 14)) + + // modify x in right hand operand + return typeof x === "string" && ((x = 10) && x); // string | number +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 6, 14)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 6, 14)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 6, 14)) +} +function foo3(x: number | string) { +>foo3 : Symbol(foo3, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 9, 1)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 10, 14)) + + // modify x in right hand operand with string type itself + return typeof x === "string" && ((x = "hello") && x); // string | number +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 10, 14)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 10, 14)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 10, 14)) +} +function foo4(x: number | string | boolean) { +>foo4 : Symbol(foo4, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 13, 1)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 14, 14)) + + return typeof x !== "string" // string | number | boolean +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 14, 14)) + + && typeof x !== "number" // number | boolean +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 14, 14)) + + && x; // boolean +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 14, 14)) +} +function foo5(x: number | string | boolean) { +>foo5 : Symbol(foo5, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 18, 1)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 19, 14)) + + // usage of x or assignment to separate variable shouldn't cause narrowing of type to stop + var b: number | boolean; +>b : Symbol(b, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 21, 7)) + + return typeof x !== "string" // string | number | boolean +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 19, 14)) + + && ((b = x) && (typeof x !== "number" // number | boolean +>b : Symbol(b, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 21, 7)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 19, 14)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 19, 14)) + + && x)); // boolean +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 19, 14)) +} +function foo6(x: number | string | boolean) { +>foo6 : Symbol(foo6, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 25, 1)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 26, 14)) + + // Mixing typeguard narrowing in if statement with conditional expression typeguard + return typeof x !== "string" // string | number | boolean +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 26, 14)) + + && (typeof x !== "number" // number | boolean +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 26, 14)) + + ? x // boolean +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 26, 14)) + + : x === 10) // number +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 26, 14)) +} +function foo7(x: number | string | boolean) { +>foo7 : Symbol(foo7, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 32, 1)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 33, 14)) + + var y: number| boolean | string; +>y : Symbol(y, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 34, 7)) + + var z: number| boolean | string; +>z : Symbol(z, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 35, 7)) + + // Mixing typeguard narrowing + // Assigning value to x deep inside another guard stops narrowing of type too + return typeof x !== "string" +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 33, 14)) + + && ((z = x) // string | number | boolean - x changed deeper in conditional expression +>z : Symbol(z, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 35, 7)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 33, 14)) + + && (typeof x === "number" +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 33, 14)) + + // change value of x + ? (x = 10 && x.toString()) // number | boolean | string +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 33, 14)) +>x.toString : Symbol(toString, Decl(lib.d.ts, 458, 18), Decl(lib.d.ts, 277, 18), Decl(lib.d.ts, 96, 26)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 33, 14)) +>toString : Symbol(toString, Decl(lib.d.ts, 458, 18), Decl(lib.d.ts, 277, 18), Decl(lib.d.ts, 96, 26)) + + // do not change value + : (y = x && x.toString()))); // number | boolean | string +>y : Symbol(y, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 34, 7)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 33, 14)) +>x.toString : Symbol(toString, Decl(lib.d.ts, 458, 18), Decl(lib.d.ts, 277, 18), Decl(lib.d.ts, 96, 26)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 33, 14)) +>toString : Symbol(toString, Decl(lib.d.ts, 458, 18), Decl(lib.d.ts, 277, 18), Decl(lib.d.ts, 96, 26)) +} +function foo8(x: number | string) { +>foo8 : Symbol(foo8, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 45, 1)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 46, 14)) + + // Mixing typeguard + // Assigning value to x in outer guard shouldn't stop narrowing in the inner expression + return typeof x !== "string" +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 46, 14)) + + && (x = 10) // change x - number| string +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 46, 14)) + + && (typeof x === "number" +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 46, 14)) + + ? x // number +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 46, 14)) + + : x.length); // string +>x.length : Symbol(String.length, Decl(lib.d.ts, 414, 19)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfAndAndOperator.ts, 46, 14)) +>length : Symbol(String.length, Decl(lib.d.ts, 414, 19)) +} diff --git a/tests/baselines/reference/typeGuardsInRightOperandOfAndAndOperator.types b/tests/baselines/reference/typeGuardsInRightOperandOfAndAndOperator.types new file mode 100644 index 00000000000..b69c80ff55a --- /dev/null +++ b/tests/baselines/reference/typeGuardsInRightOperandOfAndAndOperator.types @@ -0,0 +1,234 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardsInRightOperandOfAndAndOperator.ts === +// In the right operand of a && operation, +// the type of a variable or parameter is narrowed by any type guard in the left operand when true, +// provided the right operand contains no assignments to the variable or parameter. +function foo(x: number | string) { +>foo : (x: number | string) => boolean +>x : number | string + + return typeof x === "string" && x.length === 10; // string +>typeof x === "string" && x.length === 10 : boolean +>typeof x === "string" : boolean +>typeof x : string +>x : number | string +>"string" : string +>x.length === 10 : boolean +>x.length : number +>x : string +>length : number +>10 : number +} +function foo2(x: number | string) { +>foo2 : (x: number | string) => number | string +>x : number | string + + // modify x in right hand operand + return typeof x === "string" && ((x = 10) && x); // string | number +>typeof x === "string" && ((x = 10) && x) : number | string +>typeof x === "string" : boolean +>typeof x : string +>x : number | string +>"string" : string +>((x = 10) && x) : number | string +>(x = 10) && x : number | string +>(x = 10) : number +>x = 10 : number +>x : number | string +>10 : number +>x : number | string +} +function foo3(x: number | string) { +>foo3 : (x: number | string) => number | string +>x : number | string + + // modify x in right hand operand with string type itself + return typeof x === "string" && ((x = "hello") && x); // string | number +>typeof x === "string" && ((x = "hello") && x) : number | string +>typeof x === "string" : boolean +>typeof x : string +>x : number | string +>"string" : string +>((x = "hello") && x) : number | string +>(x = "hello") && x : number | string +>(x = "hello") : string +>x = "hello" : string +>x : number | string +>"hello" : string +>x : number | string +} +function foo4(x: number | string | boolean) { +>foo4 : (x: number | string | boolean) => boolean +>x : number | string | boolean + + return typeof x !== "string" // string | number | boolean +>typeof x !== "string" // string | number | boolean && typeof x !== "number" // number | boolean && x : boolean +>typeof x !== "string" // string | number | boolean && typeof x !== "number" : boolean +>typeof x !== "string" : boolean +>typeof x : string +>x : number | string | boolean +>"string" : string + + && typeof x !== "number" // number | boolean +>typeof x !== "number" : boolean +>typeof x : string +>x : number | boolean +>"number" : string + + && x; // boolean +>x : boolean +} +function foo5(x: number | string | boolean) { +>foo5 : (x: number | string | boolean) => boolean +>x : number | string | boolean + + // usage of x or assignment to separate variable shouldn't cause narrowing of type to stop + var b: number | boolean; +>b : number | boolean + + return typeof x !== "string" // string | number | boolean +>typeof x !== "string" // string | number | boolean && ((b = x) && (typeof x !== "number" // number | boolean && x)) : boolean +>typeof x !== "string" : boolean +>typeof x : string +>x : number | string | boolean +>"string" : string + + && ((b = x) && (typeof x !== "number" // number | boolean +>((b = x) && (typeof x !== "number" // number | boolean && x)) : boolean +>(b = x) && (typeof x !== "number" // number | boolean && x) : boolean +>(b = x) : number | boolean +>b = x : number | boolean +>b : number | boolean +>x : number | boolean +>(typeof x !== "number" // number | boolean && x) : boolean +>typeof x !== "number" // number | boolean && x : boolean +>typeof x !== "number" : boolean +>typeof x : string +>x : number | boolean +>"number" : string + + && x)); // boolean +>x : boolean +} +function foo6(x: number | string | boolean) { +>foo6 : (x: number | string | boolean) => boolean +>x : number | string | boolean + + // Mixing typeguard narrowing in if statement with conditional expression typeguard + return typeof x !== "string" // string | number | boolean +>typeof x !== "string" // string | number | boolean && (typeof x !== "number" // number | boolean ? x // boolean : x === 10) : boolean +>typeof x !== "string" : boolean +>typeof x : string +>x : number | string | boolean +>"string" : string + + && (typeof x !== "number" // number | boolean +>(typeof x !== "number" // number | boolean ? x // boolean : x === 10) : boolean +>typeof x !== "number" // number | boolean ? x // boolean : x === 10 : boolean +>typeof x !== "number" : boolean +>typeof x : string +>x : number | boolean +>"number" : string + + ? x // boolean +>x : boolean + + : x === 10) // number +>x === 10 : boolean +>x : number +>10 : number +} +function foo7(x: number | string | boolean) { +>foo7 : (x: number | string | boolean) => string +>x : number | string | boolean + + var y: number| boolean | string; +>y : number | boolean | string + + var z: number| boolean | string; +>z : number | boolean | string + + // Mixing typeguard narrowing + // Assigning value to x deep inside another guard stops narrowing of type too + return typeof x !== "string" +>typeof x !== "string" && ((z = x) // string | number | boolean - x changed deeper in conditional expression && (typeof x === "number" // change value of x ? (x = 10 && x.toString()) // number | boolean | string // do not change value : (y = x && x.toString()))) : string +>typeof x !== "string" : boolean +>typeof x : string +>x : number | string | boolean +>"string" : string + + && ((z = x) // string | number | boolean - x changed deeper in conditional expression +>((z = x) // string | number | boolean - x changed deeper in conditional expression && (typeof x === "number" // change value of x ? (x = 10 && x.toString()) // number | boolean | string // do not change value : (y = x && x.toString()))) : string +>(z = x) // string | number | boolean - x changed deeper in conditional expression && (typeof x === "number" // change value of x ? (x = 10 && x.toString()) // number | boolean | string // do not change value : (y = x && x.toString())) : string +>(z = x) : number | string | boolean +>z = x : number | string | boolean +>z : number | boolean | string +>x : number | string | boolean + + && (typeof x === "number" +>(typeof x === "number" // change value of x ? (x = 10 && x.toString()) // number | boolean | string // do not change value : (y = x && x.toString())) : string +>typeof x === "number" // change value of x ? (x = 10 && x.toString()) // number | boolean | string // do not change value : (y = x && x.toString()) : string +>typeof x === "number" : boolean +>typeof x : string +>x : number | string | boolean +>"number" : string + + // change value of x + ? (x = 10 && x.toString()) // number | boolean | string +>(x = 10 && x.toString()) : string +>x = 10 && x.toString() : string +>x : number | string | boolean +>10 && x.toString() : string +>10 : number +>x.toString() : string +>x.toString : ((radix?: number) => string) | (() => string) +>x : number | string | boolean +>toString : ((radix?: number) => string) | (() => string) + + // do not change value + : (y = x && x.toString()))); // number | boolean | string +>(y = x && x.toString()) : string +>y = x && x.toString() : string +>y : number | boolean | string +>x && x.toString() : string +>x : number | string | boolean +>x.toString() : string +>x.toString : ((radix?: number) => string) | (() => string) +>x : number | string | boolean +>toString : ((radix?: number) => string) | (() => string) +} +function foo8(x: number | string) { +>foo8 : (x: number | string) => number +>x : number | string + + // Mixing typeguard + // Assigning value to x in outer guard shouldn't stop narrowing in the inner expression + return typeof x !== "string" +>typeof x !== "string" && (x = 10) // change x - number| string && (typeof x === "number" ? x // number : x.length) : number +>typeof x !== "string" && (x = 10) : number +>typeof x !== "string" : boolean +>typeof x : string +>x : number | string +>"string" : string + + && (x = 10) // change x - number| string +>(x = 10) : number +>x = 10 : number +>x : number | string +>10 : number + + && (typeof x === "number" +>(typeof x === "number" ? x // number : x.length) : number +>typeof x === "number" ? x // number : x.length : number +>typeof x === "number" : boolean +>typeof x : string +>x : number | string +>"number" : string + + ? x // number +>x : number + + : x.length); // string +>x.length : number +>x : string +>length : number +} diff --git a/tests/baselines/reference/typeGuardsInRightOperandOfOrOrOperator.errors.txt b/tests/baselines/reference/typeGuardsInRightOperandOfOrOrOperator.errors.txt deleted file mode 100644 index f34d035fa40..00000000000 --- a/tests/baselines/reference/typeGuardsInRightOperandOfOrOrOperator.errors.txt +++ /dev/null @@ -1,64 +0,0 @@ -tests/cases/conformance/expressions/typeGuards/typeGuardsInRightOperandOfOrOrOperator.ts(43,22): error TS2349: Cannot invoke an expression whose type lacks a call signature. -tests/cases/conformance/expressions/typeGuards/typeGuardsInRightOperandOfOrOrOperator.ts(45,21): error TS2349: Cannot invoke an expression whose type lacks a call signature. - - -==== tests/cases/conformance/expressions/typeGuards/typeGuardsInRightOperandOfOrOrOperator.ts (2 errors) ==== - // In the right operand of a || operation, - // the type of a variable or parameter is narrowed by any type guard in the left operand when false, - // provided the right operand contains no assignments to the variable or parameter. - function foo(x: number | string) { - return typeof x !== "string" || x.length === 10; // string - } - function foo2(x: number | string) { - // modify x in right hand operand - return typeof x !== "string" || ((x = 10) || x); // string | number - } - function foo3(x: number | string) { - // modify x in right hand operand with string type itself - return typeof x !== "string" || ((x = "hello") || x); // string | number - } - function foo4(x: number | string | boolean) { - return typeof x === "string" // string | number | boolean - || typeof x === "number" // number | boolean - || x; // boolean - } - function foo5(x: number | string | boolean) { - // usage of x or assignment to separate variable shouldn't cause narrowing of type to stop - var b: number | boolean; - return typeof x === "string" // string | number | boolean - || ((b = x) || (typeof x === "number" // number | boolean - || x)); // boolean - } - function foo6(x: number | string | boolean) { - // Mixing typeguard - return typeof x === "string" // string | number | boolean - || (typeof x !== "number" // number | boolean - ? x // boolean - : x === 10) // number - } - function foo7(x: number | string | boolean) { - var y: number| boolean | string; - var z: number| boolean | string; - // Mixing typeguard narrowing - // Assigning value to x deep inside another guard stops narrowing of type too - return typeof x === "string" - || ((z = x) // string | number | boolean - x changed deeper in conditional expression - || (typeof x === "number" - // change value of x - ? (x = 10 && x.toString()) // number | boolean | string - ~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. - // do not change value - : (y = x && x.toString()))); // number | boolean | string - ~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. - } - function foo8(x: number | string) { - // Mixing typeguard - // Assigning value to x in outer guard shouldn't stop narrowing in the inner expression - return typeof x === "string" - || (x = 10) // change x - number| string - || (typeof x === "number" - ? x // number - : x.length); // string - } \ No newline at end of file diff --git a/tests/baselines/reference/typeGuardsInRightOperandOfOrOrOperator.symbols b/tests/baselines/reference/typeGuardsInRightOperandOfOrOrOperator.symbols new file mode 100644 index 00000000000..d33f0b6877b --- /dev/null +++ b/tests/baselines/reference/typeGuardsInRightOperandOfOrOrOperator.symbols @@ -0,0 +1,143 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardsInRightOperandOfOrOrOperator.ts === +// In the right operand of a || operation, +// the type of a variable or parameter is narrowed by any type guard in the left operand when false, +// provided the right operand contains no assignments to the variable or parameter. +function foo(x: number | string) { +>foo : Symbol(foo, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 0, 0)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 3, 13)) + + return typeof x !== "string" || x.length === 10; // string +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 3, 13)) +>x.length : Symbol(String.length, Decl(lib.d.ts, 414, 19)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 3, 13)) +>length : Symbol(String.length, Decl(lib.d.ts, 414, 19)) +} +function foo2(x: number | string) { +>foo2 : Symbol(foo2, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 5, 1)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 6, 14)) + + // modify x in right hand operand + return typeof x !== "string" || ((x = 10) || x); // string | number +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 6, 14)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 6, 14)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 6, 14)) +} +function foo3(x: number | string) { +>foo3 : Symbol(foo3, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 9, 1)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 10, 14)) + + // modify x in right hand operand with string type itself + return typeof x !== "string" || ((x = "hello") || x); // string | number +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 10, 14)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 10, 14)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 10, 14)) +} +function foo4(x: number | string | boolean) { +>foo4 : Symbol(foo4, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 13, 1)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 14, 14)) + + return typeof x === "string" // string | number | boolean +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 14, 14)) + + || typeof x === "number" // number | boolean +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 14, 14)) + + || x; // boolean +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 14, 14)) +} +function foo5(x: number | string | boolean) { +>foo5 : Symbol(foo5, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 18, 1)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 19, 14)) + + // usage of x or assignment to separate variable shouldn't cause narrowing of type to stop + var b: number | boolean; +>b : Symbol(b, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 21, 7)) + + return typeof x === "string" // string | number | boolean +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 19, 14)) + + || ((b = x) || (typeof x === "number" // number | boolean +>b : Symbol(b, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 21, 7)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 19, 14)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 19, 14)) + + || x)); // boolean +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 19, 14)) +} +function foo6(x: number | string | boolean) { +>foo6 : Symbol(foo6, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 25, 1)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 26, 14)) + + // Mixing typeguard + return typeof x === "string" // string | number | boolean +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 26, 14)) + + || (typeof x !== "number" // number | boolean +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 26, 14)) + + ? x // boolean +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 26, 14)) + + : x === 10) // number +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 26, 14)) +} +function foo7(x: number | string | boolean) { +>foo7 : Symbol(foo7, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 32, 1)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 33, 14)) + + var y: number| boolean | string; +>y : Symbol(y, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 34, 7)) + + var z: number| boolean | string; +>z : Symbol(z, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 35, 7)) + + // Mixing typeguard narrowing + // Assigning value to x deep inside another guard stops narrowing of type too + return typeof x === "string" +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 33, 14)) + + || ((z = x) // string | number | boolean - x changed deeper in conditional expression +>z : Symbol(z, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 35, 7)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 33, 14)) + + || (typeof x === "number" +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 33, 14)) + + // change value of x + ? (x = 10 && x.toString()) // number | boolean | string +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 33, 14)) +>x.toString : Symbol(toString, Decl(lib.d.ts, 458, 18), Decl(lib.d.ts, 277, 18), Decl(lib.d.ts, 96, 26)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 33, 14)) +>toString : Symbol(toString, Decl(lib.d.ts, 458, 18), Decl(lib.d.ts, 277, 18), Decl(lib.d.ts, 96, 26)) + + // do not change value + : (y = x && x.toString()))); // number | boolean | string +>y : Symbol(y, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 34, 7)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 33, 14)) +>x.toString : Symbol(toString, Decl(lib.d.ts, 458, 18), Decl(lib.d.ts, 277, 18), Decl(lib.d.ts, 96, 26)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 33, 14)) +>toString : Symbol(toString, Decl(lib.d.ts, 458, 18), Decl(lib.d.ts, 277, 18), Decl(lib.d.ts, 96, 26)) +} +function foo8(x: number | string) { +>foo8 : Symbol(foo8, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 45, 1)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 46, 14)) + + // Mixing typeguard + // Assigning value to x in outer guard shouldn't stop narrowing in the inner expression + return typeof x === "string" +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 46, 14)) + + || (x = 10) // change x - number| string +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 46, 14)) + + || (typeof x === "number" +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 46, 14)) + + ? x // number +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 46, 14)) + + : x.length); // string +>x.length : Symbol(String.length, Decl(lib.d.ts, 414, 19)) +>x : Symbol(x, Decl(typeGuardsInRightOperandOfOrOrOperator.ts, 46, 14)) +>length : Symbol(String.length, Decl(lib.d.ts, 414, 19)) +} diff --git a/tests/baselines/reference/typeGuardsInRightOperandOfOrOrOperator.types b/tests/baselines/reference/typeGuardsInRightOperandOfOrOrOperator.types new file mode 100644 index 00000000000..b2f5401e843 --- /dev/null +++ b/tests/baselines/reference/typeGuardsInRightOperandOfOrOrOperator.types @@ -0,0 +1,234 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardsInRightOperandOfOrOrOperator.ts === +// In the right operand of a || operation, +// the type of a variable or parameter is narrowed by any type guard in the left operand when false, +// provided the right operand contains no assignments to the variable or parameter. +function foo(x: number | string) { +>foo : (x: number | string) => boolean +>x : number | string + + return typeof x !== "string" || x.length === 10; // string +>typeof x !== "string" || x.length === 10 : boolean +>typeof x !== "string" : boolean +>typeof x : string +>x : number | string +>"string" : string +>x.length === 10 : boolean +>x.length : number +>x : string +>length : number +>10 : number +} +function foo2(x: number | string) { +>foo2 : (x: number | string) => boolean | number | string +>x : number | string + + // modify x in right hand operand + return typeof x !== "string" || ((x = 10) || x); // string | number +>typeof x !== "string" || ((x = 10) || x) : boolean | number | string +>typeof x !== "string" : boolean +>typeof x : string +>x : number | string +>"string" : string +>((x = 10) || x) : number | string +>(x = 10) || x : number | string +>(x = 10) : number +>x = 10 : number +>x : number | string +>10 : number +>x : number | string +} +function foo3(x: number | string) { +>foo3 : (x: number | string) => boolean | string | number +>x : number | string + + // modify x in right hand operand with string type itself + return typeof x !== "string" || ((x = "hello") || x); // string | number +>typeof x !== "string" || ((x = "hello") || x) : boolean | string | number +>typeof x !== "string" : boolean +>typeof x : string +>x : number | string +>"string" : string +>((x = "hello") || x) : string | number +>(x = "hello") || x : string | number +>(x = "hello") : string +>x = "hello" : string +>x : number | string +>"hello" : string +>x : number | string +} +function foo4(x: number | string | boolean) { +>foo4 : (x: number | string | boolean) => boolean +>x : number | string | boolean + + return typeof x === "string" // string | number | boolean +>typeof x === "string" // string | number | boolean || typeof x === "number" // number | boolean || x : boolean +>typeof x === "string" // string | number | boolean || typeof x === "number" : boolean +>typeof x === "string" : boolean +>typeof x : string +>x : number | string | boolean +>"string" : string + + || typeof x === "number" // number | boolean +>typeof x === "number" : boolean +>typeof x : string +>x : number | boolean +>"number" : string + + || x; // boolean +>x : boolean +} +function foo5(x: number | string | boolean) { +>foo5 : (x: number | string | boolean) => boolean | number +>x : number | string | boolean + + // usage of x or assignment to separate variable shouldn't cause narrowing of type to stop + var b: number | boolean; +>b : number | boolean + + return typeof x === "string" // string | number | boolean +>typeof x === "string" // string | number | boolean || ((b = x) || (typeof x === "number" // number | boolean || x)) : boolean | number +>typeof x === "string" : boolean +>typeof x : string +>x : number | string | boolean +>"string" : string + + || ((b = x) || (typeof x === "number" // number | boolean +>((b = x) || (typeof x === "number" // number | boolean || x)) : number | boolean +>(b = x) || (typeof x === "number" // number | boolean || x) : number | boolean +>(b = x) : number | boolean +>b = x : number | boolean +>b : number | boolean +>x : number | boolean +>(typeof x === "number" // number | boolean || x) : boolean +>typeof x === "number" // number | boolean || x : boolean +>typeof x === "number" : boolean +>typeof x : string +>x : number | boolean +>"number" : string + + || x)); // boolean +>x : boolean +} +function foo6(x: number | string | boolean) { +>foo6 : (x: number | string | boolean) => boolean +>x : number | string | boolean + + // Mixing typeguard + return typeof x === "string" // string | number | boolean +>typeof x === "string" // string | number | boolean || (typeof x !== "number" // number | boolean ? x // boolean : x === 10) : boolean +>typeof x === "string" : boolean +>typeof x : string +>x : number | string | boolean +>"string" : string + + || (typeof x !== "number" // number | boolean +>(typeof x !== "number" // number | boolean ? x // boolean : x === 10) : boolean +>typeof x !== "number" // number | boolean ? x // boolean : x === 10 : boolean +>typeof x !== "number" : boolean +>typeof x : string +>x : number | boolean +>"number" : string + + ? x // boolean +>x : boolean + + : x === 10) // number +>x === 10 : boolean +>x : number +>10 : number +} +function foo7(x: number | string | boolean) { +>foo7 : (x: number | string | boolean) => boolean | number | string +>x : number | string | boolean + + var y: number| boolean | string; +>y : number | boolean | string + + var z: number| boolean | string; +>z : number | boolean | string + + // Mixing typeguard narrowing + // Assigning value to x deep inside another guard stops narrowing of type too + return typeof x === "string" +>typeof x === "string" || ((z = x) // string | number | boolean - x changed deeper in conditional expression || (typeof x === "number" // change value of x ? (x = 10 && x.toString()) // number | boolean | string // do not change value : (y = x && x.toString()))) : boolean | number | string +>typeof x === "string" : boolean +>typeof x : string +>x : number | string | boolean +>"string" : string + + || ((z = x) // string | number | boolean - x changed deeper in conditional expression +>((z = x) // string | number | boolean - x changed deeper in conditional expression || (typeof x === "number" // change value of x ? (x = 10 && x.toString()) // number | boolean | string // do not change value : (y = x && x.toString()))) : number | string | boolean +>(z = x) // string | number | boolean - x changed deeper in conditional expression || (typeof x === "number" // change value of x ? (x = 10 && x.toString()) // number | boolean | string // do not change value : (y = x && x.toString())) : number | string | boolean +>(z = x) : number | string | boolean +>z = x : number | string | boolean +>z : number | boolean | string +>x : number | string | boolean + + || (typeof x === "number" +>(typeof x === "number" // change value of x ? (x = 10 && x.toString()) // number | boolean | string // do not change value : (y = x && x.toString())) : string +>typeof x === "number" // change value of x ? (x = 10 && x.toString()) // number | boolean | string // do not change value : (y = x && x.toString()) : string +>typeof x === "number" : boolean +>typeof x : string +>x : number | string | boolean +>"number" : string + + // change value of x + ? (x = 10 && x.toString()) // number | boolean | string +>(x = 10 && x.toString()) : string +>x = 10 && x.toString() : string +>x : number | string | boolean +>10 && x.toString() : string +>10 : number +>x.toString() : string +>x.toString : ((radix?: number) => string) | (() => string) +>x : number | string | boolean +>toString : ((radix?: number) => string) | (() => string) + + // do not change value + : (y = x && x.toString()))); // number | boolean | string +>(y = x && x.toString()) : string +>y = x && x.toString() : string +>y : number | boolean | string +>x && x.toString() : string +>x : number | string | boolean +>x.toString() : string +>x.toString : ((radix?: number) => string) | (() => string) +>x : number | string | boolean +>toString : ((radix?: number) => string) | (() => string) +} +function foo8(x: number | string) { +>foo8 : (x: number | string) => boolean | number +>x : number | string + + // Mixing typeguard + // Assigning value to x in outer guard shouldn't stop narrowing in the inner expression + return typeof x === "string" +>typeof x === "string" || (x = 10) // change x - number| string || (typeof x === "number" ? x // number : x.length) : boolean | number +>typeof x === "string" || (x = 10) : boolean | number +>typeof x === "string" : boolean +>typeof x : string +>x : number | string +>"string" : string + + || (x = 10) // change x - number| string +>(x = 10) : number +>x = 10 : number +>x : number | string +>10 : number + + || (typeof x === "number" +>(typeof x === "number" ? x // number : x.length) : number +>typeof x === "number" ? x // number : x.length : number +>typeof x === "number" : boolean +>typeof x : string +>x : number | string +>"number" : string + + ? x // number +>x : number + + : x.length); // string +>x.length : number +>x : string +>length : number +} diff --git a/tests/baselines/reference/unionTypeCallSignatures.errors.txt b/tests/baselines/reference/unionTypeCallSignatures.errors.txt index c25a2bf9f84..0ec5644db1d 100644 --- a/tests/baselines/reference/unionTypeCallSignatures.errors.txt +++ b/tests/baselines/reference/unionTypeCallSignatures.errors.txt @@ -16,10 +16,9 @@ tests/cases/conformance/types/union/unionTypeCallSignatures.ts(40,12): error TS2 tests/cases/conformance/types/union/unionTypeCallSignatures.ts(41,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. tests/cases/conformance/types/union/unionTypeCallSignatures.ts(42,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. tests/cases/conformance/types/union/unionTypeCallSignatures.ts(43,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. -tests/cases/conformance/types/union/unionTypeCallSignatures.ts(46,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. -tests/cases/conformance/types/union/unionTypeCallSignatures.ts(47,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. -tests/cases/conformance/types/union/unionTypeCallSignatures.ts(48,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. -tests/cases/conformance/types/union/unionTypeCallSignatures.ts(49,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(47,12): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(48,12): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(49,12): error TS2346: Supplied parameters do not match any signature of call target. tests/cases/conformance/types/union/unionTypeCallSignatures.ts(55,45): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. tests/cases/conformance/types/union/unionTypeCallSignatures.ts(56,12): error TS2346: Supplied parameters do not match any signature of call target. tests/cases/conformance/types/union/unionTypeCallSignatures.ts(59,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. @@ -27,14 +26,13 @@ tests/cases/conformance/types/union/unionTypeCallSignatures.ts(60,12): error TS2 tests/cases/conformance/types/union/unionTypeCallSignatures.ts(61,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. tests/cases/conformance/types/union/unionTypeCallSignatures.ts(62,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. tests/cases/conformance/types/union/unionTypeCallSignatures.ts(63,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. -tests/cases/conformance/types/union/unionTypeCallSignatures.ts(66,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. -tests/cases/conformance/types/union/unionTypeCallSignatures.ts(67,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. -tests/cases/conformance/types/union/unionTypeCallSignatures.ts(68,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. -tests/cases/conformance/types/union/unionTypeCallSignatures.ts(69,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. -tests/cases/conformance/types/union/unionTypeCallSignatures.ts(70,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(67,12): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(68,12): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(69,12): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(70,12): error TS2346: Supplied parameters do not match any signature of call target. -==== tests/cases/conformance/types/union/unionTypeCallSignatures.ts (34 errors) ==== +==== tests/cases/conformance/types/union/unionTypeCallSignatures.ts (32 errors) ==== var numOrDate: number | Date; var strOrBoolean: string | boolean; var strOrNum: string | number; @@ -80,7 +78,7 @@ tests/cases/conformance/types/union/unionTypeCallSignatures.ts(70,12): error TS2 ~~~~~~~ !!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. - var unionWithDifferentParameterCount: { (a: string): string; } | { (a: string, b: number): number; } ; + var unionWithDifferentParameterCount: { (a: string): string; } | { (a: string, b: number): number; } ; unionWithDifferentParameterCount();// no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !!! error TS2349: Cannot invoke an expression whose type lacks a call signature. @@ -91,7 +89,7 @@ tests/cases/conformance/types/union/unionTypeCallSignatures.ts(70,12): error TS2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !!! error TS2349: Cannot invoke an expression whose type lacks a call signature. - var unionWithOptionalParameter1: { (a: string, b?: number): string; } | { (a: string, b?: number): number; }; + var unionWithOptionalParameter1: { (a: string, b?: number): string; } | { (a: string, b?: number): number; }; strOrNum = unionWithOptionalParameter1('hello'); strOrNum = unionWithOptionalParameter1('hello', 10); strOrNum = unionWithOptionalParameter1('hello', "hello"); // error in parameter type @@ -116,18 +114,16 @@ tests/cases/conformance/types/union/unionTypeCallSignatures.ts(70,12): error TS2 !!! error TS2349: Cannot invoke an expression whose type lacks a call signature. var unionWithOptionalParameter3: { (a: string, b?: number): string; } | { (a: string): number; }; - strOrNum = unionWithOptionalParameter3('hello'); // error no call signature - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. + strOrNum = unionWithOptionalParameter3('hello'); strOrNum = unionWithOptionalParameter3('hello', 10); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. +!!! error TS2346: Supplied parameters do not match any signature of call target. strOrNum = unionWithOptionalParameter3('hello', "hello"); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. +!!! error TS2346: Supplied parameters do not match any signature of call target. strOrNum = unionWithOptionalParameter3(); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. +!!! error TS2346: Supplied parameters do not match any signature of call target. var unionWithRestParameter1: { (a: string, ...b: number[]): string; } | { (a: string, ...b: number[]): number }; strOrNum = unionWithRestParameter1('hello'); @@ -158,18 +154,18 @@ tests/cases/conformance/types/union/unionTypeCallSignatures.ts(70,12): error TS2 !!! error TS2349: Cannot invoke an expression whose type lacks a call signature. var unionWithRestParameter3: { (a: string, ...b: number[]): string; } | { (a: string): number }; - strOrNum = unionWithRestParameter3('hello'); // error no call signature - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. + strOrNum = unionWithRestParameter3('hello'); strOrNum = unionWithRestParameter3('hello', 10); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. +!!! error TS2346: Supplied parameters do not match any signature of call target. strOrNum = unionWithRestParameter3('hello', 10, 11); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. +!!! error TS2346: Supplied parameters do not match any signature of call target. strOrNum = unionWithRestParameter3('hello', "hello"); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. +!!! error TS2346: Supplied parameters do not match any signature of call target. strOrNum = unionWithRestParameter3(); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. \ No newline at end of file +!!! error TS2346: Supplied parameters do not match any signature of call target. + + \ No newline at end of file diff --git a/tests/baselines/reference/unionTypeCallSignatures.js b/tests/baselines/reference/unionTypeCallSignatures.js index a4000038ce6..fc3dfc8ebbc 100644 --- a/tests/baselines/reference/unionTypeCallSignatures.js +++ b/tests/baselines/reference/unionTypeCallSignatures.js @@ -26,12 +26,12 @@ unionOfDifferentNumberOfSignatures(); // error - no call signatures unionOfDifferentNumberOfSignatures(10); // error - no call signatures unionOfDifferentNumberOfSignatures("hello"); // error - no call signatures - var unionWithDifferentParameterCount: { (a: string): string; } | { (a: string, b: number): number; } ; +var unionWithDifferentParameterCount: { (a: string): string; } | { (a: string, b: number): number; } ; unionWithDifferentParameterCount();// no call signature unionWithDifferentParameterCount("hello");// no call signature unionWithDifferentParameterCount("hello", 10);// no call signature - var unionWithOptionalParameter1: { (a: string, b?: number): string; } | { (a: string, b?: number): number; }; +var unionWithOptionalParameter1: { (a: string, b?: number): string; } | { (a: string, b?: number): number; }; strOrNum = unionWithOptionalParameter1('hello'); strOrNum = unionWithOptionalParameter1('hello', 10); strOrNum = unionWithOptionalParameter1('hello', "hello"); // error in parameter type @@ -44,7 +44,7 @@ strOrNum = unionWithOptionalParameter2('hello', "hello"); // error no call signa strOrNum = unionWithOptionalParameter2(); // error no call signature var unionWithOptionalParameter3: { (a: string, b?: number): string; } | { (a: string): number; }; -strOrNum = unionWithOptionalParameter3('hello'); // error no call signature +strOrNum = unionWithOptionalParameter3('hello'); strOrNum = unionWithOptionalParameter3('hello', 10); // error no call signature strOrNum = unionWithOptionalParameter3('hello', "hello"); // error no call signature strOrNum = unionWithOptionalParameter3(); // error no call signature @@ -64,11 +64,13 @@ strOrNum = unionWithRestParameter2('hello', "hello"); // error no call signature strOrNum = unionWithRestParameter2(); // error no call signature var unionWithRestParameter3: { (a: string, ...b: number[]): string; } | { (a: string): number }; -strOrNum = unionWithRestParameter3('hello'); // error no call signature +strOrNum = unionWithRestParameter3('hello'); strOrNum = unionWithRestParameter3('hello', 10); // error no call signature strOrNum = unionWithRestParameter3('hello', 10, 11); // error no call signature strOrNum = unionWithRestParameter3('hello', "hello"); // error no call signature -strOrNum = unionWithRestParameter3(); // error no call signature +strOrNum = unionWithRestParameter3(); // error no call signature + + //// [unionTypeCallSignatures.js] var numOrDate; @@ -108,7 +110,7 @@ strOrNum = unionWithOptionalParameter2('hello', 10); // error no call signature strOrNum = unionWithOptionalParameter2('hello', "hello"); // error no call signature strOrNum = unionWithOptionalParameter2(); // error no call signature var unionWithOptionalParameter3; -strOrNum = unionWithOptionalParameter3('hello'); // error no call signature +strOrNum = unionWithOptionalParameter3('hello'); strOrNum = unionWithOptionalParameter3('hello', 10); // error no call signature strOrNum = unionWithOptionalParameter3('hello', "hello"); // error no call signature strOrNum = unionWithOptionalParameter3(); // error no call signature @@ -125,7 +127,7 @@ strOrNum = unionWithRestParameter2('hello', 10, 11); // error no call signature strOrNum = unionWithRestParameter2('hello', "hello"); // error no call signature strOrNum = unionWithRestParameter2(); // error no call signature var unionWithRestParameter3; -strOrNum = unionWithRestParameter3('hello'); // error no call signature +strOrNum = unionWithRestParameter3('hello'); strOrNum = unionWithRestParameter3('hello', 10); // error no call signature strOrNum = unionWithRestParameter3('hello', 10, 11); // error no call signature strOrNum = unionWithRestParameter3('hello', "hello"); // error no call signature diff --git a/tests/baselines/reference/unionTypeCallSignatures2.js b/tests/baselines/reference/unionTypeCallSignatures2.js new file mode 100644 index 00000000000..82383625902 --- /dev/null +++ b/tests/baselines/reference/unionTypeCallSignatures2.js @@ -0,0 +1,32 @@ +//// [unionTypeCallSignatures2.ts] +interface A { + (x: number): number; + (x: string, y?: string): boolean; + (x: Date): void; + (x: T[]): T[]; +} + +interface B { + (x: number): number; + (x: string): string; + (x: Date): void; + (x: T[]): T[]; +} + +interface C { + (x: string, ...y: string[]): number; + (x: number, s?: string): number; + (x: T[]): T[]; +} + +var f: A | B | C; +var n = f(42); // number +var s = f("abc"); // boolean | string | number +var a = f([true, false]); // boolean[] + + +//// [unionTypeCallSignatures2.js] +var f; +var n = f(42); // number +var s = f("abc"); // boolean | string | number +var a = f([true, false]); // boolean[] diff --git a/tests/baselines/reference/unionTypeCallSignatures2.symbols b/tests/baselines/reference/unionTypeCallSignatures2.symbols new file mode 100644 index 00000000000..747fefb665d --- /dev/null +++ b/tests/baselines/reference/unionTypeCallSignatures2.symbols @@ -0,0 +1,78 @@ +=== tests/cases/conformance/types/union/unionTypeCallSignatures2.ts === +interface A { +>A : Symbol(A, Decl(unionTypeCallSignatures2.ts, 0, 0)) + + (x: number): number; +>x : Symbol(x, Decl(unionTypeCallSignatures2.ts, 1, 5)) + + (x: string, y?: string): boolean; +>x : Symbol(x, Decl(unionTypeCallSignatures2.ts, 2, 5)) +>y : Symbol(y, Decl(unionTypeCallSignatures2.ts, 2, 15)) + + (x: Date): void; +>x : Symbol(x, Decl(unionTypeCallSignatures2.ts, 3, 5)) +>Date : Symbol(Date, Decl(lib.d.ts, 633, 23), Decl(lib.d.ts, 815, 11)) + + (x: T[]): T[]; +>T : Symbol(T, Decl(unionTypeCallSignatures2.ts, 4, 5)) +>x : Symbol(x, Decl(unionTypeCallSignatures2.ts, 4, 8)) +>T : Symbol(T, Decl(unionTypeCallSignatures2.ts, 4, 5)) +>T : Symbol(T, Decl(unionTypeCallSignatures2.ts, 4, 5)) +} + +interface B { +>B : Symbol(B, Decl(unionTypeCallSignatures2.ts, 5, 1)) + + (x: number): number; +>x : Symbol(x, Decl(unionTypeCallSignatures2.ts, 8, 5)) + + (x: string): string; +>x : Symbol(x, Decl(unionTypeCallSignatures2.ts, 9, 5)) + + (x: Date): void; +>x : Symbol(x, Decl(unionTypeCallSignatures2.ts, 10, 5)) +>Date : Symbol(Date, Decl(lib.d.ts, 633, 23), Decl(lib.d.ts, 815, 11)) + + (x: T[]): T[]; +>T : Symbol(T, Decl(unionTypeCallSignatures2.ts, 11, 5)) +>x : Symbol(x, Decl(unionTypeCallSignatures2.ts, 11, 8)) +>T : Symbol(T, Decl(unionTypeCallSignatures2.ts, 11, 5)) +>T : Symbol(T, Decl(unionTypeCallSignatures2.ts, 11, 5)) +} + +interface C { +>C : Symbol(C, Decl(unionTypeCallSignatures2.ts, 12, 1)) + + (x: string, ...y: string[]): number; +>x : Symbol(x, Decl(unionTypeCallSignatures2.ts, 15, 5)) +>y : Symbol(y, Decl(unionTypeCallSignatures2.ts, 15, 15)) + + (x: number, s?: string): number; +>x : Symbol(x, Decl(unionTypeCallSignatures2.ts, 16, 5)) +>s : Symbol(s, Decl(unionTypeCallSignatures2.ts, 16, 15)) + + (x: T[]): T[]; +>T : Symbol(T, Decl(unionTypeCallSignatures2.ts, 17, 5)) +>x : Symbol(x, Decl(unionTypeCallSignatures2.ts, 17, 8)) +>T : Symbol(T, Decl(unionTypeCallSignatures2.ts, 17, 5)) +>T : Symbol(T, Decl(unionTypeCallSignatures2.ts, 17, 5)) +} + +var f: A | B | C; +>f : Symbol(f, Decl(unionTypeCallSignatures2.ts, 20, 3)) +>A : Symbol(A, Decl(unionTypeCallSignatures2.ts, 0, 0)) +>B : Symbol(B, Decl(unionTypeCallSignatures2.ts, 5, 1)) +>C : Symbol(C, Decl(unionTypeCallSignatures2.ts, 12, 1)) + +var n = f(42); // number +>n : Symbol(n, Decl(unionTypeCallSignatures2.ts, 21, 3)) +>f : Symbol(f, Decl(unionTypeCallSignatures2.ts, 20, 3)) + +var s = f("abc"); // boolean | string | number +>s : Symbol(s, Decl(unionTypeCallSignatures2.ts, 22, 3)) +>f : Symbol(f, Decl(unionTypeCallSignatures2.ts, 20, 3)) + +var a = f([true, false]); // boolean[] +>a : Symbol(a, Decl(unionTypeCallSignatures2.ts, 23, 3)) +>f : Symbol(f, Decl(unionTypeCallSignatures2.ts, 20, 3)) + diff --git a/tests/baselines/reference/unionTypeCallSignatures2.types b/tests/baselines/reference/unionTypeCallSignatures2.types new file mode 100644 index 00000000000..8a4b80d6ee3 --- /dev/null +++ b/tests/baselines/reference/unionTypeCallSignatures2.types @@ -0,0 +1,86 @@ +=== tests/cases/conformance/types/union/unionTypeCallSignatures2.ts === +interface A { +>A : A + + (x: number): number; +>x : number + + (x: string, y?: string): boolean; +>x : string +>y : string + + (x: Date): void; +>x : Date +>Date : Date + + (x: T[]): T[]; +>T : T +>x : T[] +>T : T +>T : T +} + +interface B { +>B : B + + (x: number): number; +>x : number + + (x: string): string; +>x : string + + (x: Date): void; +>x : Date +>Date : Date + + (x: T[]): T[]; +>T : T +>x : T[] +>T : T +>T : T +} + +interface C { +>C : C + + (x: string, ...y: string[]): number; +>x : string +>y : string[] + + (x: number, s?: string): number; +>x : number +>s : string + + (x: T[]): T[]; +>T : T +>x : T[] +>T : T +>T : T +} + +var f: A | B | C; +>f : A | B | C +>A : A +>B : B +>C : C + +var n = f(42); // number +>n : number +>f(42) : number +>f : A | B | C +>42 : number + +var s = f("abc"); // boolean | string | number +>s : boolean | string | number +>f("abc") : boolean | string | number +>f : A | B | C +>"abc" : string + +var a = f([true, false]); // boolean[] +>a : boolean[] +>f([true, false]) : boolean[] +>f : A | B | C +>[true, false] : boolean[] +>true : boolean +>false : boolean + diff --git a/tests/baselines/reference/unionTypeConstructSignatures.errors.txt b/tests/baselines/reference/unionTypeConstructSignatures.errors.txt index cbdcc9ed12a..2710ce09850 100644 --- a/tests/baselines/reference/unionTypeConstructSignatures.errors.txt +++ b/tests/baselines/reference/unionTypeConstructSignatures.errors.txt @@ -16,10 +16,9 @@ tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(40,12): erro tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(41,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(42,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(43,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. -tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(46,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. -tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(47,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. -tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(48,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. -tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(49,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(47,12): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(48,12): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(49,12): error TS2346: Supplied parameters do not match any signature of call target. tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(55,49): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(56,12): error TS2346: Supplied parameters do not match any signature of call target. tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(59,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. @@ -27,14 +26,13 @@ tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(60,12): erro tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(61,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(62,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(63,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. -tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(66,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. -tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(67,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. -tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(68,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. -tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(69,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. -tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(70,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(67,12): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(68,12): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(69,12): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(70,12): error TS2346: Supplied parameters do not match any signature of call target. -==== tests/cases/conformance/types/union/unionTypeConstructSignatures.ts (34 errors) ==== +==== tests/cases/conformance/types/union/unionTypeConstructSignatures.ts (32 errors) ==== var numOrDate: number | Date; var strOrBoolean: string | boolean; var strOrNum: string | number; @@ -117,17 +115,15 @@ tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(70,12): erro var unionWithOptionalParameter3: { new (a: string, b?: number): string; } | { new (a: string): number; }; strOrNum = new unionWithOptionalParameter3('hello'); // error no call signature - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. strOrNum = new unionWithOptionalParameter3('hello', 10); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +!!! error TS2346: Supplied parameters do not match any signature of call target. strOrNum = new unionWithOptionalParameter3('hello', "hello"); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +!!! error TS2346: Supplied parameters do not match any signature of call target. strOrNum = new unionWithOptionalParameter3(); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +!!! error TS2346: Supplied parameters do not match any signature of call target. var unionWithRestParameter1: { new (a: string, ...b: number[]): string; } | { new (a: string, ...b: number[]): number }; strOrNum = new unionWithRestParameter1('hello'); @@ -159,17 +155,15 @@ tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(70,12): erro var unionWithRestParameter3: { new (a: string, ...b: number[]): string; } | { new (a: string): number }; strOrNum = new unionWithRestParameter3('hello'); // error no call signature - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. strOrNum = new unionWithRestParameter3('hello', 10); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +!!! error TS2346: Supplied parameters do not match any signature of call target. strOrNum = new unionWithRestParameter3('hello', 10, 11); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +!!! error TS2346: Supplied parameters do not match any signature of call target. strOrNum = new unionWithRestParameter3('hello', "hello"); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +!!! error TS2346: Supplied parameters do not match any signature of call target. strOrNum = new unionWithRestParameter3(); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. \ No newline at end of file +!!! error TS2346: Supplied parameters do not match any signature of call target. \ No newline at end of file From 07fd7ba8da8f52a239a7dca9511e9eea5921eb69 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 6 Aug 2015 15:40:20 -0700 Subject: [PATCH 50/93] Fixing fourslash test --- tests/cases/fourslash/completionEntryForUnionProperty2.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cases/fourslash/completionEntryForUnionProperty2.ts b/tests/cases/fourslash/completionEntryForUnionProperty2.ts index 0b2d50fc130..aa5bc40b5e3 100644 --- a/tests/cases/fourslash/completionEntryForUnionProperty2.ts +++ b/tests/cases/fourslash/completionEntryForUnionProperty2.ts @@ -15,6 +15,6 @@ ////x.commonProperty./**/ goTo.marker(); -verify.memberListContains("toString", "(property) toString: ((radix?: number) => string) | (() => string)"); +verify.memberListContains("toString", "(method) toString(): string"); verify.memberListContains("valueOf", "(method) valueOf(): number | string"); verify.memberListCount(2); \ No newline at end of file From 9a29a827cef8f9a27f9dbaaeb0b66b7d6a954527 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Thu, 6 Aug 2015 16:10:21 -0700 Subject: [PATCH 51/93] Fix #4025: report options diagnostics --- src/compiler/tsc.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index 22bd6d79b0e..c322187fa14 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -363,7 +363,7 @@ namespace ts { // If we didn't have any syntactic errors, then also try getting the global and // semantic errors. if (diagnostics.length === 0) { - diagnostics = program.getGlobalDiagnostics(); + diagnostics = program.getOptionsDiagnostics().concat(program.getGlobalDiagnostics()); if (diagnostics.length === 0) { diagnostics = program.getSemanticDiagnostics(); From 3e5965115229fe8740299958a9fa60ffbab0004f Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Thu, 6 Aug 2015 16:13:28 -0700 Subject: [PATCH 52/93] simplified docParams --- src/services/services.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/services/services.ts b/src/services/services.ts index 4478caae338..4d2df78c212 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -6845,9 +6845,9 @@ namespace ts { // TODO: call a helper method instead once PR #4133 gets merged in. const newLine = host.getNewLine ? host.getNewLine() : "\r\n"; - let docParams = parameters.map((p, index) => - indentationStr + " * @param " + (p.name.kind === SyntaxKind.Identifier ? (p.name).text : "param" + index) + newLine); - + let docParams = parameters.reduce((prev, cur, index) => + prev + + indentationStr + " * @param " + (cur.name.kind === SyntaxKind.Identifier ? (cur.name).text : "param" + index) + newLine, ""); // A doc comment consists of the following // * The opening comment line @@ -6860,7 +6860,7 @@ namespace ts { indentationStr + " * "; let result = preamble + newLine + - docParams.join("") + + docParams + indentationStr + " */" + (tokenStart === position ? newLine + indentationStr : ""); From 8ea1a226c2c70c915a204ca989cc9f5b4eaf1358 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Thu, 6 Aug 2015 16:14:14 -0700 Subject: [PATCH 53/93] Updated baselines --- tests/baselines/reference/decoratorMetadata.js | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/baselines/reference/decoratorMetadata.js b/tests/baselines/reference/decoratorMetadata.js index 71dc4de383a..ea776d09910 100644 --- a/tests/baselines/reference/decoratorMetadata.js +++ b/tests/baselines/reference/decoratorMetadata.js @@ -20,6 +20,7 @@ var Service = (function () { } return Service; })(); +Object.defineProperty(exports, "__esModule", { value: true }); exports.default = Service; //// [component.js] var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { From 3f3aea1380951a0f9c04fa273658d6b4fe74a58a Mon Sep 17 00:00:00 2001 From: Tien Nguyen Date: Thu, 6 Aug 2015 16:17:19 -0700 Subject: [PATCH 54/93] Fix mistyped `occurrence`. --- src/harness/fourslash.ts | 10 +++---- src/services/services.ts | 4 +-- .../cases/fourslash/getOccurrencesIfElse5.ts | 28 ++++++++--------- .../cases/fourslash/getOccurrencesReturn4.ts | 16 +++++----- .../getOccurrencesSwitchCaseDefault5.ts | 30 +++++++++---------- tests/cases/fourslash/getOccurrencesThis6.ts | 14 ++++----- .../getOccurrencesTryCatchFinally4.ts | 18 +++++------ 7 files changed, 60 insertions(+), 60 deletions(-) diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 2ebf086cb74..fd473558b08 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -2115,17 +2115,17 @@ module FourSlash { } } - private getOccurancesAtCurrentPosition() { + private getOccurrencesAtCurrentPosition() { return this.languageService.getOccurrencesAtPosition(this.activeFile.fileName, this.currentCaretPosition); } public verifyOccurrencesAtPositionListContains(fileName: string, start: number, end: number, isWriteAccess?: boolean) { this.taoInvalidReason = "verifyOccurrencesAtPositionListContains NYI"; - let occurrences = this.getOccurancesAtCurrentPosition(); + let occurrences = this.getOccurrencesAtCurrentPosition(); if (!occurrences || occurrences.length === 0) { - this.raiseError('verifyOccurancesAtPositionListContains failed - found 0 references, expected at least one.'); + this.raiseError('verifyOccurrencesAtPositionListContains failed - found 0 references, expected at least one.'); } for (let occurrence of occurrences) { @@ -2144,7 +2144,7 @@ module FourSlash { public verifyOccurrencesAtPositionListCount(expectedCount: number) { this.taoInvalidReason = "verifyOccurrencesAtPositionListCount NYI"; - let occurrences = this.getOccurancesAtCurrentPosition(); + let occurrences = this.getOccurrencesAtCurrentPosition(); let actualCount = occurrences ? occurrences.length : 0; if (expectedCount !== actualCount) { this.raiseError(`verifyOccurrencesAtPositionListCount failed - actual: ${actualCount}, expected:${expectedCount}`); @@ -2181,7 +2181,7 @@ module FourSlash { } let missingItem = { fileName: fileName, start: start, end: end, kind: kind }; - this.raiseError('verifyOccurancesAtPositionListContains failed - could not find the item: ' + JSON.stringify(missingItem) + ' in the returned list: (' + JSON.stringify(documentHighlights) + ')'); + this.raiseError(`verifyDocumentHighlightsAtPositionListContains failed - could not find the item: ${JSON.stringify(missingItem)} in the returned list: (${JSON.stringify(documentHighlights)})`); } public verifyDocumentHighlightsAtPositionListCount(expectedCount: number, fileNamesToSearch: string[]) { diff --git a/src/services/services.ts b/src/services/services.ts index 72b4b617b3a..f5743abd412 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -4620,7 +4620,7 @@ namespace ts { case SyntaxKind.BreakKeyword: case SyntaxKind.ContinueKeyword: if (hasKind(node.parent, SyntaxKind.BreakStatement) || hasKind(node.parent, SyntaxKind.ContinueStatement)) { - return getBreakOrContinueStatementOccurences(node.parent); + return getBreakOrContinueStatementOccurrences(node.parent); } break; case SyntaxKind.ForKeyword: @@ -4946,7 +4946,7 @@ namespace ts { return map(keywords, getHighlightSpanForNode); } - function getBreakOrContinueStatementOccurences(breakOrContinueStatement: BreakOrContinueStatement): HighlightSpan[] { + function getBreakOrContinueStatementOccurrences(breakOrContinueStatement: BreakOrContinueStatement): HighlightSpan[] { let owner = getBreakOrContinueOwner(breakOrContinueStatement); if (owner) { diff --git a/tests/cases/fourslash/getOccurrencesIfElse5.ts b/tests/cases/fourslash/getOccurrencesIfElse5.ts index b0519630b7b..7360a803027 100644 --- a/tests/cases/fourslash/getOccurrencesIfElse5.ts +++ b/tests/cases/fourslash/getOccurrencesIfElse5.ts @@ -22,21 +22,21 @@ ////} ////else/*13*/ { } -function verifyOccurencesAtMarker(marker: string, count: number) { +function verifyOccurrencesAtMarker(marker: string, count: number) { goTo.marker(marker); verify.occurrencesAtPositionCount(count); } -verifyOccurencesAtMarker("1", 7); -verifyOccurencesAtMarker("2", 2); -verifyOccurencesAtMarker("3", 2); -verifyOccurencesAtMarker("4", 2); -verifyOccurencesAtMarker("5", 2); -verifyOccurencesAtMarker("6", 1); -verifyOccurencesAtMarker("7", 1); -verifyOccurencesAtMarker("8", 7); -verifyOccurencesAtMarker("9", 7); -verifyOccurencesAtMarker("10", 7); -verifyOccurencesAtMarker("11", 7); -verifyOccurencesAtMarker("12", 7); -verifyOccurencesAtMarker("13", 7); +verifyOccurrencesAtMarker("1", 7); +verifyOccurrencesAtMarker("2", 2); +verifyOccurrencesAtMarker("3", 2); +verifyOccurrencesAtMarker("4", 2); +verifyOccurrencesAtMarker("5", 2); +verifyOccurrencesAtMarker("6", 1); +verifyOccurrencesAtMarker("7", 1); +verifyOccurrencesAtMarker("8", 7); +verifyOccurrencesAtMarker("9", 7); +verifyOccurrencesAtMarker("10", 7); +verifyOccurrencesAtMarker("11", 7); +verifyOccurrencesAtMarker("12", 7); +verifyOccurrencesAtMarker("13", 7); diff --git a/tests/cases/fourslash/getOccurrencesReturn4.ts b/tests/cases/fourslash/getOccurrencesReturn4.ts index 4e25162f80f..4066b093f3d 100644 --- a/tests/cases/fourslash/getOccurrencesReturn4.ts +++ b/tests/cases/fourslash/getOccurrencesReturn4.ts @@ -19,15 +19,15 @@ //// return/*7*/ true; ////} -function verifyOccurencesAtMarker(marker: string, count: number) { +function verifyOccurrencesAtMarker(marker: string, count: number) { goTo.marker(marker); verify.occurrencesAtPositionCount(count); } -verifyOccurencesAtMarker("1", 4); -verifyOccurencesAtMarker("2", 4); -verifyOccurencesAtMarker("3", 4); -verifyOccurencesAtMarker("4", 4); -verifyOccurencesAtMarker("5", 1); -verifyOccurencesAtMarker("6", 3); -verifyOccurencesAtMarker("7", 3); \ No newline at end of file +verifyOccurrencesAtMarker("1", 4); +verifyOccurrencesAtMarker("2", 4); +verifyOccurrencesAtMarker("3", 4); +verifyOccurrencesAtMarker("4", 4); +verifyOccurrencesAtMarker("5", 1); +verifyOccurrencesAtMarker("6", 3); +verifyOccurrencesAtMarker("7", 3); \ No newline at end of file diff --git a/tests/cases/fourslash/getOccurrencesSwitchCaseDefault5.ts b/tests/cases/fourslash/getOccurrencesSwitchCaseDefault5.ts index 162c2e1a94f..3c6d5374ce6 100644 --- a/tests/cases/fourslash/getOccurrencesSwitchCaseDefault5.ts +++ b/tests/cases/fourslash/getOccurrencesSwitchCaseDefault5.ts @@ -18,23 +18,23 @@ //// case 16/*14*/: ////} -function verifyOccurencesAtMarker(marker: string, count: number) { +function verifyOccurrencesAtMarker(marker: string, count: number) { goTo.marker(marker); verify.occurrencesAtPositionCount(count); } -verifyOccurencesAtMarker("1", 9); -verifyOccurencesAtMarker("2", 9); -verifyOccurencesAtMarker("3", 9); -verifyOccurencesAtMarker("4", 9); -verifyOccurencesAtMarker("5", 9); -verifyOccurencesAtMarker("6", 6); -verifyOccurencesAtMarker("7", 6); -verifyOccurencesAtMarker("8", 6); -verifyOccurencesAtMarker("9", 6); -verifyOccurencesAtMarker("10", 6); -verifyOccurencesAtMarker("11", 9); -verifyOccurencesAtMarker("12", 9); -verifyOccurencesAtMarker("13", 9); -verifyOccurencesAtMarker("14", 0); +verifyOccurrencesAtMarker("1", 9); +verifyOccurrencesAtMarker("2", 9); +verifyOccurrencesAtMarker("3", 9); +verifyOccurrencesAtMarker("4", 9); +verifyOccurrencesAtMarker("5", 9); +verifyOccurrencesAtMarker("6", 6); +verifyOccurrencesAtMarker("7", 6); +verifyOccurrencesAtMarker("8", 6); +verifyOccurrencesAtMarker("9", 6); +verifyOccurrencesAtMarker("10", 6); +verifyOccurrencesAtMarker("11", 9); +verifyOccurrencesAtMarker("12", 9); +verifyOccurrencesAtMarker("13", 9); +verifyOccurrencesAtMarker("14", 0); diff --git a/tests/cases/fourslash/getOccurrencesThis6.ts b/tests/cases/fourslash/getOccurrencesThis6.ts index 6ff779c0b46..e9a5c545f23 100644 --- a/tests/cases/fourslash/getOccurrencesThis6.ts +++ b/tests/cases/fourslash/getOccurrencesThis6.ts @@ -142,14 +142,14 @@ ////} -function verifyOccurencesAtMarker(marker: string, count: number) { +function verifyOccurrencesAtMarker(marker: string, count: number) { goTo.marker(marker); verify.occurrencesAtPositionCount(count); } -verifyOccurencesAtMarker("1", 2); -verifyOccurencesAtMarker("2", 6); -verifyOccurencesAtMarker("3", 1); -verifyOccurencesAtMarker("4", 1); -verifyOccurencesAtMarker("5", 1); -verifyOccurencesAtMarker("6", 0); \ No newline at end of file +verifyOccurrencesAtMarker("1", 2); +verifyOccurrencesAtMarker("2", 6); +verifyOccurrencesAtMarker("3", 1); +verifyOccurrencesAtMarker("4", 1); +verifyOccurrencesAtMarker("5", 1); +verifyOccurrencesAtMarker("6", 0); \ No newline at end of file diff --git a/tests/cases/fourslash/getOccurrencesTryCatchFinally4.ts b/tests/cases/fourslash/getOccurrencesTryCatchFinally4.ts index dc6b0540312..3d97bd319ea 100644 --- a/tests/cases/fourslash/getOccurrencesTryCatchFinally4.ts +++ b/tests/cases/fourslash/getOccurrencesTryCatchFinally4.ts @@ -15,16 +15,16 @@ ////} ////finally/*7*/ { ////} -function verifyOccurencesAtMarker(marker: string, count: number) { +function verifyOccurrencesAtMarker(marker: string, count: number) { goTo.marker(marker); verify.occurrencesAtPositionCount(count); } -verifyOccurencesAtMarker("1", 3); -verifyOccurencesAtMarker("2", 2); -verifyOccurencesAtMarker("3", 2); -verifyOccurencesAtMarker("4", 2); -verifyOccurencesAtMarker("5", 2); -verifyOccurencesAtMarker("6", 3); -verifyOccurencesAtMarker("7", 3); -verifyOccurencesAtMarker("8", 0); \ No newline at end of file +verifyOccurrencesAtMarker("1", 3); +verifyOccurrencesAtMarker("2", 2); +verifyOccurrencesAtMarker("3", 2); +verifyOccurrencesAtMarker("4", 2); +verifyOccurrencesAtMarker("5", 2); +verifyOccurrencesAtMarker("6", 3); +verifyOccurrencesAtMarker("7", 3); +verifyOccurrencesAtMarker("8", 0); \ No newline at end of file From fbba50b31293fb2c3f621c95335ec50df56d752f Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Thu, 6 Aug 2015 16:23:08 -0700 Subject: [PATCH 55/93] Fix #4194: emit type paramters in type alias declaration --- src/compiler/declarationEmitter.ts | 1 + src/compiler/types.ts | 4 ++-- .../reference/typeAliasDeclarationEmit.js | 14 ++++++++++++++ .../reference/typeAliasDeclarationEmit.symbols | 13 +++++++++++++ .../reference/typeAliasDeclarationEmit.types | 13 +++++++++++++ tests/cases/compiler/typeAliasDeclarationEmit.ts | 7 +++++++ 6 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/typeAliasDeclarationEmit.js create mode 100644 tests/baselines/reference/typeAliasDeclarationEmit.symbols create mode 100644 tests/baselines/reference/typeAliasDeclarationEmit.types create mode 100644 tests/cases/compiler/typeAliasDeclarationEmit.ts diff --git a/src/compiler/declarationEmitter.ts b/src/compiler/declarationEmitter.ts index 63d71b0339e..5c44bf7b371 100644 --- a/src/compiler/declarationEmitter.ts +++ b/src/compiler/declarationEmitter.ts @@ -754,6 +754,7 @@ namespace ts { emitModuleElementDeclarationFlags(node); write("type "); writeTextOfNode(currentSourceFile, node.name); + emitTypeParameters(node.typeParameters); write(" = "); emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.type, getTypeAliasDeclarationVisibilityError); write(";"); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index da43984ee13..d19ed62332e 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1786,10 +1786,10 @@ namespace ts { ObjectType = Class | Interface | Reference | Tuple | Anonymous, UnionOrIntersection = Union | Intersection, StructuredType = ObjectType | Union | Intersection, - /* @internal */ + /* @internal */ RequiresWidening = ContainsUndefinedOrNull | ContainsObjectLiteral, /* @internal */ - PropagatingFlags = ContainsUndefinedOrNull | ContainsObjectLiteral | ContainsAnyFunctionType + PropagatingFlags = ContainsUndefinedOrNull | ContainsObjectLiteral | ContainsAnyFunctionType } // Properties common to all types diff --git a/tests/baselines/reference/typeAliasDeclarationEmit.js b/tests/baselines/reference/typeAliasDeclarationEmit.js new file mode 100644 index 00000000000..6e82fe4b07d --- /dev/null +++ b/tests/baselines/reference/typeAliasDeclarationEmit.js @@ -0,0 +1,14 @@ +//// [typeAliasDeclarationEmit.ts] + +export type callback = () => T; + +export type CallbackArray = () => T; + +//// [typeAliasDeclarationEmit.js] +define(["require", "exports"], function (require, exports) { +}); + + +//// [typeAliasDeclarationEmit.d.ts] +export declare type callback = () => T; +export declare type CallbackArray = () => T; diff --git a/tests/baselines/reference/typeAliasDeclarationEmit.symbols b/tests/baselines/reference/typeAliasDeclarationEmit.symbols new file mode 100644 index 00000000000..5f98ea75a5a --- /dev/null +++ b/tests/baselines/reference/typeAliasDeclarationEmit.symbols @@ -0,0 +1,13 @@ +=== tests/cases/compiler/typeAliasDeclarationEmit.ts === + +export type callback = () => T; +>callback : Symbol(callback, Decl(typeAliasDeclarationEmit.ts, 0, 0)) +>T : Symbol(T, Decl(typeAliasDeclarationEmit.ts, 1, 21)) +>T : Symbol(T, Decl(typeAliasDeclarationEmit.ts, 1, 21)) + +export type CallbackArray = () => T; +>CallbackArray : Symbol(CallbackArray, Decl(typeAliasDeclarationEmit.ts, 1, 34)) +>T : Symbol(T, Decl(typeAliasDeclarationEmit.ts, 3, 26)) +>callback : Symbol(callback, Decl(typeAliasDeclarationEmit.ts, 0, 0)) +>T : Symbol(T, Decl(typeAliasDeclarationEmit.ts, 3, 26)) + diff --git a/tests/baselines/reference/typeAliasDeclarationEmit.types b/tests/baselines/reference/typeAliasDeclarationEmit.types new file mode 100644 index 00000000000..6f9359e36f5 --- /dev/null +++ b/tests/baselines/reference/typeAliasDeclarationEmit.types @@ -0,0 +1,13 @@ +=== tests/cases/compiler/typeAliasDeclarationEmit.ts === + +export type callback = () => T; +>callback : () => T +>T : T +>T : T + +export type CallbackArray = () => T; +>CallbackArray : () => T +>T : T +>callback : () => T +>T : T + diff --git a/tests/cases/compiler/typeAliasDeclarationEmit.ts b/tests/cases/compiler/typeAliasDeclarationEmit.ts new file mode 100644 index 00000000000..be7e40453f6 --- /dev/null +++ b/tests/cases/compiler/typeAliasDeclarationEmit.ts @@ -0,0 +1,7 @@ +// @target: ES5 +// @module: AMD +// @declaration: true + +export type callback = () => T; + +export type CallbackArray = () => T; \ No newline at end of file From 013b92c3e7b9e4fa4d8dcb53246eaa5d0230b5af Mon Sep 17 00:00:00 2001 From: Tien Nguyen Date: Thu, 6 Aug 2015 16:27:25 -0700 Subject: [PATCH 56/93] Use template string to shorten code. --- src/harness/fourslash.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index fd473558b08..ebf1b1d1814 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -2172,7 +2172,7 @@ module FourSlash { for (let highlight of highlightSpans) { if (highlight && highlight.textSpan.start === start && ts.textSpanEnd(highlight.textSpan) === end) { if (typeof kind !== "undefined" && highlight.kind !== kind) { - this.raiseError('verifyDocumentHighlightsAtPositionListContains failed - item "kind" value does not match, actual: ' + highlight.kind + ', expected: ' + kind + '.'); + this.raiseError(`verifyDocumentHighlightsAtPositionListContains failed - item "kind" value does not match, actual: ${highlight.kind}, expected: ${kind}.`); } return; } From 02539d91e23a931546dd8697f94bfbd16f0ae145 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Thu, 6 Aug 2015 16:38:53 -0700 Subject: [PATCH 57/93] deduplicate module dependencies --- src/compiler/emitter.ts | 147 ++++++++++-------- .../reference/aliasesInSystemModule1.js | 4 +- .../reference/aliasesInSystemModule2.js | 4 +- tests/baselines/reference/systemModule10.js | 8 +- .../baselines/reference/systemModule10_ES5.js | 8 +- tests/baselines/reference/systemModule11.js | 28 ++-- tests/baselines/reference/systemModule14.js | 4 +- tests/baselines/reference/systemModule15.js | 88 +++++++++++ .../reference/systemModule15.symbols | 66 ++++++++ .../baselines/reference/systemModule15.types | 71 +++++++++ .../reference/systemModule16.errors.txt | 33 ++++ tests/baselines/reference/systemModule16.js | 54 +++++++ tests/baselines/reference/systemModule9.js | 26 ++-- .../reference/systemModuleWithSuperClass.js | 4 +- tests/cases/compiler/systemModule15.ts | 34 ++++ tests/cases/compiler/systemModule16.ts | 13 ++ 16 files changed, 487 insertions(+), 105 deletions(-) create mode 100644 tests/baselines/reference/systemModule15.js create mode 100644 tests/baselines/reference/systemModule15.symbols create mode 100644 tests/baselines/reference/systemModule15.types create mode 100644 tests/baselines/reference/systemModule16.errors.txt create mode 100644 tests/baselines/reference/systemModule16.js create mode 100644 tests/cases/compiler/systemModule15.ts create mode 100644 tests/cases/compiler/systemModule16.ts diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index da268892ad9..76d07395f32 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -6058,7 +6058,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi return compilerOptions.module === ModuleKind.System && isExternalModule(currentSourceFile); } - function emitSystemModuleBody(node: SourceFile, startIndex: number): void { + function emitSystemModuleBody(node: SourceFile, dependencyGroups: DependencyGroup[], startIndex: number): void { // shape of the body in system modules: // function (exports) { // @@ -6103,7 +6103,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi write("return {"); increaseIndent(); writeLine(); - emitSetters(exportStarFunction); + emitSetters(exportStarFunction, dependencyGroups); writeLine(); emitExecute(node, startIndex); decreaseIndent(); @@ -6112,77 +6112,83 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi emitTempDeclarations(/*newLine*/ true); } - function emitSetters(exportStarFunction: string) { + function emitSetters(exportStarFunction: string, dependencyGroups: DependencyGroup[]) { write("setters:["); - for (let i = 0; i < externalImports.length; ++i) { + + for (let i = 0; i < dependencyGroups.length; ++i) { if (i !== 0) { write(","); } writeLine(); increaseIndent(); - let importNode = externalImports[i]; - let importVariableName = getLocalNameForExternalImport(importNode) || ""; - let parameterName = "_" + importVariableName; + + let group = dependencyGroups[i]; + + // derive a unique name for parameter from the first named entry in the group + let parameterName = makeUniqueName(forEach(group, getLocalNameForExternalImport) || ""); write(`function (${parameterName}) {`); - - switch (importNode.kind) { - case SyntaxKind.ImportDeclaration: - if (!(importNode).importClause) { - // 'import "..."' case - // module is imported only for side-effects, setter body will be empty - break; - } - // fall-through - case SyntaxKind.ImportEqualsDeclaration: - Debug.assert(importVariableName !== ""); - - increaseIndent(); - writeLine(); - // save import into the local - write(`${importVariableName} = ${parameterName};`); - writeLine(); - decreaseIndent(); - break; - case SyntaxKind.ExportDeclaration: - Debug.assert(importVariableName !== ""); - - increaseIndent(); - - if ((importNode).exportClause) { - // export {a, b as c} from 'foo' - // emit as: - // var reexports = {} - // reexports['a'] = _foo["a"]; - // reexports['c'] = _foo["b"]; - // exports_(reexports); - let reexportsVariableName = makeUniqueName("reexports"); - writeLine(); - write(`var ${reexportsVariableName} = {};`); - writeLine(); - for (let e of (importNode).exportClause.elements) { - write(`${reexportsVariableName}["`); - emitNodeWithoutSourceMap(e.name); - write(`"] = ${parameterName}["`); - emitNodeWithoutSourceMap(e.propertyName || e.name); - write(`"];`); - writeLine(); + increaseIndent(); + + for(let entry of group) { + let importVariableName = getLocalNameForExternalImport(entry) || ""; + + switch (entry.kind) { + case SyntaxKind.ImportDeclaration: + if (!(entry).importClause) { + // 'import "..."' case + // module is imported only for side-effects, no emit required + break; } - write(`${exportFunctionForFile}(${reexportsVariableName});`); - } - else { - writeLine(); - // export * from 'foo' - // emit as: - // exportStar(_foo); - write(`${exportStarFunction}(${parameterName});`); - } + // fall-through + case SyntaxKind.ImportEqualsDeclaration: + Debug.assert(importVariableName !== ""); + + writeLine(); + // save import into the local + write(`${importVariableName} = ${parameterName};`); + writeLine(); + break; + case SyntaxKind.ExportDeclaration: + Debug.assert(importVariableName !== ""); + + if ((entry).exportClause) { + // export {a, b as c} from 'foo' + // emit as: + // var reexports = {} + // reexports['a'] = _foo["a"]; + // reexports['c'] = _foo["b"]; + // exports_(reexports); + let reexportsVariableName = makeUniqueName("reexports"); + writeLine(); + write(`var ${reexportsVariableName} = {};`); + writeLine(); + for (let e of (entry).exportClause.elements) { + write(`${reexportsVariableName}["`); + emitNodeWithoutSourceMap(e.name); + write(`"] = ${parameterName}["`); + emitNodeWithoutSourceMap(e.propertyName || e.name); + write(`"];`); + writeLine(); + } + write(`${exportFunctionForFile}(${reexportsVariableName});`); + } + else { + writeLine(); + // export * from 'foo' + // emit as: + // exportStar(_foo); + write(`${exportStarFunction}(${parameterName});`); + } + + writeLine(); + break; + } - writeLine(); - decreaseIndent(); - break; } + decreaseIndent(); + write("}"); decreaseIndent(); } @@ -6228,6 +6234,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi write("}"); // execute } + type DependencyGroup = Array; + function emitSystemModule(node: SourceFile, startIndex: number): void { collectExternalModuleInfo(node); // System modules has the following shape @@ -6247,8 +6255,23 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi write(`"${node.moduleName}", `); } write("["); + + let groupIndices: Map = {}; + let dependencyGroups: DependencyGroup[] = []; + for (let i = 0; i < externalImports.length; ++i) { let text = getExternalModuleNameText(externalImports[i]); + if (hasProperty(groupIndices, text)) { + // deduplicate/group entries in dependency list by the dependency name + let groupIndex = groupIndices[text]; + dependencyGroups[groupIndex].push(externalImports[i]); + continue; + } + else { + groupIndices[text] = dependencyGroups.length; + dependencyGroups.push([externalImports[i]]); + } + if (i !== 0) { write(", "); } @@ -6259,7 +6282,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi increaseIndent(); emitEmitHelpers(node); emitCaptureThisForNodeIfNecessary(node); - emitSystemModuleBody(node, startIndex); + emitSystemModuleBody(node, dependencyGroups, startIndex); decreaseIndent(); writeLine(); write("});"); diff --git a/tests/baselines/reference/aliasesInSystemModule1.js b/tests/baselines/reference/aliasesInSystemModule1.js index 28ac1e9b4ad..05f74aef852 100644 --- a/tests/baselines/reference/aliasesInSystemModule1.js +++ b/tests/baselines/reference/aliasesInSystemModule1.js @@ -22,8 +22,8 @@ System.register(['foo'], function(exports_1) { var cls, cls2, x, y, z, M; return { setters:[ - function (_alias) { - alias = _alias; + function (alias_1) { + alias = alias_1; }], execute: function() { cls = alias.Class; diff --git a/tests/baselines/reference/aliasesInSystemModule2.js b/tests/baselines/reference/aliasesInSystemModule2.js index 0256d03a179..32d663a11e1 100644 --- a/tests/baselines/reference/aliasesInSystemModule2.js +++ b/tests/baselines/reference/aliasesInSystemModule2.js @@ -21,8 +21,8 @@ System.register(["foo"], function(exports_1) { var cls, cls2, x, y, z, M; return { setters:[ - function (_foo_1) { - foo_1 = _foo_1; + function (foo_1_1) { + foo_1 = foo_1_1; }], execute: function() { cls = foo_1.alias.Class; diff --git a/tests/baselines/reference/systemModule10.js b/tests/baselines/reference/systemModule10.js index dec185a3063..fcecfc9b0f8 100644 --- a/tests/baselines/reference/systemModule10.js +++ b/tests/baselines/reference/systemModule10.js @@ -14,11 +14,11 @@ System.register(['file1', 'file2'], function(exports_1) { var file1_1, n2; return { setters:[ - function (_file1_1) { - file1_1 = _file1_1; + function (file1_1_1) { + file1_1 = file1_1_1; }, - function (_n2) { - n2 = _n2; + function (n2_1) { + n2 = n2_1; }], execute: function() { exports_1("x", file1_1.x); diff --git a/tests/baselines/reference/systemModule10_ES5.js b/tests/baselines/reference/systemModule10_ES5.js index c080b893513..a86088a3463 100644 --- a/tests/baselines/reference/systemModule10_ES5.js +++ b/tests/baselines/reference/systemModule10_ES5.js @@ -14,11 +14,11 @@ System.register(['file1', 'file2'], function(exports_1) { var file1_1, n2; return { setters:[ - function (_file1_1) { - file1_1 = _file1_1; + function (file1_1_1) { + file1_1 = file1_1_1; }, - function (_n2) { - n2 = _n2; + function (n2_1) { + n2 = n2_1; }], execute: function() { exports_1("x", file1_1.x); diff --git a/tests/baselines/reference/systemModule11.js b/tests/baselines/reference/systemModule11.js index 34dd0d3df5f..7111968f3ce 100644 --- a/tests/baselines/reference/systemModule11.js +++ b/tests/baselines/reference/systemModule11.js @@ -59,8 +59,8 @@ System.register(['bar'], function(exports_1) { } return { setters:[ - function (_bar_1) { - exportStar_1(_bar_1); + function (bar_1_1) { + exportStar_1(bar_1_1); }], execute: function() { } @@ -82,8 +82,8 @@ System.register(['bar'], function(exports_1) { } return { setters:[ - function (_bar_1) { - exportStar_1(_bar_1); + function (bar_1_1) { + exportStar_1(bar_1_1); }], execute: function() { exports_1("x", x); @@ -108,14 +108,14 @@ System.register(['a', 'bar'], function(exports_1) { } return { setters:[ - function (_a_1) { + function (a_1_1) { var reexports_1 = {}; - reexports_1["x"] = _a_1["x"]; - reexports_1["z"] = _a_1["y"]; + reexports_1["x"] = a_1_1["x"]; + reexports_1["z"] = a_1_1["y"]; exports_1(reexports_1); }, - function (_bar_1) { - exportStar_1(_bar_1); + function (bar_1_1) { + exportStar_1(bar_1_1); }], execute: function() { } @@ -130,10 +130,10 @@ System.register(['a'], function(exports_1) { exports_1("default", default_1); return { setters:[ - function (_a_1) { + function (a_1_1) { var reexports_1 = {}; - reexports_1["s"] = _a_1["s"]; - reexports_1["s2"] = _a_1["s1"]; + reexports_1["s"] = a_1_1["s"]; + reexports_1["s2"] = a_1_1["s1"]; exports_1(reexports_1); }], execute: function() { @@ -154,8 +154,8 @@ System.register(['a'], function(exports_1) { } return { setters:[ - function (_a_1) { - exportStar_1(_a_1); + function (a_1_1) { + exportStar_1(a_1_1); }], execute: function() { } diff --git a/tests/baselines/reference/systemModule14.js b/tests/baselines/reference/systemModule14.js index 9365754a1e5..76906db5980 100644 --- a/tests/baselines/reference/systemModule14.js +++ b/tests/baselines/reference/systemModule14.js @@ -19,8 +19,8 @@ System.register(["foo"], function(exports_1) { } return { setters:[ - function (_foo_1) { - foo_1 = _foo_1; + function (foo_1_1) { + foo_1 = foo_1_1; }], execute: function() { exports_1("foo", foo); diff --git a/tests/baselines/reference/systemModule15.js b/tests/baselines/reference/systemModule15.js new file mode 100644 index 00000000000..4d5536cbaa1 --- /dev/null +++ b/tests/baselines/reference/systemModule15.js @@ -0,0 +1,88 @@ +//// [tests/cases/compiler/systemModule15.ts] //// + +//// [file1.ts] + + +import * as moduleB from "./file2" + +declare function use(v: any): void; + +use(moduleB.value); +use(moduleB.moduleC); +use(moduleB.moduleCStar); + +//// [file2.ts] + +import * as moduleCStar from "./file3" +import {value2} from "./file4" +import moduleC from "./file3" +import {value} from "./file3" + +export { + moduleCStar, + moduleC, + value +} + +//// [file3.ts] + +export var value = "youpi"; +export default value; + +//// [file4.ts] + +export var value2 = "v"; + +//// [file3.js] +System.register([], function(exports_1) { + var value; + return { + setters:[], + execute: function() { + exports_1("value", value = "youpi"); + exports_1("default",value); + } + } +}); +//// [file4.js] +System.register([], function(exports_1) { + var value2; + return { + setters:[], + execute: function() { + exports_1("value2", value2 = "v"); + } + } +}); +//// [file2.js] +System.register(["./file3"], function(exports_1) { + var moduleCStar, file3_1, file3_2; + return { + setters:[ + function (moduleCStar_1) { + moduleCStar = moduleCStar_1; + file3_1 = moduleCStar_1; + file3_2 = moduleCStar_1; + }], + execute: function() { + exports_1("moduleCStar", moduleCStar); + exports_1("moduleC", file3_1["default"]); + exports_1("value", file3_2.value); + } + } +}); +//// [file1.js] +System.register(["./file2"], function(exports_1) { + var moduleB; + return { + setters:[ + function (moduleB_1) { + moduleB = moduleB_1; + }], + execute: function() { + use(moduleB.value); + use(moduleB.moduleC); + use(moduleB.moduleCStar); + } + } +}); diff --git a/tests/baselines/reference/systemModule15.symbols b/tests/baselines/reference/systemModule15.symbols new file mode 100644 index 00000000000..2572950a7f2 --- /dev/null +++ b/tests/baselines/reference/systemModule15.symbols @@ -0,0 +1,66 @@ +=== tests/cases/compiler/file1.ts === + + +import * as moduleB from "./file2" +>moduleB : Symbol(moduleB, Decl(file1.ts, 2, 6)) + +declare function use(v: any): void; +>use : Symbol(use, Decl(file1.ts, 2, 34)) +>v : Symbol(v, Decl(file1.ts, 4, 21)) + +use(moduleB.value); +>use : Symbol(use, Decl(file1.ts, 2, 34)) +>moduleB.value : Symbol(moduleB.value, Decl(file2.ts, 8, 12)) +>moduleB : Symbol(moduleB, Decl(file1.ts, 2, 6)) +>value : Symbol(moduleB.value, Decl(file2.ts, 8, 12)) + +use(moduleB.moduleC); +>use : Symbol(use, Decl(file1.ts, 2, 34)) +>moduleB.moduleC : Symbol(moduleB.moduleC, Decl(file2.ts, 7, 16)) +>moduleB : Symbol(moduleB, Decl(file1.ts, 2, 6)) +>moduleC : Symbol(moduleB.moduleC, Decl(file2.ts, 7, 16)) + +use(moduleB.moduleCStar); +>use : Symbol(use, Decl(file1.ts, 2, 34)) +>moduleB.moduleCStar : Symbol(moduleB.moduleCStar, Decl(file2.ts, 6, 8)) +>moduleB : Symbol(moduleB, Decl(file1.ts, 2, 6)) +>moduleCStar : Symbol(moduleB.moduleCStar, Decl(file2.ts, 6, 8)) + +=== tests/cases/compiler/file2.ts === + +import * as moduleCStar from "./file3" +>moduleCStar : Symbol(moduleCStar, Decl(file2.ts, 1, 6)) + +import {value2} from "./file4" +>value2 : Symbol(value2, Decl(file2.ts, 2, 8)) + +import moduleC from "./file3" +>moduleC : Symbol(moduleC, Decl(file2.ts, 3, 6)) + +import {value} from "./file3" +>value : Symbol(value, Decl(file2.ts, 4, 8)) + +export { + moduleCStar, +>moduleCStar : Symbol(moduleCStar, Decl(file2.ts, 6, 8)) + + moduleC, +>moduleC : Symbol(moduleC, Decl(file2.ts, 7, 16)) + + value +>value : Symbol(value, Decl(file2.ts, 8, 12)) +} + +=== tests/cases/compiler/file3.ts === + +export var value = "youpi"; +>value : Symbol(value, Decl(file3.ts, 1, 10)) + +export default value; +>value : Symbol(value, Decl(file3.ts, 1, 10)) + +=== tests/cases/compiler/file4.ts === + +export var value2 = "v"; +>value2 : Symbol(value2, Decl(file4.ts, 1, 10)) + diff --git a/tests/baselines/reference/systemModule15.types b/tests/baselines/reference/systemModule15.types new file mode 100644 index 00000000000..502638dab93 --- /dev/null +++ b/tests/baselines/reference/systemModule15.types @@ -0,0 +1,71 @@ +=== tests/cases/compiler/file1.ts === + + +import * as moduleB from "./file2" +>moduleB : typeof moduleB + +declare function use(v: any): void; +>use : (v: any) => void +>v : any + +use(moduleB.value); +>use(moduleB.value) : void +>use : (v: any) => void +>moduleB.value : string +>moduleB : typeof moduleB +>value : string + +use(moduleB.moduleC); +>use(moduleB.moduleC) : void +>use : (v: any) => void +>moduleB.moduleC : string +>moduleB : typeof moduleB +>moduleC : string + +use(moduleB.moduleCStar); +>use(moduleB.moduleCStar) : void +>use : (v: any) => void +>moduleB.moduleCStar : typeof +>moduleB : typeof moduleB +>moduleCStar : typeof + +=== tests/cases/compiler/file2.ts === + +import * as moduleCStar from "./file3" +>moduleCStar : typeof moduleCStar + +import {value2} from "./file4" +>value2 : string + +import moduleC from "./file3" +>moduleC : string + +import {value} from "./file3" +>value : string + +export { + moduleCStar, +>moduleCStar : typeof moduleCStar + + moduleC, +>moduleC : string + + value +>value : string +} + +=== tests/cases/compiler/file3.ts === + +export var value = "youpi"; +>value : string +>"youpi" : string + +export default value; +>value : string + +=== tests/cases/compiler/file4.ts === + +export var value2 = "v"; +>value2 : string +>"v" : string + diff --git a/tests/baselines/reference/systemModule16.errors.txt b/tests/baselines/reference/systemModule16.errors.txt new file mode 100644 index 00000000000..8c79c9218e4 --- /dev/null +++ b/tests/baselines/reference/systemModule16.errors.txt @@ -0,0 +1,33 @@ +tests/cases/compiler/systemModule16.ts(2,20): error TS2307: Cannot find module 'foo'. +tests/cases/compiler/systemModule16.ts(3,20): error TS2307: Cannot find module 'bar'. +tests/cases/compiler/systemModule16.ts(4,15): error TS2307: Cannot find module 'foo'. +tests/cases/compiler/systemModule16.ts(5,15): error TS2307: Cannot find module 'bar'. +tests/cases/compiler/systemModule16.ts(8,32): error TS2307: Cannot find module 'foo'. +tests/cases/compiler/systemModule16.ts(9,32): error TS2307: Cannot find module 'bar'. + + +==== tests/cases/compiler/systemModule16.ts (6 errors) ==== + + import * as x from "foo"; + ~~~~~ +!!! error TS2307: Cannot find module 'foo'. + import * as y from "bar"; + ~~~~~ +!!! error TS2307: Cannot find module 'bar'. + export * from "foo"; + ~~~~~ +!!! error TS2307: Cannot find module 'foo'. + export * from "bar" + ~~~~~ +!!! error TS2307: Cannot find module 'bar'. + export {x} + export {y} + import {a1, b1, c1 as d1} from "foo"; + ~~~~~ +!!! error TS2307: Cannot find module 'foo'. + export {a2, b2, c2 as d2} from "bar"; + ~~~~~ +!!! error TS2307: Cannot find module 'bar'. + + x,y,a1,b1,d1; + \ No newline at end of file diff --git a/tests/baselines/reference/systemModule16.js b/tests/baselines/reference/systemModule16.js new file mode 100644 index 00000000000..0c53275cdd8 --- /dev/null +++ b/tests/baselines/reference/systemModule16.js @@ -0,0 +1,54 @@ +//// [systemModule16.ts] + +import * as x from "foo"; +import * as y from "bar"; +export * from "foo"; +export * from "bar" +export {x} +export {y} +import {a1, b1, c1 as d1} from "foo"; +export {a2, b2, c2 as d2} from "bar"; + +x,y,a1,b1,d1; + + +//// [systemModule16.js] +System.register(["foo", "bar"], function(exports_1) { + var x, y, foo_1; + var exportedNames_1 = { + 'x': true, + 'y': true, + 'a2': true, + 'b2': true, + 'd2': true + }; + function exportStar_1(m) { + var exports = {}; + for(var n in m) { + if (n !== "default"&& !exportedNames_1.hasOwnProperty(n)) exports[n] = m[n]; + } + exports_1(exports); + } + return { + setters:[ + function (x_1) { + x = x_1; + exportStar_1(x_1); + foo_1 = x_1; + }, + function (y_1) { + y = y_1; + exportStar_1(y_1); + var reexports_1 = {}; + reexports_1["a2"] = y_1["a2"]; + reexports_1["b2"] = y_1["b2"]; + reexports_1["d2"] = y_1["c2"]; + exports_1(reexports_1); + }], + execute: function() { + exports_1("x", x); + exports_1("y", y); + x, y, foo_1.a1, foo_1.b1, foo_1.c1; + } + } +}); diff --git a/tests/baselines/reference/systemModule9.js b/tests/baselines/reference/systemModule9.js index c282a47b686..d7913f2f8b7 100644 --- a/tests/baselines/reference/systemModule9.js +++ b/tests/baselines/reference/systemModule9.js @@ -38,24 +38,24 @@ System.register(['file1', 'file2', 'file3', 'file4', 'file5', 'file6', 'file7'], } return { setters:[ - function (_ns) { - ns = _ns; + function (ns_1) { + ns = ns_1; }, - function (_file2_1) { - file2_1 = _file2_1; + function (file2_1_1) { + file2_1 = file2_1_1; }, - function (_file3_1) { - file3_1 = _file3_1; + function (file3_1_1) { + file3_1 = file3_1_1; }, - function (_) {}, - function (_file5_1) { - file5_1 = _file5_1; + function (_1) {}, + function (file5_1_1) { + file5_1 = file5_1_1; }, - function (_ns3) { - ns3 = _ns3; + function (ns3_1) { + ns3 = ns3_1; }, - function (_file7_1) { - exportStar_1(_file7_1); + function (file7_1_1) { + exportStar_1(file7_1_1); }], execute: function() { ns.f(); diff --git a/tests/baselines/reference/systemModuleWithSuperClass.js b/tests/baselines/reference/systemModuleWithSuperClass.js index 3484606ee0e..9d1e87fbc66 100644 --- a/tests/baselines/reference/systemModuleWithSuperClass.js +++ b/tests/baselines/reference/systemModuleWithSuperClass.js @@ -38,8 +38,8 @@ System.register(['./foo'], function(exports_1) { var Bar; return { setters:[ - function (_foo_1) { - foo_1 = _foo_1; + function (foo_1_1) { + foo_1 = foo_1_1; }], execute: function() { Bar = (function (_super) { diff --git a/tests/cases/compiler/systemModule15.ts b/tests/cases/compiler/systemModule15.ts new file mode 100644 index 00000000000..2c29f0a5d20 --- /dev/null +++ b/tests/cases/compiler/systemModule15.ts @@ -0,0 +1,34 @@ +// @module: system +// @isolatedModules: true + +// @filename: file1.ts + +import * as moduleB from "./file2" + +declare function use(v: any): void; + +use(moduleB.value); +use(moduleB.moduleC); +use(moduleB.moduleCStar); + +// @filename: file2.ts + +import * as moduleCStar from "./file3" +import {value2} from "./file4" +import moduleC from "./file3" +import {value} from "./file3" + +export { + moduleCStar, + moduleC, + value +} + +// @filename: file3.ts + +export var value = "youpi"; +export default value; + +// @filename: file4.ts + +export var value2 = "v"; \ No newline at end of file diff --git a/tests/cases/compiler/systemModule16.ts b/tests/cases/compiler/systemModule16.ts new file mode 100644 index 00000000000..ba64bd32b59 --- /dev/null +++ b/tests/cases/compiler/systemModule16.ts @@ -0,0 +1,13 @@ +// @module: system +// @isolatedModules: true + +import * as x from "foo"; +import * as y from "bar"; +export * from "foo"; +export * from "bar" +export {x} +export {y} +import {a1, b1, c1 as d1} from "foo"; +export {a2, b2, c2 as d2} from "bar"; + +x,y,a1,b1,d1; From d58ec43b3f0cddec1fbb9c2b6d9c275d24da21ba Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Thu, 6 Aug 2015 16:43:15 -0700 Subject: [PATCH 58/93] Fix #4159: look up the type alias paramter within the context of the parent type alias declaration --- src/compiler/declarationEmitter.ts | 3 +++ .../reference/typeAliasDeclarationEmit2.js | 13 +++++++++++++ .../reference/typeAliasDeclarationEmit2.symbols | 8 ++++++++ .../reference/typeAliasDeclarationEmit2.types | 8 ++++++++ tests/cases/compiler/typeAliasDeclarationEmit2.ts | 5 +++++ 5 files changed, 37 insertions(+) create mode 100644 tests/baselines/reference/typeAliasDeclarationEmit2.js create mode 100644 tests/baselines/reference/typeAliasDeclarationEmit2.symbols create mode 100644 tests/baselines/reference/typeAliasDeclarationEmit2.types create mode 100644 tests/cases/compiler/typeAliasDeclarationEmit2.ts diff --git a/src/compiler/declarationEmitter.ts b/src/compiler/declarationEmitter.ts index 5c44bf7b371..32a51de899e 100644 --- a/src/compiler/declarationEmitter.ts +++ b/src/compiler/declarationEmitter.ts @@ -750,6 +750,8 @@ namespace ts { } function writeTypeAliasDeclaration(node: TypeAliasDeclaration) { + let prevEnclosingDeclaration = enclosingDeclaration; + enclosingDeclaration = node; emitJsDocComments(node); emitModuleElementDeclarationFlags(node); write("type "); @@ -759,6 +761,7 @@ namespace ts { emitTypeWithNewGetSymbolAccessibilityDiagnostic(node.type, getTypeAliasDeclarationVisibilityError); write(";"); writeLine(); + enclosingDeclaration = prevEnclosingDeclaration; function getTypeAliasDeclarationVisibilityError(symbolAccesibilityResult: SymbolAccessiblityResult): SymbolAccessibilityDiagnostic { return { diff --git a/tests/baselines/reference/typeAliasDeclarationEmit2.js b/tests/baselines/reference/typeAliasDeclarationEmit2.js new file mode 100644 index 00000000000..4bb1bd3efd9 --- /dev/null +++ b/tests/baselines/reference/typeAliasDeclarationEmit2.js @@ -0,0 +1,13 @@ +//// [typeAliasDeclarationEmit2.ts] + +export type A = { value: a }; + +//// [typeAliasDeclarationEmit2.js] +define(["require", "exports"], function (require, exports) { +}); + + +//// [typeAliasDeclarationEmit2.d.ts] +export declare type A = { + value: a; +}; diff --git a/tests/baselines/reference/typeAliasDeclarationEmit2.symbols b/tests/baselines/reference/typeAliasDeclarationEmit2.symbols new file mode 100644 index 00000000000..aebd457d24e --- /dev/null +++ b/tests/baselines/reference/typeAliasDeclarationEmit2.symbols @@ -0,0 +1,8 @@ +=== tests/cases/compiler/typeAliasDeclarationEmit2.ts === + +export type A = { value: a }; +>A : Symbol(A, Decl(typeAliasDeclarationEmit2.ts, 0, 0)) +>a : Symbol(a, Decl(typeAliasDeclarationEmit2.ts, 1, 14)) +>value : Symbol(value, Decl(typeAliasDeclarationEmit2.ts, 1, 20)) +>a : Symbol(a, Decl(typeAliasDeclarationEmit2.ts, 1, 14)) + diff --git a/tests/baselines/reference/typeAliasDeclarationEmit2.types b/tests/baselines/reference/typeAliasDeclarationEmit2.types new file mode 100644 index 00000000000..bc8bd30935e --- /dev/null +++ b/tests/baselines/reference/typeAliasDeclarationEmit2.types @@ -0,0 +1,8 @@ +=== tests/cases/compiler/typeAliasDeclarationEmit2.ts === + +export type A = { value: a }; +>A : { value: a; } +>a : a +>value : a +>a : a + diff --git a/tests/cases/compiler/typeAliasDeclarationEmit2.ts b/tests/cases/compiler/typeAliasDeclarationEmit2.ts new file mode 100644 index 00000000000..33aecd7d5c9 --- /dev/null +++ b/tests/cases/compiler/typeAliasDeclarationEmit2.ts @@ -0,0 +1,5 @@ +// @target: ES5 +// @module: AMD +// @declaration: true + +export type A = { value: a }; \ No newline at end of file From 105979a89f8715b8894cd5b409ea2f41725c68ec Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 6 Aug 2015 17:17:20 -0700 Subject: [PATCH 59/93] Addressing CR feedback --- .../reference/unionTypeCallSignatures2.js | 35 ++++++-- .../unionTypeCallSignatures2.symbols | 59 +++++++++++--- .../reference/unionTypeCallSignatures2.types | 81 +++++++++++++++---- .../types/union/unionTypeCallSignatures2.ts | 19 ++++- 4 files changed, 157 insertions(+), 37 deletions(-) diff --git a/tests/baselines/reference/unionTypeCallSignatures2.js b/tests/baselines/reference/unionTypeCallSignatures2.js index 82383625902..7ec5180972a 100644 --- a/tests/baselines/reference/unionTypeCallSignatures2.js +++ b/tests/baselines/reference/unionTypeCallSignatures2.js @@ -19,14 +19,33 @@ interface C { (x: T[]): T[]; } -var f: A | B | C; -var n = f(42); // number -var s = f("abc"); // boolean | string | number -var a = f([true, false]); // boolean[] +var f1: A | B | C; +var n1 = f1(42); // number +var s1 = f1("abc"); // boolean | string | number +var a1 = f1([true, false]); // boolean[] + +var f2: C | B | A; +var n2 = f2(42); // number +var s2 = f2("abc"); // number | string | boolean +var a2 = f2([true, false]); // boolean[] + +var f3: B | A | C; +var n3 = f3(42); // number +var s3 = f3("abc"); // string | boolean | number +var a3 = f3([true, false]); // boolean[] + //// [unionTypeCallSignatures2.js] -var f; -var n = f(42); // number -var s = f("abc"); // boolean | string | number -var a = f([true, false]); // boolean[] +var f1; +var n1 = f1(42); // number +var s1 = f1("abc"); // boolean | string | number +var a1 = f1([true, false]); // boolean[] +var f2; +var n2 = f2(42); // number +var s2 = f2("abc"); // number | string | boolean +var a2 = f2([true, false]); // boolean[] +var f3; +var n3 = f3(42); // number +var s3 = f3("abc"); // string | boolean | number +var a3 = f3([true, false]); // boolean[] diff --git a/tests/baselines/reference/unionTypeCallSignatures2.symbols b/tests/baselines/reference/unionTypeCallSignatures2.symbols index 747fefb665d..35ba9464df0 100644 --- a/tests/baselines/reference/unionTypeCallSignatures2.symbols +++ b/tests/baselines/reference/unionTypeCallSignatures2.symbols @@ -58,21 +58,58 @@ interface C { >T : Symbol(T, Decl(unionTypeCallSignatures2.ts, 17, 5)) } -var f: A | B | C; ->f : Symbol(f, Decl(unionTypeCallSignatures2.ts, 20, 3)) +var f1: A | B | C; +>f1 : Symbol(f1, Decl(unionTypeCallSignatures2.ts, 20, 3)) >A : Symbol(A, Decl(unionTypeCallSignatures2.ts, 0, 0)) >B : Symbol(B, Decl(unionTypeCallSignatures2.ts, 5, 1)) >C : Symbol(C, Decl(unionTypeCallSignatures2.ts, 12, 1)) -var n = f(42); // number ->n : Symbol(n, Decl(unionTypeCallSignatures2.ts, 21, 3)) ->f : Symbol(f, Decl(unionTypeCallSignatures2.ts, 20, 3)) +var n1 = f1(42); // number +>n1 : Symbol(n1, Decl(unionTypeCallSignatures2.ts, 21, 3)) +>f1 : Symbol(f1, Decl(unionTypeCallSignatures2.ts, 20, 3)) -var s = f("abc"); // boolean | string | number ->s : Symbol(s, Decl(unionTypeCallSignatures2.ts, 22, 3)) ->f : Symbol(f, Decl(unionTypeCallSignatures2.ts, 20, 3)) +var s1 = f1("abc"); // boolean | string | number +>s1 : Symbol(s1, Decl(unionTypeCallSignatures2.ts, 22, 3)) +>f1 : Symbol(f1, Decl(unionTypeCallSignatures2.ts, 20, 3)) + +var a1 = f1([true, false]); // boolean[] +>a1 : Symbol(a1, Decl(unionTypeCallSignatures2.ts, 23, 3)) +>f1 : Symbol(f1, Decl(unionTypeCallSignatures2.ts, 20, 3)) + +var f2: C | B | A; +>f2 : Symbol(f2, Decl(unionTypeCallSignatures2.ts, 25, 3)) +>C : Symbol(C, Decl(unionTypeCallSignatures2.ts, 12, 1)) +>B : Symbol(B, Decl(unionTypeCallSignatures2.ts, 5, 1)) +>A : Symbol(A, Decl(unionTypeCallSignatures2.ts, 0, 0)) + +var n2 = f2(42); // number +>n2 : Symbol(n2, Decl(unionTypeCallSignatures2.ts, 26, 3)) +>f2 : Symbol(f2, Decl(unionTypeCallSignatures2.ts, 25, 3)) + +var s2 = f2("abc"); // number | string | boolean +>s2 : Symbol(s2, Decl(unionTypeCallSignatures2.ts, 27, 3)) +>f2 : Symbol(f2, Decl(unionTypeCallSignatures2.ts, 25, 3)) + +var a2 = f2([true, false]); // boolean[] +>a2 : Symbol(a2, Decl(unionTypeCallSignatures2.ts, 28, 3)) +>f2 : Symbol(f2, Decl(unionTypeCallSignatures2.ts, 25, 3)) + +var f3: B | A | C; +>f3 : Symbol(f3, Decl(unionTypeCallSignatures2.ts, 30, 3)) +>B : Symbol(B, Decl(unionTypeCallSignatures2.ts, 5, 1)) +>A : Symbol(A, Decl(unionTypeCallSignatures2.ts, 0, 0)) +>C : Symbol(C, Decl(unionTypeCallSignatures2.ts, 12, 1)) + +var n3 = f3(42); // number +>n3 : Symbol(n3, Decl(unionTypeCallSignatures2.ts, 31, 3)) +>f3 : Symbol(f3, Decl(unionTypeCallSignatures2.ts, 30, 3)) + +var s3 = f3("abc"); // string | boolean | number +>s3 : Symbol(s3, Decl(unionTypeCallSignatures2.ts, 32, 3)) +>f3 : Symbol(f3, Decl(unionTypeCallSignatures2.ts, 30, 3)) + +var a3 = f3([true, false]); // boolean[] +>a3 : Symbol(a3, Decl(unionTypeCallSignatures2.ts, 33, 3)) +>f3 : Symbol(f3, Decl(unionTypeCallSignatures2.ts, 30, 3)) -var a = f([true, false]); // boolean[] ->a : Symbol(a, Decl(unionTypeCallSignatures2.ts, 23, 3)) ->f : Symbol(f, Decl(unionTypeCallSignatures2.ts, 20, 3)) diff --git a/tests/baselines/reference/unionTypeCallSignatures2.types b/tests/baselines/reference/unionTypeCallSignatures2.types index 8a4b80d6ee3..64295c1b452 100644 --- a/tests/baselines/reference/unionTypeCallSignatures2.types +++ b/tests/baselines/reference/unionTypeCallSignatures2.types @@ -58,29 +58,82 @@ interface C { >T : T } -var f: A | B | C; ->f : A | B | C +var f1: A | B | C; +>f1 : A | B | C >A : A >B : B >C : C -var n = f(42); // number ->n : number ->f(42) : number ->f : A | B | C +var n1 = f1(42); // number +>n1 : number +>f1(42) : number +>f1 : A | B | C >42 : number -var s = f("abc"); // boolean | string | number ->s : boolean | string | number ->f("abc") : boolean | string | number ->f : A | B | C +var s1 = f1("abc"); // boolean | string | number +>s1 : boolean | string | number +>f1("abc") : boolean | string | number +>f1 : A | B | C >"abc" : string -var a = f([true, false]); // boolean[] ->a : boolean[] ->f([true, false]) : boolean[] ->f : A | B | C +var a1 = f1([true, false]); // boolean[] +>a1 : boolean[] +>f1([true, false]) : boolean[] +>f1 : A | B | C >[true, false] : boolean[] >true : boolean >false : boolean +var f2: C | B | A; +>f2 : C | B | A +>C : C +>B : B +>A : A + +var n2 = f2(42); // number +>n2 : number +>f2(42) : number +>f2 : C | B | A +>42 : number + +var s2 = f2("abc"); // number | string | boolean +>s2 : number | string | boolean +>f2("abc") : number | string | boolean +>f2 : C | B | A +>"abc" : string + +var a2 = f2([true, false]); // boolean[] +>a2 : boolean[] +>f2([true, false]) : boolean[] +>f2 : C | B | A +>[true, false] : boolean[] +>true : boolean +>false : boolean + +var f3: B | A | C; +>f3 : B | A | C +>B : B +>A : A +>C : C + +var n3 = f3(42); // number +>n3 : number +>f3(42) : number +>f3 : B | A | C +>42 : number + +var s3 = f3("abc"); // string | boolean | number +>s3 : string | boolean | number +>f3("abc") : string | boolean | number +>f3 : B | A | C +>"abc" : string + +var a3 = f3([true, false]); // boolean[] +>a3 : boolean[] +>f3([true, false]) : boolean[] +>f3 : B | A | C +>[true, false] : boolean[] +>true : boolean +>false : boolean + + diff --git a/tests/cases/conformance/types/union/unionTypeCallSignatures2.ts b/tests/cases/conformance/types/union/unionTypeCallSignatures2.ts index 8095f649330..2fa5190cc35 100644 --- a/tests/cases/conformance/types/union/unionTypeCallSignatures2.ts +++ b/tests/cases/conformance/types/union/unionTypeCallSignatures2.ts @@ -18,7 +18,18 @@ interface C { (x: T[]): T[]; } -var f: A | B | C; -var n = f(42); // number -var s = f("abc"); // boolean | string | number -var a = f([true, false]); // boolean[] +var f1: A | B | C; +var n1 = f1(42); // number +var s1 = f1("abc"); // boolean | string | number +var a1 = f1([true, false]); // boolean[] + +var f2: C | B | A; +var n2 = f2(42); // number +var s2 = f2("abc"); // number | string | boolean +var a2 = f2([true, false]); // boolean[] + +var f3: B | A | C; +var n3 = f3(42); // number +var s3 = f3("abc"); // string | boolean | number +var a3 = f3([true, false]); // boolean[] + From 01667eff1c9f63828e5e99f424d7b5f27864259b Mon Sep 17 00:00:00 2001 From: Yui T Date: Thu, 6 Aug 2015 17:20:35 -0700 Subject: [PATCH 60/93] Preserve comment in arguments of call expression and object literal --- src/compiler/emitter.ts | 47 ++++++++++++++++++++++++++++++++++++--- src/compiler/utilities.ts | 18 +++------------ 2 files changed, 47 insertions(+), 18 deletions(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index cb5eb864660..d0947b35693 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -832,7 +832,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi write(", "); } } - emitNode(nodes[start + i]); + let node = nodes[start + i]; + // This emitting is to make sure we emit following comment properly + // ...(x, /comment1/ y)... + // ^ => node.pos + // "comment1" is not considered leading comment for node-y but rather + // considered as trailing comment of the previous node. + emitTrailingCommentsOfPosition(node.pos); + emitNode(node); leadingComma = true; } if (trailingComma) { @@ -1976,6 +1983,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitPropertyAssignment(node: PropertyDeclaration) { emit(node.name); write(": "); + // This is to ensure that we emit comment in the following case: + // For example: + // obj = { + // id: /comment1/ ()=>void + // } + // "comment1" is not considered to be leading comment for node.initializer + // but rather a trailing comment on the previous node. + emitTrailingCommentsOfPosition(node.initializer.pos); emit(node.initializer); } @@ -3617,8 +3632,22 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi return emitOnlyPinnedOrTripleSlashComments(node); } - if (node.kind !== SyntaxKind.MethodDeclaration && node.kind !== SyntaxKind.MethodSignature) { - // Methods will emit the comments as part of emitting method declaration + if (node.kind !== SyntaxKind.MethodDeclaration && node.kind !== SyntaxKind.MethodSignature && + node.parent && node.parent.kind !== SyntaxKind.PropertyAssignment && + node.parent.kind !== SyntaxKind.CallExpression) { + // 1. Methods will emit the comments as part of emitting method declaration + + // 2. If the function is a property of object literal, emitting leading-comments + // is done by emitNodeWithoutSourceMap which then call this function. + // In particular, we would like to avoid emit comments twice in following case: + // For example: + // var obj = { + // id: + // /*comment*/ () => void + // } + + // 3. If the function is an argument in call expression, emitting of comments will be + // taken care of in emit list of arguments inside of emitCallexpression emitLeadingComments(node); } @@ -6925,6 +6954,18 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi emitComments(currentSourceFile, writer, trailingComments, /*trailingSeparator*/ false, newLine, writeComment); } + /** + * Emit trailing comments at the position. The term trailing comment is used here to describe following comment: + * x, /comment1/ y + * ^ => pos; the function will emit "comment1" in the emitJS + */ + function emitTrailingCommentsOfPosition(pos: number) { + let trailingComments = filterComments(getTrailingCommentRanges(currentSourceFile.text, pos), /*onlyPinnedOrTripleSlashComments:*/ compilerOptions.removeComments); + + // trailing comments are emitted at space/*trailing comment1 */space/*trailing comment*/ + emitComments(currentSourceFile, writer, trailingComments, /*trailingSeparator*/ true, newLine, writeComment); + } + function emitLeadingCommentsOfPosition(pos: number) { let leadingComments: CommentRange[]; if (hasDetachedComments(pos)) { diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 312a3666757..5d24db35762 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -381,24 +381,12 @@ namespace ts { } export function getLeadingCommentRangesOfNode(node: Node, sourceFileOfNode: SourceFile) { - // If parameter/type parameter, the prev token trailing comments are part of this node too - if (node.kind === SyntaxKind.Parameter || node.kind === SyntaxKind.TypeParameter) { - // e.g. (/** blah */ a, /** blah */ b); - - // e.g.: ( - // /** blah */ a, - // /** blah */ b); - return concatenate( - getTrailingCommentRanges(sourceFileOfNode.text, node.pos), - getLeadingCommentRanges(sourceFileOfNode.text, node.pos)); - } - else { - return getLeadingCommentRanges(sourceFileOfNode.text, node.pos); - } + return getLeadingCommentRanges(sourceFileOfNode.text, node.pos); } export function getJsDocComments(node: Node, sourceFileOfNode: SourceFile) { - return filter(getLeadingCommentRangesOfNode(node, sourceFileOfNode), isJsDocComment); + let commentRanges = (node.kind === SyntaxKind.Parameter || node.kind === SyntaxKind.TypeParameter) ? concatenate(getTrailingCommentRanges(sourceFileOfNode.text, node.pos), getLeadingCommentRanges(sourceFileOfNode.text, node.pos)) : getLeadingCommentRangesOfNode(node, sourceFileOfNode); + return filter(commentRanges, isJsDocComment); function isJsDocComment(comment: CommentRange) { // True if the comment starts with '/**' but not if it is '/**/' From 1421c39d8ccf85b2fb7319834053705d1c18d6a9 Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Thu, 6 Aug 2015 17:27:43 -0700 Subject: [PATCH 61/93] Fixed assignability bug --- src/compiler/checker.ts | 67 ++++++++++++++++++++++++++++------------- src/compiler/types.ts | 4 +-- 2 files changed, 48 insertions(+), 23 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6a65743b648..25e763a7277 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5090,30 +5090,21 @@ namespace ts { let result = Ternary.True; let saveErrorInfo = errorInfo; - // Because the "abstractness" of a class is the same across all construct signatures - // (internally we are checking the corresponding declaration), it is enough to perform - // the check and report an error once over all pairs of source and target construct signatures. - let sourceSig = sourceSignatures[0]; - // Note that in an extends-clause, targetSignatures is stripped, so the check never proceeds. - let targetSig = targetSignatures[0]; - if (sourceSig && targetSig) { - let sourceErasedSignature = getErasedSignature(sourceSig); - let targetErasedSignature = getErasedSignature(targetSig); - let sourceReturnType = sourceErasedSignature && getReturnTypeOfSignature(sourceErasedSignature); - let targetReturnType = targetErasedSignature && getReturnTypeOfSignature(targetErasedSignature); + if (kind === SignatureKind.Construct) { + // Only want to compare the construct signatures for abstractness guarantees. + + // Because the "abstractness" of a class is the same across all construct signatures + // (internally we are checking the corresponding declaration), it is enough to perform + // the check and report an error once over all pairs of source and target construct signatures. + let sourceSig = sourceSignatures[0]; + // Note that in an extends-clause, targetSignatures is stripped, so the check never proceeds. + let targetSig = targetSignatures[0]; - let sourceReturnDecl = sourceReturnType && sourceReturnType.symbol && getDeclarationOfKind(sourceReturnType.symbol, SyntaxKind.ClassDeclaration); - let targetReturnDecl = targetReturnType && targetReturnType.symbol && getDeclarationOfKind(targetReturnType.symbol, SyntaxKind.ClassDeclaration); - let sourceIsAbstract = sourceReturnDecl && sourceReturnDecl.flags & NodeFlags.Abstract; - let targetIsAbstract = targetReturnDecl && targetReturnDecl.flags & NodeFlags.Abstract; - - if (sourceIsAbstract && !targetIsAbstract) { - if (reportErrors) { - reportError(Diagnostics.Cannot_assign_an_abstract_constructor_type_to_a_non_abstract_constructor_type); - } - return Ternary.False; + result &= abstractSignatureRelatedTo(source, sourceSig, target, targetSig); + if (result !== Ternary.True) { + return result; } } @@ -5137,6 +5128,40 @@ namespace ts { } } return result; + + function abstractSignatureRelatedTo(source: Type, sourceSig: Signature, target: Type, targetSig: Signature) { + if (sourceSig && targetSig) { + + let sourceDecl = getDeclarationOfKind(source.symbol, SyntaxKind.ClassDeclaration); + let targetDecl = getDeclarationOfKind(target.symbol, SyntaxKind.ClassDeclaration); + + if (!sourceDecl) { + // If the source object isn't itself a class declaration, it can be freely assigned, regardless + // of whether the constructed object is abstract or not. + return Ternary.True; + } + + let sourceErasedSignature = getErasedSignature(sourceSig); + let targetErasedSignature = getErasedSignature(targetSig); + + let sourceReturnType = sourceErasedSignature && getReturnTypeOfSignature(sourceErasedSignature); + let targetReturnType = targetErasedSignature && getReturnTypeOfSignature(targetErasedSignature); + + let sourceReturnDecl = sourceReturnType && sourceReturnType.symbol && getDeclarationOfKind(sourceReturnType.symbol, SyntaxKind.ClassDeclaration); + let targetReturnDecl = targetReturnType && targetReturnType.symbol && getDeclarationOfKind(targetReturnType.symbol, SyntaxKind.ClassDeclaration); + let sourceIsAbstract = sourceReturnDecl && sourceReturnDecl.flags & NodeFlags.Abstract; + let targetIsAbstract = targetReturnDecl && targetReturnDecl.flags & NodeFlags.Abstract; + + // abstract constructor functions are only + if (sourceIsAbstract && !(targetIsAbstract && targetDecl)) { + if (reportErrors) { + reportError(Diagnostics.Cannot_assign_an_abstract_constructor_type_to_a_non_abstract_constructor_type); + } + return Ternary.False; + } + } + return Ternary.True; + } } function signatureRelatedTo(source: Signature, target: Signature, reportErrors: boolean): Ternary { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index da43984ee13..d19ed62332e 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1786,10 +1786,10 @@ namespace ts { ObjectType = Class | Interface | Reference | Tuple | Anonymous, UnionOrIntersection = Union | Intersection, StructuredType = ObjectType | Union | Intersection, - /* @internal */ + /* @internal */ RequiresWidening = ContainsUndefinedOrNull | ContainsObjectLiteral, /* @internal */ - PropagatingFlags = ContainsUndefinedOrNull | ContainsObjectLiteral | ContainsAnyFunctionType + PropagatingFlags = ContainsUndefinedOrNull | ContainsObjectLiteral | ContainsAnyFunctionType } // Properties common to all types From a693e82e27c729c37f58d90a862abccdeda7451b Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Thu, 6 Aug 2015 17:27:52 -0700 Subject: [PATCH 62/93] Added test --- .../classAbstractAssignabilityConstructorFunction.ts | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractAssignabilityConstructorFunction.ts diff --git a/tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractAssignabilityConstructorFunction.ts b/tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractAssignabilityConstructorFunction.ts new file mode 100644 index 00000000000..4a6f6cc3d61 --- /dev/null +++ b/tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractAssignabilityConstructorFunction.ts @@ -0,0 +1,8 @@ +abstract class A { } + +// var AA: typeof A; +var AAA: new() => A; + +// AA = A; // okay +AAA = A; // error. +AAA = "asdf"; \ No newline at end of file From 8f18912d28f53d4a5b884e7455f0b0254751f949 Mon Sep 17 00:00:00 2001 From: Yui T Date: Thu, 6 Aug 2015 17:28:11 -0700 Subject: [PATCH 63/93] Add tests for preserving comments --- tests/baselines/reference/APISample_linter.js | 2 +- tests/baselines/reference/commentInMethodCall.js | 3 ++- .../baselines/reference/commentsBeforeFunctionExpression1.js | 2 +- tests/baselines/reference/commentsInterface.js | 2 +- .../baselines/reference/declFileObjectLiteralWithAccessors.js | 4 ++-- .../reference/declFileObjectLiteralWithOnlyGetter.js | 4 ++-- .../reference/declFileObjectLiteralWithOnlySetter.js | 2 +- tests/baselines/reference/parserindenter.js | 4 ++-- 8 files changed, 12 insertions(+), 11 deletions(-) diff --git a/tests/baselines/reference/APISample_linter.js b/tests/baselines/reference/APISample_linter.js index 9d44dfdc03e..4a467a60a84 100644 --- a/tests/baselines/reference/APISample_linter.js +++ b/tests/baselines/reference/APISample_linter.js @@ -112,7 +112,7 @@ exports.delint = delint; var fileNames = process.argv.slice(2); fileNames.forEach(function (fileName) { // Parse a file - var sourceFile = ts.createSourceFile(fileName, readFileSync(fileName).toString(), 2 /* ES6 */, true); + var sourceFile = ts.createSourceFile(fileName, readFileSync(fileName).toString(), 2 /* ES6 */, /*setParentNodes */ true); // delint it delint(sourceFile); }); diff --git a/tests/baselines/reference/commentInMethodCall.js b/tests/baselines/reference/commentInMethodCall.js index 4ad2fc552d7..4cbd4824a82 100644 --- a/tests/baselines/reference/commentInMethodCall.js +++ b/tests/baselines/reference/commentInMethodCall.js @@ -8,4 +8,5 @@ s.map(// do something //// [commentInMethodCall.js] //commment here var s; -s.map(function () { }); +s.map(// do something +function () { }); diff --git a/tests/baselines/reference/commentsBeforeFunctionExpression1.js b/tests/baselines/reference/commentsBeforeFunctionExpression1.js index 0e23722faf3..5b250b9c064 100644 --- a/tests/baselines/reference/commentsBeforeFunctionExpression1.js +++ b/tests/baselines/reference/commentsBeforeFunctionExpression1.js @@ -6,5 +6,5 @@ var v = { //// [commentsBeforeFunctionExpression1.js] var v = { - f: function (a) { return 0; } + f: /**own f*/ function (a) { return 0; } }; diff --git a/tests/baselines/reference/commentsInterface.js b/tests/baselines/reference/commentsInterface.js index bff79a02aa5..3deac9871f1 100644 --- a/tests/baselines/reference/commentsInterface.js +++ b/tests/baselines/reference/commentsInterface.js @@ -89,7 +89,7 @@ var i2_i_nc_fnfoo = i2_i.nc_fnfoo; var i2_i_nc_fnfoo_r = i2_i.nc_fnfoo(10); var i3_i; i3_i = { - f: function (/**i3_i a*/ a) { return "Hello" + a; }, + f: /**own f*/ function (/**i3_i a*/ a) { return "Hello" + a; }, l: this.f, /** own x*/ x: this.f(10), diff --git a/tests/baselines/reference/declFileObjectLiteralWithAccessors.js b/tests/baselines/reference/declFileObjectLiteralWithAccessors.js index 85897bc2c9d..7886736f7e4 100644 --- a/tests/baselines/reference/declFileObjectLiteralWithAccessors.js +++ b/tests/baselines/reference/declFileObjectLiteralWithAccessors.js @@ -20,8 +20,8 @@ function makePoint(x) { }; } ; -var point = makePoint(2); -var x = point.x; +var /*4*/ point = makePoint(2); +var /*2*/ x = point.x; point.x = 30; diff --git a/tests/baselines/reference/declFileObjectLiteralWithOnlyGetter.js b/tests/baselines/reference/declFileObjectLiteralWithOnlyGetter.js index dd39a30f7a2..8d79a576b06 100644 --- a/tests/baselines/reference/declFileObjectLiteralWithOnlyGetter.js +++ b/tests/baselines/reference/declFileObjectLiteralWithOnlyGetter.js @@ -16,8 +16,8 @@ function makePoint(x) { }; } ; -var point = makePoint(2); -var x = point.x; +var /*4*/ point = makePoint(2); +var /*2*/ x = point.x; //// [declFileObjectLiteralWithOnlyGetter.d.ts] diff --git a/tests/baselines/reference/declFileObjectLiteralWithOnlySetter.js b/tests/baselines/reference/declFileObjectLiteralWithOnlySetter.js index e219e885053..f7a48fe810c 100644 --- a/tests/baselines/reference/declFileObjectLiteralWithOnlySetter.js +++ b/tests/baselines/reference/declFileObjectLiteralWithOnlySetter.js @@ -17,7 +17,7 @@ function makePoint(x) { }; } ; -var point = makePoint(2); +var /*3*/ point = makePoint(2); point.x = 30; diff --git a/tests/baselines/reference/parserindenter.js b/tests/baselines/reference/parserindenter.js index 511e75ea135..a60eadc66a1 100644 --- a/tests/baselines/reference/parserindenter.js +++ b/tests/baselines/reference/parserindenter.js @@ -890,7 +890,7 @@ var Formatting; return result; }; Indenter.GetIndentSizeFromIndentText = function (indentText, editorOptions) { - return GetIndentSizeFromText(indentText, editorOptions, false); + return GetIndentSizeFromText(indentText, editorOptions, /*includeNonIndentChars:*/ false); }; Indenter.GetIndentSizeFromText = function (text, editorOptions, includeNonIndentChars) { var indentSize = 0; @@ -1174,7 +1174,7 @@ var Formatting; return null; var origIndentText = this.snapshot.GetText(new Span(indentEditInfo.OrigIndentPosition, indentEditInfo.OrigIndentLength())); var newIndentText = indentEditInfo.Indentation(); - var origIndentSize = Indenter.GetIndentSizeFromText(origIndentText, this.editorOptions, true); + var origIndentSize = Indenter.GetIndentSizeFromText(origIndentText, this.editorOptions, /*includeNonIndentChars*/ true); var newIndentSize = Indenter.GetIndentSizeFromIndentText(newIndentText, this.editorOptions); // Check the child's position whether it's before the parent position // if so indent the child based on the first token on the line as opposed to the parent position From e8497d3d8a78a37c883c3df826648656962abbdd Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Thu, 6 Aug 2015 17:28:16 -0700 Subject: [PATCH 64/93] Updated baselines --- ...ssignabilityConstructorFunction.errors.txt | 19 +++++++++++++++++ ...bstractAssignabilityConstructorFunction.js | 21 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 tests/baselines/reference/classAbstractAssignabilityConstructorFunction.errors.txt create mode 100644 tests/baselines/reference/classAbstractAssignabilityConstructorFunction.js diff --git a/tests/baselines/reference/classAbstractAssignabilityConstructorFunction.errors.txt b/tests/baselines/reference/classAbstractAssignabilityConstructorFunction.errors.txt new file mode 100644 index 00000000000..c6c242396d8 --- /dev/null +++ b/tests/baselines/reference/classAbstractAssignabilityConstructorFunction.errors.txt @@ -0,0 +1,19 @@ +tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractAssignabilityConstructorFunction.ts(7,1): error TS2322: Type 'typeof A' is not assignable to type 'new () => A'. + Cannot assign an abstract constructor type to a non-abstract constructor type. +tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractAssignabilityConstructorFunction.ts(8,1): error TS2322: Type 'string' is not assignable to type 'new () => A'. + + +==== tests/cases/conformance/classes/classDeclarations/classAbstractKeyword/classAbstractAssignabilityConstructorFunction.ts (2 errors) ==== + abstract class A { } + + // var AA: typeof A; + var AAA: new() => A; + + // AA = A; // okay + AAA = A; // error. + ~~~ +!!! error TS2322: Type 'typeof A' is not assignable to type 'new () => A'. +!!! error TS2322: Cannot assign an abstract constructor type to a non-abstract constructor type. + AAA = "asdf"; + ~~~ +!!! error TS2322: Type 'string' is not assignable to type 'new () => A'. \ No newline at end of file diff --git a/tests/baselines/reference/classAbstractAssignabilityConstructorFunction.js b/tests/baselines/reference/classAbstractAssignabilityConstructorFunction.js new file mode 100644 index 00000000000..3d8fd404afc --- /dev/null +++ b/tests/baselines/reference/classAbstractAssignabilityConstructorFunction.js @@ -0,0 +1,21 @@ +//// [classAbstractAssignabilityConstructorFunction.ts] +abstract class A { } + +// var AA: typeof A; +var AAA: new() => A; + +// AA = A; // okay +AAA = A; // error. +AAA = "asdf"; + +//// [classAbstractAssignabilityConstructorFunction.js] +var A = (function () { + function A() { + } + return A; +})(); +// var AA: typeof A; +var AAA; +// AA = A; // okay +AAA = A; // error. +AAA = "asdf"; From 7de321d16777b525e652206b2243fe08ef6cc32b Mon Sep 17 00:00:00 2001 From: Yui T Date: Thu, 6 Aug 2015 17:28:30 -0700 Subject: [PATCH 65/93] Update baselines --- .../commentsArgumentsOfCallExpression1.js | 32 +++++++++++ ...commentsArgumentsOfCallExpression1.symbols | 31 +++++++++++ .../commentsArgumentsOfCallExpression1.types | 47 ++++++++++++++++ .../commentsArgumentsOfCallExpression2.js | 23 ++++++++ ...commentsArgumentsOfCallExpression2.symbols | 33 +++++++++++ .../commentsArgumentsOfCallExpression2.types | 55 +++++++++++++++++++ .../commentsOnPropertyOfObjectLiteral1.js | 29 ++++++++++ ...commentsOnPropertyOfObjectLiteral1.symbols | 37 +++++++++++++ .../commentsOnPropertyOfObjectLiteral1.types | 51 +++++++++++++++++ .../commentsArgumentsOfCallExpression1.ts | 15 +++++ .../commentsArgumentsOfCallExpression2.ts | 10 ++++ .../commentsOnPropertyOfObjectLiteral1.ts | 13 +++++ 12 files changed, 376 insertions(+) create mode 100644 tests/baselines/reference/commentsArgumentsOfCallExpression1.js create mode 100644 tests/baselines/reference/commentsArgumentsOfCallExpression1.symbols create mode 100644 tests/baselines/reference/commentsArgumentsOfCallExpression1.types create mode 100644 tests/baselines/reference/commentsArgumentsOfCallExpression2.js create mode 100644 tests/baselines/reference/commentsArgumentsOfCallExpression2.symbols create mode 100644 tests/baselines/reference/commentsArgumentsOfCallExpression2.types create mode 100644 tests/baselines/reference/commentsOnPropertyOfObjectLiteral1.js create mode 100644 tests/baselines/reference/commentsOnPropertyOfObjectLiteral1.symbols create mode 100644 tests/baselines/reference/commentsOnPropertyOfObjectLiteral1.types create mode 100644 tests/cases/compiler/commentsArgumentsOfCallExpression1.ts create mode 100644 tests/cases/compiler/commentsArgumentsOfCallExpression2.ts create mode 100644 tests/cases/compiler/commentsOnPropertyOfObjectLiteral1.ts diff --git a/tests/baselines/reference/commentsArgumentsOfCallExpression1.js b/tests/baselines/reference/commentsArgumentsOfCallExpression1.js new file mode 100644 index 00000000000..4e6d693c5c2 --- /dev/null +++ b/tests/baselines/reference/commentsArgumentsOfCallExpression1.js @@ -0,0 +1,32 @@ +//// [commentsArgumentsOfCallExpression1.ts] +function foo(/*c1*/ x: any) { } +foo(/*c2*/ 1); +foo(/*c3*/ function () { }); +foo( + /*c4*/ + () => { }); +foo( + /*c5*/ + /*c6*/ + () => { }); +foo(/*c7*/ + () => { }); +foo( + /*c7*/ + /*c8*/() => { }); + +//// [commentsArgumentsOfCallExpression1.js] +function foo(/*c1*/ x) { } +foo(/*c2*/ 1); +foo(/*c3*/ function () { }); +foo( +/*c4*/ +function () { }); +foo( +/*c5*/ +/*c6*/ +function () { }); +foo(/*c7*/ function () { }); +foo( +/*c7*/ +/*c8*/ function () { }); diff --git a/tests/baselines/reference/commentsArgumentsOfCallExpression1.symbols b/tests/baselines/reference/commentsArgumentsOfCallExpression1.symbols new file mode 100644 index 00000000000..9d8495f948c --- /dev/null +++ b/tests/baselines/reference/commentsArgumentsOfCallExpression1.symbols @@ -0,0 +1,31 @@ +=== tests/cases/compiler/commentsArgumentsOfCallExpression1.ts === +function foo(/*c1*/ x: any) { } +>foo : Symbol(foo, Decl(commentsArgumentsOfCallExpression1.ts, 0, 0)) +>x : Symbol(x, Decl(commentsArgumentsOfCallExpression1.ts, 0, 13)) + +foo(/*c2*/ 1); +>foo : Symbol(foo, Decl(commentsArgumentsOfCallExpression1.ts, 0, 0)) + +foo(/*c3*/ function () { }); +>foo : Symbol(foo, Decl(commentsArgumentsOfCallExpression1.ts, 0, 0)) + +foo( +>foo : Symbol(foo, Decl(commentsArgumentsOfCallExpression1.ts, 0, 0)) + + /*c4*/ + () => { }); +foo( +>foo : Symbol(foo, Decl(commentsArgumentsOfCallExpression1.ts, 0, 0)) + + /*c5*/ + /*c6*/ + () => { }); +foo(/*c7*/ +>foo : Symbol(foo, Decl(commentsArgumentsOfCallExpression1.ts, 0, 0)) + + () => { }); +foo( +>foo : Symbol(foo, Decl(commentsArgumentsOfCallExpression1.ts, 0, 0)) + + /*c7*/ + /*c8*/() => { }); diff --git a/tests/baselines/reference/commentsArgumentsOfCallExpression1.types b/tests/baselines/reference/commentsArgumentsOfCallExpression1.types new file mode 100644 index 00000000000..bcab3e3de36 --- /dev/null +++ b/tests/baselines/reference/commentsArgumentsOfCallExpression1.types @@ -0,0 +1,47 @@ +=== tests/cases/compiler/commentsArgumentsOfCallExpression1.ts === +function foo(/*c1*/ x: any) { } +>foo : (x: any) => void +>x : any + +foo(/*c2*/ 1); +>foo(/*c2*/ 1) : void +>foo : (x: any) => void +>1 : number + +foo(/*c3*/ function () { }); +>foo(/*c3*/ function () { }) : void +>foo : (x: any) => void +>function () { } : () => void + +foo( +>foo( /*c4*/ () => { }) : void +>foo : (x: any) => void + + /*c4*/ + () => { }); +>() => { } : () => void + +foo( +>foo( /*c5*/ /*c6*/ () => { }) : void +>foo : (x: any) => void + + /*c5*/ + /*c6*/ + () => { }); +>() => { } : () => void + +foo(/*c7*/ +>foo(/*c7*/ () => { }) : void +>foo : (x: any) => void + + () => { }); +>() => { } : () => void + +foo( +>foo( /*c7*/ /*c8*/() => { }) : void +>foo : (x: any) => void + + /*c7*/ + /*c8*/() => { }); +>() => { } : () => void + diff --git a/tests/baselines/reference/commentsArgumentsOfCallExpression2.js b/tests/baselines/reference/commentsArgumentsOfCallExpression2.js new file mode 100644 index 00000000000..a7065410ff4 --- /dev/null +++ b/tests/baselines/reference/commentsArgumentsOfCallExpression2.js @@ -0,0 +1,23 @@ +//// [commentsArgumentsOfCallExpression2.ts] +function foo(/*c1*/ x: any, /*d1*/ y: any,/*e1*/w?: any) { } +var a, b: any; +foo(/*c2*/ 1, /*d2*/ 1 + 2, /*e1*/ a + b); +foo(/*c3*/ function () { }, /*d2*/() => { }, /*e2*/ a + /*e3*/ b); +foo(/*c3*/ function () { }, /*d3*/() => { }, /*e3*/(a + b)); +foo( + /*c4*/ function () { }, + /*d4*/() => { }, + /*e4*/ + /*e5*/ "hello"); + +//// [commentsArgumentsOfCallExpression2.js] +function foo(/*c1*/ x, /*d1*/ y, /*e1*/ w) { } +var a, b; +foo(/*c2*/ 1, /*d2*/ 1 + 2, /*e1*/ a + b); +foo(/*c3*/ function () { }, /*d2*/ function () { }, /*e2*/ a + b); +foo(/*c3*/ function () { }, /*d3*/ function () { }, /*e3*/ (a + b)); +foo( +/*c4*/ function () { }, +/*d4*/ function () { }, +/*e4*/ +/*e5*/ "hello"); diff --git a/tests/baselines/reference/commentsArgumentsOfCallExpression2.symbols b/tests/baselines/reference/commentsArgumentsOfCallExpression2.symbols new file mode 100644 index 00000000000..59047dd46c3 --- /dev/null +++ b/tests/baselines/reference/commentsArgumentsOfCallExpression2.symbols @@ -0,0 +1,33 @@ +=== tests/cases/compiler/commentsArgumentsOfCallExpression2.ts === +function foo(/*c1*/ x: any, /*d1*/ y: any,/*e1*/w?: any) { } +>foo : Symbol(foo, Decl(commentsArgumentsOfCallExpression2.ts, 0, 0)) +>x : Symbol(x, Decl(commentsArgumentsOfCallExpression2.ts, 0, 13)) +>y : Symbol(y, Decl(commentsArgumentsOfCallExpression2.ts, 0, 27)) +>w : Symbol(w, Decl(commentsArgumentsOfCallExpression2.ts, 0, 42)) + +var a, b: any; +>a : Symbol(a, Decl(commentsArgumentsOfCallExpression2.ts, 1, 3)) +>b : Symbol(b, Decl(commentsArgumentsOfCallExpression2.ts, 1, 6)) + +foo(/*c2*/ 1, /*d2*/ 1 + 2, /*e1*/ a + b); +>foo : Symbol(foo, Decl(commentsArgumentsOfCallExpression2.ts, 0, 0)) +>a : Symbol(a, Decl(commentsArgumentsOfCallExpression2.ts, 1, 3)) +>b : Symbol(b, Decl(commentsArgumentsOfCallExpression2.ts, 1, 6)) + +foo(/*c3*/ function () { }, /*d2*/() => { }, /*e2*/ a + /*e3*/ b); +>foo : Symbol(foo, Decl(commentsArgumentsOfCallExpression2.ts, 0, 0)) +>a : Symbol(a, Decl(commentsArgumentsOfCallExpression2.ts, 1, 3)) +>b : Symbol(b, Decl(commentsArgumentsOfCallExpression2.ts, 1, 6)) + +foo(/*c3*/ function () { }, /*d3*/() => { }, /*e3*/(a + b)); +>foo : Symbol(foo, Decl(commentsArgumentsOfCallExpression2.ts, 0, 0)) +>a : Symbol(a, Decl(commentsArgumentsOfCallExpression2.ts, 1, 3)) +>b : Symbol(b, Decl(commentsArgumentsOfCallExpression2.ts, 1, 6)) + +foo( +>foo : Symbol(foo, Decl(commentsArgumentsOfCallExpression2.ts, 0, 0)) + + /*c4*/ function () { }, + /*d4*/() => { }, + /*e4*/ + /*e5*/ "hello"); diff --git a/tests/baselines/reference/commentsArgumentsOfCallExpression2.types b/tests/baselines/reference/commentsArgumentsOfCallExpression2.types new file mode 100644 index 00000000000..f0a10077e66 --- /dev/null +++ b/tests/baselines/reference/commentsArgumentsOfCallExpression2.types @@ -0,0 +1,55 @@ +=== tests/cases/compiler/commentsArgumentsOfCallExpression2.ts === +function foo(/*c1*/ x: any, /*d1*/ y: any,/*e1*/w?: any) { } +>foo : (x: any, y: any, w?: any) => void +>x : any +>y : any +>w : any + +var a, b: any; +>a : any +>b : any + +foo(/*c2*/ 1, /*d2*/ 1 + 2, /*e1*/ a + b); +>foo(/*c2*/ 1, /*d2*/ 1 + 2, /*e1*/ a + b) : void +>foo : (x: any, y: any, w?: any) => void +>1 : number +>1 + 2 : number +>1 : number +>2 : number +>a + b : any +>a : any +>b : any + +foo(/*c3*/ function () { }, /*d2*/() => { }, /*e2*/ a + /*e3*/ b); +>foo(/*c3*/ function () { }, /*d2*/() => { }, /*e2*/ a + /*e3*/ b) : void +>foo : (x: any, y: any, w?: any) => void +>function () { } : () => void +>() => { } : () => void +>a + /*e3*/ b : any +>a : any +>b : any + +foo(/*c3*/ function () { }, /*d3*/() => { }, /*e3*/(a + b)); +>foo(/*c3*/ function () { }, /*d3*/() => { }, /*e3*/(a + b)) : void +>foo : (x: any, y: any, w?: any) => void +>function () { } : () => void +>() => { } : () => void +>(a + b) : any +>a + b : any +>a : any +>b : any + +foo( +>foo( /*c4*/ function () { }, /*d4*/() => { }, /*e4*/ /*e5*/ "hello") : void +>foo : (x: any, y: any, w?: any) => void + + /*c4*/ function () { }, +>function () { } : () => void + + /*d4*/() => { }, +>() => { } : () => void + + /*e4*/ + /*e5*/ "hello"); +>"hello" : string + diff --git a/tests/baselines/reference/commentsOnPropertyOfObjectLiteral1.js b/tests/baselines/reference/commentsOnPropertyOfObjectLiteral1.js new file mode 100644 index 00000000000..fa7790443ac --- /dev/null +++ b/tests/baselines/reference/commentsOnPropertyOfObjectLiteral1.js @@ -0,0 +1,29 @@ +//// [commentsOnPropertyOfObjectLiteral1.ts] +var resolve = { + id: /*! @ngInject */ (details: any) => details.id, + id1: /* c1 */ "hello", + id2: + /*! @ngInject */ (details: any) => details.id, + id3: + /*! @ngInject */ + (details: any) => details.id, + id4: + /*! @ngInject */ + /* C2 */ + (details: any) => details.id, +}; + +//// [commentsOnPropertyOfObjectLiteral1.js] +var resolve = { + id: /*! @ngInject */ function (details) { return details.id; }, + id1: /* c1 */ "hello", + id2: + /*! @ngInject */ function (details) { return details.id; }, + id3: + /*! @ngInject */ + function (details) { return details.id; }, + id4: + /*! @ngInject */ + /* C2 */ + function (details) { return details.id; } +}; diff --git a/tests/baselines/reference/commentsOnPropertyOfObjectLiteral1.symbols b/tests/baselines/reference/commentsOnPropertyOfObjectLiteral1.symbols new file mode 100644 index 00000000000..b48c1fb982c --- /dev/null +++ b/tests/baselines/reference/commentsOnPropertyOfObjectLiteral1.symbols @@ -0,0 +1,37 @@ +=== tests/cases/compiler/commentsOnPropertyOfObjectLiteral1.ts === +var resolve = { +>resolve : Symbol(resolve, Decl(commentsOnPropertyOfObjectLiteral1.ts, 0, 3)) + + id: /*! @ngInject */ (details: any) => details.id, +>id : Symbol(id, Decl(commentsOnPropertyOfObjectLiteral1.ts, 0, 15)) +>details : Symbol(details, Decl(commentsOnPropertyOfObjectLiteral1.ts, 1, 26)) +>details : Symbol(details, Decl(commentsOnPropertyOfObjectLiteral1.ts, 1, 26)) + + id1: /* c1 */ "hello", +>id1 : Symbol(id1, Decl(commentsOnPropertyOfObjectLiteral1.ts, 1, 54)) + + id2: +>id2 : Symbol(id2, Decl(commentsOnPropertyOfObjectLiteral1.ts, 2, 26)) + + /*! @ngInject */ (details: any) => details.id, +>details : Symbol(details, Decl(commentsOnPropertyOfObjectLiteral1.ts, 4, 26)) +>details : Symbol(details, Decl(commentsOnPropertyOfObjectLiteral1.ts, 4, 26)) + + id3: +>id3 : Symbol(id3, Decl(commentsOnPropertyOfObjectLiteral1.ts, 4, 54)) + + /*! @ngInject */ + (details: any) => details.id, +>details : Symbol(details, Decl(commentsOnPropertyOfObjectLiteral1.ts, 7, 5)) +>details : Symbol(details, Decl(commentsOnPropertyOfObjectLiteral1.ts, 7, 5)) + + id4: +>id4 : Symbol(id4, Decl(commentsOnPropertyOfObjectLiteral1.ts, 7, 33)) + + /*! @ngInject */ + /* C2 */ + (details: any) => details.id, +>details : Symbol(details, Decl(commentsOnPropertyOfObjectLiteral1.ts, 11, 5)) +>details : Symbol(details, Decl(commentsOnPropertyOfObjectLiteral1.ts, 11, 5)) + +}; diff --git a/tests/baselines/reference/commentsOnPropertyOfObjectLiteral1.types b/tests/baselines/reference/commentsOnPropertyOfObjectLiteral1.types new file mode 100644 index 00000000000..93ce87558d8 --- /dev/null +++ b/tests/baselines/reference/commentsOnPropertyOfObjectLiteral1.types @@ -0,0 +1,51 @@ +=== tests/cases/compiler/commentsOnPropertyOfObjectLiteral1.ts === +var resolve = { +>resolve : { id: (details: any) => any; id1: string; id2: (details: any) => any; id3: (details: any) => any; id4: (details: any) => any; } +>{ id: /*! @ngInject */ (details: any) => details.id, id1: /* c1 */ "hello", id2: /*! @ngInject */ (details: any) => details.id, id3: /*! @ngInject */ (details: any) => details.id, id4: /*! @ngInject */ /* C2 */ (details: any) => details.id,} : { id: (details: any) => any; id1: string; id2: (details: any) => any; id3: (details: any) => any; id4: (details: any) => any; } + + id: /*! @ngInject */ (details: any) => details.id, +>id : (details: any) => any +>(details: any) => details.id : (details: any) => any +>details : any +>details.id : any +>details : any +>id : any + + id1: /* c1 */ "hello", +>id1 : string +>"hello" : string + + id2: +>id2 : (details: any) => any + + /*! @ngInject */ (details: any) => details.id, +>(details: any) => details.id : (details: any) => any +>details : any +>details.id : any +>details : any +>id : any + + id3: +>id3 : (details: any) => any + + /*! @ngInject */ + (details: any) => details.id, +>(details: any) => details.id : (details: any) => any +>details : any +>details.id : any +>details : any +>id : any + + id4: +>id4 : (details: any) => any + + /*! @ngInject */ + /* C2 */ + (details: any) => details.id, +>(details: any) => details.id : (details: any) => any +>details : any +>details.id : any +>details : any +>id : any + +}; diff --git a/tests/cases/compiler/commentsArgumentsOfCallExpression1.ts b/tests/cases/compiler/commentsArgumentsOfCallExpression1.ts new file mode 100644 index 00000000000..4dfab371d62 --- /dev/null +++ b/tests/cases/compiler/commentsArgumentsOfCallExpression1.ts @@ -0,0 +1,15 @@ +function foo(/*c1*/ x: any) { } +foo(/*c2*/ 1); +foo(/*c3*/ function () { }); +foo( + /*c4*/ + () => { }); +foo( + /*c5*/ + /*c6*/ + () => { }); +foo(/*c7*/ + () => { }); +foo( + /*c7*/ + /*c8*/() => { }); \ No newline at end of file diff --git a/tests/cases/compiler/commentsArgumentsOfCallExpression2.ts b/tests/cases/compiler/commentsArgumentsOfCallExpression2.ts new file mode 100644 index 00000000000..65350880b5d --- /dev/null +++ b/tests/cases/compiler/commentsArgumentsOfCallExpression2.ts @@ -0,0 +1,10 @@ +function foo(/*c1*/ x: any, /*d1*/ y: any,/*e1*/w?: any) { } +var a, b: any; +foo(/*c2*/ 1, /*d2*/ 1 + 2, /*e1*/ a + b); +foo(/*c3*/ function () { }, /*d2*/() => { }, /*e2*/ a + /*e3*/ b); +foo(/*c3*/ function () { }, /*d3*/() => { }, /*e3*/(a + b)); +foo( + /*c4*/ function () { }, + /*d4*/() => { }, + /*e4*/ + /*e5*/ "hello"); \ No newline at end of file diff --git a/tests/cases/compiler/commentsOnPropertyOfObjectLiteral1.ts b/tests/cases/compiler/commentsOnPropertyOfObjectLiteral1.ts new file mode 100644 index 00000000000..6ecf7a754bd --- /dev/null +++ b/tests/cases/compiler/commentsOnPropertyOfObjectLiteral1.ts @@ -0,0 +1,13 @@ +var resolve = { + id: /*! @ngInject */ (details: any) => details.id, + id1: /* c1 */ "hello", + id2: + /*! @ngInject */ (details: any) => details.id, + id3: + /*! @ngInject */ + (details: any) => details.id, + id4: + /*! @ngInject */ + /* C2 */ + (details: any) => details.id, +}; \ No newline at end of file From cbb159770f1a60a718424df86f891559511f1904 Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Thu, 6 Aug 2015 17:43:06 -0700 Subject: [PATCH 66/93] fixed null de-reference --- src/compiler/checker.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 25e763a7277..77aebe9118a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5132,8 +5132,8 @@ namespace ts { function abstractSignatureRelatedTo(source: Type, sourceSig: Signature, target: Type, targetSig: Signature) { if (sourceSig && targetSig) { - let sourceDecl = getDeclarationOfKind(source.symbol, SyntaxKind.ClassDeclaration); - let targetDecl = getDeclarationOfKind(target.symbol, SyntaxKind.ClassDeclaration); + let sourceDecl = source.symbol && getDeclarationOfKind(source.symbol, SyntaxKind.ClassDeclaration); + let targetDecl = target.symbol && getDeclarationOfKind(target.symbol, SyntaxKind.ClassDeclaration); if (!sourceDecl) { // If the source object isn't itself a class declaration, it can be freely assigned, regardless @@ -5152,8 +5152,8 @@ namespace ts { let sourceIsAbstract = sourceReturnDecl && sourceReturnDecl.flags & NodeFlags.Abstract; let targetIsAbstract = targetReturnDecl && targetReturnDecl.flags & NodeFlags.Abstract; - // abstract constructor functions are only if (sourceIsAbstract && !(targetIsAbstract && targetDecl)) { + // if target isn't a class-declaration type, then it can be new'd, so we forbid the assignment. if (reportErrors) { reportError(Diagnostics.Cannot_assign_an_abstract_constructor_type_to_a_non_abstract_constructor_type); } From 4cb789984c65618c0a748d034a00f37158d72aae Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Fri, 7 Aug 2015 19:58:19 +0800 Subject: [PATCH 67/93] Adds columns and rows properties to process.stdout --- src/server/node.d.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/server/node.d.ts b/src/server/node.d.ts index 8f7237382e5..438b152a1f4 100644 --- a/src/server/node.d.ts +++ b/src/server/node.d.ts @@ -123,9 +123,14 @@ declare module NodeJS { export interface ReadWriteStream extends ReadableStream, WritableStream { } + interface WindowSize { + columns: number; + rows: number; + } + export interface Process extends EventEmitter { - stdout: WritableStream; - stderr: WritableStream; + stdout: WritableStream & WindowSize; + stderr: WritableStream & WindowSize; stdin: ReadableStream; argv: string[]; execPath: string; From 61b3a185ce6a6d72333cb64e24b91b218d5a9e1e Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 7 Aug 2015 08:03:59 -0700 Subject: [PATCH 68/93] Making partial signature matching more inclusive --- src/compiler/checker.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index c5c51f88b04..fd6b1f45da4 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5390,14 +5390,12 @@ namespace ts { if (source === target) { return Ternary.True; } - if (source.minArgumentCount !== target.minArgumentCount) { - return Ternary.False; - } if (source.parameters.length !== target.parameters.length || + source.minArgumentCount !== target.minArgumentCount || source.hasRestParameter !== target.hasRestParameter) { if (!partialMatch || - source.parameters.length < target.parameters.length || - target.hasRestParameter) { + source.parameters.length < target.parameters.length && !source.hasRestParameter || + source.minArgumentCount > target.minArgumentCount) { return Ternary.False; } } From d372eb4ef5ab0dd4567b5450683a6ef61b7fdc24 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 7 Aug 2015 08:06:10 -0700 Subject: [PATCH 69/93] Adding new test --- .../reference/unionTypeCallSignatures3.js | 39 +++++++++++++++ .../unionTypeCallSignatures3.symbols | 46 ++++++++++++++++++ .../reference/unionTypeCallSignatures3.types | 48 +++++++++++++++++++ .../types/union/unionTypeCallSignatures3.ts | 11 +++++ 4 files changed, 144 insertions(+) create mode 100644 tests/baselines/reference/unionTypeCallSignatures3.js create mode 100644 tests/baselines/reference/unionTypeCallSignatures3.symbols create mode 100644 tests/baselines/reference/unionTypeCallSignatures3.types create mode 100644 tests/cases/conformance/types/union/unionTypeCallSignatures3.ts diff --git a/tests/baselines/reference/unionTypeCallSignatures3.js b/tests/baselines/reference/unionTypeCallSignatures3.js new file mode 100644 index 00000000000..2dae152e474 --- /dev/null +++ b/tests/baselines/reference/unionTypeCallSignatures3.js @@ -0,0 +1,39 @@ +//// [unionTypeCallSignatures3.ts] +function f1(s: string) { } +function f2(s?: string) { } +function f3(...s: string[]) { } +function f4(s: string, s2?: string) { } +function f5(s?: string, n?: number) { } +function f6(s?: string, ...n: number[]) { } +function f7(s: string, ...sRest: string[]) { } + +var fUnion: typeof f1 | typeof f2 | typeof f3 | typeof f4 | typeof f5 | typeof f6 | typeof f7; + +fUnion(""); // All constituents can be called by passing a single string. + + +//// [unionTypeCallSignatures3.js] +function f1(s) { } +function f2(s) { } +function f3() { + var s = []; + for (var _i = 0; _i < arguments.length; _i++) { + s[_i - 0] = arguments[_i]; + } +} +function f4(s, s2) { } +function f5(s, n) { } +function f6(s) { + var n = []; + for (var _i = 1; _i < arguments.length; _i++) { + n[_i - 1] = arguments[_i]; + } +} +function f7(s) { + var sRest = []; + for (var _i = 1; _i < arguments.length; _i++) { + sRest[_i - 1] = arguments[_i]; + } +} +var fUnion; +fUnion(""); // All constituents can be called by passing a single string. diff --git a/tests/baselines/reference/unionTypeCallSignatures3.symbols b/tests/baselines/reference/unionTypeCallSignatures3.symbols new file mode 100644 index 00000000000..45dffe2d821 --- /dev/null +++ b/tests/baselines/reference/unionTypeCallSignatures3.symbols @@ -0,0 +1,46 @@ +=== tests/cases/conformance/types/union/unionTypeCallSignatures3.ts === +function f1(s: string) { } +>f1 : Symbol(f1, Decl(unionTypeCallSignatures3.ts, 0, 0)) +>s : Symbol(s, Decl(unionTypeCallSignatures3.ts, 0, 12)) + +function f2(s?: string) { } +>f2 : Symbol(f2, Decl(unionTypeCallSignatures3.ts, 0, 26)) +>s : Symbol(s, Decl(unionTypeCallSignatures3.ts, 1, 12)) + +function f3(...s: string[]) { } +>f3 : Symbol(f3, Decl(unionTypeCallSignatures3.ts, 1, 27)) +>s : Symbol(s, Decl(unionTypeCallSignatures3.ts, 2, 12)) + +function f4(s: string, s2?: string) { } +>f4 : Symbol(f4, Decl(unionTypeCallSignatures3.ts, 2, 31)) +>s : Symbol(s, Decl(unionTypeCallSignatures3.ts, 3, 12)) +>s2 : Symbol(s2, Decl(unionTypeCallSignatures3.ts, 3, 22)) + +function f5(s?: string, n?: number) { } +>f5 : Symbol(f5, Decl(unionTypeCallSignatures3.ts, 3, 39)) +>s : Symbol(s, Decl(unionTypeCallSignatures3.ts, 4, 12)) +>n : Symbol(n, Decl(unionTypeCallSignatures3.ts, 4, 23)) + +function f6(s?: string, ...n: number[]) { } +>f6 : Symbol(f6, Decl(unionTypeCallSignatures3.ts, 4, 39)) +>s : Symbol(s, Decl(unionTypeCallSignatures3.ts, 5, 12)) +>n : Symbol(n, Decl(unionTypeCallSignatures3.ts, 5, 23)) + +function f7(s: string, ...sRest: string[]) { } +>f7 : Symbol(f7, Decl(unionTypeCallSignatures3.ts, 5, 43)) +>s : Symbol(s, Decl(unionTypeCallSignatures3.ts, 6, 12)) +>sRest : Symbol(sRest, Decl(unionTypeCallSignatures3.ts, 6, 22)) + +var fUnion: typeof f1 | typeof f2 | typeof f3 | typeof f4 | typeof f5 | typeof f6 | typeof f7; +>fUnion : Symbol(fUnion, Decl(unionTypeCallSignatures3.ts, 8, 3)) +>f1 : Symbol(f1, Decl(unionTypeCallSignatures3.ts, 0, 0)) +>f2 : Symbol(f2, Decl(unionTypeCallSignatures3.ts, 0, 26)) +>f3 : Symbol(f3, Decl(unionTypeCallSignatures3.ts, 1, 27)) +>f4 : Symbol(f4, Decl(unionTypeCallSignatures3.ts, 2, 31)) +>f5 : Symbol(f5, Decl(unionTypeCallSignatures3.ts, 3, 39)) +>f6 : Symbol(f6, Decl(unionTypeCallSignatures3.ts, 4, 39)) +>f7 : Symbol(f7, Decl(unionTypeCallSignatures3.ts, 5, 43)) + +fUnion(""); // All constituents can be called by passing a single string. +>fUnion : Symbol(fUnion, Decl(unionTypeCallSignatures3.ts, 8, 3)) + diff --git a/tests/baselines/reference/unionTypeCallSignatures3.types b/tests/baselines/reference/unionTypeCallSignatures3.types new file mode 100644 index 00000000000..52aae993e4a --- /dev/null +++ b/tests/baselines/reference/unionTypeCallSignatures3.types @@ -0,0 +1,48 @@ +=== tests/cases/conformance/types/union/unionTypeCallSignatures3.ts === +function f1(s: string) { } +>f1 : (s: string) => void +>s : string + +function f2(s?: string) { } +>f2 : (s?: string) => void +>s : string + +function f3(...s: string[]) { } +>f3 : (...s: string[]) => void +>s : string[] + +function f4(s: string, s2?: string) { } +>f4 : (s: string, s2?: string) => void +>s : string +>s2 : string + +function f5(s?: string, n?: number) { } +>f5 : (s?: string, n?: number) => void +>s : string +>n : number + +function f6(s?: string, ...n: number[]) { } +>f6 : (s?: string, ...n: number[]) => void +>s : string +>n : number[] + +function f7(s: string, ...sRest: string[]) { } +>f7 : (s: string, ...sRest: string[]) => void +>s : string +>sRest : string[] + +var fUnion: typeof f1 | typeof f2 | typeof f3 | typeof f4 | typeof f5 | typeof f6 | typeof f7; +>fUnion : ((s: string) => void) | ((s?: string) => void) | ((...s: string[]) => void) | ((s: string, s2?: string) => void) | ((s?: string, n?: number) => void) | ((s?: string, ...n: number[]) => void) | ((s: string, ...sRest: string[]) => void) +>f1 : (s: string) => void +>f2 : (s?: string) => void +>f3 : (...s: string[]) => void +>f4 : (s: string, s2?: string) => void +>f5 : (s?: string, n?: number) => void +>f6 : (s?: string, ...n: number[]) => void +>f7 : (s: string, ...sRest: string[]) => void + +fUnion(""); // All constituents can be called by passing a single string. +>fUnion("") : void +>fUnion : ((s: string) => void) | ((s?: string) => void) | ((...s: string[]) => void) | ((s: string, s2?: string) => void) | ((s?: string, n?: number) => void) | ((s?: string, ...n: number[]) => void) | ((s: string, ...sRest: string[]) => void) +>"" : string + diff --git a/tests/cases/conformance/types/union/unionTypeCallSignatures3.ts b/tests/cases/conformance/types/union/unionTypeCallSignatures3.ts new file mode 100644 index 00000000000..8549315a319 --- /dev/null +++ b/tests/cases/conformance/types/union/unionTypeCallSignatures3.ts @@ -0,0 +1,11 @@ +function f1(s: string) { } +function f2(s?: string) { } +function f3(...s: string[]) { } +function f4(s: string, s2?: string) { } +function f5(s?: string, n?: number) { } +function f6(s?: string, ...n: number[]) { } +function f7(s: string, ...sRest: string[]) { } + +var fUnion: typeof f1 | typeof f2 | typeof f3 | typeof f4 | typeof f5 | typeof f6 | typeof f7; + +fUnion(""); // All constituents can be called by passing a single string. From 1a53a38fb08c8ab1be1994fbc1dbb9e249a4cc09 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 7 Aug 2015 08:06:19 -0700 Subject: [PATCH 70/93] Accepting new baselines --- .../unionTypeCallSignatures.errors.txt | 40 ++++++++----------- .../unionTypeConstructSignatures.errors.txt | 40 ++++++++----------- 2 files changed, 34 insertions(+), 46 deletions(-) diff --git a/tests/baselines/reference/unionTypeCallSignatures.errors.txt b/tests/baselines/reference/unionTypeCallSignatures.errors.txt index 0ec5644db1d..ebe38a589ee 100644 --- a/tests/baselines/reference/unionTypeCallSignatures.errors.txt +++ b/tests/baselines/reference/unionTypeCallSignatures.errors.txt @@ -12,27 +12,25 @@ tests/cases/conformance/types/union/unionTypeCallSignatures.ts(30,1): error TS23 tests/cases/conformance/types/union/unionTypeCallSignatures.ts(31,1): error TS2349: Cannot invoke an expression whose type lacks a call signature. tests/cases/conformance/types/union/unionTypeCallSignatures.ts(36,49): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. tests/cases/conformance/types/union/unionTypeCallSignatures.ts(37,12): error TS2346: Supplied parameters do not match any signature of call target. -tests/cases/conformance/types/union/unionTypeCallSignatures.ts(40,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. -tests/cases/conformance/types/union/unionTypeCallSignatures.ts(41,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. -tests/cases/conformance/types/union/unionTypeCallSignatures.ts(42,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. -tests/cases/conformance/types/union/unionTypeCallSignatures.ts(43,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(40,12): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(42,49): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(43,12): error TS2346: Supplied parameters do not match any signature of call target. tests/cases/conformance/types/union/unionTypeCallSignatures.ts(47,12): error TS2346: Supplied parameters do not match any signature of call target. tests/cases/conformance/types/union/unionTypeCallSignatures.ts(48,12): error TS2346: Supplied parameters do not match any signature of call target. tests/cases/conformance/types/union/unionTypeCallSignatures.ts(49,12): error TS2346: Supplied parameters do not match any signature of call target. tests/cases/conformance/types/union/unionTypeCallSignatures.ts(55,45): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. tests/cases/conformance/types/union/unionTypeCallSignatures.ts(56,12): error TS2346: Supplied parameters do not match any signature of call target. -tests/cases/conformance/types/union/unionTypeCallSignatures.ts(59,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. -tests/cases/conformance/types/union/unionTypeCallSignatures.ts(60,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. -tests/cases/conformance/types/union/unionTypeCallSignatures.ts(61,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. -tests/cases/conformance/types/union/unionTypeCallSignatures.ts(62,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. -tests/cases/conformance/types/union/unionTypeCallSignatures.ts(63,12): error TS2349: Cannot invoke an expression whose type lacks a call signature. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(59,12): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(61,12): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(62,45): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. +tests/cases/conformance/types/union/unionTypeCallSignatures.ts(63,12): error TS2346: Supplied parameters do not match any signature of call target. tests/cases/conformance/types/union/unionTypeCallSignatures.ts(67,12): error TS2346: Supplied parameters do not match any signature of call target. tests/cases/conformance/types/union/unionTypeCallSignatures.ts(68,12): error TS2346: Supplied parameters do not match any signature of call target. tests/cases/conformance/types/union/unionTypeCallSignatures.ts(69,12): error TS2346: Supplied parameters do not match any signature of call target. tests/cases/conformance/types/union/unionTypeCallSignatures.ts(70,12): error TS2346: Supplied parameters do not match any signature of call target. -==== tests/cases/conformance/types/union/unionTypeCallSignatures.ts (32 errors) ==== +==== tests/cases/conformance/types/union/unionTypeCallSignatures.ts (30 errors) ==== var numOrDate: number | Date; var strOrBoolean: string | boolean; var strOrNum: string | number; @@ -102,16 +100,14 @@ tests/cases/conformance/types/union/unionTypeCallSignatures.ts(70,12): error TS2 var unionWithOptionalParameter2: { (a: string, b?: number): string; } | { (a: string, b: number): number }; strOrNum = unionWithOptionalParameter2('hello'); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. +!!! error TS2346: Supplied parameters do not match any signature of call target. strOrNum = unionWithOptionalParameter2('hello', 10); // error no call signature - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. strOrNum = unionWithOptionalParameter2('hello', "hello"); // error no call signature - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. + ~~~~~~~ +!!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. strOrNum = unionWithOptionalParameter2(); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. +!!! error TS2346: Supplied parameters do not match any signature of call target. var unionWithOptionalParameter3: { (a: string, b?: number): string; } | { (a: string): number; }; strOrNum = unionWithOptionalParameter3('hello'); @@ -139,19 +135,17 @@ tests/cases/conformance/types/union/unionTypeCallSignatures.ts(70,12): error TS2 var unionWithRestParameter2: { (a: string, ...b: number[]): string; } | { (a: string, b: number): number }; strOrNum = unionWithRestParameter2('hello'); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. +!!! error TS2346: Supplied parameters do not match any signature of call target. strOrNum = unionWithRestParameter2('hello', 10); // error no call signature - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. strOrNum = unionWithRestParameter2('hello', 10, 11); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. +!!! error TS2346: Supplied parameters do not match any signature of call target. strOrNum = unionWithRestParameter2('hello', "hello"); // error no call signature - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. + ~~~~~~~ +!!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. strOrNum = unionWithRestParameter2(); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. +!!! error TS2346: Supplied parameters do not match any signature of call target. var unionWithRestParameter3: { (a: string, ...b: number[]): string; } | { (a: string): number }; strOrNum = unionWithRestParameter3('hello'); diff --git a/tests/baselines/reference/unionTypeConstructSignatures.errors.txt b/tests/baselines/reference/unionTypeConstructSignatures.errors.txt index 2710ce09850..0332aa61110 100644 --- a/tests/baselines/reference/unionTypeConstructSignatures.errors.txt +++ b/tests/baselines/reference/unionTypeConstructSignatures.errors.txt @@ -12,27 +12,25 @@ tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(30,1): error tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(31,1): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(36,53): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(37,12): error TS2346: Supplied parameters do not match any signature of call target. -tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(40,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. -tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(41,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. -tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(42,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. -tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(43,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(40,12): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(42,53): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(43,12): error TS2346: Supplied parameters do not match any signature of call target. tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(47,12): error TS2346: Supplied parameters do not match any signature of call target. tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(48,12): error TS2346: Supplied parameters do not match any signature of call target. tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(49,12): error TS2346: Supplied parameters do not match any signature of call target. tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(55,49): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(56,12): error TS2346: Supplied parameters do not match any signature of call target. -tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(59,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. -tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(60,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. -tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(61,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. -tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(62,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. -tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(63,12): error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(59,12): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(61,12): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(62,49): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. +tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(63,12): error TS2346: Supplied parameters do not match any signature of call target. tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(67,12): error TS2346: Supplied parameters do not match any signature of call target. tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(68,12): error TS2346: Supplied parameters do not match any signature of call target. tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(69,12): error TS2346: Supplied parameters do not match any signature of call target. tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(70,12): error TS2346: Supplied parameters do not match any signature of call target. -==== tests/cases/conformance/types/union/unionTypeConstructSignatures.ts (32 errors) ==== +==== tests/cases/conformance/types/union/unionTypeConstructSignatures.ts (30 errors) ==== var numOrDate: number | Date; var strOrBoolean: string | boolean; var strOrNum: string | number; @@ -102,16 +100,14 @@ tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(70,12): erro var unionWithOptionalParameter2: { new (a: string, b?: number): string; } | { new (a: string, b: number): number }; strOrNum = new unionWithOptionalParameter2('hello'); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +!!! error TS2346: Supplied parameters do not match any signature of call target. strOrNum = new unionWithOptionalParameter2('hello', 10); // error no call signature - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. strOrNum = new unionWithOptionalParameter2('hello', "hello"); // error no call signature - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. + ~~~~~~~ +!!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. strOrNum = new unionWithOptionalParameter2(); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +!!! error TS2346: Supplied parameters do not match any signature of call target. var unionWithOptionalParameter3: { new (a: string, b?: number): string; } | { new (a: string): number; }; strOrNum = new unionWithOptionalParameter3('hello'); // error no call signature @@ -139,19 +135,17 @@ tests/cases/conformance/types/union/unionTypeConstructSignatures.ts(70,12): erro var unionWithRestParameter2: { new (a: string, ...b: number[]): string; } | { new (a: string, b: number): number }; strOrNum = new unionWithRestParameter2('hello'); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +!!! error TS2346: Supplied parameters do not match any signature of call target. strOrNum = new unionWithRestParameter2('hello', 10); // error no call signature - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. strOrNum = new unionWithRestParameter2('hello', 10, 11); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +!!! error TS2346: Supplied parameters do not match any signature of call target. strOrNum = new unionWithRestParameter2('hello', "hello"); // error no call signature - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. + ~~~~~~~ +!!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. strOrNum = new unionWithRestParameter2(); // error no call signature ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature. +!!! error TS2346: Supplied parameters do not match any signature of call target. var unionWithRestParameter3: { new (a: string, ...b: number[]): string; } | { new (a: string): number }; strOrNum = new unionWithRestParameter3('hello'); // error no call signature From 410e4e4df7b5698312e323a63477c429cf4919d6 Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Fri, 7 Aug 2015 11:07:06 -0700 Subject: [PATCH 71/93] added a clarifying comment --- src/compiler/checker.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 77aebe9118a..7f09917ea1e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3474,8 +3474,10 @@ namespace ts { return emptyArray; } - // Return the signatures of the given kind in the given type. Creates synthetic union signatures when necessary and - // maps primitive types and type parameters are to their apparent types. + /** + * Return the signatures of the given kind in the given type. Creates synthetic union signatures when necessary and + * maps primitive types and type parameters are to their apparent types. + */ function getSignaturesOfType(type: Type, kind: SignatureKind): Signature[] { return getSignaturesOfStructuredType(getApparentType(type), kind); } @@ -5098,8 +5100,11 @@ namespace ts { // Because the "abstractness" of a class is the same across all construct signatures // (internally we are checking the corresponding declaration), it is enough to perform // the check and report an error once over all pairs of source and target construct signatures. - let sourceSig = sourceSignatures[0]; + // + // sourceSig and targetSig are (possibly) undefined. + // // Note that in an extends-clause, targetSignatures is stripped, so the check never proceeds. + let sourceSig = sourceSignatures[0]; let targetSig = targetSignatures[0]; result &= abstractSignatureRelatedTo(source, sourceSig, target, targetSig); From e9fa806c9ffd61569b9e081d4ab578f2ba3ea747 Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Fri, 7 Aug 2015 14:01:07 -0700 Subject: [PATCH 72/93] move helper and add capture of this --- src/compiler/utilities.ts | 8 -------- src/services/services.ts | 2 +- src/services/utilities.ts | 8 ++++++++ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 88a5322977d..312a3666757 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2092,14 +2092,6 @@ namespace ts { } return carriageReturnLineFeed; } - - /** - * The default is CRLF. - */ - export function getNewLineOrDefault(getNewLine?: () => string): string { - return getNewLine ? getNewLine() : carriageReturnLineFeed; - var x: number; - } } namespace ts { diff --git a/src/services/services.ts b/src/services/services.ts index bf777a9d653..6fe45a775ca 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -2528,7 +2528,7 @@ namespace ts { getCancellationToken: () => cancellationToken, getCanonicalFileName, useCaseSensitiveFileNames: () => useCaseSensitivefileNames, - getNewLine: () => getNewLineOrDefault(host.getNewLine), + getNewLine: () => host.getNewLine ? host.getNewLine() : carriageReturnLineFeed, getDefaultLibFileName: (options) => host.getDefaultLibFileName(options), writeFile: (fileName, data, writeByteOrderMark) => { }, getCurrentDirectory: () => host.getCurrentDirectory() diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 5f8859c815e..a1548fc3dd4 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -625,6 +625,14 @@ namespace ts { return displayPart(text, SymbolDisplayPartKind.text); } + const carriageReturnLineFeed = "\r\n"; + /** + * The default is CRLF. + */ + export function getNewLineOrDefaultFromHost(host: LanguageServiceHost) { + return host.getNewLine ? host.getNewLine() : carriageReturnLineFeed; + } + export function lineBreakPart() { return displayPart("\n", SymbolDisplayPartKind.lineBreak); } From f9c82ea2743a35ad5858f0f3ac16a5dfd6fbe523 Mon Sep 17 00:00:00 2001 From: Arthur Ozga Date: Fri, 7 Aug 2015 14:24:30 -0700 Subject: [PATCH 73/93] save files changed in refactoring --- src/services/services.ts | 2 +- src/services/shims.ts | 2 +- src/services/utilities.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/services/services.ts b/src/services/services.ts index 6fe45a775ca..d0bc5c96ec8 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -2528,7 +2528,7 @@ namespace ts { getCancellationToken: () => cancellationToken, getCanonicalFileName, useCaseSensitiveFileNames: () => useCaseSensitivefileNames, - getNewLine: () => host.getNewLine ? host.getNewLine() : carriageReturnLineFeed, + getNewLine: () => getNewLineOrDefaultFromHost(host), getDefaultLibFileName: (options) => host.getDefaultLibFileName(options), writeFile: (fileName, data, writeByteOrderMark) => { }, getCurrentDirectory: () => host.getCurrentDirectory() diff --git a/src/services/shims.ts b/src/services/shims.ts index 42247c31ece..d808f94a906 100644 --- a/src/services/shims.ts +++ b/src/services/shims.ts @@ -529,7 +529,7 @@ namespace ts { } private realizeDiagnostics(diagnostics: Diagnostic[]): { message: string; start: number; length: number; category: string; }[]{ - var newLine = getNewLineOrDefault(this.host.getNewLine); + var newLine = getNewLineOrDefaultFromHost(this.host); return ts.realizeDiagnostics(diagnostics, newLine); } diff --git a/src/services/utilities.ts b/src/services/utilities.ts index a1548fc3dd4..fb897851f05 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -629,7 +629,7 @@ namespace ts { /** * The default is CRLF. */ - export function getNewLineOrDefaultFromHost(host: LanguageServiceHost) { + export function getNewLineOrDefaultFromHost(host: LanguageServiceHost | LanguageServiceShimHost) { return host.getNewLine ? host.getNewLine() : carriageReturnLineFeed; } From 555297a62b6ba2026cb08e838a3e78b2221c772f Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Fri, 7 Aug 2015 15:46:36 -0700 Subject: [PATCH 74/93] Fix case where # occurs after > in JSX expression --- src/compiler/parser.ts | 67 +++++++++++---- .../reference/jsxAndTypeAssertion.js | 13 ++- tests/baselines/reference/jsxHash.js | 26 ++++++ tests/baselines/reference/jsxHash.symbols | 34 ++++++++ tests/baselines/reference/jsxHash.types | 86 +++++++++++++++++++ .../jsxInvalidEsprimaTestSuite.errors.txt | 8 +- .../reference/jsxInvalidEsprimaTestSuite.js | 12 +-- .../reference/tsxErrorRecovery1.errors.txt | 13 ++- .../baselines/reference/tsxErrorRecovery1.js | 8 +- tests/cases/compiler/jsxHash.tsx | 12 +++ 10 files changed, 237 insertions(+), 42 deletions(-) create mode 100644 tests/baselines/reference/jsxHash.js create mode 100644 tests/baselines/reference/jsxHash.symbols create mode 100644 tests/baselines/reference/jsxHash.types create mode 100644 tests/cases/compiler/jsxHash.tsx diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 10ebe86368d..ffd081f09d0 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -844,6 +844,10 @@ namespace ts { return token = scanner.scanJsxIdentifier(); } + function scanJsxText(): SyntaxKind { + return token = scanner.scanJsxToken(); + } + function speculationHelper(callback: () => T, isLookAhead: boolean): T { // Keep track of the state we'll need to rollback to if lookahead fails (or if the // caller asked us to always reset our state). @@ -913,9 +917,11 @@ namespace ts { return token > SyntaxKind.LastReservedWord; } - function parseExpected(kind: SyntaxKind, diagnosticMessage?: DiagnosticMessage): boolean { + function parseExpected(kind: SyntaxKind, diagnosticMessage?: DiagnosticMessage, advance = true): boolean { if (token === kind) { - nextToken(); + if (advance) { + nextToken(); + } return true; } @@ -929,6 +935,13 @@ namespace ts { return false; } + function parseOptionalWithoutAdvancing(t: SyntaxKind): boolean { + if (token === t) { + return true; + } + return false; + } + function parseOptional(t: SyntaxKind): boolean { if (token === t) { nextToken(); @@ -3178,7 +3191,7 @@ namespace ts { return parseTypeAssertion(); } if (lookAhead(nextTokenIsIdentifierOrKeyword)) { - return parseJsxElementOrSelfClosingElement(); + return parseJsxElementOrSelfClosingElement(/*inExpressionContext*/ true); } // Fall through default: @@ -3308,14 +3321,14 @@ namespace ts { return finishNode(node); } - function parseJsxElementOrSelfClosingElement(): JsxElement|JsxSelfClosingElement { - let opening = parseJsxOpeningOrSelfClosingElement(); + function parseJsxElementOrSelfClosingElement(inExpressionContext: boolean): JsxElement|JsxSelfClosingElement { + let opening = parseJsxOpeningOrSelfClosingElement(inExpressionContext); if (opening.kind === SyntaxKind.JsxOpeningElement) { let node = createNode(SyntaxKind.JsxElement, opening.pos); node.openingElement = opening; node.children = parseJsxChildren(node.openingElement.tagName); - node.closingElement = parseJsxClosingElement(); + node.closingElement = parseJsxClosingElement(inExpressionContext); return finishNode(node); } else { @@ -3336,9 +3349,9 @@ namespace ts { case SyntaxKind.JsxText: return parseJsxText(); case SyntaxKind.OpenBraceToken: - return parseJsxExpression(); + return parseJsxExpression(/*inExpression*/false); case SyntaxKind.LessThanToken: - return parseJsxElementOrSelfClosingElement(); + return parseJsxElementOrSelfClosingElement(/*inExpression*/false); } Debug.fail("Unknown JSX child kind " + token); } @@ -3368,7 +3381,7 @@ namespace ts { return result; } - function parseJsxOpeningOrSelfClosingElement(): JsxOpeningElement|JsxSelfClosingElement { + function parseJsxOpeningOrSelfClosingElement(inExpressionContext: boolean): JsxOpeningElement|JsxSelfClosingElement { let fullStart = scanner.getStartPos(); parseExpected(SyntaxKind.LessThanToken); @@ -3378,12 +3391,22 @@ namespace ts { let attributes = parseList(ParsingContext.JsxAttributes, parseJsxAttribute); let node: JsxOpeningLikeElement; - if (parseOptional(SyntaxKind.GreaterThanToken)) { + if (parseOptionalWithoutAdvancing(SyntaxKind.GreaterThanToken)) { + // Closing tag, so scan the immediately-following text with the JSX scanning instead + // of regular scanning to avoid treating illegal characters (e.g. '#') as immediate + // scanning errors node = createNode(SyntaxKind.JsxOpeningElement, fullStart); + scanJsxText(); } else { parseExpected(SyntaxKind.SlashToken); - parseExpected(SyntaxKind.GreaterThanToken); + if (inExpressionContext) { + parseExpected(SyntaxKind.GreaterThanToken); + } + else { + parseExpected(SyntaxKind.GreaterThanToken, /*diagnostic*/ undefined, /*advance*/ false); + scanJsxText(); + } node = createNode(SyntaxKind.JsxSelfClosingElement, fullStart); } @@ -3406,14 +3429,20 @@ namespace ts { return elementName; } - function parseJsxExpression(): JsxExpression { + function parseJsxExpression(inExpressionContext: boolean): JsxExpression { let node = createNode(SyntaxKind.JsxExpression); parseExpected(SyntaxKind.OpenBraceToken); if (token !== SyntaxKind.CloseBraceToken) { node.expression = parseExpression(); } - parseExpected(SyntaxKind.CloseBraceToken); + if(inExpressionContext) { + parseExpected(SyntaxKind.CloseBraceToken); + } + else { + parseExpected(SyntaxKind.CloseBraceToken, /*message*/ undefined, /*advance*/ false); + scanJsxText(); + } return finishNode(node); } @@ -3432,7 +3461,7 @@ namespace ts { node.initializer = parseLiteralNode(); break; default: - node.initializer = parseJsxExpression(); + node.initializer = parseJsxExpression(/*inExpressionContext*/ true); break; } } @@ -3448,11 +3477,17 @@ namespace ts { return finishNode(node); } - function parseJsxClosingElement(): JsxClosingElement { + function parseJsxClosingElement(inExpressionContext: boolean): JsxClosingElement { let node = createNode(SyntaxKind.JsxClosingElement); parseExpected(SyntaxKind.LessThanSlashToken); node.tagName = parseJsxElementName(); - parseExpected(SyntaxKind.GreaterThanToken); + if (inExpressionContext) { + parseExpected(SyntaxKind.GreaterThanToken); + } + else { + parseExpected(SyntaxKind.GreaterThanToken, /*diagnostic*/ undefined, /*advance*/ false); + scanJsxText(); + } return finishNode(node); } diff --git a/tests/baselines/reference/jsxAndTypeAssertion.js b/tests/baselines/reference/jsxAndTypeAssertion.js index 0b402b43de2..0a493006dc6 100644 --- a/tests/baselines/reference/jsxAndTypeAssertion.js +++ b/tests/baselines/reference/jsxAndTypeAssertion.js @@ -29,21 +29,18 @@ var foo = (function () { return foo; })(); var x; -x = {test}: }; +x = {test} }; x = ; -x = hello {} }; +x = hello {} } -x = }>hello}/>; +x = }>hello}/> -x = }>hello{}}; +x = }>hello{}} x = x, x = ; {{/foo/.test(x) ? : }} : -} - - -}}/>; +}}}/>; diff --git a/tests/baselines/reference/jsxHash.js b/tests/baselines/reference/jsxHash.js new file mode 100644 index 00000000000..04409a56eea --- /dev/null +++ b/tests/baselines/reference/jsxHash.js @@ -0,0 +1,26 @@ +//// [jsxHash.tsx] +var t02 = {0}#; +var t03 = #{0}; +var t04 = #{0}#; +var t05 = #; +var t06 = #; +var t07 = ##; +var t08 = #; +var t09 = ##; +var t10 = #; +var t11 = #; +var t12 = #; + + +//// [jsxHash.jsx] +var t02 = {0}#; +var t03 = #{0}; +var t04 = #{0}#; +var t05 = #; +var t06 = #; +var t07 = ##; +var t08 = #; +var t09 = ##; +var t10 = #; +var t11 = #; +var t12 = #; diff --git a/tests/baselines/reference/jsxHash.symbols b/tests/baselines/reference/jsxHash.symbols new file mode 100644 index 00000000000..8a6ad0849f0 --- /dev/null +++ b/tests/baselines/reference/jsxHash.symbols @@ -0,0 +1,34 @@ +=== tests/cases/compiler/jsxHash.tsx === +var t02 = {0}#; +>t02 : Symbol(t02, Decl(jsxHash.tsx, 0, 3)) + +var t03 = #{0}; +>t03 : Symbol(t03, Decl(jsxHash.tsx, 1, 3)) + +var t04 = #{0}#; +>t04 : Symbol(t04, Decl(jsxHash.tsx, 2, 3)) + +var t05 = #; +>t05 : Symbol(t05, Decl(jsxHash.tsx, 3, 3)) + +var t06 = #; +>t06 : Symbol(t06, Decl(jsxHash.tsx, 4, 3)) + +var t07 = ##; +>t07 : Symbol(t07, Decl(jsxHash.tsx, 5, 3)) + +var t08 = #; +>t08 : Symbol(t08, Decl(jsxHash.tsx, 6, 3)) + +var t09 = ##; +>t09 : Symbol(t09, Decl(jsxHash.tsx, 7, 3)) + +var t10 = #; +>t10 : Symbol(t10, Decl(jsxHash.tsx, 8, 3)) + +var t11 = #; +>t11 : Symbol(t11, Decl(jsxHash.tsx, 9, 3)) + +var t12 = #; +>t12 : Symbol(t12, Decl(jsxHash.tsx, 10, 3)) + diff --git a/tests/baselines/reference/jsxHash.types b/tests/baselines/reference/jsxHash.types new file mode 100644 index 00000000000..e614ebd3e0b --- /dev/null +++ b/tests/baselines/reference/jsxHash.types @@ -0,0 +1,86 @@ +=== tests/cases/compiler/jsxHash.tsx === +var t02 = {0}#; +>t02 : any +>{0}# : any +>a : any +>a : any + +var t03 = #{0}; +>t03 : any +>#{0} : any +>a : any +>a : any + +var t04 = #{0}#; +>t04 : any +>#{0}# : any +>a : any +>a : any + +var t05 = #; +>t05 : any +># : any +>a : any +> : any +>i : any +>i : any +>a : any + +var t06 = #; +>t06 : any +># : any +>a : any +> : any +>i : any +>i : any +>a : any + +var t07 = ##; +>t07 : any +>## : any +>a : any +># : any +>i : any +>i : any +>a : any + +var t08 = #; +>t08 : any +># : any +>a : any +> : any +>i : any +>i : any +>a : any + +var t09 = ##; +>t09 : any +>## : any +>a : any +> : any +>i : any +>i : any +>a : any + +var t10 = #; +>t10 : any +># : any +>a : any +> : any +>i : any +>a : any + +var t11 = #; +>t11 : any +># : any +>a : any +> : any +>i : any +>a : any + +var t12 = #; +>t12 : any +># : any +>a : any +>a : any + diff --git a/tests/baselines/reference/jsxInvalidEsprimaTestSuite.errors.txt b/tests/baselines/reference/jsxInvalidEsprimaTestSuite.errors.txt index 99ae5056a4c..02bc56e823e 100644 --- a/tests/baselines/reference/jsxInvalidEsprimaTestSuite.errors.txt +++ b/tests/baselines/reference/jsxInvalidEsprimaTestSuite.errors.txt @@ -62,10 +62,8 @@ tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(24,15): error TS1003: tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(25,7): error TS1005: '...' expected. tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(25,7): error TS2304: Cannot find name 'props'. tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(27,17): error TS1005: '>' expected. -tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(27,18): error TS1109: Expression expected. tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(28,10): error TS2304: Cannot find name 'props'. tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(28,28): error TS1005: '>' expected. -tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(28,29): error TS1109: Expression expected. tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(32,6): error TS1005: '{' expected. tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(33,6): error TS1005: '{' expected. tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(33,7): error TS1109: Expression expected. @@ -73,7 +71,7 @@ tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(35,4): error TS1003: tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(35,21): error TS17002: Expected corresponding JSX closing tag for 'a'. -==== tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx (73 errors) ==== +==== tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx (71 errors) ==== declare var React: any; ; @@ -229,15 +227,11 @@ tests/cases/conformance/jsx/jsxInvalidEsprimaTestSuite.tsx(35,21): error TS17002
stuff
; ~ !!! error TS1005: '>' expected. - ~~~ -!!! error TS1109: Expression expected.
stuff
; ~~~~~ !!! error TS2304: Cannot find name 'props'. ~ !!! error TS1005: '>' expected. - ~~~ -!!! error TS1109: Expression expected. >; >; diff --git a/tests/baselines/reference/jsxInvalidEsprimaTestSuite.js b/tests/baselines/reference/jsxInvalidEsprimaTestSuite.js index 13808cc29e0..daf344b08da 100644 --- a/tests/baselines/reference/jsxInvalidEsprimaTestSuite.js +++ b/tests/baselines/reference/jsxInvalidEsprimaTestSuite.js @@ -65,17 +65,17 @@ a['foo'] > ; ; var x =
one
two
;; var x =
one
/* intervening comment */ /* intervening comment */
two
;; -
{"str"};}; -, id="b" />; -
"app">; +{"str"}}; + id="b" />; +
>;
; -
stuff
{}...props}>; -
stuff
{}...props}>; +
stuff
...props}>; +
stuff
...props}>; >; >; ; ; }; - .../*hai*/asdf/>;; + /*hai*//*hai*/asdf/>;; diff --git a/tests/baselines/reference/tsxErrorRecovery1.errors.txt b/tests/baselines/reference/tsxErrorRecovery1.errors.txt index dc4f4d51afe..7aea986526b 100644 --- a/tests/baselines/reference/tsxErrorRecovery1.errors.txt +++ b/tests/baselines/reference/tsxErrorRecovery1.errors.txt @@ -1,7 +1,10 @@ tests/cases/conformance/jsx/tsxErrorRecovery1.tsx(5,19): error TS1109: Expression expected. +tests/cases/conformance/jsx/tsxErrorRecovery1.tsx(8,11): error TS2304: Cannot find name 'a'. +tests/cases/conformance/jsx/tsxErrorRecovery1.tsx(8,12): error TS1005: '}' expected. +tests/cases/conformance/jsx/tsxErrorRecovery1.tsx(9,1): error TS17002: Expected corresponding JSX closing tag for 'div'. -==== tests/cases/conformance/jsx/tsxErrorRecovery1.tsx (1 errors) ==== +==== tests/cases/conformance/jsx/tsxErrorRecovery1.tsx (4 errors) ==== declare namespace JSX { interface Element { } } @@ -12,4 +15,10 @@ tests/cases/conformance/jsx/tsxErrorRecovery1.tsx(5,19): error TS1109: Expressio } // Shouldn't see any errors down here var y = { a: 1 }; - \ No newline at end of file + ~ +!!! error TS2304: Cannot find name 'a'. + ~ +!!! error TS1005: '}' expected. + + +!!! error TS17002: Expected corresponding JSX closing tag for 'div'. \ No newline at end of file diff --git a/tests/baselines/reference/tsxErrorRecovery1.js b/tests/baselines/reference/tsxErrorRecovery1.js index 8d20951f6ed..62db6b0f012 100644 --- a/tests/baselines/reference/tsxErrorRecovery1.js +++ b/tests/baselines/reference/tsxErrorRecovery1.js @@ -11,7 +11,9 @@ var y = { a: 1 }; //// [tsxErrorRecovery1.jsx] function foo() { - var x =
{}
; + var x =
{}div> +} +// Shouldn't see any errors down here +var y = {a} 1 }; +; } -// Shouldn't see any errors down here -var y = { a: 1 }; diff --git a/tests/cases/compiler/jsxHash.tsx b/tests/cases/compiler/jsxHash.tsx new file mode 100644 index 00000000000..ddd6c7e928f --- /dev/null +++ b/tests/cases/compiler/jsxHash.tsx @@ -0,0 +1,12 @@ +//@jsx: preserve +var t02 = {0}#; +var t03 = #{0}; +var t04 = #{0}#; +var t05 = #; +var t06 = #; +var t07 = ##; +var t08 = #; +var t09 = ##; +var t10 = #; +var t11 = #; +var t12 = #; From 5f6ac45bded276ac01bbdd3b00fefc6a0c78af07 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Fri, 7 Aug 2015 16:03:45 -0700 Subject: [PATCH 75/93] S p a c e s --- src/compiler/parser.ts | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index ffd081f09d0..385d9dda226 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -936,10 +936,7 @@ namespace ts { } function parseOptionalWithoutAdvancing(t: SyntaxKind): boolean { - if (token === t) { - return true; - } - return false; + return token === t; } function parseOptional(t: SyntaxKind): boolean { @@ -3321,7 +3318,7 @@ namespace ts { return finishNode(node); } - function parseJsxElementOrSelfClosingElement(inExpressionContext: boolean): JsxElement|JsxSelfClosingElement { + function parseJsxElementOrSelfClosingElement(inExpressionContext: boolean): JsxElement | JsxSelfClosingElement { let opening = parseJsxOpeningOrSelfClosingElement(inExpressionContext); if (opening.kind === SyntaxKind.JsxOpeningElement) { let node = createNode(SyntaxKind.JsxElement, opening.pos); @@ -3349,9 +3346,9 @@ namespace ts { case SyntaxKind.JsxText: return parseJsxText(); case SyntaxKind.OpenBraceToken: - return parseJsxExpression(/*inExpression*/false); + return parseJsxExpression(/*inExpression*/ false); case SyntaxKind.LessThanToken: - return parseJsxElementOrSelfClosingElement(/*inExpression*/false); + return parseJsxElementOrSelfClosingElement(/*inExpression*/ false); } Debug.fail("Unknown JSX child kind " + token); } @@ -3436,7 +3433,7 @@ namespace ts { if (token !== SyntaxKind.CloseBraceToken) { node.expression = parseExpression(); } - if(inExpressionContext) { + if (inExpressionContext) { parseExpected(SyntaxKind.CloseBraceToken); } else { From 4a96491d5b0233a0c2a32a285b620bc8b224f29b Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Fri, 7 Aug 2015 16:06:49 -0700 Subject: [PATCH 76/93] Remove silly function --- src/compiler/parser.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 385d9dda226..a83b6d91828 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -935,10 +935,6 @@ namespace ts { return false; } - function parseOptionalWithoutAdvancing(t: SyntaxKind): boolean { - return token === t; - } - function parseOptional(t: SyntaxKind): boolean { if (token === t) { nextToken(); @@ -3388,7 +3384,7 @@ namespace ts { let attributes = parseList(ParsingContext.JsxAttributes, parseJsxAttribute); let node: JsxOpeningLikeElement; - if (parseOptionalWithoutAdvancing(SyntaxKind.GreaterThanToken)) { + if (token === SyntaxKind.GreaterThanToken) { // Closing tag, so scan the immediately-following text with the JSX scanning instead // of regular scanning to avoid treating illegal characters (e.g. '#') as immediate // scanning errors From cdd5b6a7e9f8cee9f4a3fc3501a1d8644b3a961e Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Fri, 7 Aug 2015 16:23:34 -0700 Subject: [PATCH 77/93] Rename parameter --- src/compiler/parser.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index a83b6d91828..a1f11a5d8d7 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -917,9 +917,9 @@ namespace ts { return token > SyntaxKind.LastReservedWord; } - function parseExpected(kind: SyntaxKind, diagnosticMessage?: DiagnosticMessage, advance = true): boolean { + function parseExpected(kind: SyntaxKind, diagnosticMessage?: DiagnosticMessage, shouldAdvance = true): boolean { if (token === kind) { - if (advance) { + if (shouldAdvance) { nextToken(); } return true; From 673e741f57aa6610219f6b11520b3963dc77421e Mon Sep 17 00:00:00 2001 From: Yui T Date: Fri, 7 Aug 2015 16:30:16 -0700 Subject: [PATCH 78/93] Add comments to do clean-up --- src/compiler/emitter.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index d0947b35693..7f8e1b2f8df 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -3632,6 +3632,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi return emitOnlyPinnedOrTripleSlashComments(node); } + // TODO (yuisu) : we should not have special cases to condition emitting comments + // but have one place to fix check for these conditions. if (node.kind !== SyntaxKind.MethodDeclaration && node.kind !== SyntaxKind.MethodSignature && node.parent && node.parent.kind !== SyntaxKind.PropertyAssignment && node.parent.kind !== SyntaxKind.CallExpression) { From 9bfba56c60b09d4beeb5aa7b4b9d13a62a013fd8 Mon Sep 17 00:00:00 2001 From: Yui T Date: Fri, 7 Aug 2015 16:56:25 -0700 Subject: [PATCH 79/93] Add baseline for error baseline --- .../baselines/reference/objectTypesWithOptionalProperties2.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/baselines/reference/objectTypesWithOptionalProperties2.js b/tests/baselines/reference/objectTypesWithOptionalProperties2.js index cf0d113c244..e5ffbf09c10 100644 --- a/tests/baselines/reference/objectTypesWithOptionalProperties2.js +++ b/tests/baselines/reference/objectTypesWithOptionalProperties2.js @@ -42,5 +42,6 @@ var C2 = (function () { return C2; })(); var b = { - x: function () { }, 1: // error + x: function () { }, 1: // error + // error }; From 7f49375f3e5edc324b3e94a0c3eaeccdf2da0996 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 28 Jul 2015 14:30:27 -0700 Subject: [PATCH 80/93] Fix #3912: emit declaration for binding elements correctelly --- src/compiler/declarationEmitter.ts | 5 +---- .../paramterDestrcuturingDeclaration.js | 20 +++++++++++++++++++ .../paramterDestrcuturingDeclaration.symbols | 14 +++++++++++++ .../paramterDestrcuturingDeclaration.types | 14 +++++++++++++ .../paramterDestrcuturingDeclaration.ts | 6 ++++++ 5 files changed, 55 insertions(+), 4 deletions(-) create mode 100644 tests/baselines/reference/paramterDestrcuturingDeclaration.js create mode 100644 tests/baselines/reference/paramterDestrcuturingDeclaration.symbols create mode 100644 tests/baselines/reference/paramterDestrcuturingDeclaration.types create mode 100644 tests/cases/compiler/paramterDestrcuturingDeclaration.ts diff --git a/src/compiler/declarationEmitter.ts b/src/compiler/declarationEmitter.ts index 32a51de899e..a490ba39a46 100644 --- a/src/compiler/declarationEmitter.ts +++ b/src/compiler/declarationEmitter.ts @@ -1501,11 +1501,8 @@ namespace ts { // emit : declare function foo({y: [a, b, c]}: { y: [any, any, any] }) void; writeTextOfNode(currentSourceFile, bindingElement.propertyName); write(": "); - - // If bindingElement has propertyName property, then its name must be another bindingPattern of SyntaxKind.ObjectBindingPattern - emitBindingPattern(bindingElement.name); } - else if (bindingElement.name) { + if (bindingElement.name) { if (isBindingPattern(bindingElement.name)) { // If it is a nested binding pattern, we will recursively descend into each element and emit each one separately. // In the case of rest element, we will omit rest element. diff --git a/tests/baselines/reference/paramterDestrcuturingDeclaration.js b/tests/baselines/reference/paramterDestrcuturingDeclaration.js new file mode 100644 index 00000000000..6920f22b0d4 --- /dev/null +++ b/tests/baselines/reference/paramterDestrcuturingDeclaration.js @@ -0,0 +1,20 @@ +//// [paramterDestrcuturingDeclaration.ts] + +interface C { + ({p: name}): any; + new ({p: boolean}): any; +} + + +//// [paramterDestrcuturingDeclaration.js] + + +//// [paramterDestrcuturingDeclaration.d.ts] +interface C { + ({p: name}: { + p: any; + }): any; + new ({p: boolean}: { + p: any; + }): any; +} diff --git a/tests/baselines/reference/paramterDestrcuturingDeclaration.symbols b/tests/baselines/reference/paramterDestrcuturingDeclaration.symbols new file mode 100644 index 00000000000..dd11b302eea --- /dev/null +++ b/tests/baselines/reference/paramterDestrcuturingDeclaration.symbols @@ -0,0 +1,14 @@ +=== tests/cases/compiler/paramterDestrcuturingDeclaration.ts === + +interface C { +>C : Symbol(C, Decl(paramterDestrcuturingDeclaration.ts, 0, 0)) + + ({p: name}): any; +>p : Symbol(p) +>name : Symbol(name, Decl(paramterDestrcuturingDeclaration.ts, 2, 6)) + + new ({p: boolean}): any; +>p : Symbol(p) +>boolean : Symbol(boolean, Decl(paramterDestrcuturingDeclaration.ts, 3, 10)) +} + diff --git a/tests/baselines/reference/paramterDestrcuturingDeclaration.types b/tests/baselines/reference/paramterDestrcuturingDeclaration.types new file mode 100644 index 00000000000..4b49ce22035 --- /dev/null +++ b/tests/baselines/reference/paramterDestrcuturingDeclaration.types @@ -0,0 +1,14 @@ +=== tests/cases/compiler/paramterDestrcuturingDeclaration.ts === + +interface C { +>C : C + + ({p: name}): any; +>p : any +>name : any + + new ({p: boolean}): any; +>p : any +>boolean : any +} + diff --git a/tests/cases/compiler/paramterDestrcuturingDeclaration.ts b/tests/cases/compiler/paramterDestrcuturingDeclaration.ts new file mode 100644 index 00000000000..d05d6076bf0 --- /dev/null +++ b/tests/cases/compiler/paramterDestrcuturingDeclaration.ts @@ -0,0 +1,6 @@ +// @declaration: true + +interface C { + ({p: name}): any; + new ({p: boolean}): any; +} From 7ecaea39266d6b830816bbda201ee11155123cf2 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Mon, 10 Aug 2015 13:51:54 -0700 Subject: [PATCH 81/93] addressed PR feedback --- src/compiler/emitter.ts | 60 +++++++++++---------- tests/baselines/reference/systemModule11.js | 16 +++--- tests/baselines/reference/systemModule16.js | 10 ++-- 3 files changed, 46 insertions(+), 40 deletions(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 76d07395f32..f15f3827bd7 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -3090,7 +3090,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi } } - function emitExportMemberAssignmentsInNonSystemModule(name: Identifier) { + function emitExportMemberAssignments(name: Identifier) { if (compilerOptions.module === ModuleKind.System) { return; } @@ -3412,7 +3412,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi } let name = node.name; if (name.kind === SyntaxKind.Identifier) { - emitExportMemberAssignmentsInNonSystemModule(name); + emitExportMemberAssignments(name); } else if (isBindingPattern(name)) { forEach((name).elements, emitExportVariableAssignments); @@ -3667,7 +3667,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi emitSignatureAndBody(node); if (languageVersion < ScriptTarget.ES6 && node.kind === SyntaxKind.FunctionDeclaration && node.parent === currentSourceFile && node.name) { - emitExportMemberAssignmentsInNonSystemModule((node).name); + emitExportMemberAssignments((node).name); } if (node.kind !== SyntaxKind.MethodDeclaration && node.kind !== SyntaxKind.MethodSignature) { emitTrailingComments(node); @@ -4590,7 +4590,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi } if (languageVersion < ScriptTarget.ES6 && node.parent === currentSourceFile && node.name) { - emitExportMemberAssignmentsInNonSystemModule(node.name); + emitExportMemberAssignments(node.name); } } @@ -5179,7 +5179,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi emitDeclarationName(node); write(");"); } - emitExportMemberAssignmentsInNonSystemModule(node.name); + emitExportMemberAssignments(node.name); } } @@ -5300,7 +5300,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi emitDeclarationName(node); write(");"); } - emitExportMemberAssignmentsInNonSystemModule(node.name); + emitExportMemberAssignments(node.name); } } @@ -5333,7 +5333,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitExportImportAssignments(node: Node) { if (isAliasSymbolDeclaration(node) && resolver.isValueAliasDeclaration(node)) { - emitExportMemberAssignmentsInNonSystemModule((node).name); + emitExportMemberAssignments((node).name); } forEachChild(node, emitExportImportAssignments); } @@ -6155,23 +6155,30 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi if ((entry).exportClause) { // export {a, b as c} from 'foo' // emit as: - // var reexports = {} - // reexports['a'] = _foo["a"]; - // reexports['c'] = _foo["b"]; - // exports_(reexports); - let reexportsVariableName = makeUniqueName("reexports"); + // exports_({ + // "a": _["a"], + // "c": _["b"] + // }); writeLine(); - write(`var ${reexportsVariableName} = {};`); + write(`${exportFunctionForFile}({`); writeLine(); - for (let e of (entry).exportClause.elements) { - write(`${reexportsVariableName}["`); + increaseIndent(); + for (let i = 0, len = (entry).exportClause.elements.length; i < len; ++i) { + if (i !== 0) { + write(","); + writeLine(); + } + + let e = (entry).exportClause.elements[i]; + write(`"`); emitNodeWithoutSourceMap(e.name); - write(`"] = ${parameterName}["`); + write(`": ${parameterName}["`); emitNodeWithoutSourceMap(e.propertyName || e.name); - write(`"];`); - writeLine(); + write(`"]`); } - write(`${exportFunctionForFile}(${reexportsVariableName});`); + decreaseIndent(); + writeLine(); + write("});") } else { writeLine(); @@ -6206,15 +6213,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi // - import declarations are not emitted since they are already handled in setters // - export declarations with module specifiers are not emitted since they were already written in setters // - export declarations without module specifiers are emitted preserving the order - case SyntaxKind.FunctionDeclaration: - case SyntaxKind.ExportDeclaration: + case SyntaxKind.FunctionDeclaration: case SyntaxKind.ImportDeclaration: - if (statement.kind === SyntaxKind.ExportDeclaration) { - if (!(statement).moduleSpecifier) { - for (let element of (statement).exportClause.elements) { - // write call to exporter function for every export specifier in exports list - emitExportSpecifierInSystemModule(element); - } + continue; + case SyntaxKind.ExportDeclaration: + if (!(statement).moduleSpecifier) { + for (let element of (statement).exportClause.elements) { + // write call to exporter function for every export specifier in exports list + emitExportSpecifierInSystemModule(element); } } continue; diff --git a/tests/baselines/reference/systemModule11.js b/tests/baselines/reference/systemModule11.js index 7111968f3ce..bf9b57c511c 100644 --- a/tests/baselines/reference/systemModule11.js +++ b/tests/baselines/reference/systemModule11.js @@ -109,10 +109,10 @@ System.register(['a', 'bar'], function(exports_1) { return { setters:[ function (a_1_1) { - var reexports_1 = {}; - reexports_1["x"] = a_1_1["x"]; - reexports_1["z"] = a_1_1["y"]; - exports_1(reexports_1); + exports_1({ + "x": a_1_1["x"], + "z": a_1_1["y"] + }); }, function (bar_1_1) { exportStar_1(bar_1_1); @@ -131,10 +131,10 @@ System.register(['a'], function(exports_1) { return { setters:[ function (a_1_1) { - var reexports_1 = {}; - reexports_1["s"] = a_1_1["s"]; - reexports_1["s2"] = a_1_1["s1"]; - exports_1(reexports_1); + exports_1({ + "s": a_1_1["s"], + "s2": a_1_1["s1"] + }); }], execute: function() { exports_1("z", z); diff --git a/tests/baselines/reference/systemModule16.js b/tests/baselines/reference/systemModule16.js index 0c53275cdd8..851b941492a 100644 --- a/tests/baselines/reference/systemModule16.js +++ b/tests/baselines/reference/systemModule16.js @@ -39,11 +39,11 @@ System.register(["foo", "bar"], function(exports_1) { function (y_1) { y = y_1; exportStar_1(y_1); - var reexports_1 = {}; - reexports_1["a2"] = y_1["a2"]; - reexports_1["b2"] = y_1["b2"]; - reexports_1["d2"] = y_1["c2"]; - exports_1(reexports_1); + exports_1({ + "a2": y_1["a2"], + "b2": y_1["b2"], + "d2": y_1["c2"] + }); }], execute: function() { exports_1("x", x); From 86b104133f5d1e058e9277600e08eeed2c43e57e Mon Sep 17 00:00:00 2001 From: Yui T Date: Mon, 10 Aug 2015 17:34:39 -0700 Subject: [PATCH 82/93] Fix comments --- src/compiler/emitter.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 7f8e1b2f8df..80e67b17423 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -834,9 +834,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi } let node = nodes[start + i]; // This emitting is to make sure we emit following comment properly - // ...(x, /comment1/ y)... + // ...(x, /*comment1*/ y)... // ^ => node.pos - // "comment1" is not considered leading comment for node-y but rather + // "comment1" is not considered leading comment for "y" but rather // considered as trailing comment of the previous node. emitTrailingCommentsOfPosition(node.pos); emitNode(node); @@ -1986,7 +1986,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi // This is to ensure that we emit comment in the following case: // For example: // obj = { - // id: /comment1/ ()=>void + // id: /*comment1*/ ()=>void // } // "comment1" is not considered to be leading comment for node.initializer // but rather a trailing comment on the previous node. From dfcc1e694401929dfbd5e8476a09d570367bc879 Mon Sep 17 00:00:00 2001 From: SaschaNaz Date: Tue, 11 Aug 2015 23:47:44 +0900 Subject: [PATCH 83/93] fix generics/type-assertion formatting --- src/services/formatting/rules.ts | 28 ++++++++++++------- tests/cases/fourslash/genericsFormatting.ts | 3 ++ .../fourslash/typeAssertionsFormatting.ts | 13 +++++++++ 3 files changed, 34 insertions(+), 10 deletions(-) create mode 100644 tests/cases/fourslash/typeAssertionsFormatting.ts diff --git a/src/services/formatting/rules.ts b/src/services/formatting/rules.ts index 1a758886350..497c5114400 100644 --- a/src/services/formatting/rules.ts +++ b/src/services/formatting/rules.ts @@ -135,6 +135,7 @@ namespace ts.formatting { public NoSpaceAfterOpenAngularBracket: Rule; public NoSpaceBeforeCloseAngularBracket: Rule; public NoSpaceAfterCloseAngularBracket: Rule; + public NoSpaceAfterTypeAssertion: Rule; // Remove spaces in empty interface literals. e.g.: x: {} public NoSpaceBetweenEmptyInterfaceBraceBrackets: Rule; @@ -331,12 +332,13 @@ namespace ts.formatting { this.NoSpaceAfterEllipsis = new Rule(RuleDescriptor.create1(SyntaxKind.DotDotDotToken, SyntaxKind.Identifier), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete)); this.NoSpaceAfterOptionalParameters = new Rule(RuleDescriptor.create3(SyntaxKind.QuestionToken, Shared.TokenRange.FromTokens([SyntaxKind.CloseParenToken, SyntaxKind.CommaToken])), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBinaryOpContext), RuleAction.Delete)); - // generics - this.NoSpaceBeforeOpenAngularBracket = new Rule(RuleDescriptor.create2(Shared.TokenRange.TypeNames, SyntaxKind.LessThanToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeArgumentOrParameterContext), RuleAction.Delete)); - this.NoSpaceBetweenCloseParenAndAngularBracket = new Rule(RuleDescriptor.create1(SyntaxKind.CloseParenToken, SyntaxKind.LessThanToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeArgumentOrParameterContext), RuleAction.Delete)); - this.NoSpaceAfterOpenAngularBracket = new Rule(RuleDescriptor.create3(SyntaxKind.LessThanToken, Shared.TokenRange.TypeNames), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeArgumentOrParameterContext), RuleAction.Delete)); - this.NoSpaceBeforeCloseAngularBracket = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.GreaterThanToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeArgumentOrParameterContext), RuleAction.Delete)); - this.NoSpaceAfterCloseAngularBracket = new Rule(RuleDescriptor.create3(SyntaxKind.GreaterThanToken, Shared.TokenRange.FromTokens([SyntaxKind.OpenParenToken, SyntaxKind.OpenBracketToken, SyntaxKind.GreaterThanToken, SyntaxKind.CommaToken])), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeArgumentOrParameterContext), RuleAction.Delete)); + // generics and type assertions + this.NoSpaceBeforeOpenAngularBracket = new Rule(RuleDescriptor.create2(Shared.TokenRange.TypeNames, SyntaxKind.LessThanToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeArgumentOrParameterOrAssertionContext), RuleAction.Delete)); + this.NoSpaceBetweenCloseParenAndAngularBracket = new Rule(RuleDescriptor.create1(SyntaxKind.CloseParenToken, SyntaxKind.LessThanToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeArgumentOrParameterOrAssertionContext), RuleAction.Delete)); + this.NoSpaceAfterOpenAngularBracket = new Rule(RuleDescriptor.create3(SyntaxKind.LessThanToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeArgumentOrParameterOrAssertionContext), RuleAction.Delete)); + this.NoSpaceBeforeCloseAngularBracket = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.GreaterThanToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeArgumentOrParameterOrAssertionContext), RuleAction.Delete)); + this.NoSpaceAfterCloseAngularBracket = new Rule(RuleDescriptor.create3(SyntaxKind.GreaterThanToken, Shared.TokenRange.FromTokens([SyntaxKind.OpenParenToken, SyntaxKind.OpenBracketToken, SyntaxKind.GreaterThanToken, SyntaxKind.CommaToken])), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeArgumentOrParameterOrAssertionContext), RuleAction.Delete)); + this.NoSpaceAfterTypeAssertion = new Rule(RuleDescriptor.create3(SyntaxKind.GreaterThanToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsTypeAssertionContext), RuleAction.Delete)); // Remove spaces in empty interface literals. e.g.: x: {} this.NoSpaceBetweenEmptyInterfaceBraceBrackets = new Rule(RuleDescriptor.create1(SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsObjectTypeContext), RuleAction.Delete)); @@ -391,6 +393,7 @@ namespace ts.formatting { this.NoSpaceAfterOpenAngularBracket, this.NoSpaceBeforeCloseAngularBracket, this.NoSpaceAfterCloseAngularBracket, + this.NoSpaceAfterTypeAssertion, this.SpaceBeforeAt, this.NoSpaceAfterAt, this.SpaceAfterDecorator, @@ -704,12 +707,13 @@ namespace ts.formatting { return context.contextNode.kind === SyntaxKind.TypeLiteral;// && context.contextNode.parent.kind !== SyntaxKind.InterfaceDeclaration; } - static IsTypeArgumentOrParameter(token: TextRangeWithKind, parent: Node): boolean { + static IsTypeArgumentOrParameterOrAssertion(token: TextRangeWithKind, parent: Node): boolean { if (token.kind !== SyntaxKind.LessThanToken && token.kind !== SyntaxKind.GreaterThanToken) { return false; } switch (parent.kind) { case SyntaxKind.TypeReference: + case SyntaxKind.TypeAssertionExpression: case SyntaxKind.ClassDeclaration: case SyntaxKind.InterfaceDeclaration: case SyntaxKind.FunctionDeclaration: @@ -728,9 +732,13 @@ namespace ts.formatting { } } - static IsTypeArgumentOrParameterContext(context: FormattingContext): boolean { - return Rules.IsTypeArgumentOrParameter(context.currentTokenSpan, context.currentTokenParent) || - Rules.IsTypeArgumentOrParameter(context.nextTokenSpan, context.nextTokenParent); + static IsTypeArgumentOrParameterOrAssertionContext(context: FormattingContext): boolean { + return Rules.IsTypeArgumentOrParameterOrAssertion(context.currentTokenSpan, context.currentTokenParent) || + Rules.IsTypeArgumentOrParameterOrAssertion(context.nextTokenSpan, context.nextTokenParent); + } + + static IsTypeAssertionContext(context: FormattingContext): boolean { + return context.contextNode.kind === SyntaxKind.TypeAssertionExpression; } static IsVoidOpContext(context: FormattingContext): boolean { diff --git a/tests/cases/fourslash/genericsFormatting.ts b/tests/cases/fourslash/genericsFormatting.ts index 36833cadd10..b8ef27fa8f2 100644 --- a/tests/cases/fourslash/genericsFormatting.ts +++ b/tests/cases/fourslash/genericsFormatting.ts @@ -5,6 +5,7 @@ //// } ////} /////*typeArguments*/var foo = new Foo < number, Array < number > > ( ); +/////*typeArgumentsWithTypeLiterals*/foo = new Foo < { bar : number }, Array < { baz : string } > > ( ); //// ////interface IFoo { /////*inNewSignature*/new < T > ( a: T); @@ -25,6 +26,8 @@ verify.currentLineContentIs(" public method(a: T1, b: Array): Map goTo.marker("typeArguments"); verify.currentLineContentIs("var foo = new Foo>();"); +goTo.marker("typeArgumentsWithTypeLiterals"); +verify.currentLineContentIs("foo = new Foo<{ bar: number }, Array<{ baz: string }>>();"); goTo.marker("inNewSignature"); verify.currentLineContentIs(" new (a: T);"); diff --git a/tests/cases/fourslash/typeAssertionsFormatting.ts b/tests/cases/fourslash/typeAssertionsFormatting.ts new file mode 100644 index 00000000000..3f3ab070fec --- /dev/null +++ b/tests/cases/fourslash/typeAssertionsFormatting.ts @@ -0,0 +1,13 @@ +/// + +////( < any > publisher);/*1*/ +//// < any > 3;/*2*/ + + +format.document(); + +goTo.marker("1"); +verify.currentLineContentIs("(publisher);"); + +goTo.marker("2"); +verify.currentLineContentIs("3;"); \ No newline at end of file From dd446d80ad6b2eb54f6760104cd87849811107da Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Tue, 11 Aug 2015 11:05:37 -0700 Subject: [PATCH 84/93] Fix comment --- src/compiler/parser.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index a1f11a5d8d7..def08e81758 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -3342,9 +3342,9 @@ namespace ts { case SyntaxKind.JsxText: return parseJsxText(); case SyntaxKind.OpenBraceToken: - return parseJsxExpression(/*inExpression*/ false); + return parseJsxExpression(/*inExpressionContext*/ false); case SyntaxKind.LessThanToken: - return parseJsxElementOrSelfClosingElement(/*inExpression*/ false); + return parseJsxElementOrSelfClosingElement(/*inExpressionContext*/ false); } Debug.fail("Unknown JSX child kind " + token); } From ce44d9511526c265a3d18b899017642251f1eb85 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Tue, 11 Aug 2015 12:04:55 -0700 Subject: [PATCH 85/93] keep only document highlights from the original file --- src/services/shims.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/services/shims.ts b/src/services/shims.ts index 6b679e70b4b..636c983e04c 100644 --- a/src/services/shims.ts +++ b/src/services/shims.ts @@ -752,7 +752,10 @@ namespace ts { return this.forwardJSONCall( "getDocumentHighlights('" + fileName + "', " + position + ")", () => { - return this.languageService.getDocumentHighlights(fileName, position, JSON.parse(filesToSearch)); + var results = this.languageService.getDocumentHighlights(fileName, position, JSON.parse(filesToSearch)); + // workaround for VS document higlighting issue - keep only items from the initial file + let normalizedName = normalizeSlashes(fileName).toLowerCase(); + return filter(results, r => normalizeSlashes(r.fileName).toLowerCase() === normalizedName); }); } From 500861c4f8e00635bbb2a7fa0f861a1733bf92e1 Mon Sep 17 00:00:00 2001 From: JBerger Date: Wed, 12 Aug 2015 15:34:03 -0600 Subject: [PATCH 86/93] Test cases that address https://github.com/Microsoft/TypeScript/issues/4288 --- .../extendClassExpressionFromModule.js | 35 +++++++++++++++ .../extendClassExpressionFromModule.symbols | 18 ++++++++ .../extendClassExpressionFromModule.types | 19 ++++++++ .../reference/reexportClassDefinition.js | 45 +++++++++++++++++++ .../reference/reexportClassDefinition.symbols | 26 +++++++++++ .../reference/reexportClassDefinition.types | 30 +++++++++++++ .../extendClassExpressionFromModule.ts | 10 +++++ .../reexportClassDefinition.ts | 16 +++++++ 8 files changed, 199 insertions(+) create mode 100644 tests/baselines/reference/extendClassExpressionFromModule.js create mode 100644 tests/baselines/reference/extendClassExpressionFromModule.symbols create mode 100644 tests/baselines/reference/extendClassExpressionFromModule.types create mode 100644 tests/baselines/reference/reexportClassDefinition.js create mode 100644 tests/baselines/reference/reexportClassDefinition.symbols create mode 100644 tests/baselines/reference/reexportClassDefinition.types create mode 100644 tests/cases/conformance/classes/classExpressions/extendClassExpressionFromModule.ts create mode 100644 tests/cases/conformance/externalModules/reexportClassDefinition.ts diff --git a/tests/baselines/reference/extendClassExpressionFromModule.js b/tests/baselines/reference/extendClassExpressionFromModule.js new file mode 100644 index 00000000000..cbd36f7e799 --- /dev/null +++ b/tests/baselines/reference/extendClassExpressionFromModule.js @@ -0,0 +1,35 @@ +//// [tests/cases/conformance/classes/classExpressions/extendClassExpressionFromModule.ts] //// + +//// [foo1.ts] +class x{} + +export = x; + +//// [foo2.ts] +import foo1 = require('./foo1'); +var x = foo1; +class y extends x {} + + +//// [foo1.js] +var x = (function () { + function x() { + } + return x; +})(); +module.exports = x; +//// [foo2.js] +var __extends = (this && this.__extends) || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +}; +var foo1 = require('./foo1'); +var x = foo1; +var y = (function (_super) { + __extends(y, _super); + function y() { + _super.apply(this, arguments); + } + return y; +})(x); diff --git a/tests/baselines/reference/extendClassExpressionFromModule.symbols b/tests/baselines/reference/extendClassExpressionFromModule.symbols new file mode 100644 index 00000000000..c131ea8fa28 --- /dev/null +++ b/tests/baselines/reference/extendClassExpressionFromModule.symbols @@ -0,0 +1,18 @@ +=== tests/cases/conformance/classes/classExpressions/foo2.ts === +import foo1 = require('./foo1'); +>foo1 : Symbol(foo1, Decl(foo2.ts, 0, 0)) + +var x = foo1; +>x : Symbol(x, Decl(foo2.ts, 1, 3)) +>foo1 : Symbol(foo1, Decl(foo2.ts, 0, 0)) + +class y extends x {} +>y : Symbol(y, Decl(foo2.ts, 1, 13)) + +=== tests/cases/conformance/classes/classExpressions/foo1.ts === +class x{} +>x : Symbol(x, Decl(foo1.ts, 0, 0)) + +export = x; +>x : Symbol(x, Decl(foo1.ts, 0, 0)) + diff --git a/tests/baselines/reference/extendClassExpressionFromModule.types b/tests/baselines/reference/extendClassExpressionFromModule.types new file mode 100644 index 00000000000..d03623d50aa --- /dev/null +++ b/tests/baselines/reference/extendClassExpressionFromModule.types @@ -0,0 +1,19 @@ +=== tests/cases/conformance/classes/classExpressions/foo2.ts === +import foo1 = require('./foo1'); +>foo1 : typeof foo1 + +var x = foo1; +>x : typeof foo1 +>foo1 : typeof foo1 + +class y extends x {} +>y : y +>x : foo1 + +=== tests/cases/conformance/classes/classExpressions/foo1.ts === +class x{} +>x : x + +export = x; +>x : x + diff --git a/tests/baselines/reference/reexportClassDefinition.js b/tests/baselines/reference/reexportClassDefinition.js new file mode 100644 index 00000000000..5d534f1e3a3 --- /dev/null +++ b/tests/baselines/reference/reexportClassDefinition.js @@ -0,0 +1,45 @@ +//// [tests/cases/conformance/externalModules/reexportClassDefinition.ts] //// + +//// [foo1.ts] +class x{} +export = x; + +//// [foo2.ts] +import foo1 = require('./foo1'); + +export = { + x: foo1 +} + +//// [foo3.ts] +import foo2 = require('./foo2') +class x extends foo2.x {} + + + +//// [foo1.js] +var x = (function () { + function x() { + } + return x; +})(); +module.exports = x; +//// [foo2.js] +var foo1 = require('./foo1'); +module.exports = { + x: foo1 +}; +//// [foo3.js] +var __extends = (this && this.__extends) || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +}; +var foo2 = require('./foo2'); +var x = (function (_super) { + __extends(x, _super); + function x() { + _super.apply(this, arguments); + } + return x; +})(foo2.x); diff --git a/tests/baselines/reference/reexportClassDefinition.symbols b/tests/baselines/reference/reexportClassDefinition.symbols new file mode 100644 index 00000000000..52133657985 --- /dev/null +++ b/tests/baselines/reference/reexportClassDefinition.symbols @@ -0,0 +1,26 @@ +=== tests/cases/conformance/externalModules/foo3.ts === +import foo2 = require('./foo2') +>foo2 : Symbol(foo2, Decl(foo3.ts, 0, 0)) + +class x extends foo2.x {} +>x : Symbol(x, Decl(foo3.ts, 0, 31)) +>foo2 : Symbol(foo2, Decl(foo3.ts, 0, 0)) + + +=== tests/cases/conformance/externalModules/foo1.ts === +class x{} +>x : Symbol(x, Decl(foo1.ts, 0, 0)) + +export = x; +>x : Symbol(x, Decl(foo1.ts, 0, 0)) + +=== tests/cases/conformance/externalModules/foo2.ts === +import foo1 = require('./foo1'); +>foo1 : Symbol(foo1, Decl(foo2.ts, 0, 0)) + +export = { + x: foo1 +>x : Symbol(x, Decl(foo2.ts, 2, 10)) +>foo1 : Symbol(foo1, Decl(foo2.ts, 0, 0)) +} + diff --git a/tests/baselines/reference/reexportClassDefinition.types b/tests/baselines/reference/reexportClassDefinition.types new file mode 100644 index 00000000000..c39bbf9c136 --- /dev/null +++ b/tests/baselines/reference/reexportClassDefinition.types @@ -0,0 +1,30 @@ +=== tests/cases/conformance/externalModules/foo3.ts === +import foo2 = require('./foo2') +>foo2 : { x: typeof x; } + +class x extends foo2.x {} +>x : x +>foo2.x : x +>foo2 : { x: typeof x; } +>x : typeof x + + +=== tests/cases/conformance/externalModules/foo1.ts === +class x{} +>x : x + +export = x; +>x : x + +=== tests/cases/conformance/externalModules/foo2.ts === +import foo1 = require('./foo1'); +>foo1 : typeof foo1 + +export = { +>{ x: foo1} : { x: typeof foo1; } + + x: foo1 +>x : typeof foo1 +>foo1 : typeof foo1 +} + diff --git a/tests/cases/conformance/classes/classExpressions/extendClassExpressionFromModule.ts b/tests/cases/conformance/classes/classExpressions/extendClassExpressionFromModule.ts new file mode 100644 index 00000000000..d4d25743333 --- /dev/null +++ b/tests/cases/conformance/classes/classExpressions/extendClassExpressionFromModule.ts @@ -0,0 +1,10 @@ +// @module: commonjs +// @Filename: foo1.ts +class x{} + +export = x; + +// @Filename: foo2.ts +import foo1 = require('./foo1'); +var x = foo1; +class y extends x {} diff --git a/tests/cases/conformance/externalModules/reexportClassDefinition.ts b/tests/cases/conformance/externalModules/reexportClassDefinition.ts new file mode 100644 index 00000000000..31d90fd7fd2 --- /dev/null +++ b/tests/cases/conformance/externalModules/reexportClassDefinition.ts @@ -0,0 +1,16 @@ +// @module: commonjs +// @Filename: foo1.ts +class x{} +export = x; + +// @Filename: foo2.ts +import foo1 = require('./foo1'); + +export = { + x: foo1 +} + +// @Filename: foo3.ts +import foo2 = require('./foo2') +class x extends foo2.x {} + From c0801b1388d0ec737c8dcb85f45821601facc8c2 Mon Sep 17 00:00:00 2001 From: Yui T Date: Wed, 12 Aug 2015 17:46:24 -0700 Subject: [PATCH 87/93] Add asterisks --- src/compiler/emitter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 80e67b17423..62f15429726 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -6958,7 +6958,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi /** * Emit trailing comments at the position. The term trailing comment is used here to describe following comment: - * x, /comment1/ y + * x, /*comment1*/ y * ^ => pos; the function will emit "comment1" in the emitJS */ function emitTrailingCommentsOfPosition(pos: number) { From 6adf7feb5eea512b0b29e1361808cf3b1441cb5f Mon Sep 17 00:00:00 2001 From: Yui T Date: Wed, 12 Aug 2015 17:52:36 -0700 Subject: [PATCH 88/93] Remove asterisks --- src/compiler/emitter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 4fd597f519f..4750538c9b6 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -6983,7 +6983,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi /** * Emit trailing comments at the position. The term trailing comment is used here to describe following comment: - * x, /*comment1*/ y + * x, /comment1/ y * ^ => pos; the function will emit "comment1" in the emitJS */ function emitTrailingCommentsOfPosition(pos: number) { From f832bd20f238b6c70e99302e8ecf8a8a72839237 Mon Sep 17 00:00:00 2001 From: SaschaNaz Date: Fri, 14 Aug 2015 03:45:52 +0900 Subject: [PATCH 89/93] fix class expression + expressionWithTypeArgument --- src/services/formatting/rules.ts | 2 ++ tests/cases/fourslash/genericsFormatting.ts | 15 ++++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/services/formatting/rules.ts b/src/services/formatting/rules.ts index 497c5114400..a5e37bf6902 100644 --- a/src/services/formatting/rules.ts +++ b/src/services/formatting/rules.ts @@ -715,6 +715,7 @@ namespace ts.formatting { case SyntaxKind.TypeReference: case SyntaxKind.TypeAssertionExpression: case SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassExpression: case SyntaxKind.InterfaceDeclaration: case SyntaxKind.FunctionDeclaration: case SyntaxKind.FunctionExpression: @@ -725,6 +726,7 @@ namespace ts.formatting { case SyntaxKind.ConstructSignature: case SyntaxKind.CallExpression: case SyntaxKind.NewExpression: + case SyntaxKind.ExpressionWithTypeArguments: return true; default: return false; diff --git a/tests/cases/fourslash/genericsFormatting.ts b/tests/cases/fourslash/genericsFormatting.ts index b8ef27fa8f2..f5e44522a8e 100644 --- a/tests/cases/fourslash/genericsFormatting.ts +++ b/tests/cases/fourslash/genericsFormatting.ts @@ -14,6 +14,13 @@ //// ////foo()(); ////(a + b)(); +//// +////function bar() { +/////*inClassExpression*/ return class < T2 > { +//// } +////} +/////*expressionWithTypeArguments*/class A < T > extends bar < T >( ) < T > { +////} format.document(); @@ -33,4 +40,10 @@ goTo.marker("inNewSignature"); verify.currentLineContentIs(" new (a: T);"); goTo.marker("inOptionalMethodSignature"); -verify.currentLineContentIs(" op?(a: T, b: M);"); \ No newline at end of file +verify.currentLineContentIs(" op?(a: T, b: M);"); + +goTo.marker("inClassExpression"); +verify.currentLineContentIs(" return class {"); + +goTo.marker("expressionWithTypeArguments"); +verify.currentLineContentIs("class A extends bar() {"); \ No newline at end of file From 9146d9bc2f216449eb5bbfc011e6b44915f98796 Mon Sep 17 00:00:00 2001 From: ToddThomson Date: Thu, 13 Aug 2015 11:56:35 -0700 Subject: [PATCH 90/93] Add Spacing for Nonempty Brackets Formatting Option User formatting option to add single space after opening and before closing nonempty brackets. --- src/harness/fourslash.ts | 1 + src/server/editorServices.ts | 1 + src/server/protocol.d.ts | 3 ++ src/services/formatting/rules.ts | 38 +++++++++++++------ src/services/formatting/rulesProvider.ts | 11 ++++++ src/services/services.ts | 1 + .../fourslash/formattingOptionsChange.ts | 2 + tests/cases/fourslash/fourslash.ts | 1 + 8 files changed, 46 insertions(+), 12 deletions(-) diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 7f0cf8ee840..d44da0781dc 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -364,6 +364,7 @@ module FourSlash { InsertSpaceAfterKeywordsInControlFlowStatements: true, InsertSpaceAfterFunctionKeywordForAnonymousFunctions: false, InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false, + InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: false, PlaceOpenBraceOnNewLineForFunctions: false, PlaceOpenBraceOnNewLineForControlBlocks: false, }; diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 7eaf944e916..11486264dea 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -990,6 +990,7 @@ namespace ts.server { InsertSpaceAfterKeywordsInControlFlowStatements: true, InsertSpaceAfterFunctionKeywordForAnonymousFunctions: false, InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: false, + InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: false, PlaceOpenBraceOnNewLineForFunctions: false, PlaceOpenBraceOnNewLineForControlBlocks: false, } diff --git a/src/server/protocol.d.ts b/src/server/protocol.d.ts index 99008770bba..2d694025c84 100644 --- a/src/server/protocol.d.ts +++ b/src/server/protocol.d.ts @@ -452,6 +452,9 @@ declare namespace ts.server.protocol { /** Defines space handling after opening and before closing non empty parenthesis. Default value is false. */ insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis?: boolean; + + /** Defines space handling after opening and before closing non empty brackets. Default value is false. */ + insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets?: boolean; /** Defines whether an open brace is put onto a new line for functions or not. Default value is false. */ placeOpenBraceOnNewLineForFunctions?: boolean; diff --git a/src/services/formatting/rules.ts b/src/services/formatting/rules.ts index 497c5114400..50b8d1ef24c 100644 --- a/src/services/formatting/rules.ts +++ b/src/services/formatting/rules.ts @@ -39,12 +39,12 @@ namespace ts.formatting { public SpaceBetweenCloseBraceAndWhile: Rule; public NoSpaceAfterCloseBrace: Rule; - // No space for indexer and dot + // No space for dot public NoSpaceBeforeDot: Rule; public NoSpaceAfterDot: Rule; + + // No space before and after indexer public NoSpaceBeforeOpenBracket: Rule; - public NoSpaceAfterOpenBracket: Rule; - public NoSpaceBeforeCloseBracket: Rule; public NoSpaceAfterCloseBracket: Rule; // Insert a space after { and before } in single-line contexts, but remove space from empty object literals {}. @@ -191,6 +191,13 @@ namespace ts.formatting { public NoSpaceAfterOpenParen: Rule; public NoSpaceBeforeCloseParen: Rule; + // Insert space after opening and before closing nonempty brackets + public SpaceAfterOpenBracket: Rule; + public SpaceBeforeCloseBracket: Rule; + public NoSpaceBetweenBrackets: Rule; + public NoSpaceAfterOpenBracket: Rule; + public NoSpaceBeforeCloseBracket: Rule; + // Insert space after function keyword for anonymous functions public SpaceAfterAnonymousFunctionKeyword: Rule; public NoSpaceAfterAnonymousFunctionKeyword: Rule; @@ -232,13 +239,13 @@ namespace ts.formatting { this.SpaceBetweenCloseBraceAndWhile = new Rule(RuleDescriptor.create1(SyntaxKind.CloseBraceToken, SyntaxKind.WhileKeyword), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space)); this.NoSpaceAfterCloseBrace = new Rule(RuleDescriptor.create3(SyntaxKind.CloseBraceToken, Shared.TokenRange.FromTokens([SyntaxKind.CloseParenToken, SyntaxKind.CloseBracketToken, SyntaxKind.CommaToken, SyntaxKind.SemicolonToken])), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete)); - // No space for indexer and dot - this.NoSpaceBeforeDot = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.DotToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete)); - this.NoSpaceAfterDot = new Rule(RuleDescriptor.create3(SyntaxKind.DotToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete)); - this.NoSpaceBeforeOpenBracket = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.OpenBracketToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete)); - this.NoSpaceAfterOpenBracket = new Rule(RuleDescriptor.create3(SyntaxKind.OpenBracketToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete)); - this.NoSpaceBeforeCloseBracket = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.CloseBracketToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete)); - this.NoSpaceAfterCloseBracket = new Rule(RuleDescriptor.create3(SyntaxKind.CloseBracketToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBeforeBlockInFunctionDeclarationContext), RuleAction.Delete)); + // No space for dot + this.NoSpaceBeforeDot = new Rule( RuleDescriptor.create2( Shared.TokenRange.Any, SyntaxKind.DotToken ), RuleOperation.create2( new RuleOperationContext( Rules.IsSameLineTokenContext ), RuleAction.Delete ) ); + this.NoSpaceAfterDot = new Rule( RuleDescriptor.create3( SyntaxKind.DotToken, Shared.TokenRange.Any ), RuleOperation.create2( new RuleOperationContext( Rules.IsSameLineTokenContext ), RuleAction.Delete ) ); + + // No space before and after indexer + this.NoSpaceBeforeOpenBracket = new Rule( RuleDescriptor.create2( Shared.TokenRange.Any, SyntaxKind.OpenBracketToken ), RuleOperation.create2( new RuleOperationContext( Rules.IsSameLineTokenContext ), RuleAction.Delete ) ); + this.NoSpaceAfterCloseBracket = new Rule( RuleDescriptor.create3( SyntaxKind.CloseBracketToken, Shared.TokenRange.Any ), RuleOperation.create2( new RuleOperationContext( Rules.IsSameLineTokenContext, Rules.IsNotBeforeBlockInFunctionDeclarationContext ), RuleAction.Delete ) ); // Place a space before open brace in a function declaration this.FunctionOpenBraceLeftTokenRange = Shared.TokenRange.AnyIncludingMultilineComments; @@ -405,8 +412,8 @@ namespace ts.formatting { this.NoSpaceBeforeSemicolon, this.SpaceBeforeOpenBraceInControl, this.SpaceBeforeOpenBraceInFunction, this.SpaceBeforeOpenBraceInTypeScriptDeclWithBlock, this.NoSpaceBeforeComma, - this.NoSpaceBeforeOpenBracket, this.NoSpaceAfterOpenBracket, - this.NoSpaceBeforeCloseBracket, this.NoSpaceAfterCloseBracket, + this.NoSpaceBeforeOpenBracket, + this.NoSpaceAfterCloseBracket, this.SpaceAfterSemicolon, this.NoSpaceBeforeOpenParenInFuncDecl, this.SpaceBetweenStatements, this.SpaceAfterTryFinally @@ -451,6 +458,13 @@ namespace ts.formatting { this.NoSpaceAfterOpenParen = new Rule(RuleDescriptor.create3(SyntaxKind.OpenParenToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete)); this.NoSpaceBeforeCloseParen = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.CloseParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete)); + // Insert space after opening and before closing nonempty brackets + this.SpaceAfterOpenBracket = new Rule( RuleDescriptor.create3( SyntaxKind.OpenBracketToken, Shared.TokenRange.Any ), RuleOperation.create2( new RuleOperationContext( Rules.IsSameLineTokenContext ), RuleAction.Space ) ); + this.SpaceBeforeCloseBracket = new Rule( RuleDescriptor.create2( Shared.TokenRange.Any, SyntaxKind.CloseBracketToken ), RuleOperation.create2( new RuleOperationContext( Rules.IsSameLineTokenContext ), RuleAction.Space ) ); + this.NoSpaceBetweenBrackets = new Rule( RuleDescriptor.create1( SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken ), RuleOperation.create2( new RuleOperationContext( Rules.IsSameLineTokenContext ), RuleAction.Delete ) ); + this.NoSpaceAfterOpenBracket = new Rule( RuleDescriptor.create3( SyntaxKind.OpenBracketToken, Shared.TokenRange.Any ), RuleOperation.create2( new RuleOperationContext( Rules.IsSameLineTokenContext ), RuleAction.Delete ) ); + this.NoSpaceBeforeCloseBracket = new Rule( RuleDescriptor.create2( Shared.TokenRange.Any, SyntaxKind.CloseBracketToken ), RuleOperation.create2( new RuleOperationContext( Rules.IsSameLineTokenContext ), RuleAction.Delete ) ); + // Insert space after function keyword for anonymous functions this.SpaceAfterAnonymousFunctionKeyword = new Rule(RuleDescriptor.create1(SyntaxKind.FunctionKeyword, SyntaxKind.OpenParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsFunctionDeclContext), RuleAction.Space)); this.NoSpaceAfterAnonymousFunctionKeyword = new Rule(RuleDescriptor.create1(SyntaxKind.FunctionKeyword, SyntaxKind.OpenParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsFunctionDeclContext), RuleAction.Delete)); diff --git a/src/services/formatting/rulesProvider.ts b/src/services/formatting/rulesProvider.ts index ac1494571d1..f6cf1de474b 100644 --- a/src/services/formatting/rulesProvider.ts +++ b/src/services/formatting/rulesProvider.ts @@ -71,6 +71,17 @@ namespace ts.formatting { rules.push(this.globalRules.NoSpaceBetweenParens); } + if ( options.InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets ) { + rules.push( this.globalRules.SpaceAfterOpenBracket ); + rules.push( this.globalRules.SpaceBeforeCloseBracket ); + rules.push( this.globalRules.NoSpaceBetweenBrackets ); + } + else { + rules.push( this.globalRules.NoSpaceAfterOpenBracket ); + rules.push( this.globalRules.NoSpaceBeforeCloseBracket ); + rules.push( this.globalRules.NoSpaceBetweenBrackets ); + } + if (options.InsertSpaceAfterSemicolonInForStatements) { rules.push(this.globalRules.SpaceAfterSemicolonInFor); } diff --git a/src/services/services.ts b/src/services/services.ts index 07ba30f4e1d..bfee19b3a6a 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1149,6 +1149,7 @@ namespace ts { InsertSpaceAfterKeywordsInControlFlowStatements: boolean; InsertSpaceAfterFunctionKeywordForAnonymousFunctions: boolean; InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: boolean; + InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: boolean; PlaceOpenBraceOnNewLineForFunctions: boolean; PlaceOpenBraceOnNewLineForControlBlocks: boolean; [s: string]: boolean | number| string; diff --git a/tests/cases/fourslash/formattingOptionsChange.ts b/tests/cases/fourslash/formattingOptionsChange.ts index d84e876f06b..3ac994ab6fc 100644 --- a/tests/cases/fourslash/formattingOptionsChange.ts +++ b/tests/cases/fourslash/formattingOptionsChange.ts @@ -6,6 +6,7 @@ /////*InsertSpaceAfterKeywordsInControlFlowStatements*/if (true) { } /////*InsertSpaceAfterFunctionKeywordForAnonymousFunctions*/(function () { }) /////*InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis*/(1 ) +/////*InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets*/[1 ] /////*PlaceOpenBraceOnNewLineForFunctions*/class foo { ////} /////*PlaceOpenBraceOnNewLineForControlBlocks*/if (true) { @@ -17,6 +18,7 @@ runTest("InsertSpaceBeforeAndAfterBinaryOperators", "1 + 2 - 3", "1+2-3"); runTest("InsertSpaceAfterKeywordsInControlFlowStatements", "if (true) { }", "if(true) { }"); runTest("InsertSpaceAfterFunctionKeywordForAnonymousFunctions", "(function () { })", "(function() { })"); runTest("InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis", " ( 1 )", " (1)"); +runTest( "InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets", "[ 1 ]", "[1]" ); runTest("PlaceOpenBraceOnNewLineForFunctions", "class foo", "class foo {"); runTest("PlaceOpenBraceOnNewLineForControlBlocks", "if ( true )", "if ( true ) {"); diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index 8ce5869a004..42cfc1248b0 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -90,6 +90,7 @@ module FourSlashInterface { InsertSpaceAfterKeywordsInControlFlowStatements: boolean; InsertSpaceAfterFunctionKeywordForAnonymousFunctions: boolean; InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis: boolean; + InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets: boolean; PlaceOpenBraceOnNewLineForFunctions: boolean; PlaceOpenBraceOnNewLineForControlBlocks: boolean; [s: string]: boolean | number| string; From 5a48508ffac824ad0335f624d3332c96ba427bc5 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Thu, 13 Aug 2015 13:14:38 -0700 Subject: [PATCH 91/93] adjust check for node env to handle webpack\browserify --- src/compiler/sys.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 1730e45ee9e..6535bb792ff 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -334,7 +334,9 @@ namespace ts { if (typeof WScript !== "undefined" && typeof ActiveXObject === "function") { return getWScriptSystem(); } - else if (typeof module !== "undefined" && module.exports) { + else if (typeof process !== "undefined" && process.nextTick && !process.browser) { + // process and process.nextTick checks if current environment is node-like + // process.browser check excludes webpack and browserify return getNodeSystem(); } else { From 0415cc7f68d2320257438eaaaa28e174399a9896 Mon Sep 17 00:00:00 2001 From: ToddThomson Date: Thu, 13 Aug 2015 14:06:56 -0700 Subject: [PATCH 92/93] Addresses PR comments Removed all spaces from nonempty parenthesis in code for this PR. Modified the input string for testing the InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets option in the fourslash test. --- src/services/formatting/rules.ts | 18 +++++++++--------- .../cases/fourslash/formattingOptionsChange.ts | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/services/formatting/rules.ts b/src/services/formatting/rules.ts index 50b8d1ef24c..32e76975528 100644 --- a/src/services/formatting/rules.ts +++ b/src/services/formatting/rules.ts @@ -240,12 +240,12 @@ namespace ts.formatting { this.NoSpaceAfterCloseBrace = new Rule(RuleDescriptor.create3(SyntaxKind.CloseBraceToken, Shared.TokenRange.FromTokens([SyntaxKind.CloseParenToken, SyntaxKind.CloseBracketToken, SyntaxKind.CommaToken, SyntaxKind.SemicolonToken])), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete)); // No space for dot - this.NoSpaceBeforeDot = new Rule( RuleDescriptor.create2( Shared.TokenRange.Any, SyntaxKind.DotToken ), RuleOperation.create2( new RuleOperationContext( Rules.IsSameLineTokenContext ), RuleAction.Delete ) ); - this.NoSpaceAfterDot = new Rule( RuleDescriptor.create3( SyntaxKind.DotToken, Shared.TokenRange.Any ), RuleOperation.create2( new RuleOperationContext( Rules.IsSameLineTokenContext ), RuleAction.Delete ) ); + this.NoSpaceBeforeDot = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.DotToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete)); + this.NoSpaceAfterDot = new Rule(RuleDescriptor.create3(SyntaxKind.DotToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete)); // No space before and after indexer - this.NoSpaceBeforeOpenBracket = new Rule( RuleDescriptor.create2( Shared.TokenRange.Any, SyntaxKind.OpenBracketToken ), RuleOperation.create2( new RuleOperationContext( Rules.IsSameLineTokenContext ), RuleAction.Delete ) ); - this.NoSpaceAfterCloseBracket = new Rule( RuleDescriptor.create3( SyntaxKind.CloseBracketToken, Shared.TokenRange.Any ), RuleOperation.create2( new RuleOperationContext( Rules.IsSameLineTokenContext, Rules.IsNotBeforeBlockInFunctionDeclarationContext ), RuleAction.Delete ) ); + this.NoSpaceBeforeOpenBracket = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.OpenBracketToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete)); + this.NoSpaceAfterCloseBracket = new Rule(RuleDescriptor.create3(SyntaxKind.CloseBracketToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext, Rules.IsNotBeforeBlockInFunctionDeclarationContext ), RuleAction.Delete)); // Place a space before open brace in a function declaration this.FunctionOpenBraceLeftTokenRange = Shared.TokenRange.AnyIncludingMultilineComments; @@ -459,11 +459,11 @@ namespace ts.formatting { this.NoSpaceBeforeCloseParen = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.CloseParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete)); // Insert space after opening and before closing nonempty brackets - this.SpaceAfterOpenBracket = new Rule( RuleDescriptor.create3( SyntaxKind.OpenBracketToken, Shared.TokenRange.Any ), RuleOperation.create2( new RuleOperationContext( Rules.IsSameLineTokenContext ), RuleAction.Space ) ); - this.SpaceBeforeCloseBracket = new Rule( RuleDescriptor.create2( Shared.TokenRange.Any, SyntaxKind.CloseBracketToken ), RuleOperation.create2( new RuleOperationContext( Rules.IsSameLineTokenContext ), RuleAction.Space ) ); - this.NoSpaceBetweenBrackets = new Rule( RuleDescriptor.create1( SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken ), RuleOperation.create2( new RuleOperationContext( Rules.IsSameLineTokenContext ), RuleAction.Delete ) ); - this.NoSpaceAfterOpenBracket = new Rule( RuleDescriptor.create3( SyntaxKind.OpenBracketToken, Shared.TokenRange.Any ), RuleOperation.create2( new RuleOperationContext( Rules.IsSameLineTokenContext ), RuleAction.Delete ) ); - this.NoSpaceBeforeCloseBracket = new Rule( RuleDescriptor.create2( Shared.TokenRange.Any, SyntaxKind.CloseBracketToken ), RuleOperation.create2( new RuleOperationContext( Rules.IsSameLineTokenContext ), RuleAction.Delete ) ); + this.SpaceAfterOpenBracket = new Rule(RuleDescriptor.create3(SyntaxKind.OpenBracketToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space)); + this.SpaceBeforeCloseBracket = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.CloseBracketToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Space)); + this.NoSpaceBetweenBrackets = new Rule(RuleDescriptor.create1(SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete)); + this.NoSpaceAfterOpenBracket = new Rule(RuleDescriptor.create3(SyntaxKind.OpenBracketToken, Shared.TokenRange.Any), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete)); + this.NoSpaceBeforeCloseBracket = new Rule(RuleDescriptor.create2(Shared.TokenRange.Any, SyntaxKind.CloseBracketToken), RuleOperation.create2(new RuleOperationContext(Rules.IsSameLineTokenContext), RuleAction.Delete)); // Insert space after function keyword for anonymous functions this.SpaceAfterAnonymousFunctionKeyword = new Rule(RuleDescriptor.create1(SyntaxKind.FunctionKeyword, SyntaxKind.OpenParenToken), RuleOperation.create2(new RuleOperationContext(Rules.IsFunctionDeclContext), RuleAction.Space)); diff --git a/tests/cases/fourslash/formattingOptionsChange.ts b/tests/cases/fourslash/formattingOptionsChange.ts index 3ac994ab6fc..cdd8f61a215 100644 --- a/tests/cases/fourslash/formattingOptionsChange.ts +++ b/tests/cases/fourslash/formattingOptionsChange.ts @@ -6,7 +6,7 @@ /////*InsertSpaceAfterKeywordsInControlFlowStatements*/if (true) { } /////*InsertSpaceAfterFunctionKeywordForAnonymousFunctions*/(function () { }) /////*InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis*/(1 ) -/////*InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets*/[1 ] +/////*InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets*/[1 ]; [ ]; []; [,] /////*PlaceOpenBraceOnNewLineForFunctions*/class foo { ////} /////*PlaceOpenBraceOnNewLineForControlBlocks*/if (true) { @@ -18,7 +18,7 @@ runTest("InsertSpaceBeforeAndAfterBinaryOperators", "1 + 2 - 3", "1+2-3"); runTest("InsertSpaceAfterKeywordsInControlFlowStatements", "if (true) { }", "if(true) { }"); runTest("InsertSpaceAfterFunctionKeywordForAnonymousFunctions", "(function () { })", "(function() { })"); runTest("InsertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis", " ( 1 )", " (1)"); -runTest( "InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets", "[ 1 ]", "[1]" ); +runTest("InsertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets", "[ 1 ];[];[];[ , ]", "[1];[];[];[, ]"); runTest("PlaceOpenBraceOnNewLineForFunctions", "class foo", "class foo {"); runTest("PlaceOpenBraceOnNewLineForControlBlocks", "if ( true )", "if ( true ) {"); From b27125adc2fa1f1cacae7e72de2f8fa625a04482 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Thu, 13 Aug 2015 21:04:05 -0700 Subject: [PATCH 93/93] add 'browser' section to suppress import discovery for webpack/browserify --- package.json | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 2079c41fdd4..52dabc79f6e 100644 --- a/package.json +++ b/package.json @@ -43,5 +43,11 @@ "build:compiler": "jake local", "build:tests": "jake tests", "clean": "jake clean" - } + }, + "browser": { + "buffer": false, + "fs": false, + "os": false, + "path": false + } }