From 668ac108902fc6f7fd3d55b0fd50aed70f64d998 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Fri, 3 Nov 2017 11:51:16 -0700 Subject: [PATCH 01/12] Test where script info path and program path differ because of current directory --- .../unittests/tsserverProjectSystem.ts | 148 ++++++++++++------ src/harness/virtualFileSystemWithWatch.ts | 20 ++- 2 files changed, 121 insertions(+), 47 deletions(-) diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index be38176fb15..5df045335cb 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -437,6 +437,50 @@ namespace ts.projectSystem { verifyDiagnostics(actual, []); } + function assertEvent(actualOutput: string, expectedEvent: protocol.Event, host: TestServerHost) { + assert.equal(actualOutput, server.formatMessage(expectedEvent, nullLogger, Utils.byteLength, host.newLine)); + } + + function checkErrorMessage(host: TestServerHost, eventName: "syntaxDiag" | "semanticDiag", diagnostics: protocol.DiagnosticEventBody) { + const outputs = host.getOutput(); + assert.isTrue(outputs.length >= 1, outputs.toString()); + const event: protocol.Event = { + seq: 0, + type: "event", + event: eventName, + body: diagnostics + }; + assertEvent(outputs[0], event, host); + } + + function checkCompleteEvent(host: TestServerHost, numberOfCurrentEvents: number, expectedSequenceId: number) { + const outputs = host.getOutput(); + assert.equal(outputs.length, numberOfCurrentEvents, outputs.toString()); + const event: protocol.RequestCompletedEvent = { + seq: 0, + type: "event", + event: "requestCompleted", + body: { + request_seq: expectedSequenceId + } + }; + assertEvent(outputs[numberOfCurrentEvents - 1], event, host); + } + + function checkProjectUpdatedInBackgroundEvent(host: TestServerHost, openFiles: string[]) { + const outputs = host.getOutput(); + assert.equal(outputs.length, 1, outputs.toString()); + const event: protocol.ProjectsUpdatedInBackgroundEvent = { + seq: 0, + type: "event", + event: "projectsUpdatedInBackground", + body: { + openFiles + } + }; + assertEvent(outputs[0], event, host); + } + describe("tsserverProjectSystem", () => { const commonFile1: FileOrFolder = { path: "/a/b/commonFile1.ts", @@ -2744,6 +2788,66 @@ namespace ts.projectSystem { const project = projectService.findProject(corruptedConfig.path); checkProjectRootFiles(project, [file1.path]); }); + + it("when opening new file that doesnt exist on disk yet", () => { + const host = createServerHost([libFile]); + let hasError = false; + const errLogger: server.Logger = { + close: noop, + hasLevel: () => true, + loggingEnabled: () => true, + perftrc: noop, + info: noop, + msg: (_s, type) => { + if (type === server.Msg.Err) { + hasError = true; + } + }, + startGroup: noop, + endGroup: noop, + getLogFileName: (): string => undefined + }; + const session = createSession(host, { canUseEvents: true, logger: errLogger, useInferredProjectPerProjectRoot: true }); + + const folderPath = "/user/someuser/projects/someFolder"; + const projectService = session.getProjectService(); + const untitledFile = "untitled:Untitled-1"; + session.executeCommandSeq({ + command: server.CommandNames.Open, + arguments: { + file: untitledFile, + fileContent: "", + scriptKindName: "JS", + projectRootPath: folderPath + } + }); + checkNumberOfProjects(projectService, { inferredProjects: 1 }); + host.checkTimeoutQueueLength(2); + + const newTimeoutId = host.getNextTimeoutId(); + const expectedSequenceId = session.getNextSeq(); + session.executeCommandSeq({ + command: server.CommandNames.Geterr, + arguments: { + delay: 0, + files: [untitledFile] + } + }); + host.checkTimeoutQueueLength(3); + + // Run the last one = get error request + host.runQueuedTimeoutCallbacks(newTimeoutId); + host.checkTimeoutQueueLength(2); + + checkErrorMessage(host, "syntaxDiag", { file: untitledFile, diagnostics: [] }); + host.clearOutput(); + + host.runQueuedImmediateCallbacks(); + assert.isFalse(hasError); + checkErrorMessage(host, "semanticDiag", { file: untitledFile, diagnostics: [] }); + + checkCompleteEvent(host, 2, expectedSequenceId); + }); }); describe("autoDiscovery", () => { @@ -3446,50 +3550,6 @@ namespace ts.projectSystem { verifyNoDiagnostics(diags); }); - function assertEvent(actualOutput: string, expectedEvent: protocol.Event, host: TestServerHost) { - assert.equal(actualOutput, server.formatMessage(expectedEvent, nullLogger, Utils.byteLength, host.newLine)); - } - - function checkErrorMessage(host: TestServerHost, eventName: "syntaxDiag" | "semanticDiag", diagnostics: protocol.DiagnosticEventBody) { - const outputs = host.getOutput(); - assert.isTrue(outputs.length >= 1, outputs.toString()); - const event: protocol.Event = { - seq: 0, - type: "event", - event: eventName, - body: diagnostics - }; - assertEvent(outputs[0], event, host); - } - - function checkCompleteEvent(host: TestServerHost, numberOfCurrentEvents: number, expectedSequenceId: number) { - const outputs = host.getOutput(); - assert.equal(outputs.length, numberOfCurrentEvents, outputs.toString()); - const event: protocol.RequestCompletedEvent = { - seq: 0, - type: "event", - event: "requestCompleted", - body: { - request_seq: expectedSequenceId - } - }; - assertEvent(outputs[numberOfCurrentEvents - 1], event, host); - } - - function checkProjectUpdatedInBackgroundEvent(host: TestServerHost, openFiles: string[]) { - const outputs = host.getOutput(); - assert.equal(outputs.length, 1, outputs.toString()); - const event: protocol.ProjectsUpdatedInBackgroundEvent = { - seq: 0, - type: "event", - event: "projectsUpdatedInBackground", - body: { - openFiles - } - }; - assertEvent(outputs[0], event, host); - } - it("npm install @types works", () => { const folderPath = "/a/b/projects/temp"; const file1: FileOrFolder = { diff --git a/src/harness/virtualFileSystemWithWatch.ts b/src/harness/virtualFileSystemWithWatch.ts index fe40cb42844..6c3bd8a635a 100644 --- a/src/harness/virtualFileSystemWithWatch.ts +++ b/src/harness/virtualFileSystemWithWatch.ts @@ -182,6 +182,10 @@ interface Array {}` private map: TimeOutCallback[] = []; private nextId = 1; + getNextId() { + return this.nextId; + } + register(cb: (...args: any[]) => void, args: any[]) { const timeoutId = this.nextId; this.nextId++; @@ -203,7 +207,13 @@ interface Array {}` return n; } - invoke() { + invoke(invokeKey?: number) { + if (invokeKey) { + this.map[invokeKey](); + delete this.map[invokeKey]; + return; + } + // Note: invoking a callback may result in new callbacks been queued, // so do not clear the entire callback list regardless. Only remove the // ones we have invoked. @@ -553,6 +563,10 @@ interface Array {}` return this.timeoutCallbacks.register(callback, args); } + getNextTimeoutId() { + return this.timeoutCallbacks.getNextId(); + } + clearTimeout(timeoutId: any): void { this.timeoutCallbacks.unregister(timeoutId); } @@ -567,9 +581,9 @@ interface Array {}` assert.equal(callbacksCount, expected, `expected ${expected} timeout callbacks queued but found ${callbacksCount}.`); } - runQueuedTimeoutCallbacks() { + runQueuedTimeoutCallbacks(timeoutId?: number) { try { - this.timeoutCallbacks.invoke(); + this.timeoutCallbacks.invoke(timeoutId); } catch (e) { if (e.message === this.existMessage) { From 373510c4d9f1673fde5f3e17d9a4b63728acb4e7 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Fri, 3 Nov 2017 15:28:28 -0700 Subject: [PATCH 02/12] Handle the script infos that are opened with non rooted disk path Fixes #19588 --- .../unittests/tsserverProjectSystem.ts | 3 +- src/server/editorServices.ts | 46 ++++++++++++++----- src/server/project.ts | 10 ++-- src/server/scriptInfo.ts | 4 +- .../reference/api/tsserverlibrary.d.ts | 10 +++- 5 files changed, 52 insertions(+), 21 deletions(-) diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 5df045335cb..ae90ec7d741 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -2837,8 +2837,9 @@ namespace ts.projectSystem { // Run the last one = get error request host.runQueuedTimeoutCallbacks(newTimeoutId); - host.checkTimeoutQueueLength(2); + assert.isFalse(hasError); + host.checkTimeoutQueueLength(2); checkErrorMessage(host, "syntaxDiag", { file: untitledFile, diagnostics: [] }); host.clearOutput(); diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 9ec190c152f..1730e545257 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -353,6 +353,10 @@ namespace ts.server { * Open files: with value being project root path, and key being Path of the file that is open */ readonly openFiles = createMap(); + /** + * Map of open files that are opened without complete path but have projectRoot as current directory + */ + private readonly openFilesWithNonRootedDiskPath = createMap(); private compilerOptionsForInferredProjects: CompilerOptions; private compilerOptionsForInferredProjectsPerProjectRoot = createMap(); @@ -930,12 +934,16 @@ namespace ts.server { // Closing file should trigger re-reading the file content from disk. This is // because the user may chose to discard the buffer content before saving // to the disk, and the server's version of the file can be out of sync. - info.close(); + const fileExists = this.host.fileExists(info.fileName); + info.close(fileExists); this.stopWatchingConfigFilesForClosedScriptInfo(info); this.openFiles.delete(info.path); + const canonicalFileName = this.toCanonicalFileName(info.fileName); + if (this.openFilesWithNonRootedDiskPath.get(canonicalFileName) === info) { + this.openFilesWithNonRootedDiskPath.delete(canonicalFileName); + } - const fileExists = this.host.fileExists(info.fileName); // collect all projects that should be removed let projectsToRemove: Project[]; @@ -1535,7 +1543,7 @@ namespace ts.server { else { const scriptKind = propertyReader.getScriptKind(f, this.hostConfiguration.extraFileExtensions); const hasMixedContent = propertyReader.hasMixedContent(f, this.hostConfiguration.extraFileExtensions); - scriptInfo = this.getOrCreateScriptInfoNotOpenedByClientForNormalizedPath(normalizedPath, scriptKind, hasMixedContent, project.directoryStructureHost); + scriptInfo = this.getOrCreateScriptInfoNotOpenedByClientForNormalizedPath(normalizedPath, project.currentDirectory, scriptKind, hasMixedContent, project.directoryStructureHost); path = scriptInfo.path; // If this script info is not already a root add it if (!project.isRoot(scriptInfo)) { @@ -1689,9 +1697,9 @@ namespace ts.server { } /*@internal*/ - getOrCreateScriptInfoNotOpenedByClient(uncheckedFileName: string, hostToQueryFileExistsOn: DirectoryStructureHost) { + getOrCreateScriptInfoNotOpenedByClient(uncheckedFileName: string, currentDirectory: string, hostToQueryFileExistsOn: DirectoryStructureHost) { return this.getOrCreateScriptInfoNotOpenedByClientForNormalizedPath( - toNormalizedPath(uncheckedFileName), /*scriptKind*/ undefined, + toNormalizedPath(uncheckedFileName), currentDirectory, /*scriptKind*/ undefined, /*hasMixedContent*/ undefined, hostToQueryFileExistsOn ); } @@ -1722,20 +1730,26 @@ namespace ts.server { } /*@internal*/ - getOrCreateScriptInfoNotOpenedByClientForNormalizedPath(fileName: NormalizedPath, scriptKind?: ScriptKind, hasMixedContent?: boolean, hostToQueryFileExistsOn?: DirectoryStructureHost) { - return this.getOrCreateScriptInfoForNormalizedPath(fileName, /*openedByClient*/ false, /*fileContent*/ undefined, scriptKind, hasMixedContent, hostToQueryFileExistsOn); + getOrCreateScriptInfoNotOpenedByClientForNormalizedPath(fileName: NormalizedPath, currentDirectory: string, scriptKind: ScriptKind | undefined, hasMixedContent: boolean | undefined, hostToQueryFileExistsOn: DirectoryStructureHost | undefined) { + return this.getOrCreateScriptInfoWorker(fileName, currentDirectory, /*openedByClient*/ false, /*fileContent*/ undefined, scriptKind, hasMixedContent, hostToQueryFileExistsOn); } /*@internal*/ - getOrCreateScriptInfoOpenedByClientForNormalizedPath(fileName: NormalizedPath, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, hostToQueryFileExistsOn?: DirectoryStructureHost) { - return this.getOrCreateScriptInfoForNormalizedPath(fileName, /*openedByClient*/ true, fileContent, scriptKind, hasMixedContent, hostToQueryFileExistsOn); + getOrCreateScriptInfoOpenedByClientForNormalizedPath(fileName: NormalizedPath, currentDirectory: string, fileContent: string | undefined, scriptKind: ScriptKind | undefined, hasMixedContent: boolean | undefined) { + return this.getOrCreateScriptInfoWorker(fileName, currentDirectory, /*openedByClient*/ true, fileContent, scriptKind, hasMixedContent); } getOrCreateScriptInfoForNormalizedPath(fileName: NormalizedPath, openedByClient: boolean, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, hostToQueryFileExistsOn?: DirectoryStructureHost) { + return this.getOrCreateScriptInfoWorker(fileName, this.currentDirectory, openedByClient, fileContent, scriptKind, hasMixedContent, hostToQueryFileExistsOn); + } + + private getOrCreateScriptInfoWorker(fileName: NormalizedPath, currentDirectory: string, openedByClient: boolean, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, hostToQueryFileExistsOn?: DirectoryStructureHost) { Debug.assert(fileContent === undefined || openedByClient, "ScriptInfo needs to be opened by client to be able to set its user defined content"); - const path = normalizedPathToPath(fileName, this.currentDirectory, this.toCanonicalFileName); + const path = normalizedPathToPath(fileName, currentDirectory, this.toCanonicalFileName); let info = this.getScriptInfoForPath(path); if (!info) { + Debug.assert(isRootedDiskPath(fileName) || openedByClient, "Script info with relative file name can only be open script info"); + Debug.assert(!isRootedDiskPath(fileName) || this.currentDirectory === currentDirectory || !this.openFilesWithNonRootedDiskPath.has(this.toCanonicalFileName(fileName)), "Open script files with non rooted disk path opened with current directory context cannot have same canonical names"); const isDynamic = isDynamicFileName(fileName); // If the file is not opened by client and the file doesnot exist on the disk, return if (!openedByClient && !isDynamic && !(hostToQueryFileExistsOn || this.host).fileExists(fileName)) { @@ -1746,6 +1760,10 @@ namespace ts.server { if (!openedByClient) { this.watchClosedScriptInfo(info); } + else if (!isRootedDiskPath(fileName) && currentDirectory !== this.currentDirectory) { + // File that is opened by user but isn't rooted disk path + this.openFilesWithNonRootedDiskPath.set(this.toCanonicalFileName(fileName), info); + } } if (openedByClient && !info.isScriptOpen()) { // Opening closed script info @@ -1762,8 +1780,12 @@ namespace ts.server { return info; } + /** + * This gets the script info for the normalized path. If the path is not rooted disk path then the open script info with project root context is preferred + */ getScriptInfoForNormalizedPath(fileName: NormalizedPath) { - return this.getScriptInfoForPath(normalizedPathToPath(fileName, this.currentDirectory, this.toCanonicalFileName)); + return !isRootedDiskPath(fileName) && this.openFilesWithNonRootedDiskPath.get(this.toCanonicalFileName(fileName)) || + this.getScriptInfoForPath(normalizedPathToPath(fileName, this.currentDirectory, this.toCanonicalFileName)); } getScriptInfoForPath(fileName: Path) { @@ -1948,7 +1970,7 @@ namespace ts.server { let sendConfigFileDiagEvent = false; let configFileErrors: ReadonlyArray; - const info = this.getOrCreateScriptInfoOpenedByClientForNormalizedPath(fileName, fileContent, scriptKind, hasMixedContent); + const info = this.getOrCreateScriptInfoOpenedByClientForNormalizedPath(fileName, projectRootPath ? this.getNormalizedAbsolutePath(projectRootPath) : this.currentDirectory, fileContent, scriptKind, hasMixedContent); let project: ConfiguredProject | ExternalProject = this.findContainingExternalProject(fileName); if (!project) { configFileName = this.getConfigFileNameForFile(info, projectRootPath); diff --git a/src/server/project.ts b/src/server/project.ts index 0444e9304b5..edb1d6730e9 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -285,7 +285,7 @@ namespace ts.server { } private getOrCreateScriptInfoAndAttachToProject(fileName: string) { - const scriptInfo = this.projectService.getOrCreateScriptInfoNotOpenedByClient(fileName, this.directoryStructureHost); + const scriptInfo = this.projectService.getOrCreateScriptInfoNotOpenedByClient(fileName, this.currentDirectory, this.directoryStructureHost); if (scriptInfo) { const existingValue = this.rootFilesMap.get(scriptInfo.path); if (existingValue !== scriptInfo && existingValue !== undefined) { @@ -365,7 +365,7 @@ namespace ts.server { /*@internal*/ toPath(fileName: string) { - return this.projectService.toPath(fileName); + return toPath(fileName, this.currentDirectory, this.projectService.toCanonicalFileName); } /*@internal*/ @@ -658,7 +658,7 @@ namespace ts.server { } containsFile(filename: NormalizedPath, requireOpen?: boolean) { - const info = this.projectService.getScriptInfoForNormalizedPath(filename); + const info = this.projectService.getScriptInfoForPath(this.toPath(filename)); if (info && (info.isScriptOpen() || !requireOpen)) { return this.containsScriptInfo(info); } @@ -855,7 +855,7 @@ namespace ts.server { // by the LSHost for files in the program when the program is retrieved above but // the program doesn't contain external files so this must be done explicitly. inserted => { - const scriptInfo = this.projectService.getOrCreateScriptInfoNotOpenedByClient(inserted, this.directoryStructureHost); + const scriptInfo = this.projectService.getOrCreateScriptInfoNotOpenedByClient(inserted, this.currentDirectory, this.directoryStructureHost); scriptInfo.attachToProject(this); }, removed => this.detachScriptInfoFromProject(removed) @@ -901,7 +901,7 @@ namespace ts.server { } getScriptInfoForNormalizedPath(fileName: NormalizedPath) { - const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(fileName); + const scriptInfo = this.projectService.getScriptInfoForPath(this.toPath(fileName)); if (scriptInfo && !scriptInfo.isAttached(this)) { return Errors.ThrowProjectDoesNotContainDocument(fileName, this); } diff --git a/src/server/scriptInfo.ts b/src/server/scriptInfo.ts index 9f029c00f0a..f800a1117d0 100644 --- a/src/server/scriptInfo.ts +++ b/src/server/scriptInfo.ts @@ -248,9 +248,9 @@ namespace ts.server { } } - public close() { + public close(fileExists = true) { this.textStorage.isOpen = false; - if (this.isDynamicOrHasMixedContent()) { + if (this.isDynamicOrHasMixedContent() || !fileExists) { if (this.textStorage.reload("")) { this.markContainingProjectsAsDirty(); } diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index cffa1375608..64bbdd60c7c 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -7058,7 +7058,7 @@ declare namespace ts.server { constructor(host: ServerHost, fileName: NormalizedPath, scriptKind: ScriptKind, hasMixedContent: boolean, path: Path); isScriptOpen(): boolean; open(newText: string): void; - close(): void; + close(fileExists?: boolean): void; getSnapshot(): IScriptSnapshot; getFormatCodeSettings(): FormatCodeSettings; attachToProject(project: Project): boolean; @@ -7482,6 +7482,10 @@ declare namespace ts.server { * Open files: with value being project root path, and key being Path of the file that is open */ readonly openFiles: Map; + /** + * Map of open files that are opened without complete path but have projectRoot as current directory + */ + private readonly openFilesWithNonRootedDiskPath; private compilerOptionsForInferredProjects; private compilerOptionsForInferredProjectsPerProjectRoot; /** @@ -7621,6 +7625,10 @@ declare namespace ts.server { private watchClosedScriptInfo(info); private stopWatchingScriptInfo(info); getOrCreateScriptInfoForNormalizedPath(fileName: NormalizedPath, openedByClient: boolean, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, hostToQueryFileExistsOn?: DirectoryStructureHost): ScriptInfo; + private getOrCreateScriptInfoWorker(fileName, currentDirectory, openedByClient, fileContent?, scriptKind?, hasMixedContent?, hostToQueryFileExistsOn?); + /** + * This gets the script info for the normalized path. If the path is not rooted disk path then the open script info with project root context is preferred + */ getScriptInfoForNormalizedPath(fileName: NormalizedPath): ScriptInfo; getScriptInfoForPath(fileName: Path): ScriptInfo; setHostConfiguration(args: protocol.ConfigureRequestArguments): void; From 163e40cde68d945dda726a93b748fa900e0b782e Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 6 Nov 2017 10:56:52 -0800 Subject: [PATCH 03/12] Add testcase for non existent file without absolute path when opened with/without projectRoot --- .../unittests/tsserverProjectSystem.ts | 128 ++++++++++-------- 1 file changed, 74 insertions(+), 54 deletions(-) diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index ae90ec7d741..a0a5995a1f0 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -2789,65 +2789,85 @@ namespace ts.projectSystem { checkProjectRootFiles(project, [file1.path]); }); - it("when opening new file that doesnt exist on disk yet", () => { - const host = createServerHost([libFile]); - let hasError = false; - const errLogger: server.Logger = { - close: noop, - hasLevel: () => true, - loggingEnabled: () => true, - perftrc: noop, - info: noop, - msg: (_s, type) => { - if (type === server.Msg.Err) { - hasError = true; + describe("when opening new file that doesnt exist on disk yet", () => { + function verifyNonExistentFile(useProjectRoot: boolean) { + const host = createServerHost([libFile]); + let hasError = false; + const errLogger: server.Logger = { + close: noop, + hasLevel: () => true, + loggingEnabled: () => true, + perftrc: noop, + info: noop, + msg: (_s, type) => { + if (type === server.Msg.Err) { + hasError = true; + } + }, + startGroup: noop, + endGroup: noop, + getLogFileName: (): string => undefined + }; + const session = createSession(host, { canUseEvents: true, logger: errLogger, useInferredProjectPerProjectRoot: true }); + + const folderPath = "/user/someuser/projects/someFolder"; + const projectService = session.getProjectService(); + const untitledFile = "untitled:Untitled-1"; + session.executeCommandSeq({ + command: server.CommandNames.Open, + arguments: { + file: untitledFile, + fileContent: "", + scriptKindName: "JS", + projectRootPath: useProjectRoot ? folderPath : undefined } - }, - startGroup: noop, - endGroup: noop, - getLogFileName: (): string => undefined - }; - const session = createSession(host, { canUseEvents: true, logger: errLogger, useInferredProjectPerProjectRoot: true }); - - const folderPath = "/user/someuser/projects/someFolder"; - const projectService = session.getProjectService(); - const untitledFile = "untitled:Untitled-1"; - session.executeCommandSeq({ - command: server.CommandNames.Open, - arguments: { - file: untitledFile, - fileContent: "", - scriptKindName: "JS", - projectRootPath: folderPath + }); + checkNumberOfProjects(projectService, { inferredProjects: 1 }); + const infoForUntitledAtProjectRoot = projectService.getScriptInfoForPath(`${folderPath.toLowerCase()}/${untitledFile.toLowerCase()}` as Path); + const infoForUnitiledAtRoot = projectService.getScriptInfoForPath(`/${untitledFile.toLowerCase()}` as Path); + if (useProjectRoot) { + assert.isDefined(infoForUntitledAtProjectRoot); + assert.isUndefined(infoForUnitiledAtRoot); } - }); - checkNumberOfProjects(projectService, { inferredProjects: 1 }); - host.checkTimeoutQueueLength(2); - - const newTimeoutId = host.getNextTimeoutId(); - const expectedSequenceId = session.getNextSeq(); - session.executeCommandSeq({ - command: server.CommandNames.Geterr, - arguments: { - delay: 0, - files: [untitledFile] + else { + assert.isDefined(infoForUnitiledAtRoot); + assert.isUndefined(infoForUntitledAtProjectRoot); } + host.checkTimeoutQueueLength(2); + + const newTimeoutId = host.getNextTimeoutId(); + const expectedSequenceId = session.getNextSeq(); + session.executeCommandSeq({ + command: server.CommandNames.Geterr, + arguments: { + delay: 0, + files: [untitledFile] + } + }); + host.checkTimeoutQueueLength(3); + + // Run the last one = get error request + host.runQueuedTimeoutCallbacks(newTimeoutId); + + assert.isFalse(hasError); + host.checkTimeoutQueueLength(2); + checkErrorMessage(host, "syntaxDiag", { file: untitledFile, diagnostics: [] }); + host.clearOutput(); + + host.runQueuedImmediateCallbacks(); + assert.isFalse(hasError); + checkErrorMessage(host, "semanticDiag", { file: untitledFile, diagnostics: [] }); + + checkCompleteEvent(host, 2, expectedSequenceId); + } + + it("has projectRoot", () => { + verifyNonExistentFile(/*useProjectRoot*/ true); }); - host.checkTimeoutQueueLength(3); - // Run the last one = get error request - host.runQueuedTimeoutCallbacks(newTimeoutId); - - assert.isFalse(hasError); - host.checkTimeoutQueueLength(2); - checkErrorMessage(host, "syntaxDiag", { file: untitledFile, diagnostics: [] }); - host.clearOutput(); - - host.runQueuedImmediateCallbacks(); - assert.isFalse(hasError); - checkErrorMessage(host, "semanticDiag", { file: untitledFile, diagnostics: [] }); - - checkCompleteEvent(host, 2, expectedSequenceId); + it("does not have projectRoot", () => { + verifyNonExistentFile(/*useProjectRoot*/ false); + }); }); }); From 4f48bf80fe2780741cbeb91dbaae2f2142a67995 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Mon, 6 Nov 2017 12:51:34 -0800 Subject: [PATCH 04/12] Revised emit for computed property names, including with decorators (#19430) * Revised emit for computed property names * Fix downlevel name generation scopes * Accept slightly more conservative baseline * First feedback pass * Reduce number of nonrequired variable declarations and assignments * Remove side-effect-free identifier references * skip partially emitted expressions * Comments, move starsOnNewLine to emitNode * Put expressions on newlines when inlined in class expressions for consistency * Update new ref * Fix typo in comment --- src/compiler/binder.ts | 2 + src/compiler/emitter.ts | 64 +- src/compiler/factory.ts | 41 +- src/compiler/transformers/es2015.ts | 17 +- src/compiler/transformers/generators.ts | 5 +- src/compiler/transformers/ts.ts | 96 ++- src/compiler/types.ts | 3 +- .../capturedParametersInInitializers2.js | 15 +- .../reference/computedPropertyNames12_ES5.js | 8 +- .../reference/computedPropertyNames12_ES6.js | 8 +- .../reference/decoratorOnClassMethod13.js | 9 +- .../reference/decoratorOnClassMethod4.js | 5 +- .../reference/decoratorOnClassMethod5.js | 5 +- .../reference/decoratorOnClassMethod6.js | 5 +- .../reference/decoratorOnClassMethod7.js | 5 +- .../decoratorsOnComputedProperties.errors.txt | 435 ++++++++++ .../decoratorsOnComputedProperties.js | 457 ++++++++++ .../decoratorsOnComputedProperties.symbols | 664 ++++++++++++++ .../decoratorsOnComputedProperties.types | 816 ++++++++++++++++++ tests/baselines/reference/newTarget.es5.js | 6 +- .../reference/parserComputedPropertyName10.js | 4 +- .../reference/parserComputedPropertyName25.js | 4 +- .../reference/parserComputedPropertyName27.js | 4 +- .../reference/parserComputedPropertyName28.js | 4 +- .../reference/parserComputedPropertyName29.js | 4 +- .../reference/parserComputedPropertyName33.js | 4 +- .../parserES5ComputedPropertyName10.js | 4 +- tests/baselines/reference/symbolProperty7.js | 5 +- .../decoratorsOnComputedProperties.ts | 191 ++++ 29 files changed, 2777 insertions(+), 113 deletions(-) create mode 100644 tests/baselines/reference/decoratorsOnComputedProperties.errors.txt create mode 100644 tests/baselines/reference/decoratorsOnComputedProperties.js create mode 100644 tests/baselines/reference/decoratorsOnComputedProperties.symbols create mode 100644 tests/baselines/reference/decoratorsOnComputedProperties.types create mode 100644 tests/cases/compiler/decoratorsOnComputedProperties.ts diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 72cff733b0c..cf8b3eefde8 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -2963,6 +2963,7 @@ namespace ts { || hasModifier(node, ModifierFlags.TypeScriptModifier) || node.typeParameters || node.type + || (node.name && isComputedPropertyName(node.name)) // While computed method names aren't typescript, the TS transform must visit them to emit property declarations correctly || !node.body) { transformFlags |= TransformFlags.AssertTypeScript; } @@ -2993,6 +2994,7 @@ namespace ts { if (node.decorators || hasModifier(node, ModifierFlags.TypeScriptModifier) || node.type + || (node.name && isComputedPropertyName(node.name)) // While computed accessor names aren't typescript, the TS transform must visit them to emit property declarations correctly || !node.body) { transformFlags |= TransformFlags.AssertTypeScript; } diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 74e5d4d5539..7a1d88d3bfd 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1733,26 +1733,15 @@ namespace ts { increaseIndent(); } - if (getEmitFlags(node) & EmitFlags.ReuseTempVariableScope) { - emitSignatureHead(node); - if (onEmitNode) { - onEmitNode(EmitHint.Unspecified, body, emitBlockCallback); - } - else { - emitBlockFunctionBody(body); - } + pushNameGenerationScope(node); + emitSignatureHead(node); + if (onEmitNode) { + onEmitNode(EmitHint.Unspecified, body, emitBlockCallback); } else { - pushNameGenerationScope(); - emitSignatureHead(node); - if (onEmitNode) { - onEmitNode(EmitHint.Unspecified, body, emitBlockCallback); - } - else { - emitBlockFunctionBody(body); - } - popNameGenerationScope(); + emitBlockFunctionBody(body); } + popNameGenerationScope(node); if (indentedFlag) { decreaseIndent(); @@ -1871,11 +1860,9 @@ namespace ts { emitTypeParameters(node, node.typeParameters); emitList(node, node.heritageClauses, ListFormat.ClassHeritageClauses); - pushNameGenerationScope(); write(" {"); emitList(node, node.members, ListFormat.ClassMembers); write("}"); - popNameGenerationScope(); if (indentedFlag) { decreaseIndent(); @@ -1909,11 +1896,9 @@ namespace ts { emitModifiers(node, node.modifiers); write("enum "); emit(node.name); - pushNameGenerationScope(); write(" {"); emitList(node, node.members, ListFormat.EnumMembers); write("}"); - popNameGenerationScope(); } function emitModuleDeclaration(node: ModuleDeclaration) { @@ -1935,11 +1920,11 @@ namespace ts { } function emitModuleBlock(node: ModuleBlock) { - pushNameGenerationScope(); + pushNameGenerationScope(node); write("{"); emitBlockStatements(node, /*forceSingleLine*/ isEmptyBlock(node)); write("}"); - popNameGenerationScope(); + popNameGenerationScope(node); } function emitCaseBlock(node: CaseBlock) { @@ -2284,11 +2269,11 @@ namespace ts { function emitSourceFileWorker(node: SourceFile) { const statements = node.statements; - pushNameGenerationScope(); + pushNameGenerationScope(node); emitHelpersIndirect(node); const index = findIndex(statements, statement => !isPrologueDirective(statement)); emitList(node, statements, ListFormat.MultiLine, index === -1 ? statements.length : index); - popNameGenerationScope(); + popNameGenerationScope(node); } // Transformation nodes @@ -2751,7 +2736,7 @@ namespace ts { } } else { - return nextNode.startsOnNewLine; + return getStartsOnNewLine(nextNode); } } @@ -2782,7 +2767,7 @@ namespace ts { function synthesizedNodeStartsOnNewLine(node: Node, format?: ListFormat) { if (nodeIsSynthesized(node)) { - const startsOnNewLine = node.startsOnNewLine; + const startsOnNewLine = getStartsOnNewLine(node); if (startsOnNewLine === undefined) { return (format & ListFormat.PreferNewLine) !== 0; } @@ -2799,7 +2784,7 @@ namespace ts { node2 = skipSynthesizedParentheses(node2); // Always use a newline for synthesized code if the synthesizer desires it. - if (node2.startsOnNewLine) { + if (getStartsOnNewLine(node2)) { return true; } @@ -2858,7 +2843,10 @@ namespace ts { /** * Push a new name generation scope. */ - function pushNameGenerationScope() { + function pushNameGenerationScope(node: Node | undefined) { + if (node && getEmitFlags(node) & EmitFlags.ReuseTempVariableScope) { + return; + } tempFlagsStack.push(tempFlags); tempFlags = 0; } @@ -2866,7 +2854,10 @@ namespace ts { /** * Pop the current name generation scope. */ - function popNameGenerationScope() { + function popNameGenerationScope(node: Node | undefined) { + if (node && getEmitFlags(node) & EmitFlags.ReuseTempVariableScope) { + return; + } tempFlags = tempFlagsStack.pop(); } @@ -2877,8 +2868,17 @@ namespace ts { if (name.autoGenerateKind === GeneratedIdentifierKind.Node) { // Node names generate unique names based on their original node // and are cached based on that node's id. - const node = getNodeForGeneratedName(name); - return generateNameCached(node); + if (name.skipNameGenerationScope) { + const savedTempFlags = tempFlags; + popNameGenerationScope(/*node*/ undefined); + const result = generateNameCached(getNodeForGeneratedName(name)); + pushNameGenerationScope(/*node*/ undefined); + tempFlags = savedTempFlags; + return result; + } + else { + return generateNameCached(getNodeForGeneratedName(name)); + } } else { // Auto, Loop, and Unique names are cached based on their unique diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 053672d19df..c9e0fec5927 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -13,9 +13,6 @@ namespace ts { if (updated !== original) { setOriginalNode(updated, original); setTextRange(updated, original); - if (original.startsOnNewLine) { - updated.startsOnNewLine = true; - } aggregateTransformFlags(updated); } return updated; @@ -168,11 +165,14 @@ namespace ts { } /** Create a unique name generated for a node. */ - export function getGeneratedNameForNode(node: Node): Identifier { + export function getGeneratedNameForNode(node: Node): Identifier; + /*@internal*/ export function getGeneratedNameForNode(node: Node, shouldSkipNameGenerationScope?: boolean): Identifier; + export function getGeneratedNameForNode(node: Node, shouldSkipNameGenerationScope?: boolean): Identifier { const name = createIdentifier(""); name.autoGenerateKind = GeneratedIdentifierKind.Node; name.autoGenerateId = nextAutoGenerateId; name.original = node; + name.skipNameGenerationScope = !!shouldSkipNameGenerationScope; nextAutoGenerateId++; return name; } @@ -2683,6 +2683,24 @@ namespace ts { return node; } + /** + * Gets a custom text range to use when emitting comments. + */ + /*@internal*/ + export function getStartsOnNewLine(node: Node) { + const emitNode = node.emitNode; + return emitNode && emitNode.startsOnNewLine; + } + + /** + * Sets a custom text range to use when emitting comments. + */ + /*@internal*/ + export function setStartsOnNewLine(node: T, newLine: boolean) { + getOrCreateEmitNode(node).startsOnNewLine = newLine; + return node; + } + /** * Gets a custom text range to use when emitting comments. */ @@ -2841,7 +2859,8 @@ namespace ts { sourceMapRange, tokenSourceMapRanges, constantValue, - helpers + helpers, + startsOnNewLine, } = sourceEmitNode; if (!destEmitNode) destEmitNode = {}; // We are using `.slice()` here in case `destEmitNode.leadingComments` is pushed to later. @@ -2853,6 +2872,7 @@ namespace ts { if (tokenSourceMapRanges) destEmitNode.tokenSourceMapRanges = mergeTokenSourceMapRanges(tokenSourceMapRanges, destEmitNode.tokenSourceMapRanges); if (constantValue !== undefined) destEmitNode.constantValue = constantValue; if (helpers) destEmitNode.helpers = addRange(destEmitNode.helpers, helpers); + if (startsOnNewLine !== undefined) destEmitNode.startsOnNewLine = startsOnNewLine; return destEmitNode; } @@ -3014,7 +3034,7 @@ namespace ts { if (children.length > 1) { for (const child of children) { - child.startsOnNewLine = true; + startOnNewLine(child); argumentsList.push(child); } } @@ -3045,7 +3065,7 @@ namespace ts { if (children && children.length > 0) { if (children.length > 1) { for (const child of children) { - child.startsOnNewLine = true; + startOnNewLine(child); argumentsList.push(child); } } @@ -3620,8 +3640,8 @@ namespace ts { ); setOriginalNode(updated, node); setTextRange(updated, node); - if (node.startsOnNewLine) { - updated.startsOnNewLine = true; + if (getStartsOnNewLine(node)) { + setStartsOnNewLine(updated, /*newLine*/ true); } aggregateTransformFlags(updated); return updated; @@ -4250,8 +4270,7 @@ namespace ts { } export function startOnNewLine(node: T): T { - node.startsOnNewLine = true; - return node; + return setStartsOnNewLine(node, /*newLine*/ true); } export function getExternalHelpersModuleName(node: SourceFile) { diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index a1e52480172..989b0827570 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -787,9 +787,7 @@ namespace ts { // To preserve the behavior of the old emitter, we explicitly indent // the body of the function here if it was requested in an earlier // transformation. - if (getEmitFlags(node) & EmitFlags.Indented) { - setEmitFlags(classFunction, EmitFlags.Indented); - } + setEmitFlags(classFunction, (getEmitFlags(node) & EmitFlags.Indented) | EmitFlags.ReuseTempVariableScope); // "inner" and "outer" below are added purely to preserve source map locations from // the old emitter @@ -1327,7 +1325,8 @@ namespace ts { EmitFlags.SingleLine | EmitFlags.NoTrailingSourceMap | EmitFlags.NoTokenSourceMaps ) ); - statement.startsOnNewLine = true; + + startOnNewLine(statement); setTextRange(statement, parameter); setEmitFlags(statement, EmitFlags.NoTokenSourceMaps | EmitFlags.NoTrailingSourceMap | EmitFlags.CustomPrologue); statements.push(statement); @@ -1683,7 +1682,7 @@ namespace ts { ] ); if (startsOnNewLine) { - call.startsOnNewLine = true; + startOnNewLine(call); } exitSubtree(ancestorFacts, HierarchyFacts.PropagateNewTargetMask, hierarchyFacts & HierarchyFacts.PropagateNewTargetMask ? HierarchyFacts.NewTarget : HierarchyFacts.None); @@ -2602,7 +2601,7 @@ namespace ts { ); if (node.multiLine) { - assignment.startsOnNewLine = true; + startOnNewLine(assignment); } expressions.push(assignment); @@ -3083,7 +3082,7 @@ namespace ts { ); setTextRange(expression, property); if (startsOnNewLine) { - expression.startsOnNewLine = true; + startOnNewLine(expression); } return expression; } @@ -3105,7 +3104,7 @@ namespace ts { ); setTextRange(expression, property); if (startsOnNewLine) { - expression.startsOnNewLine = true; + startOnNewLine(expression); } return expression; } @@ -3128,7 +3127,7 @@ namespace ts { ); setTextRange(expression, method); if (startsOnNewLine) { - expression.startsOnNewLine = true; + startOnNewLine(expression); } exitSubtree(ancestorFacts, HierarchyFacts.PropagateNewTargetMask, hierarchyFacts & HierarchyFacts.PropagateNewTargetMask ? HierarchyFacts.NewTarget : HierarchyFacts.None); return expression; diff --git a/src/compiler/transformers/generators.ts b/src/compiler/transformers/generators.ts index 7ede62b1540..bd2a4ef554d 100644 --- a/src/compiler/transformers/generators.ts +++ b/src/compiler/transformers/generators.ts @@ -1077,7 +1077,7 @@ namespace ts { const visited = visitNode(expression, visitor, isExpression); if (visited) { if (multiLine) { - visited.startsOnNewLine = true; + startOnNewLine(visited); } expressions.push(visited); } @@ -2683,8 +2683,7 @@ namespace ts { if (clauses) { const labelExpression = createPropertyAccess(state, "label"); const switchStatement = createSwitch(labelExpression, createCaseBlock(clauses)); - switchStatement.startsOnNewLine = true; - return [switchStatement]; + return [startOnNewLine(switchStatement)]; } if (statements) { diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 5339f2aaee5..39a4cc83bda 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -86,6 +86,12 @@ namespace ts { */ let applicableSubstitutions: TypeScriptSubstitutionFlags; + /** + * Tracks what computed name expressions originating from elided names must be inlined + * at the next execution site, in document order + */ + let pendingExpressions: Expression[] | undefined; + return transformSourceFile; /** @@ -395,9 +401,11 @@ namespace ts { case SyntaxKind.TypeAliasDeclaration: // TypeScript type-only declarations are elided. + return undefined; case SyntaxKind.PropertyDeclaration: - // TypeScript property declarations are elided. + // TypeScript property declarations are elided. However their names are still visited, and can potentially be retained if they could have sideeffects + return visitPropertyDeclaration(node as PropertyDeclaration); case SyntaxKind.NamespaceExportDeclaration: // TypeScript namespace export declarations are elided. @@ -584,6 +592,9 @@ namespace ts { * @param node The node to transform. */ function visitClassDeclaration(node: ClassDeclaration): VisitResult { + const savedPendingExpressions = pendingExpressions; + pendingExpressions = undefined; + const staticProperties = getInitializedProperties(node, /*isStatic*/ true); const facts = getClassFacts(node, staticProperties); @@ -598,6 +609,12 @@ namespace ts { let statements: Statement[] = [classStatement]; + // Write any pending expressions from elided or moved computed property names + if (some(pendingExpressions)) { + statements.push(createStatement(inlineExpressions(pendingExpressions))); + } + pendingExpressions = savedPendingExpressions; + // Emit static property assignment. Because classDeclaration is lexically evaluated, // it is safe to emit static property assignment after classDeclaration // From ES6 specification: @@ -856,6 +873,9 @@ namespace ts { * @param node The node to transform. */ function visitClassExpression(node: ClassExpression): Expression { + const savedPendingExpressions = pendingExpressions; + pendingExpressions = undefined; + const staticProperties = getInitializedProperties(node, /*isStatic*/ true); const heritageClauses = visitNodes(node.heritageClauses, visitor, isHeritageClause); const members = transformClassMembers(node, some(heritageClauses, c => c.token === SyntaxKind.ExtendsKeyword)); @@ -871,7 +891,7 @@ namespace ts { setOriginalNode(classExpression, node); setTextRange(classExpression, node); - if (staticProperties.length > 0) { + if (some(staticProperties) || some(pendingExpressions)) { const expressions: Expression[] = []; const temp = createTempVariable(hoistVariableDeclaration); if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.ClassWithConstructorReference) { @@ -884,11 +904,15 @@ namespace ts { // the body of a class with static initializers. setEmitFlags(classExpression, EmitFlags.Indented | getEmitFlags(classExpression)); expressions.push(startOnNewLine(createAssignment(temp, classExpression))); + // Add any pending expressions leftover from elided or relocated computed property names + addRange(expressions, map(pendingExpressions, startOnNewLine)); + pendingExpressions = savedPendingExpressions; addRange(expressions, generateInitializedPropertyExpressions(staticProperties, temp)); expressions.push(startOnNewLine(temp)); return inlineExpressions(expressions); } + pendingExpressions = savedPendingExpressions; return classExpression; } @@ -1202,7 +1226,7 @@ namespace ts { const expressions: Expression[] = []; for (const property of properties) { const expression = transformInitializedProperty(property, receiver); - expression.startsOnNewLine = true; + startOnNewLine(expression); setSourceMapRange(expression, moveRangePastModifiers(property)); setCommentRange(expression, property); expressions.push(expression); @@ -1218,7 +1242,10 @@ namespace ts { * @param receiver The object receiving the property assignment. */ function transformInitializedProperty(property: PropertyDeclaration, receiver: LeftHandSideExpression) { - const propertyName = visitPropertyNameOfClassElement(property); + // We generate a name here in order to reuse the value cached by the relocated computed name expression (which uses the same generated name) + const propertyName = isComputedPropertyName(property.name) && !isSimpleInlineableExpression(property.name.expression) + ? updateComputedPropertyName(property.name, getGeneratedNameForNode(property.name, !hasModifier(property, ModifierFlags.Static))) + : property.name; const initializer = visitNode(property.initializer, visitor, isExpression); const memberAccess = createMemberAccessForPropertyName(receiver, propertyName, /*location*/ propertyName); @@ -2041,6 +2068,16 @@ namespace ts { ); } + /** + * A simple inlinable expression is an expression which can be copied into multiple locations + * without risk of repeating any sideeffects and whose value could not possibly change between + * any such locations + */ + function isSimpleInlineableExpression(expression: Expression) { + return !isIdentifier(expression) && isSimpleCopiableExpression(expression) || + isWellKnownSymbolSyntactically(expression); + } + /** * Gets an expression that represents a property name. For a computed property, a * name is generated for the node. @@ -2050,7 +2087,7 @@ namespace ts { function getExpressionForPropertyName(member: ClassElement | EnumMember, generateNameForComputedPropertyName: boolean): Expression { const name = member.name; if (isComputedPropertyName(name)) { - return generateNameForComputedPropertyName + return generateNameForComputedPropertyName && !isSimpleInlineableExpression((name).expression) ? getGeneratedNameForNode(name) : (name).expression; } @@ -2062,6 +2099,26 @@ namespace ts { } } + /** + * If the name is a computed property, this function transforms it, then either returns an expression which caches the + * value of the result or the expression itself if the value is either unused or safe to inline into multiple locations + * @param shouldHoist Does the expression need to be reused? (ie, for an initializer or a decorator) + * @param omitSimple Should expressions with no observable side-effects be elided? (ie, the expression is not hoisted for a decorator or initializer and is a literal) + */ + function getPropertyNameExpressionIfNeeded(name: PropertyName, shouldHoist: boolean, omitSimple: boolean): Expression { + if (isComputedPropertyName(name)) { + const expression = visitNode(name.expression, visitor, isExpression); + const innerExpression = skipPartiallyEmittedExpressions(expression); + const inlinable = isSimpleInlineableExpression(innerExpression); + if (!inlinable && shouldHoist) { + const generatedName = getGeneratedNameForNode(name); + hoistVariableDeclaration(generatedName); + return createAssignment(generatedName, expression); + } + return (omitSimple && (inlinable || isIdentifier(innerExpression))) ? undefined : expression; + } + } + /** * Visits the property name of a class element, for use when emitting property * initializers. For a computed property on a node with decorators, a temporary @@ -2071,15 +2128,14 @@ namespace ts { */ function visitPropertyNameOfClassElement(member: ClassElement): PropertyName { const name = member.name; - if (isComputedPropertyName(name)) { - let expression = visitNode(name.expression, visitor, isExpression); - if (member.decorators) { - const generatedName = getGeneratedNameForNode(name); - hoistVariableDeclaration(generatedName); - expression = createAssignment(generatedName, expression); + let expr = getPropertyNameExpressionIfNeeded(name, some(member.decorators), /*omitSimple*/ false); + if (expr) { // expr only exists if `name` is a computed property name + // Inline any pending expressions from previous elided or relocated computed property name expressions in order to preserve execution order + if (some(pendingExpressions)) { + expr = inlineExpressions([...pendingExpressions, expr]); + pendingExpressions.length = 0; } - - return updateComputedPropertyName(name, expression); + return updateComputedPropertyName(name as ComputedPropertyName, expr); } else { return name; @@ -2136,6 +2192,14 @@ namespace ts { return !nodeIsMissing(node.body); } + function visitPropertyDeclaration(node: PropertyDeclaration): undefined { + const expr = getPropertyNameExpressionIfNeeded(node.name, some(node.decorators) || !!node.initializer, /*omitSimple*/ true); + if (expr && !isSimpleInlineableExpression(expr)) { + (pendingExpressions || (pendingExpressions = [])).push(expr); + } + return undefined; + } + function visitConstructor(node: ConstructorDeclaration) { if (!shouldEmitFunctionLikeDeclaration(node)) { return undefined; @@ -2156,7 +2220,7 @@ namespace ts { * This function will be called when one of the following conditions are met: * - The node is an overload * - The node is marked as abstract, public, private, protected, or readonly - * - The node has both a decorator and a computed property name + * - The node has a computed property name * * @param node The method node. */ @@ -2200,7 +2264,7 @@ namespace ts { * * This function will be called when one of the following conditions are met: * - The node is marked as abstract, public, private, or protected - * - The node has both a decorator and a computed property name + * - The node has a computed property name * * @param node The get accessor node. */ @@ -2231,7 +2295,7 @@ namespace ts { * * This function will be called when one of the following conditions are met: * - The node is marked as abstract, public, private, or protected - * - The node has both a decorator and a computed property name + * - The node has a computed property name * * @param node The set accessor node. */ diff --git a/src/compiler/types.ts b/src/compiler/types.ts index b4e84ae6a75..adab1f32492 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -520,7 +520,6 @@ namespace ts { /* @internal */ id?: number; // Unique id (used to look up NodeLinks) parent?: Node; // Parent node (initialized by binding) /* @internal */ original?: Node; // The original node if this is an updated node. - /* @internal */ startsOnNewLine?: boolean; // Whether a synthesized node should start on a new line (used by transforms). /* @internal */ symbol?: Symbol; // Symbol declared by node (initialized by binding) /* @internal */ locals?: SymbolTable; // Locals associated with node (initialized by binding) /* @internal */ nextContainer?: Node; // Next container in declaration order (initialized by binding) @@ -630,6 +629,7 @@ namespace ts { isInJSDocNamespace?: boolean; // if the node is a member in a JSDoc namespace /*@internal*/ typeArguments?: NodeArray; // Only defined on synthesized nodes. Though not syntactically valid, used in emitting diagnostics. /*@internal*/ jsdocDotPos?: number; // Identifier occurs in JSDoc-style generic: Id. + /*@internal*/ skipNameGenerationScope?: boolean; // Should skip a name generation scope when generating the name for this identifier } // Transient identifier node (marked by id === -1) @@ -4330,6 +4330,7 @@ namespace ts { constantValue?: string | number; // The constant value of an expression externalHelpersModuleName?: Identifier; // The local name for an imported helpers module helpers?: EmitHelper[]; // Emit helpers for the node + startsOnNewLine?: boolean; // If the node should begin on a new line } export const enum EmitFlags { diff --git a/tests/baselines/reference/capturedParametersInInitializers2.js b/tests/baselines/reference/capturedParametersInInitializers2.js index 2e833cac003..8982862af4f 100644 --- a/tests/baselines/reference/capturedParametersInInitializers2.js +++ b/tests/baselines/reference/capturedParametersInInitializers2.js @@ -19,11 +19,14 @@ function foo(y, x) { var _a; } function foo2(y, x) { - if (y === void 0) { y = /** @class */ (function () { - function class_2() { - this[x] = x; - } - return class_2; - }()); } + if (y === void 0) { y = (_a = /** @class */ (function () { + function class_2() { + this[_b] = x; + } + return class_2; + }()), + _b = x, + _a); } if (x === void 0) { x = 1; } + var _b, _a; } diff --git a/tests/baselines/reference/computedPropertyNames12_ES5.js b/tests/baselines/reference/computedPropertyNames12_ES5.js index b3743a36b2b..e8bcf325c34 100644 --- a/tests/baselines/reference/computedPropertyNames12_ES5.js +++ b/tests/baselines/reference/computedPropertyNames12_ES5.js @@ -22,10 +22,12 @@ var n; var a; var C = /** @class */ (function () { function C() { - this[n] = n; - this[s + n] = 2; + this[_a] = n; + this[_b] = 2; this["hello bye"] = 0; } - C["hello " + a + " bye"] = 0; + _a = n, s + s, _b = s + n, +s, _c = "hello " + a + " bye"; + C[_c] = 0; return C; + var _a, _b, _c; }()); diff --git a/tests/baselines/reference/computedPropertyNames12_ES6.js b/tests/baselines/reference/computedPropertyNames12_ES6.js index fd6ccb6e486..6f91ec92cc9 100644 --- a/tests/baselines/reference/computedPropertyNames12_ES6.js +++ b/tests/baselines/reference/computedPropertyNames12_ES6.js @@ -22,9 +22,11 @@ var n; var a; class C { constructor() { - this[n] = n; - this[s + n] = 2; + this[_a] = n; + this[_b] = 2; this[`hello bye`] = 0; } } -C[`hello ${a} bye`] = 0; +_a = n, s + s, _b = s + n, +s, _c = `hello ${a} bye`; +C[_c] = 0; +var _a, _b, _c; diff --git a/tests/baselines/reference/decoratorOnClassMethod13.js b/tests/baselines/reference/decoratorOnClassMethod13.js index adf21f733eb..e8a913070fc 100644 --- a/tests/baselines/reference/decoratorOnClassMethod13.js +++ b/tests/baselines/reference/decoratorOnClassMethod13.js @@ -14,13 +14,12 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key, return c > 3 && r && Object.defineProperty(target, key, r), r; }; class C { - [_a = "1"]() { } - [_b = "b"]() { } + ["1"]() { } + ["b"]() { } } __decorate([ dec -], C.prototype, _a, null); +], C.prototype, "1", null); __decorate([ dec -], C.prototype, _b, null); -var _a, _b; +], C.prototype, "b", null); diff --git a/tests/baselines/reference/decoratorOnClassMethod4.js b/tests/baselines/reference/decoratorOnClassMethod4.js index 5c7b91c1c83..c68cca5d3a0 100644 --- a/tests/baselines/reference/decoratorOnClassMethod4.js +++ b/tests/baselines/reference/decoratorOnClassMethod4.js @@ -13,9 +13,8 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key, return c > 3 && r && Object.defineProperty(target, key, r), r; }; class C { - [_a = "method"]() { } + ["method"]() { } } __decorate([ dec -], C.prototype, _a, null); -var _a; +], C.prototype, "method", null); diff --git a/tests/baselines/reference/decoratorOnClassMethod5.js b/tests/baselines/reference/decoratorOnClassMethod5.js index 2fedbaaf764..c89ebc6bb38 100644 --- a/tests/baselines/reference/decoratorOnClassMethod5.js +++ b/tests/baselines/reference/decoratorOnClassMethod5.js @@ -13,9 +13,8 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key, return c > 3 && r && Object.defineProperty(target, key, r), r; }; class C { - [_a = "method"]() { } + ["method"]() { } } __decorate([ dec() -], C.prototype, _a, null); -var _a; +], C.prototype, "method", null); diff --git a/tests/baselines/reference/decoratorOnClassMethod6.js b/tests/baselines/reference/decoratorOnClassMethod6.js index 7966225e221..45f5eeddb81 100644 --- a/tests/baselines/reference/decoratorOnClassMethod6.js +++ b/tests/baselines/reference/decoratorOnClassMethod6.js @@ -13,9 +13,8 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key, return c > 3 && r && Object.defineProperty(target, key, r), r; }; class C { - [_a = "method"]() { } + ["method"]() { } } __decorate([ dec -], C.prototype, _a, null); -var _a; +], C.prototype, "method", null); diff --git a/tests/baselines/reference/decoratorOnClassMethod7.js b/tests/baselines/reference/decoratorOnClassMethod7.js index 3ec509e17f0..dc92364cd89 100644 --- a/tests/baselines/reference/decoratorOnClassMethod7.js +++ b/tests/baselines/reference/decoratorOnClassMethod7.js @@ -13,9 +13,8 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key, return c > 3 && r && Object.defineProperty(target, key, r), r; }; class C { - [_a = "method"]() { } + ["method"]() { } } __decorate([ dec -], C.prototype, _a, null); -var _a; +], C.prototype, "method", null); diff --git a/tests/baselines/reference/decoratorsOnComputedProperties.errors.txt b/tests/baselines/reference/decoratorsOnComputedProperties.errors.txt new file mode 100644 index 00000000000..2aef827d4f5 --- /dev/null +++ b/tests/baselines/reference/decoratorsOnComputedProperties.errors.txt @@ -0,0 +1,435 @@ +tests/cases/compiler/decoratorsOnComputedProperties.ts(18,5): error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. +tests/cases/compiler/decoratorsOnComputedProperties.ts(19,8): error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. +tests/cases/compiler/decoratorsOnComputedProperties.ts(20,8): error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. +tests/cases/compiler/decoratorsOnComputedProperties.ts(21,5): error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. +tests/cases/compiler/decoratorsOnComputedProperties.ts(22,8): error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. +tests/cases/compiler/decoratorsOnComputedProperties.ts(23,8): error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. +tests/cases/compiler/decoratorsOnComputedProperties.ts(27,5): error TS1206: Decorators are not valid here. +tests/cases/compiler/decoratorsOnComputedProperties.ts(28,5): error TS1206: Decorators are not valid here. +tests/cases/compiler/decoratorsOnComputedProperties.ts(29,5): error TS1206: Decorators are not valid here. +tests/cases/compiler/decoratorsOnComputedProperties.ts(30,5): error TS1206: Decorators are not valid here. +tests/cases/compiler/decoratorsOnComputedProperties.ts(35,5): error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. +tests/cases/compiler/decoratorsOnComputedProperties.ts(36,5): error TS1206: Decorators are not valid here. +tests/cases/compiler/decoratorsOnComputedProperties.ts(37,5): error TS1206: Decorators are not valid here. +tests/cases/compiler/decoratorsOnComputedProperties.ts(38,5): error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. +tests/cases/compiler/decoratorsOnComputedProperties.ts(39,5): error TS1206: Decorators are not valid here. +tests/cases/compiler/decoratorsOnComputedProperties.ts(40,5): error TS1206: Decorators are not valid here. +tests/cases/compiler/decoratorsOnComputedProperties.ts(52,5): error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. +tests/cases/compiler/decoratorsOnComputedProperties.ts(53,8): error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. +tests/cases/compiler/decoratorsOnComputedProperties.ts(54,8): error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. +tests/cases/compiler/decoratorsOnComputedProperties.ts(55,5): error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. +tests/cases/compiler/decoratorsOnComputedProperties.ts(56,8): error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. +tests/cases/compiler/decoratorsOnComputedProperties.ts(57,8): error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. +tests/cases/compiler/decoratorsOnComputedProperties.ts(62,5): error TS1206: Decorators are not valid here. +tests/cases/compiler/decoratorsOnComputedProperties.ts(63,5): error TS1206: Decorators are not valid here. +tests/cases/compiler/decoratorsOnComputedProperties.ts(64,5): error TS1206: Decorators are not valid here. +tests/cases/compiler/decoratorsOnComputedProperties.ts(65,5): error TS1206: Decorators are not valid here. +tests/cases/compiler/decoratorsOnComputedProperties.ts(70,5): error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. +tests/cases/compiler/decoratorsOnComputedProperties.ts(71,5): error TS1206: Decorators are not valid here. +tests/cases/compiler/decoratorsOnComputedProperties.ts(72,5): error TS1206: Decorators are not valid here. +tests/cases/compiler/decoratorsOnComputedProperties.ts(73,5): error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. +tests/cases/compiler/decoratorsOnComputedProperties.ts(74,5): error TS1206: Decorators are not valid here. +tests/cases/compiler/decoratorsOnComputedProperties.ts(75,5): error TS1206: Decorators are not valid here. +tests/cases/compiler/decoratorsOnComputedProperties.ts(88,5): error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. +tests/cases/compiler/decoratorsOnComputedProperties.ts(89,8): error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. +tests/cases/compiler/decoratorsOnComputedProperties.ts(90,8): error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. +tests/cases/compiler/decoratorsOnComputedProperties.ts(92,5): error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. +tests/cases/compiler/decoratorsOnComputedProperties.ts(93,8): error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. +tests/cases/compiler/decoratorsOnComputedProperties.ts(94,8): error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. +tests/cases/compiler/decoratorsOnComputedProperties.ts(98,5): error TS1206: Decorators are not valid here. +tests/cases/compiler/decoratorsOnComputedProperties.ts(99,5): error TS1206: Decorators are not valid here. +tests/cases/compiler/decoratorsOnComputedProperties.ts(100,5): error TS1206: Decorators are not valid here. +tests/cases/compiler/decoratorsOnComputedProperties.ts(101,5): error TS1206: Decorators are not valid here. +tests/cases/compiler/decoratorsOnComputedProperties.ts(106,5): error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. +tests/cases/compiler/decoratorsOnComputedProperties.ts(107,5): error TS1206: Decorators are not valid here. +tests/cases/compiler/decoratorsOnComputedProperties.ts(108,5): error TS1206: Decorators are not valid here. +tests/cases/compiler/decoratorsOnComputedProperties.ts(110,5): error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. +tests/cases/compiler/decoratorsOnComputedProperties.ts(111,5): error TS1206: Decorators are not valid here. +tests/cases/compiler/decoratorsOnComputedProperties.ts(112,5): error TS1206: Decorators are not valid here. +tests/cases/compiler/decoratorsOnComputedProperties.ts(124,5): error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. +tests/cases/compiler/decoratorsOnComputedProperties.ts(125,8): error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. +tests/cases/compiler/decoratorsOnComputedProperties.ts(126,8): error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. +tests/cases/compiler/decoratorsOnComputedProperties.ts(128,5): error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. +tests/cases/compiler/decoratorsOnComputedProperties.ts(129,8): error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. +tests/cases/compiler/decoratorsOnComputedProperties.ts(131,8): error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. +tests/cases/compiler/decoratorsOnComputedProperties.ts(135,5): error TS1206: Decorators are not valid here. +tests/cases/compiler/decoratorsOnComputedProperties.ts(136,5): error TS1206: Decorators are not valid here. +tests/cases/compiler/decoratorsOnComputedProperties.ts(137,5): error TS1206: Decorators are not valid here. +tests/cases/compiler/decoratorsOnComputedProperties.ts(138,5): error TS1206: Decorators are not valid here. +tests/cases/compiler/decoratorsOnComputedProperties.ts(143,5): error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. +tests/cases/compiler/decoratorsOnComputedProperties.ts(144,5): error TS1206: Decorators are not valid here. +tests/cases/compiler/decoratorsOnComputedProperties.ts(145,5): error TS1206: Decorators are not valid here. +tests/cases/compiler/decoratorsOnComputedProperties.ts(147,5): error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. +tests/cases/compiler/decoratorsOnComputedProperties.ts(148,5): error TS1206: Decorators are not valid here. +tests/cases/compiler/decoratorsOnComputedProperties.ts(150,5): error TS1206: Decorators are not valid here. +tests/cases/compiler/decoratorsOnComputedProperties.ts(162,5): error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. +tests/cases/compiler/decoratorsOnComputedProperties.ts(163,8): error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. +tests/cases/compiler/decoratorsOnComputedProperties.ts(164,8): error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. +tests/cases/compiler/decoratorsOnComputedProperties.ts(166,5): error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. +tests/cases/compiler/decoratorsOnComputedProperties.ts(167,8): error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. +tests/cases/compiler/decoratorsOnComputedProperties.ts(169,8): error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. +tests/cases/compiler/decoratorsOnComputedProperties.ts(173,5): error TS1206: Decorators are not valid here. +tests/cases/compiler/decoratorsOnComputedProperties.ts(174,5): error TS1206: Decorators are not valid here. +tests/cases/compiler/decoratorsOnComputedProperties.ts(175,5): error TS1206: Decorators are not valid here. +tests/cases/compiler/decoratorsOnComputedProperties.ts(176,5): error TS1206: Decorators are not valid here. +tests/cases/compiler/decoratorsOnComputedProperties.ts(181,5): error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. +tests/cases/compiler/decoratorsOnComputedProperties.ts(182,5): error TS1206: Decorators are not valid here. +tests/cases/compiler/decoratorsOnComputedProperties.ts(183,5): error TS1206: Decorators are not valid here. +tests/cases/compiler/decoratorsOnComputedProperties.ts(184,5): error TS1206: Decorators are not valid here. +tests/cases/compiler/decoratorsOnComputedProperties.ts(185,5): error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. +tests/cases/compiler/decoratorsOnComputedProperties.ts(186,5): error TS1206: Decorators are not valid here. +tests/cases/compiler/decoratorsOnComputedProperties.ts(188,5): error TS1206: Decorators are not valid here. + + +==== tests/cases/compiler/decoratorsOnComputedProperties.ts (81 errors) ==== + function x(o: object, k: PropertyKey) { } + let i = 0; + function foo(): string { return ++i + ""; } + + const fieldNameA: string = "fieldName1"; + const fieldNameB: string = "fieldName2"; + const fieldNameC: string = "fieldName3"; + + class A { + @x ["property"]: any; + @x [Symbol.toStringTag]: any; + @x ["property2"]: any = 2; + @x [Symbol.iterator]: any = null; + ["property3"]: any; + [Symbol.isConcatSpreadable]: any; + ["property4"]: any = 2; + [Symbol.match]: any = null; + [foo()]: any; + ~~~~~~~ +!!! error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. + @x [foo()]: any; + ~~~~~~~ +!!! error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. + @x [foo()]: any = null; + ~~~~~~~ +!!! error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. + [fieldNameA]: any; + ~~~~~~~~~~~~ +!!! error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. + @x [fieldNameB]: any; + ~~~~~~~~~~~~ +!!! error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. + @x [fieldNameC]: any = null; + ~~~~~~~~~~~~ +!!! error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. + } + + void class B { + @x ["property"]: any; + ~ +!!! error TS1206: Decorators are not valid here. + @x [Symbol.toStringTag]: any; + ~ +!!! error TS1206: Decorators are not valid here. + @x ["property2"]: any = 2; + ~ +!!! error TS1206: Decorators are not valid here. + @x [Symbol.iterator]: any = null; + ~ +!!! error TS1206: Decorators are not valid here. + ["property3"]: any; + [Symbol.isConcatSpreadable]: any; + ["property4"]: any = 2; + [Symbol.match]: any = null; + [foo()]: any; + ~~~~~~~ +!!! error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. + @x [foo()]: any; + ~ +!!! error TS1206: Decorators are not valid here. + @x [foo()]: any = null; + ~ +!!! error TS1206: Decorators are not valid here. + [fieldNameA]: any; + ~~~~~~~~~~~~ +!!! error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. + @x [fieldNameB]: any; + ~ +!!! error TS1206: Decorators are not valid here. + @x [fieldNameC]: any = null; + ~ +!!! error TS1206: Decorators are not valid here. + }; + + class C { + @x ["property"]: any; + @x [Symbol.toStringTag]: any; + @x ["property2"]: any = 2; + @x [Symbol.iterator]: any = null; + ["property3"]: any; + [Symbol.isConcatSpreadable]: any; + ["property4"]: any = 2; + [Symbol.match]: any = null; + [foo()]: any; + ~~~~~~~ +!!! error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. + @x [foo()]: any; + ~~~~~~~ +!!! error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. + @x [foo()]: any = null; + ~~~~~~~ +!!! error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. + [fieldNameA]: any; + ~~~~~~~~~~~~ +!!! error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. + @x [fieldNameB]: any; + ~~~~~~~~~~~~ +!!! error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. + @x [fieldNameC]: any = null; + ~~~~~~~~~~~~ +!!! error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. + ["some" + "method"]() {} + } + + void class D { + @x ["property"]: any; + ~ +!!! error TS1206: Decorators are not valid here. + @x [Symbol.toStringTag]: any; + ~ +!!! error TS1206: Decorators are not valid here. + @x ["property2"]: any = 2; + ~ +!!! error TS1206: Decorators are not valid here. + @x [Symbol.iterator]: any = null; + ~ +!!! error TS1206: Decorators are not valid here. + ["property3"]: any; + [Symbol.isConcatSpreadable]: any; + ["property4"]: any = 2; + [Symbol.match]: any = null; + [foo()]: any; + ~~~~~~~ +!!! error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. + @x [foo()]: any; + ~ +!!! error TS1206: Decorators are not valid here. + @x [foo()]: any = null; + ~ +!!! error TS1206: Decorators are not valid here. + [fieldNameA]: any; + ~~~~~~~~~~~~ +!!! error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. + @x [fieldNameB]: any; + ~ +!!! error TS1206: Decorators are not valid here. + @x [fieldNameC]: any = null; + ~ +!!! error TS1206: Decorators are not valid here. + ["some" + "method"]() {} + }; + + class E { + @x ["property"]: any; + @x [Symbol.toStringTag]: any; + @x ["property2"]: any = 2; + @x [Symbol.iterator]: any = null; + ["property3"]: any; + [Symbol.isConcatSpreadable]: any; + ["property4"]: any = 2; + [Symbol.match]: any = null; + [foo()]: any; + ~~~~~~~ +!!! error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. + @x [foo()]: any; + ~~~~~~~ +!!! error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. + @x [foo()]: any = null; + ~~~~~~~ +!!! error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. + ["some" + "method"]() {} + [fieldNameA]: any; + ~~~~~~~~~~~~ +!!! error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. + @x [fieldNameB]: any; + ~~~~~~~~~~~~ +!!! error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. + @x [fieldNameC]: any = null; + ~~~~~~~~~~~~ +!!! error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. + } + + void class F { + @x ["property"]: any; + ~ +!!! error TS1206: Decorators are not valid here. + @x [Symbol.toStringTag]: any; + ~ +!!! error TS1206: Decorators are not valid here. + @x ["property2"]: any = 2; + ~ +!!! error TS1206: Decorators are not valid here. + @x [Symbol.iterator]: any = null; + ~ +!!! error TS1206: Decorators are not valid here. + ["property3"]: any; + [Symbol.isConcatSpreadable]: any; + ["property4"]: any = 2; + [Symbol.match]: any = null; + [foo()]: any; + ~~~~~~~ +!!! error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. + @x [foo()]: any; + ~ +!!! error TS1206: Decorators are not valid here. + @x [foo()]: any = null; + ~ +!!! error TS1206: Decorators are not valid here. + ["some" + "method"]() {} + [fieldNameA]: any; + ~~~~~~~~~~~~ +!!! error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. + @x [fieldNameB]: any; + ~ +!!! error TS1206: Decorators are not valid here. + @x [fieldNameC]: any = null; + ~ +!!! error TS1206: Decorators are not valid here. + }; + + class G { + @x ["property"]: any; + @x [Symbol.toStringTag]: any; + @x ["property2"]: any = 2; + @x [Symbol.iterator]: any = null; + ["property3"]: any; + [Symbol.isConcatSpreadable]: any; + ["property4"]: any = 2; + [Symbol.match]: any = null; + [foo()]: any; + ~~~~~~~ +!!! error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. + @x [foo()]: any; + ~~~~~~~ +!!! error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. + @x [foo()]: any = null; + ~~~~~~~ +!!! error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. + ["some" + "method"]() {} + [fieldNameA]: any; + ~~~~~~~~~~~~ +!!! error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. + @x [fieldNameB]: any; + ~~~~~~~~~~~~ +!!! error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. + ["some" + "method2"]() {} + @x [fieldNameC]: any = null; + ~~~~~~~~~~~~ +!!! error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. + } + + void class H { + @x ["property"]: any; + ~ +!!! error TS1206: Decorators are not valid here. + @x [Symbol.toStringTag]: any; + ~ +!!! error TS1206: Decorators are not valid here. + @x ["property2"]: any = 2; + ~ +!!! error TS1206: Decorators are not valid here. + @x [Symbol.iterator]: any = null; + ~ +!!! error TS1206: Decorators are not valid here. + ["property3"]: any; + [Symbol.isConcatSpreadable]: any; + ["property4"]: any = 2; + [Symbol.match]: any = null; + [foo()]: any; + ~~~~~~~ +!!! error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. + @x [foo()]: any; + ~ +!!! error TS1206: Decorators are not valid here. + @x [foo()]: any = null; + ~ +!!! error TS1206: Decorators are not valid here. + ["some" + "method"]() {} + [fieldNameA]: any; + ~~~~~~~~~~~~ +!!! error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. + @x [fieldNameB]: any; + ~ +!!! error TS1206: Decorators are not valid here. + ["some" + "method2"]() {} + @x [fieldNameC]: any = null; + ~ +!!! error TS1206: Decorators are not valid here. + }; + + class I { + @x ["property"]: any; + @x [Symbol.toStringTag]: any; + @x ["property2"]: any = 2; + @x [Symbol.iterator]: any = null; + ["property3"]: any; + [Symbol.isConcatSpreadable]: any; + ["property4"]: any = 2; + [Symbol.match]: any = null; + [foo()]: any; + ~~~~~~~ +!!! error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. + @x [foo()]: any; + ~~~~~~~ +!!! error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. + @x [foo()]: any = null; + ~~~~~~~ +!!! error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. + @x ["some" + "method"]() {} + [fieldNameA]: any; + ~~~~~~~~~~~~ +!!! error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. + @x [fieldNameB]: any; + ~~~~~~~~~~~~ +!!! error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. + ["some" + "method2"]() {} + @x [fieldNameC]: any = null; + ~~~~~~~~~~~~ +!!! error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. + } + + void class J { + @x ["property"]: any; + ~ +!!! error TS1206: Decorators are not valid here. + @x [Symbol.toStringTag]: any; + ~ +!!! error TS1206: Decorators are not valid here. + @x ["property2"]: any = 2; + ~ +!!! error TS1206: Decorators are not valid here. + @x [Symbol.iterator]: any = null; + ~ +!!! error TS1206: Decorators are not valid here. + ["property3"]: any; + [Symbol.isConcatSpreadable]: any; + ["property4"]: any = 2; + [Symbol.match]: any = null; + [foo()]: any; + ~~~~~~~ +!!! error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. + @x [foo()]: any; + ~ +!!! error TS1206: Decorators are not valid here. + @x [foo()]: any = null; + ~ +!!! error TS1206: Decorators are not valid here. + @x ["some" + "method"]() {} + ~ +!!! error TS1206: Decorators are not valid here. + [fieldNameA]: any; + ~~~~~~~~~~~~ +!!! error TS1166: A computed property name in a class property declaration must directly refer to a built-in symbol. + @x [fieldNameB]: any; + ~ +!!! error TS1206: Decorators are not valid here. + ["some" + "method2"]() {} + @x [fieldNameC]: any = null; + ~ +!!! error TS1206: Decorators are not valid here. + }; \ No newline at end of file diff --git a/tests/baselines/reference/decoratorsOnComputedProperties.js b/tests/baselines/reference/decoratorsOnComputedProperties.js new file mode 100644 index 00000000000..0083bc8b9a1 --- /dev/null +++ b/tests/baselines/reference/decoratorsOnComputedProperties.js @@ -0,0 +1,457 @@ +//// [decoratorsOnComputedProperties.ts] +function x(o: object, k: PropertyKey) { } +let i = 0; +function foo(): string { return ++i + ""; } + +const fieldNameA: string = "fieldName1"; +const fieldNameB: string = "fieldName2"; +const fieldNameC: string = "fieldName3"; + +class A { + @x ["property"]: any; + @x [Symbol.toStringTag]: any; + @x ["property2"]: any = 2; + @x [Symbol.iterator]: any = null; + ["property3"]: any; + [Symbol.isConcatSpreadable]: any; + ["property4"]: any = 2; + [Symbol.match]: any = null; + [foo()]: any; + @x [foo()]: any; + @x [foo()]: any = null; + [fieldNameA]: any; + @x [fieldNameB]: any; + @x [fieldNameC]: any = null; +} + +void class B { + @x ["property"]: any; + @x [Symbol.toStringTag]: any; + @x ["property2"]: any = 2; + @x [Symbol.iterator]: any = null; + ["property3"]: any; + [Symbol.isConcatSpreadable]: any; + ["property4"]: any = 2; + [Symbol.match]: any = null; + [foo()]: any; + @x [foo()]: any; + @x [foo()]: any = null; + [fieldNameA]: any; + @x [fieldNameB]: any; + @x [fieldNameC]: any = null; +}; + +class C { + @x ["property"]: any; + @x [Symbol.toStringTag]: any; + @x ["property2"]: any = 2; + @x [Symbol.iterator]: any = null; + ["property3"]: any; + [Symbol.isConcatSpreadable]: any; + ["property4"]: any = 2; + [Symbol.match]: any = null; + [foo()]: any; + @x [foo()]: any; + @x [foo()]: any = null; + [fieldNameA]: any; + @x [fieldNameB]: any; + @x [fieldNameC]: any = null; + ["some" + "method"]() {} +} + +void class D { + @x ["property"]: any; + @x [Symbol.toStringTag]: any; + @x ["property2"]: any = 2; + @x [Symbol.iterator]: any = null; + ["property3"]: any; + [Symbol.isConcatSpreadable]: any; + ["property4"]: any = 2; + [Symbol.match]: any = null; + [foo()]: any; + @x [foo()]: any; + @x [foo()]: any = null; + [fieldNameA]: any; + @x [fieldNameB]: any; + @x [fieldNameC]: any = null; + ["some" + "method"]() {} +}; + +class E { + @x ["property"]: any; + @x [Symbol.toStringTag]: any; + @x ["property2"]: any = 2; + @x [Symbol.iterator]: any = null; + ["property3"]: any; + [Symbol.isConcatSpreadable]: any; + ["property4"]: any = 2; + [Symbol.match]: any = null; + [foo()]: any; + @x [foo()]: any; + @x [foo()]: any = null; + ["some" + "method"]() {} + [fieldNameA]: any; + @x [fieldNameB]: any; + @x [fieldNameC]: any = null; +} + +void class F { + @x ["property"]: any; + @x [Symbol.toStringTag]: any; + @x ["property2"]: any = 2; + @x [Symbol.iterator]: any = null; + ["property3"]: any; + [Symbol.isConcatSpreadable]: any; + ["property4"]: any = 2; + [Symbol.match]: any = null; + [foo()]: any; + @x [foo()]: any; + @x [foo()]: any = null; + ["some" + "method"]() {} + [fieldNameA]: any; + @x [fieldNameB]: any; + @x [fieldNameC]: any = null; +}; + +class G { + @x ["property"]: any; + @x [Symbol.toStringTag]: any; + @x ["property2"]: any = 2; + @x [Symbol.iterator]: any = null; + ["property3"]: any; + [Symbol.isConcatSpreadable]: any; + ["property4"]: any = 2; + [Symbol.match]: any = null; + [foo()]: any; + @x [foo()]: any; + @x [foo()]: any = null; + ["some" + "method"]() {} + [fieldNameA]: any; + @x [fieldNameB]: any; + ["some" + "method2"]() {} + @x [fieldNameC]: any = null; +} + +void class H { + @x ["property"]: any; + @x [Symbol.toStringTag]: any; + @x ["property2"]: any = 2; + @x [Symbol.iterator]: any = null; + ["property3"]: any; + [Symbol.isConcatSpreadable]: any; + ["property4"]: any = 2; + [Symbol.match]: any = null; + [foo()]: any; + @x [foo()]: any; + @x [foo()]: any = null; + ["some" + "method"]() {} + [fieldNameA]: any; + @x [fieldNameB]: any; + ["some" + "method2"]() {} + @x [fieldNameC]: any = null; +}; + +class I { + @x ["property"]: any; + @x [Symbol.toStringTag]: any; + @x ["property2"]: any = 2; + @x [Symbol.iterator]: any = null; + ["property3"]: any; + [Symbol.isConcatSpreadable]: any; + ["property4"]: any = 2; + [Symbol.match]: any = null; + [foo()]: any; + @x [foo()]: any; + @x [foo()]: any = null; + @x ["some" + "method"]() {} + [fieldNameA]: any; + @x [fieldNameB]: any; + ["some" + "method2"]() {} + @x [fieldNameC]: any = null; +} + +void class J { + @x ["property"]: any; + @x [Symbol.toStringTag]: any; + @x ["property2"]: any = 2; + @x [Symbol.iterator]: any = null; + ["property3"]: any; + [Symbol.isConcatSpreadable]: any; + ["property4"]: any = 2; + [Symbol.match]: any = null; + [foo()]: any; + @x [foo()]: any; + @x [foo()]: any = null; + @x ["some" + "method"]() {} + [fieldNameA]: any; + @x [fieldNameB]: any; + ["some" + "method2"]() {} + @x [fieldNameC]: any = null; +}; + +//// [decoratorsOnComputedProperties.js] +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +function x(o, k) { } +let i = 0; +function foo() { return ++i + ""; } +const fieldNameA = "fieldName1"; +const fieldNameB = "fieldName2"; +const fieldNameC = "fieldName3"; +class A { + constructor() { + this["property2"] = 2; + this[Symbol.iterator] = null; + this["property4"] = 2; + this[Symbol.match] = null; + this[_a] = null; + this[_b] = null; + } +} +foo(), _c = foo(), _a = foo(), _d = fieldNameB, _b = fieldNameC; +__decorate([ + x +], A.prototype, "property", void 0); +__decorate([ + x +], A.prototype, Symbol.toStringTag, void 0); +__decorate([ + x +], A.prototype, "property2", void 0); +__decorate([ + x +], A.prototype, Symbol.iterator, void 0); +__decorate([ + x +], A.prototype, _c, void 0); +__decorate([ + x +], A.prototype, _a, void 0); +__decorate([ + x +], A.prototype, _d, void 0); +__decorate([ + x +], A.prototype, _b, void 0); +void (_e = class B { + constructor() { + this["property2"] = 2; + this[Symbol.iterator] = null; + this["property4"] = 2; + this[Symbol.match] = null; + this[_f] = null; + this[_g] = null; + } + }, + foo(), + _h = foo(), + _f = foo(), + _j = fieldNameB, + _g = fieldNameC, + _e); +class C { + constructor() { + this["property2"] = 2; + this[Symbol.iterator] = null; + this["property4"] = 2; + this[Symbol.match] = null; + this[_k] = null; + this[_l] = null; + } + [foo(), _m = foo(), _k = foo(), _o = fieldNameB, _l = fieldNameC, "some" + "method"]() { } +} +__decorate([ + x +], C.prototype, "property", void 0); +__decorate([ + x +], C.prototype, Symbol.toStringTag, void 0); +__decorate([ + x +], C.prototype, "property2", void 0); +__decorate([ + x +], C.prototype, Symbol.iterator, void 0); +__decorate([ + x +], C.prototype, _m, void 0); +__decorate([ + x +], C.prototype, _k, void 0); +__decorate([ + x +], C.prototype, _o, void 0); +__decorate([ + x +], C.prototype, _l, void 0); +void class D { + constructor() { + this["property2"] = 2; + this[Symbol.iterator] = null; + this["property4"] = 2; + this[Symbol.match] = null; + this[_p] = null; + this[_q] = null; + } + [foo(), _r = foo(), _p = foo(), _s = fieldNameB, _q = fieldNameC, "some" + "method"]() { } +}; +class E { + constructor() { + this["property2"] = 2; + this[Symbol.iterator] = null; + this["property4"] = 2; + this[Symbol.match] = null; + this[_t] = null; + this[_u] = null; + } + [foo(), _v = foo(), _t = foo(), "some" + "method"]() { } +} +_w = fieldNameB, _u = fieldNameC; +__decorate([ + x +], E.prototype, "property", void 0); +__decorate([ + x +], E.prototype, Symbol.toStringTag, void 0); +__decorate([ + x +], E.prototype, "property2", void 0); +__decorate([ + x +], E.prototype, Symbol.iterator, void 0); +__decorate([ + x +], E.prototype, _v, void 0); +__decorate([ + x +], E.prototype, _t, void 0); +__decorate([ + x +], E.prototype, _w, void 0); +__decorate([ + x +], E.prototype, _u, void 0); +void (_x = class F { + constructor() { + this["property2"] = 2; + this[Symbol.iterator] = null; + this["property4"] = 2; + this[Symbol.match] = null; + this[_y] = null; + this[_z] = null; + } + [foo(), _0 = foo(), _y = foo(), "some" + "method"]() { } + }, + _1 = fieldNameB, + _z = fieldNameC, + _x); +class G { + constructor() { + this["property2"] = 2; + this[Symbol.iterator] = null; + this["property4"] = 2; + this[Symbol.match] = null; + this[_2] = null; + this[_3] = null; + } + [foo(), _4 = foo(), _2 = foo(), "some" + "method"]() { } + [_5 = fieldNameB, "some" + "method2"]() { } +} +_3 = fieldNameC; +__decorate([ + x +], G.prototype, "property", void 0); +__decorate([ + x +], G.prototype, Symbol.toStringTag, void 0); +__decorate([ + x +], G.prototype, "property2", void 0); +__decorate([ + x +], G.prototype, Symbol.iterator, void 0); +__decorate([ + x +], G.prototype, _4, void 0); +__decorate([ + x +], G.prototype, _2, void 0); +__decorate([ + x +], G.prototype, _5, void 0); +__decorate([ + x +], G.prototype, _3, void 0); +void (_6 = class H { + constructor() { + this["property2"] = 2; + this[Symbol.iterator] = null; + this["property4"] = 2; + this[Symbol.match] = null; + this[_7] = null; + this[_8] = null; + } + [foo(), _9 = foo(), _7 = foo(), "some" + "method"]() { } + [_10 = fieldNameB, "some" + "method2"]() { } + }, + _8 = fieldNameC, + _6); +class I { + constructor() { + this["property2"] = 2; + this[Symbol.iterator] = null; + this["property4"] = 2; + this[Symbol.match] = null; + this[_11] = null; + this[_12] = null; + } + [foo(), _13 = foo(), _11 = foo(), _14 = "some" + "method"]() { } + [_15 = fieldNameB, "some" + "method2"]() { } +} +_12 = fieldNameC; +__decorate([ + x +], I.prototype, "property", void 0); +__decorate([ + x +], I.prototype, Symbol.toStringTag, void 0); +__decorate([ + x +], I.prototype, "property2", void 0); +__decorate([ + x +], I.prototype, Symbol.iterator, void 0); +__decorate([ + x +], I.prototype, _13, void 0); +__decorate([ + x +], I.prototype, _11, void 0); +__decorate([ + x +], I.prototype, _14, null); +__decorate([ + x +], I.prototype, _15, void 0); +__decorate([ + x +], I.prototype, _12, void 0); +void (_16 = class J { + constructor() { + this["property2"] = 2; + this[Symbol.iterator] = null; + this["property4"] = 2; + this[Symbol.match] = null; + this[_17] = null; + this[_18] = null; + } + [foo(), _19 = foo(), _17 = foo(), _20 = "some" + "method"]() { } + [_21 = fieldNameB, "some" + "method2"]() { } + }, + _18 = fieldNameC, + _16); +var _c, _a, _d, _b, _h, _f, _j, _g, _e, _m, _k, _o, _l, _r, _p, _s, _q, _v, _t, _w, _u, _0, _y, _1, _z, _x, _4, _2, _5, _3, _9, _7, _10, _8, _6, _13, _11, _14, _15, _12, _19, _17, _20, _21, _18, _16; diff --git a/tests/baselines/reference/decoratorsOnComputedProperties.symbols b/tests/baselines/reference/decoratorsOnComputedProperties.symbols new file mode 100644 index 00000000000..a9fb280f96e --- /dev/null +++ b/tests/baselines/reference/decoratorsOnComputedProperties.symbols @@ -0,0 +1,664 @@ +=== tests/cases/compiler/decoratorsOnComputedProperties.ts === +function x(o: object, k: PropertyKey) { } +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>o : Symbol(o, Decl(decoratorsOnComputedProperties.ts, 0, 11)) +>k : Symbol(k, Decl(decoratorsOnComputedProperties.ts, 0, 21)) +>PropertyKey : Symbol(PropertyKey, Decl(lib.es2015.core.d.ts, --, --)) + +let i = 0; +>i : Symbol(i, Decl(decoratorsOnComputedProperties.ts, 1, 3)) + +function foo(): string { return ++i + ""; } +>foo : Symbol(foo, Decl(decoratorsOnComputedProperties.ts, 1, 10)) +>i : Symbol(i, Decl(decoratorsOnComputedProperties.ts, 1, 3)) + +const fieldNameA: string = "fieldName1"; +>fieldNameA : Symbol(fieldNameA, Decl(decoratorsOnComputedProperties.ts, 4, 5)) + +const fieldNameB: string = "fieldName2"; +>fieldNameB : Symbol(fieldNameB, Decl(decoratorsOnComputedProperties.ts, 5, 5)) + +const fieldNameC: string = "fieldName3"; +>fieldNameC : Symbol(fieldNameC, Decl(decoratorsOnComputedProperties.ts, 6, 5)) + +class A { +>A : Symbol(A, Decl(decoratorsOnComputedProperties.ts, 6, 40)) + + @x ["property"]: any; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>"property" : Symbol(A[["property"]], Decl(decoratorsOnComputedProperties.ts, 8, 9)) + + @x [Symbol.toStringTag]: any; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>Symbol.toStringTag : Symbol(SymbolConstructor.toStringTag, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --)) +>toStringTag : Symbol(SymbolConstructor.toStringTag, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + + @x ["property2"]: any = 2; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>"property2" : Symbol(A[["property2"]], Decl(decoratorsOnComputedProperties.ts, 10, 33)) + + @x [Symbol.iterator]: any = null; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>Symbol.iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --)) +>iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --)) + + ["property3"]: any; +>"property3" : Symbol(A[["property3"]], Decl(decoratorsOnComputedProperties.ts, 12, 37)) + + [Symbol.isConcatSpreadable]: any; +>Symbol.isConcatSpreadable : Symbol(SymbolConstructor.isConcatSpreadable, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --)) +>isConcatSpreadable : Symbol(SymbolConstructor.isConcatSpreadable, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + + ["property4"]: any = 2; +>"property4" : Symbol(A[["property4"]], Decl(decoratorsOnComputedProperties.ts, 14, 37)) + + [Symbol.match]: any = null; +>Symbol.match : Symbol(SymbolConstructor.match, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --)) +>match : Symbol(SymbolConstructor.match, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + + [foo()]: any; +>foo : Symbol(foo, Decl(decoratorsOnComputedProperties.ts, 1, 10)) + + @x [foo()]: any; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>foo : Symbol(foo, Decl(decoratorsOnComputedProperties.ts, 1, 10)) + + @x [foo()]: any = null; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>foo : Symbol(foo, Decl(decoratorsOnComputedProperties.ts, 1, 10)) + + [fieldNameA]: any; +>fieldNameA : Symbol(fieldNameA, Decl(decoratorsOnComputedProperties.ts, 4, 5)) + + @x [fieldNameB]: any; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>fieldNameB : Symbol(fieldNameB, Decl(decoratorsOnComputedProperties.ts, 5, 5)) + + @x [fieldNameC]: any = null; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>fieldNameC : Symbol(fieldNameC, Decl(decoratorsOnComputedProperties.ts, 6, 5)) +} + +void class B { +>B : Symbol(B, Decl(decoratorsOnComputedProperties.ts, 25, 4)) + + @x ["property"]: any; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>"property" : Symbol(B[["property"]], Decl(decoratorsOnComputedProperties.ts, 25, 14)) + + @x [Symbol.toStringTag]: any; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>Symbol.toStringTag : Symbol(SymbolConstructor.toStringTag, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --)) +>toStringTag : Symbol(SymbolConstructor.toStringTag, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + + @x ["property2"]: any = 2; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>"property2" : Symbol(B[["property2"]], Decl(decoratorsOnComputedProperties.ts, 27, 33)) + + @x [Symbol.iterator]: any = null; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>Symbol.iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --)) +>iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --)) + + ["property3"]: any; +>"property3" : Symbol(B[["property3"]], Decl(decoratorsOnComputedProperties.ts, 29, 37)) + + [Symbol.isConcatSpreadable]: any; +>Symbol.isConcatSpreadable : Symbol(SymbolConstructor.isConcatSpreadable, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --)) +>isConcatSpreadable : Symbol(SymbolConstructor.isConcatSpreadable, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + + ["property4"]: any = 2; +>"property4" : Symbol(B[["property4"]], Decl(decoratorsOnComputedProperties.ts, 31, 37)) + + [Symbol.match]: any = null; +>Symbol.match : Symbol(SymbolConstructor.match, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --)) +>match : Symbol(SymbolConstructor.match, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + + [foo()]: any; +>foo : Symbol(foo, Decl(decoratorsOnComputedProperties.ts, 1, 10)) + + @x [foo()]: any; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>foo : Symbol(foo, Decl(decoratorsOnComputedProperties.ts, 1, 10)) + + @x [foo()]: any = null; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>foo : Symbol(foo, Decl(decoratorsOnComputedProperties.ts, 1, 10)) + + [fieldNameA]: any; +>fieldNameA : Symbol(fieldNameA, Decl(decoratorsOnComputedProperties.ts, 4, 5)) + + @x [fieldNameB]: any; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>fieldNameB : Symbol(fieldNameB, Decl(decoratorsOnComputedProperties.ts, 5, 5)) + + @x [fieldNameC]: any = null; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>fieldNameC : Symbol(fieldNameC, Decl(decoratorsOnComputedProperties.ts, 6, 5)) + +}; + +class C { +>C : Symbol(C, Decl(decoratorsOnComputedProperties.ts, 40, 2)) + + @x ["property"]: any; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>"property" : Symbol(C[["property"]], Decl(decoratorsOnComputedProperties.ts, 42, 9)) + + @x [Symbol.toStringTag]: any; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>Symbol.toStringTag : Symbol(SymbolConstructor.toStringTag, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --)) +>toStringTag : Symbol(SymbolConstructor.toStringTag, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + + @x ["property2"]: any = 2; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>"property2" : Symbol(C[["property2"]], Decl(decoratorsOnComputedProperties.ts, 44, 33)) + + @x [Symbol.iterator]: any = null; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>Symbol.iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --)) +>iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --)) + + ["property3"]: any; +>"property3" : Symbol(C[["property3"]], Decl(decoratorsOnComputedProperties.ts, 46, 37)) + + [Symbol.isConcatSpreadable]: any; +>Symbol.isConcatSpreadable : Symbol(SymbolConstructor.isConcatSpreadable, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --)) +>isConcatSpreadable : Symbol(SymbolConstructor.isConcatSpreadable, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + + ["property4"]: any = 2; +>"property4" : Symbol(C[["property4"]], Decl(decoratorsOnComputedProperties.ts, 48, 37)) + + [Symbol.match]: any = null; +>Symbol.match : Symbol(SymbolConstructor.match, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --)) +>match : Symbol(SymbolConstructor.match, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + + [foo()]: any; +>foo : Symbol(foo, Decl(decoratorsOnComputedProperties.ts, 1, 10)) + + @x [foo()]: any; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>foo : Symbol(foo, Decl(decoratorsOnComputedProperties.ts, 1, 10)) + + @x [foo()]: any = null; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>foo : Symbol(foo, Decl(decoratorsOnComputedProperties.ts, 1, 10)) + + [fieldNameA]: any; +>fieldNameA : Symbol(fieldNameA, Decl(decoratorsOnComputedProperties.ts, 4, 5)) + + @x [fieldNameB]: any; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>fieldNameB : Symbol(fieldNameB, Decl(decoratorsOnComputedProperties.ts, 5, 5)) + + @x [fieldNameC]: any = null; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>fieldNameC : Symbol(fieldNameC, Decl(decoratorsOnComputedProperties.ts, 6, 5)) + + ["some" + "method"]() {} +} + +void class D { +>D : Symbol(D, Decl(decoratorsOnComputedProperties.ts, 60, 4)) + + @x ["property"]: any; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>"property" : Symbol(D[["property"]], Decl(decoratorsOnComputedProperties.ts, 60, 14)) + + @x [Symbol.toStringTag]: any; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>Symbol.toStringTag : Symbol(SymbolConstructor.toStringTag, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --)) +>toStringTag : Symbol(SymbolConstructor.toStringTag, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + + @x ["property2"]: any = 2; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>"property2" : Symbol(D[["property2"]], Decl(decoratorsOnComputedProperties.ts, 62, 33)) + + @x [Symbol.iterator]: any = null; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>Symbol.iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --)) +>iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --)) + + ["property3"]: any; +>"property3" : Symbol(D[["property3"]], Decl(decoratorsOnComputedProperties.ts, 64, 37)) + + [Symbol.isConcatSpreadable]: any; +>Symbol.isConcatSpreadable : Symbol(SymbolConstructor.isConcatSpreadable, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --)) +>isConcatSpreadable : Symbol(SymbolConstructor.isConcatSpreadable, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + + ["property4"]: any = 2; +>"property4" : Symbol(D[["property4"]], Decl(decoratorsOnComputedProperties.ts, 66, 37)) + + [Symbol.match]: any = null; +>Symbol.match : Symbol(SymbolConstructor.match, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --)) +>match : Symbol(SymbolConstructor.match, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + + [foo()]: any; +>foo : Symbol(foo, Decl(decoratorsOnComputedProperties.ts, 1, 10)) + + @x [foo()]: any; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>foo : Symbol(foo, Decl(decoratorsOnComputedProperties.ts, 1, 10)) + + @x [foo()]: any = null; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>foo : Symbol(foo, Decl(decoratorsOnComputedProperties.ts, 1, 10)) + + [fieldNameA]: any; +>fieldNameA : Symbol(fieldNameA, Decl(decoratorsOnComputedProperties.ts, 4, 5)) + + @x [fieldNameB]: any; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>fieldNameB : Symbol(fieldNameB, Decl(decoratorsOnComputedProperties.ts, 5, 5)) + + @x [fieldNameC]: any = null; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>fieldNameC : Symbol(fieldNameC, Decl(decoratorsOnComputedProperties.ts, 6, 5)) + + ["some" + "method"]() {} +}; + +class E { +>E : Symbol(E, Decl(decoratorsOnComputedProperties.ts, 76, 2)) + + @x ["property"]: any; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>"property" : Symbol(E[["property"]], Decl(decoratorsOnComputedProperties.ts, 78, 9)) + + @x [Symbol.toStringTag]: any; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>Symbol.toStringTag : Symbol(SymbolConstructor.toStringTag, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --)) +>toStringTag : Symbol(SymbolConstructor.toStringTag, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + + @x ["property2"]: any = 2; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>"property2" : Symbol(E[["property2"]], Decl(decoratorsOnComputedProperties.ts, 80, 33)) + + @x [Symbol.iterator]: any = null; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>Symbol.iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --)) +>iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --)) + + ["property3"]: any; +>"property3" : Symbol(E[["property3"]], Decl(decoratorsOnComputedProperties.ts, 82, 37)) + + [Symbol.isConcatSpreadable]: any; +>Symbol.isConcatSpreadable : Symbol(SymbolConstructor.isConcatSpreadable, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --)) +>isConcatSpreadable : Symbol(SymbolConstructor.isConcatSpreadable, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + + ["property4"]: any = 2; +>"property4" : Symbol(E[["property4"]], Decl(decoratorsOnComputedProperties.ts, 84, 37)) + + [Symbol.match]: any = null; +>Symbol.match : Symbol(SymbolConstructor.match, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --)) +>match : Symbol(SymbolConstructor.match, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + + [foo()]: any; +>foo : Symbol(foo, Decl(decoratorsOnComputedProperties.ts, 1, 10)) + + @x [foo()]: any; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>foo : Symbol(foo, Decl(decoratorsOnComputedProperties.ts, 1, 10)) + + @x [foo()]: any = null; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>foo : Symbol(foo, Decl(decoratorsOnComputedProperties.ts, 1, 10)) + + ["some" + "method"]() {} + [fieldNameA]: any; +>fieldNameA : Symbol(fieldNameA, Decl(decoratorsOnComputedProperties.ts, 4, 5)) + + @x [fieldNameB]: any; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>fieldNameB : Symbol(fieldNameB, Decl(decoratorsOnComputedProperties.ts, 5, 5)) + + @x [fieldNameC]: any = null; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>fieldNameC : Symbol(fieldNameC, Decl(decoratorsOnComputedProperties.ts, 6, 5)) +} + +void class F { +>F : Symbol(F, Decl(decoratorsOnComputedProperties.ts, 96, 4)) + + @x ["property"]: any; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>"property" : Symbol(F[["property"]], Decl(decoratorsOnComputedProperties.ts, 96, 14)) + + @x [Symbol.toStringTag]: any; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>Symbol.toStringTag : Symbol(SymbolConstructor.toStringTag, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --)) +>toStringTag : Symbol(SymbolConstructor.toStringTag, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + + @x ["property2"]: any = 2; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>"property2" : Symbol(F[["property2"]], Decl(decoratorsOnComputedProperties.ts, 98, 33)) + + @x [Symbol.iterator]: any = null; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>Symbol.iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --)) +>iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --)) + + ["property3"]: any; +>"property3" : Symbol(F[["property3"]], Decl(decoratorsOnComputedProperties.ts, 100, 37)) + + [Symbol.isConcatSpreadable]: any; +>Symbol.isConcatSpreadable : Symbol(SymbolConstructor.isConcatSpreadable, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --)) +>isConcatSpreadable : Symbol(SymbolConstructor.isConcatSpreadable, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + + ["property4"]: any = 2; +>"property4" : Symbol(F[["property4"]], Decl(decoratorsOnComputedProperties.ts, 102, 37)) + + [Symbol.match]: any = null; +>Symbol.match : Symbol(SymbolConstructor.match, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --)) +>match : Symbol(SymbolConstructor.match, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + + [foo()]: any; +>foo : Symbol(foo, Decl(decoratorsOnComputedProperties.ts, 1, 10)) + + @x [foo()]: any; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>foo : Symbol(foo, Decl(decoratorsOnComputedProperties.ts, 1, 10)) + + @x [foo()]: any = null; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>foo : Symbol(foo, Decl(decoratorsOnComputedProperties.ts, 1, 10)) + + ["some" + "method"]() {} + [fieldNameA]: any; +>fieldNameA : Symbol(fieldNameA, Decl(decoratorsOnComputedProperties.ts, 4, 5)) + + @x [fieldNameB]: any; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>fieldNameB : Symbol(fieldNameB, Decl(decoratorsOnComputedProperties.ts, 5, 5)) + + @x [fieldNameC]: any = null; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>fieldNameC : Symbol(fieldNameC, Decl(decoratorsOnComputedProperties.ts, 6, 5)) + +}; + +class G { +>G : Symbol(G, Decl(decoratorsOnComputedProperties.ts, 112, 2)) + + @x ["property"]: any; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>"property" : Symbol(G[["property"]], Decl(decoratorsOnComputedProperties.ts, 114, 9)) + + @x [Symbol.toStringTag]: any; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>Symbol.toStringTag : Symbol(SymbolConstructor.toStringTag, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --)) +>toStringTag : Symbol(SymbolConstructor.toStringTag, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + + @x ["property2"]: any = 2; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>"property2" : Symbol(G[["property2"]], Decl(decoratorsOnComputedProperties.ts, 116, 33)) + + @x [Symbol.iterator]: any = null; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>Symbol.iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --)) +>iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --)) + + ["property3"]: any; +>"property3" : Symbol(G[["property3"]], Decl(decoratorsOnComputedProperties.ts, 118, 37)) + + [Symbol.isConcatSpreadable]: any; +>Symbol.isConcatSpreadable : Symbol(SymbolConstructor.isConcatSpreadable, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --)) +>isConcatSpreadable : Symbol(SymbolConstructor.isConcatSpreadable, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + + ["property4"]: any = 2; +>"property4" : Symbol(G[["property4"]], Decl(decoratorsOnComputedProperties.ts, 120, 37)) + + [Symbol.match]: any = null; +>Symbol.match : Symbol(SymbolConstructor.match, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --)) +>match : Symbol(SymbolConstructor.match, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + + [foo()]: any; +>foo : Symbol(foo, Decl(decoratorsOnComputedProperties.ts, 1, 10)) + + @x [foo()]: any; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>foo : Symbol(foo, Decl(decoratorsOnComputedProperties.ts, 1, 10)) + + @x [foo()]: any = null; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>foo : Symbol(foo, Decl(decoratorsOnComputedProperties.ts, 1, 10)) + + ["some" + "method"]() {} + [fieldNameA]: any; +>fieldNameA : Symbol(fieldNameA, Decl(decoratorsOnComputedProperties.ts, 4, 5)) + + @x [fieldNameB]: any; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>fieldNameB : Symbol(fieldNameB, Decl(decoratorsOnComputedProperties.ts, 5, 5)) + + ["some" + "method2"]() {} + @x [fieldNameC]: any = null; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>fieldNameC : Symbol(fieldNameC, Decl(decoratorsOnComputedProperties.ts, 6, 5)) +} + +void class H { +>H : Symbol(H, Decl(decoratorsOnComputedProperties.ts, 133, 4)) + + @x ["property"]: any; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>"property" : Symbol(H[["property"]], Decl(decoratorsOnComputedProperties.ts, 133, 14)) + + @x [Symbol.toStringTag]: any; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>Symbol.toStringTag : Symbol(SymbolConstructor.toStringTag, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --)) +>toStringTag : Symbol(SymbolConstructor.toStringTag, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + + @x ["property2"]: any = 2; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>"property2" : Symbol(H[["property2"]], Decl(decoratorsOnComputedProperties.ts, 135, 33)) + + @x [Symbol.iterator]: any = null; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>Symbol.iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --)) +>iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --)) + + ["property3"]: any; +>"property3" : Symbol(H[["property3"]], Decl(decoratorsOnComputedProperties.ts, 137, 37)) + + [Symbol.isConcatSpreadable]: any; +>Symbol.isConcatSpreadable : Symbol(SymbolConstructor.isConcatSpreadable, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --)) +>isConcatSpreadable : Symbol(SymbolConstructor.isConcatSpreadable, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + + ["property4"]: any = 2; +>"property4" : Symbol(H[["property4"]], Decl(decoratorsOnComputedProperties.ts, 139, 37)) + + [Symbol.match]: any = null; +>Symbol.match : Symbol(SymbolConstructor.match, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --)) +>match : Symbol(SymbolConstructor.match, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + + [foo()]: any; +>foo : Symbol(foo, Decl(decoratorsOnComputedProperties.ts, 1, 10)) + + @x [foo()]: any; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>foo : Symbol(foo, Decl(decoratorsOnComputedProperties.ts, 1, 10)) + + @x [foo()]: any = null; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>foo : Symbol(foo, Decl(decoratorsOnComputedProperties.ts, 1, 10)) + + ["some" + "method"]() {} + [fieldNameA]: any; +>fieldNameA : Symbol(fieldNameA, Decl(decoratorsOnComputedProperties.ts, 4, 5)) + + @x [fieldNameB]: any; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>fieldNameB : Symbol(fieldNameB, Decl(decoratorsOnComputedProperties.ts, 5, 5)) + + ["some" + "method2"]() {} + @x [fieldNameC]: any = null; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>fieldNameC : Symbol(fieldNameC, Decl(decoratorsOnComputedProperties.ts, 6, 5)) + +}; + +class I { +>I : Symbol(I, Decl(decoratorsOnComputedProperties.ts, 150, 2)) + + @x ["property"]: any; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>"property" : Symbol(I[["property"]], Decl(decoratorsOnComputedProperties.ts, 152, 9)) + + @x [Symbol.toStringTag]: any; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>Symbol.toStringTag : Symbol(SymbolConstructor.toStringTag, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --)) +>toStringTag : Symbol(SymbolConstructor.toStringTag, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + + @x ["property2"]: any = 2; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>"property2" : Symbol(I[["property2"]], Decl(decoratorsOnComputedProperties.ts, 154, 33)) + + @x [Symbol.iterator]: any = null; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>Symbol.iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --)) +>iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --)) + + ["property3"]: any; +>"property3" : Symbol(I[["property3"]], Decl(decoratorsOnComputedProperties.ts, 156, 37)) + + [Symbol.isConcatSpreadable]: any; +>Symbol.isConcatSpreadable : Symbol(SymbolConstructor.isConcatSpreadable, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --)) +>isConcatSpreadable : Symbol(SymbolConstructor.isConcatSpreadable, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + + ["property4"]: any = 2; +>"property4" : Symbol(I[["property4"]], Decl(decoratorsOnComputedProperties.ts, 158, 37)) + + [Symbol.match]: any = null; +>Symbol.match : Symbol(SymbolConstructor.match, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --)) +>match : Symbol(SymbolConstructor.match, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + + [foo()]: any; +>foo : Symbol(foo, Decl(decoratorsOnComputedProperties.ts, 1, 10)) + + @x [foo()]: any; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>foo : Symbol(foo, Decl(decoratorsOnComputedProperties.ts, 1, 10)) + + @x [foo()]: any = null; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>foo : Symbol(foo, Decl(decoratorsOnComputedProperties.ts, 1, 10)) + + @x ["some" + "method"]() {} +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) + + [fieldNameA]: any; +>fieldNameA : Symbol(fieldNameA, Decl(decoratorsOnComputedProperties.ts, 4, 5)) + + @x [fieldNameB]: any; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>fieldNameB : Symbol(fieldNameB, Decl(decoratorsOnComputedProperties.ts, 5, 5)) + + ["some" + "method2"]() {} + @x [fieldNameC]: any = null; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>fieldNameC : Symbol(fieldNameC, Decl(decoratorsOnComputedProperties.ts, 6, 5)) +} + +void class J { +>J : Symbol(J, Decl(decoratorsOnComputedProperties.ts, 171, 4)) + + @x ["property"]: any; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>"property" : Symbol(J[["property"]], Decl(decoratorsOnComputedProperties.ts, 171, 14)) + + @x [Symbol.toStringTag]: any; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>Symbol.toStringTag : Symbol(SymbolConstructor.toStringTag, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --)) +>toStringTag : Symbol(SymbolConstructor.toStringTag, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + + @x ["property2"]: any = 2; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>"property2" : Symbol(J[["property2"]], Decl(decoratorsOnComputedProperties.ts, 173, 33)) + + @x [Symbol.iterator]: any = null; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>Symbol.iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --)) +>iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --)) + + ["property3"]: any; +>"property3" : Symbol(J[["property3"]], Decl(decoratorsOnComputedProperties.ts, 175, 37)) + + [Symbol.isConcatSpreadable]: any; +>Symbol.isConcatSpreadable : Symbol(SymbolConstructor.isConcatSpreadable, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --)) +>isConcatSpreadable : Symbol(SymbolConstructor.isConcatSpreadable, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + + ["property4"]: any = 2; +>"property4" : Symbol(J[["property4"]], Decl(decoratorsOnComputedProperties.ts, 177, 37)) + + [Symbol.match]: any = null; +>Symbol.match : Symbol(SymbolConstructor.match, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>Symbol : Symbol(Symbol, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --)) +>match : Symbol(SymbolConstructor.match, Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + + [foo()]: any; +>foo : Symbol(foo, Decl(decoratorsOnComputedProperties.ts, 1, 10)) + + @x [foo()]: any; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>foo : Symbol(foo, Decl(decoratorsOnComputedProperties.ts, 1, 10)) + + @x [foo()]: any = null; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>foo : Symbol(foo, Decl(decoratorsOnComputedProperties.ts, 1, 10)) + + @x ["some" + "method"]() {} +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) + + [fieldNameA]: any; +>fieldNameA : Symbol(fieldNameA, Decl(decoratorsOnComputedProperties.ts, 4, 5)) + + @x [fieldNameB]: any; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>fieldNameB : Symbol(fieldNameB, Decl(decoratorsOnComputedProperties.ts, 5, 5)) + + ["some" + "method2"]() {} + @x [fieldNameC]: any = null; +>x : Symbol(x, Decl(decoratorsOnComputedProperties.ts, 0, 0)) +>fieldNameC : Symbol(fieldNameC, Decl(decoratorsOnComputedProperties.ts, 6, 5)) + +}; diff --git a/tests/baselines/reference/decoratorsOnComputedProperties.types b/tests/baselines/reference/decoratorsOnComputedProperties.types new file mode 100644 index 00000000000..4976812b8d4 --- /dev/null +++ b/tests/baselines/reference/decoratorsOnComputedProperties.types @@ -0,0 +1,816 @@ +=== tests/cases/compiler/decoratorsOnComputedProperties.ts === +function x(o: object, k: PropertyKey) { } +>x : (o: object, k: PropertyKey) => void +>o : object +>k : PropertyKey +>PropertyKey : PropertyKey + +let i = 0; +>i : number +>0 : 0 + +function foo(): string { return ++i + ""; } +>foo : () => string +>++i + "" : string +>++i : number +>i : number +>"" : "" + +const fieldNameA: string = "fieldName1"; +>fieldNameA : string +>"fieldName1" : "fieldName1" + +const fieldNameB: string = "fieldName2"; +>fieldNameB : string +>"fieldName2" : "fieldName2" + +const fieldNameC: string = "fieldName3"; +>fieldNameC : string +>"fieldName3" : "fieldName3" + +class A { +>A : A + + @x ["property"]: any; +>x : (o: object, k: PropertyKey) => void +>"property" : "property" + + @x [Symbol.toStringTag]: any; +>x : (o: object, k: PropertyKey) => void +>Symbol.toStringTag : symbol +>Symbol : SymbolConstructor +>toStringTag : symbol + + @x ["property2"]: any = 2; +>x : (o: object, k: PropertyKey) => void +>"property2" : "property2" +>2 : 2 + + @x [Symbol.iterator]: any = null; +>x : (o: object, k: PropertyKey) => void +>Symbol.iterator : symbol +>Symbol : SymbolConstructor +>iterator : symbol +>null : null + + ["property3"]: any; +>"property3" : "property3" + + [Symbol.isConcatSpreadable]: any; +>Symbol.isConcatSpreadable : symbol +>Symbol : SymbolConstructor +>isConcatSpreadable : symbol + + ["property4"]: any = 2; +>"property4" : "property4" +>2 : 2 + + [Symbol.match]: any = null; +>Symbol.match : symbol +>Symbol : SymbolConstructor +>match : symbol +>null : null + + [foo()]: any; +>foo() : string +>foo : () => string + + @x [foo()]: any; +>x : (o: object, k: PropertyKey) => void +>foo() : string +>foo : () => string + + @x [foo()]: any = null; +>x : (o: object, k: PropertyKey) => void +>foo() : string +>foo : () => string +>null : null + + [fieldNameA]: any; +>fieldNameA : string + + @x [fieldNameB]: any; +>x : (o: object, k: PropertyKey) => void +>fieldNameB : string + + @x [fieldNameC]: any = null; +>x : (o: object, k: PropertyKey) => void +>fieldNameC : string +>null : null +} + +void class B { +>void class B { @x ["property"]: any; @x [Symbol.toStringTag]: any; @x ["property2"]: any = 2; @x [Symbol.iterator]: any = null; ["property3"]: any; [Symbol.isConcatSpreadable]: any; ["property4"]: any = 2; [Symbol.match]: any = null; [foo()]: any; @x [foo()]: any; @x [foo()]: any = null; [fieldNameA]: any; @x [fieldNameB]: any; @x [fieldNameC]: any = null;} : undefined +>class B { @x ["property"]: any; @x [Symbol.toStringTag]: any; @x ["property2"]: any = 2; @x [Symbol.iterator]: any = null; ["property3"]: any; [Symbol.isConcatSpreadable]: any; ["property4"]: any = 2; [Symbol.match]: any = null; [foo()]: any; @x [foo()]: any; @x [foo()]: any = null; [fieldNameA]: any; @x [fieldNameB]: any; @x [fieldNameC]: any = null;} : typeof B +>B : typeof B + + @x ["property"]: any; +>x : (o: object, k: PropertyKey) => void +>"property" : "property" + + @x [Symbol.toStringTag]: any; +>x : (o: object, k: PropertyKey) => void +>Symbol.toStringTag : symbol +>Symbol : SymbolConstructor +>toStringTag : symbol + + @x ["property2"]: any = 2; +>x : (o: object, k: PropertyKey) => void +>"property2" : "property2" +>2 : 2 + + @x [Symbol.iterator]: any = null; +>x : (o: object, k: PropertyKey) => void +>Symbol.iterator : symbol +>Symbol : SymbolConstructor +>iterator : symbol +>null : null + + ["property3"]: any; +>"property3" : "property3" + + [Symbol.isConcatSpreadable]: any; +>Symbol.isConcatSpreadable : symbol +>Symbol : SymbolConstructor +>isConcatSpreadable : symbol + + ["property4"]: any = 2; +>"property4" : "property4" +>2 : 2 + + [Symbol.match]: any = null; +>Symbol.match : symbol +>Symbol : SymbolConstructor +>match : symbol +>null : null + + [foo()]: any; +>foo() : string +>foo : () => string + + @x [foo()]: any; +>x : (o: object, k: PropertyKey) => void +>foo() : string +>foo : () => string + + @x [foo()]: any = null; +>x : (o: object, k: PropertyKey) => void +>foo() : string +>foo : () => string +>null : null + + [fieldNameA]: any; +>fieldNameA : string + + @x [fieldNameB]: any; +>x : (o: object, k: PropertyKey) => void +>fieldNameB : string + + @x [fieldNameC]: any = null; +>x : (o: object, k: PropertyKey) => void +>fieldNameC : string +>null : null + +}; + +class C { +>C : C + + @x ["property"]: any; +>x : (o: object, k: PropertyKey) => void +>"property" : "property" + + @x [Symbol.toStringTag]: any; +>x : (o: object, k: PropertyKey) => void +>Symbol.toStringTag : symbol +>Symbol : SymbolConstructor +>toStringTag : symbol + + @x ["property2"]: any = 2; +>x : (o: object, k: PropertyKey) => void +>"property2" : "property2" +>2 : 2 + + @x [Symbol.iterator]: any = null; +>x : (o: object, k: PropertyKey) => void +>Symbol.iterator : symbol +>Symbol : SymbolConstructor +>iterator : symbol +>null : null + + ["property3"]: any; +>"property3" : "property3" + + [Symbol.isConcatSpreadable]: any; +>Symbol.isConcatSpreadable : symbol +>Symbol : SymbolConstructor +>isConcatSpreadable : symbol + + ["property4"]: any = 2; +>"property4" : "property4" +>2 : 2 + + [Symbol.match]: any = null; +>Symbol.match : symbol +>Symbol : SymbolConstructor +>match : symbol +>null : null + + [foo()]: any; +>foo() : string +>foo : () => string + + @x [foo()]: any; +>x : (o: object, k: PropertyKey) => void +>foo() : string +>foo : () => string + + @x [foo()]: any = null; +>x : (o: object, k: PropertyKey) => void +>foo() : string +>foo : () => string +>null : null + + [fieldNameA]: any; +>fieldNameA : string + + @x [fieldNameB]: any; +>x : (o: object, k: PropertyKey) => void +>fieldNameB : string + + @x [fieldNameC]: any = null; +>x : (o: object, k: PropertyKey) => void +>fieldNameC : string +>null : null + + ["some" + "method"]() {} +>"some" + "method" : string +>"some" : "some" +>"method" : "method" +} + +void class D { +>void class D { @x ["property"]: any; @x [Symbol.toStringTag]: any; @x ["property2"]: any = 2; @x [Symbol.iterator]: any = null; ["property3"]: any; [Symbol.isConcatSpreadable]: any; ["property4"]: any = 2; [Symbol.match]: any = null; [foo()]: any; @x [foo()]: any; @x [foo()]: any = null; [fieldNameA]: any; @x [fieldNameB]: any; @x [fieldNameC]: any = null; ["some" + "method"]() {}} : undefined +>class D { @x ["property"]: any; @x [Symbol.toStringTag]: any; @x ["property2"]: any = 2; @x [Symbol.iterator]: any = null; ["property3"]: any; [Symbol.isConcatSpreadable]: any; ["property4"]: any = 2; [Symbol.match]: any = null; [foo()]: any; @x [foo()]: any; @x [foo()]: any = null; [fieldNameA]: any; @x [fieldNameB]: any; @x [fieldNameC]: any = null; ["some" + "method"]() {}} : typeof D +>D : typeof D + + @x ["property"]: any; +>x : (o: object, k: PropertyKey) => void +>"property" : "property" + + @x [Symbol.toStringTag]: any; +>x : (o: object, k: PropertyKey) => void +>Symbol.toStringTag : symbol +>Symbol : SymbolConstructor +>toStringTag : symbol + + @x ["property2"]: any = 2; +>x : (o: object, k: PropertyKey) => void +>"property2" : "property2" +>2 : 2 + + @x [Symbol.iterator]: any = null; +>x : (o: object, k: PropertyKey) => void +>Symbol.iterator : symbol +>Symbol : SymbolConstructor +>iterator : symbol +>null : null + + ["property3"]: any; +>"property3" : "property3" + + [Symbol.isConcatSpreadable]: any; +>Symbol.isConcatSpreadable : symbol +>Symbol : SymbolConstructor +>isConcatSpreadable : symbol + + ["property4"]: any = 2; +>"property4" : "property4" +>2 : 2 + + [Symbol.match]: any = null; +>Symbol.match : symbol +>Symbol : SymbolConstructor +>match : symbol +>null : null + + [foo()]: any; +>foo() : string +>foo : () => string + + @x [foo()]: any; +>x : (o: object, k: PropertyKey) => void +>foo() : string +>foo : () => string + + @x [foo()]: any = null; +>x : (o: object, k: PropertyKey) => void +>foo() : string +>foo : () => string +>null : null + + [fieldNameA]: any; +>fieldNameA : string + + @x [fieldNameB]: any; +>x : (o: object, k: PropertyKey) => void +>fieldNameB : string + + @x [fieldNameC]: any = null; +>x : (o: object, k: PropertyKey) => void +>fieldNameC : string +>null : null + + ["some" + "method"]() {} +>"some" + "method" : string +>"some" : "some" +>"method" : "method" + +}; + +class E { +>E : E + + @x ["property"]: any; +>x : (o: object, k: PropertyKey) => void +>"property" : "property" + + @x [Symbol.toStringTag]: any; +>x : (o: object, k: PropertyKey) => void +>Symbol.toStringTag : symbol +>Symbol : SymbolConstructor +>toStringTag : symbol + + @x ["property2"]: any = 2; +>x : (o: object, k: PropertyKey) => void +>"property2" : "property2" +>2 : 2 + + @x [Symbol.iterator]: any = null; +>x : (o: object, k: PropertyKey) => void +>Symbol.iterator : symbol +>Symbol : SymbolConstructor +>iterator : symbol +>null : null + + ["property3"]: any; +>"property3" : "property3" + + [Symbol.isConcatSpreadable]: any; +>Symbol.isConcatSpreadable : symbol +>Symbol : SymbolConstructor +>isConcatSpreadable : symbol + + ["property4"]: any = 2; +>"property4" : "property4" +>2 : 2 + + [Symbol.match]: any = null; +>Symbol.match : symbol +>Symbol : SymbolConstructor +>match : symbol +>null : null + + [foo()]: any; +>foo() : string +>foo : () => string + + @x [foo()]: any; +>x : (o: object, k: PropertyKey) => void +>foo() : string +>foo : () => string + + @x [foo()]: any = null; +>x : (o: object, k: PropertyKey) => void +>foo() : string +>foo : () => string +>null : null + + ["some" + "method"]() {} +>"some" + "method" : string +>"some" : "some" +>"method" : "method" + + [fieldNameA]: any; +>fieldNameA : string + + @x [fieldNameB]: any; +>x : (o: object, k: PropertyKey) => void +>fieldNameB : string + + @x [fieldNameC]: any = null; +>x : (o: object, k: PropertyKey) => void +>fieldNameC : string +>null : null +} + +void class F { +>void class F { @x ["property"]: any; @x [Symbol.toStringTag]: any; @x ["property2"]: any = 2; @x [Symbol.iterator]: any = null; ["property3"]: any; [Symbol.isConcatSpreadable]: any; ["property4"]: any = 2; [Symbol.match]: any = null; [foo()]: any; @x [foo()]: any; @x [foo()]: any = null; ["some" + "method"]() {} [fieldNameA]: any; @x [fieldNameB]: any; @x [fieldNameC]: any = null;} : undefined +>class F { @x ["property"]: any; @x [Symbol.toStringTag]: any; @x ["property2"]: any = 2; @x [Symbol.iterator]: any = null; ["property3"]: any; [Symbol.isConcatSpreadable]: any; ["property4"]: any = 2; [Symbol.match]: any = null; [foo()]: any; @x [foo()]: any; @x [foo()]: any = null; ["some" + "method"]() {} [fieldNameA]: any; @x [fieldNameB]: any; @x [fieldNameC]: any = null;} : typeof F +>F : typeof F + + @x ["property"]: any; +>x : (o: object, k: PropertyKey) => void +>"property" : "property" + + @x [Symbol.toStringTag]: any; +>x : (o: object, k: PropertyKey) => void +>Symbol.toStringTag : symbol +>Symbol : SymbolConstructor +>toStringTag : symbol + + @x ["property2"]: any = 2; +>x : (o: object, k: PropertyKey) => void +>"property2" : "property2" +>2 : 2 + + @x [Symbol.iterator]: any = null; +>x : (o: object, k: PropertyKey) => void +>Symbol.iterator : symbol +>Symbol : SymbolConstructor +>iterator : symbol +>null : null + + ["property3"]: any; +>"property3" : "property3" + + [Symbol.isConcatSpreadable]: any; +>Symbol.isConcatSpreadable : symbol +>Symbol : SymbolConstructor +>isConcatSpreadable : symbol + + ["property4"]: any = 2; +>"property4" : "property4" +>2 : 2 + + [Symbol.match]: any = null; +>Symbol.match : symbol +>Symbol : SymbolConstructor +>match : symbol +>null : null + + [foo()]: any; +>foo() : string +>foo : () => string + + @x [foo()]: any; +>x : (o: object, k: PropertyKey) => void +>foo() : string +>foo : () => string + + @x [foo()]: any = null; +>x : (o: object, k: PropertyKey) => void +>foo() : string +>foo : () => string +>null : null + + ["some" + "method"]() {} +>"some" + "method" : string +>"some" : "some" +>"method" : "method" + + [fieldNameA]: any; +>fieldNameA : string + + @x [fieldNameB]: any; +>x : (o: object, k: PropertyKey) => void +>fieldNameB : string + + @x [fieldNameC]: any = null; +>x : (o: object, k: PropertyKey) => void +>fieldNameC : string +>null : null + +}; + +class G { +>G : G + + @x ["property"]: any; +>x : (o: object, k: PropertyKey) => void +>"property" : "property" + + @x [Symbol.toStringTag]: any; +>x : (o: object, k: PropertyKey) => void +>Symbol.toStringTag : symbol +>Symbol : SymbolConstructor +>toStringTag : symbol + + @x ["property2"]: any = 2; +>x : (o: object, k: PropertyKey) => void +>"property2" : "property2" +>2 : 2 + + @x [Symbol.iterator]: any = null; +>x : (o: object, k: PropertyKey) => void +>Symbol.iterator : symbol +>Symbol : SymbolConstructor +>iterator : symbol +>null : null + + ["property3"]: any; +>"property3" : "property3" + + [Symbol.isConcatSpreadable]: any; +>Symbol.isConcatSpreadable : symbol +>Symbol : SymbolConstructor +>isConcatSpreadable : symbol + + ["property4"]: any = 2; +>"property4" : "property4" +>2 : 2 + + [Symbol.match]: any = null; +>Symbol.match : symbol +>Symbol : SymbolConstructor +>match : symbol +>null : null + + [foo()]: any; +>foo() : string +>foo : () => string + + @x [foo()]: any; +>x : (o: object, k: PropertyKey) => void +>foo() : string +>foo : () => string + + @x [foo()]: any = null; +>x : (o: object, k: PropertyKey) => void +>foo() : string +>foo : () => string +>null : null + + ["some" + "method"]() {} +>"some" + "method" : string +>"some" : "some" +>"method" : "method" + + [fieldNameA]: any; +>fieldNameA : string + + @x [fieldNameB]: any; +>x : (o: object, k: PropertyKey) => void +>fieldNameB : string + + ["some" + "method2"]() {} +>"some" + "method2" : string +>"some" : "some" +>"method2" : "method2" + + @x [fieldNameC]: any = null; +>x : (o: object, k: PropertyKey) => void +>fieldNameC : string +>null : null +} + +void class H { +>void class H { @x ["property"]: any; @x [Symbol.toStringTag]: any; @x ["property2"]: any = 2; @x [Symbol.iterator]: any = null; ["property3"]: any; [Symbol.isConcatSpreadable]: any; ["property4"]: any = 2; [Symbol.match]: any = null; [foo()]: any; @x [foo()]: any; @x [foo()]: any = null; ["some" + "method"]() {} [fieldNameA]: any; @x [fieldNameB]: any; ["some" + "method2"]() {} @x [fieldNameC]: any = null;} : undefined +>class H { @x ["property"]: any; @x [Symbol.toStringTag]: any; @x ["property2"]: any = 2; @x [Symbol.iterator]: any = null; ["property3"]: any; [Symbol.isConcatSpreadable]: any; ["property4"]: any = 2; [Symbol.match]: any = null; [foo()]: any; @x [foo()]: any; @x [foo()]: any = null; ["some" + "method"]() {} [fieldNameA]: any; @x [fieldNameB]: any; ["some" + "method2"]() {} @x [fieldNameC]: any = null;} : typeof H +>H : typeof H + + @x ["property"]: any; +>x : (o: object, k: PropertyKey) => void +>"property" : "property" + + @x [Symbol.toStringTag]: any; +>x : (o: object, k: PropertyKey) => void +>Symbol.toStringTag : symbol +>Symbol : SymbolConstructor +>toStringTag : symbol + + @x ["property2"]: any = 2; +>x : (o: object, k: PropertyKey) => void +>"property2" : "property2" +>2 : 2 + + @x [Symbol.iterator]: any = null; +>x : (o: object, k: PropertyKey) => void +>Symbol.iterator : symbol +>Symbol : SymbolConstructor +>iterator : symbol +>null : null + + ["property3"]: any; +>"property3" : "property3" + + [Symbol.isConcatSpreadable]: any; +>Symbol.isConcatSpreadable : symbol +>Symbol : SymbolConstructor +>isConcatSpreadable : symbol + + ["property4"]: any = 2; +>"property4" : "property4" +>2 : 2 + + [Symbol.match]: any = null; +>Symbol.match : symbol +>Symbol : SymbolConstructor +>match : symbol +>null : null + + [foo()]: any; +>foo() : string +>foo : () => string + + @x [foo()]: any; +>x : (o: object, k: PropertyKey) => void +>foo() : string +>foo : () => string + + @x [foo()]: any = null; +>x : (o: object, k: PropertyKey) => void +>foo() : string +>foo : () => string +>null : null + + ["some" + "method"]() {} +>"some" + "method" : string +>"some" : "some" +>"method" : "method" + + [fieldNameA]: any; +>fieldNameA : string + + @x [fieldNameB]: any; +>x : (o: object, k: PropertyKey) => void +>fieldNameB : string + + ["some" + "method2"]() {} +>"some" + "method2" : string +>"some" : "some" +>"method2" : "method2" + + @x [fieldNameC]: any = null; +>x : (o: object, k: PropertyKey) => void +>fieldNameC : string +>null : null + +}; + +class I { +>I : I + + @x ["property"]: any; +>x : (o: object, k: PropertyKey) => void +>"property" : "property" + + @x [Symbol.toStringTag]: any; +>x : (o: object, k: PropertyKey) => void +>Symbol.toStringTag : symbol +>Symbol : SymbolConstructor +>toStringTag : symbol + + @x ["property2"]: any = 2; +>x : (o: object, k: PropertyKey) => void +>"property2" : "property2" +>2 : 2 + + @x [Symbol.iterator]: any = null; +>x : (o: object, k: PropertyKey) => void +>Symbol.iterator : symbol +>Symbol : SymbolConstructor +>iterator : symbol +>null : null + + ["property3"]: any; +>"property3" : "property3" + + [Symbol.isConcatSpreadable]: any; +>Symbol.isConcatSpreadable : symbol +>Symbol : SymbolConstructor +>isConcatSpreadable : symbol + + ["property4"]: any = 2; +>"property4" : "property4" +>2 : 2 + + [Symbol.match]: any = null; +>Symbol.match : symbol +>Symbol : SymbolConstructor +>match : symbol +>null : null + + [foo()]: any; +>foo() : string +>foo : () => string + + @x [foo()]: any; +>x : (o: object, k: PropertyKey) => void +>foo() : string +>foo : () => string + + @x [foo()]: any = null; +>x : (o: object, k: PropertyKey) => void +>foo() : string +>foo : () => string +>null : null + + @x ["some" + "method"]() {} +>x : (o: object, k: PropertyKey) => void +>"some" + "method" : string +>"some" : "some" +>"method" : "method" + + [fieldNameA]: any; +>fieldNameA : string + + @x [fieldNameB]: any; +>x : (o: object, k: PropertyKey) => void +>fieldNameB : string + + ["some" + "method2"]() {} +>"some" + "method2" : string +>"some" : "some" +>"method2" : "method2" + + @x [fieldNameC]: any = null; +>x : (o: object, k: PropertyKey) => void +>fieldNameC : string +>null : null +} + +void class J { +>void class J { @x ["property"]: any; @x [Symbol.toStringTag]: any; @x ["property2"]: any = 2; @x [Symbol.iterator]: any = null; ["property3"]: any; [Symbol.isConcatSpreadable]: any; ["property4"]: any = 2; [Symbol.match]: any = null; [foo()]: any; @x [foo()]: any; @x [foo()]: any = null; @x ["some" + "method"]() {} [fieldNameA]: any; @x [fieldNameB]: any; ["some" + "method2"]() {} @x [fieldNameC]: any = null;} : undefined +>class J { @x ["property"]: any; @x [Symbol.toStringTag]: any; @x ["property2"]: any = 2; @x [Symbol.iterator]: any = null; ["property3"]: any; [Symbol.isConcatSpreadable]: any; ["property4"]: any = 2; [Symbol.match]: any = null; [foo()]: any; @x [foo()]: any; @x [foo()]: any = null; @x ["some" + "method"]() {} [fieldNameA]: any; @x [fieldNameB]: any; ["some" + "method2"]() {} @x [fieldNameC]: any = null;} : typeof J +>J : typeof J + + @x ["property"]: any; +>x : (o: object, k: PropertyKey) => void +>"property" : "property" + + @x [Symbol.toStringTag]: any; +>x : (o: object, k: PropertyKey) => void +>Symbol.toStringTag : symbol +>Symbol : SymbolConstructor +>toStringTag : symbol + + @x ["property2"]: any = 2; +>x : (o: object, k: PropertyKey) => void +>"property2" : "property2" +>2 : 2 + + @x [Symbol.iterator]: any = null; +>x : (o: object, k: PropertyKey) => void +>Symbol.iterator : symbol +>Symbol : SymbolConstructor +>iterator : symbol +>null : null + + ["property3"]: any; +>"property3" : "property3" + + [Symbol.isConcatSpreadable]: any; +>Symbol.isConcatSpreadable : symbol +>Symbol : SymbolConstructor +>isConcatSpreadable : symbol + + ["property4"]: any = 2; +>"property4" : "property4" +>2 : 2 + + [Symbol.match]: any = null; +>Symbol.match : symbol +>Symbol : SymbolConstructor +>match : symbol +>null : null + + [foo()]: any; +>foo() : string +>foo : () => string + + @x [foo()]: any; +>x : (o: object, k: PropertyKey) => void +>foo() : string +>foo : () => string + + @x [foo()]: any = null; +>x : (o: object, k: PropertyKey) => void +>foo() : string +>foo : () => string +>null : null + + @x ["some" + "method"]() {} +>x : (o: object, k: PropertyKey) => void +>"some" + "method" : string +>"some" : "some" +>"method" : "method" + + [fieldNameA]: any; +>fieldNameA : string + + @x [fieldNameB]: any; +>x : (o: object, k: PropertyKey) => void +>fieldNameB : string + + ["some" + "method2"]() {} +>"some" + "method2" : string +>"some" : "some" +>"method2" : "method2" + + @x [fieldNameC]: any = null; +>x : (o: object, k: PropertyKey) => void +>fieldNameC : string +>null : null + +}; diff --git a/tests/baselines/reference/newTarget.es5.js b/tests/baselines/reference/newTarget.es5.js index 61b3f73a9b4..0ee9a7e339e 100644 --- a/tests/baselines/reference/newTarget.es5.js +++ b/tests/baselines/reference/newTarget.es5.js @@ -69,11 +69,11 @@ function f1() { var g = _newTarget; var h = function () { return _newTarget; }; } -var f2 = function _a() { - var _newTarget = this && this instanceof _a ? this.constructor : void 0; +var f2 = function _b() { + var _newTarget = this && this instanceof _b ? this.constructor : void 0; var i = _newTarget; var j = function () { return _newTarget; }; }; var O = { - k: function _b() { var _newTarget = this && this instanceof _b ? this.constructor : void 0; return _newTarget; } + k: function _c() { var _newTarget = this && this instanceof _c ? this.constructor : void 0; return _newTarget; } }; diff --git a/tests/baselines/reference/parserComputedPropertyName10.js b/tests/baselines/reference/parserComputedPropertyName10.js index eba480ba810..b6efaf3f5a7 100644 --- a/tests/baselines/reference/parserComputedPropertyName10.js +++ b/tests/baselines/reference/parserComputedPropertyName10.js @@ -6,6 +6,8 @@ class C { //// [parserComputedPropertyName10.js] class C { constructor() { - this[e] = 1; + this[_a] = 1; } } +_a = e; +var _a; diff --git a/tests/baselines/reference/parserComputedPropertyName25.js b/tests/baselines/reference/parserComputedPropertyName25.js index 47670fe14b8..f914d7de8ee 100644 --- a/tests/baselines/reference/parserComputedPropertyName25.js +++ b/tests/baselines/reference/parserComputedPropertyName25.js @@ -9,6 +9,8 @@ class C { class C { constructor() { // No ASI - this[e] = 0[e2] = 1; + this[_a] = 0[e2] = 1; } } +_a = e; +var _a; diff --git a/tests/baselines/reference/parserComputedPropertyName27.js b/tests/baselines/reference/parserComputedPropertyName27.js index f872e95e7e6..7f60ec97b5e 100644 --- a/tests/baselines/reference/parserComputedPropertyName27.js +++ b/tests/baselines/reference/parserComputedPropertyName27.js @@ -9,6 +9,8 @@ class C { class C { constructor() { // No ASI - this[e] = 0[e2]; + this[_a] = 0[e2]; } } +_a = e; +var _a; diff --git a/tests/baselines/reference/parserComputedPropertyName28.js b/tests/baselines/reference/parserComputedPropertyName28.js index 998f60db914..d01ed38069f 100644 --- a/tests/baselines/reference/parserComputedPropertyName28.js +++ b/tests/baselines/reference/parserComputedPropertyName28.js @@ -7,6 +7,8 @@ class C { //// [parserComputedPropertyName28.js] class C { constructor() { - this[e] = 0; + this[_a] = 0; } } +_a = e; +var _a; diff --git a/tests/baselines/reference/parserComputedPropertyName29.js b/tests/baselines/reference/parserComputedPropertyName29.js index a100cbf1791..d5a00df2256 100644 --- a/tests/baselines/reference/parserComputedPropertyName29.js +++ b/tests/baselines/reference/parserComputedPropertyName29.js @@ -9,6 +9,8 @@ class C { class C { constructor() { // yes ASI - this[e] = id++; + this[_a] = id++; } } +_a = e; +var _a; diff --git a/tests/baselines/reference/parserComputedPropertyName33.js b/tests/baselines/reference/parserComputedPropertyName33.js index ab80967c21a..84520a8eb51 100644 --- a/tests/baselines/reference/parserComputedPropertyName33.js +++ b/tests/baselines/reference/parserComputedPropertyName33.js @@ -9,7 +9,9 @@ class C { class C { constructor() { // No ASI - this[e] = 0[e2](); + this[_a] = 0[e2](); } } +_a = e; { } +var _a; diff --git a/tests/baselines/reference/parserES5ComputedPropertyName10.js b/tests/baselines/reference/parserES5ComputedPropertyName10.js index 78f819af375..72902c30db9 100644 --- a/tests/baselines/reference/parserES5ComputedPropertyName10.js +++ b/tests/baselines/reference/parserES5ComputedPropertyName10.js @@ -6,7 +6,9 @@ class C { //// [parserES5ComputedPropertyName10.js] var C = /** @class */ (function () { function C() { - this[e] = 1; + this[_a] = 1; } return C; }()); +_a = e; +var _a; diff --git a/tests/baselines/reference/symbolProperty7.js b/tests/baselines/reference/symbolProperty7.js index 51f3511f332..9dbe5a1abb1 100644 --- a/tests/baselines/reference/symbolProperty7.js +++ b/tests/baselines/reference/symbolProperty7.js @@ -11,10 +11,11 @@ class C { //// [symbolProperty7.js] class C { constructor() { - this[Symbol()] = 0; + this[_a] = 0; } - [Symbol()]() { } + [_a = Symbol(), Symbol(), Symbol()]() { } get [Symbol()]() { return 0; } } +var _a; diff --git a/tests/cases/compiler/decoratorsOnComputedProperties.ts b/tests/cases/compiler/decoratorsOnComputedProperties.ts new file mode 100644 index 00000000000..cb9cfe5f997 --- /dev/null +++ b/tests/cases/compiler/decoratorsOnComputedProperties.ts @@ -0,0 +1,191 @@ +// @target: es6 +// @experimentalDecorators: true +function x(o: object, k: PropertyKey) { } +let i = 0; +function foo(): string { return ++i + ""; } + +const fieldNameA: string = "fieldName1"; +const fieldNameB: string = "fieldName2"; +const fieldNameC: string = "fieldName3"; + +class A { + @x ["property"]: any; + @x [Symbol.toStringTag]: any; + @x ["property2"]: any = 2; + @x [Symbol.iterator]: any = null; + ["property3"]: any; + [Symbol.isConcatSpreadable]: any; + ["property4"]: any = 2; + [Symbol.match]: any = null; + [foo()]: any; + @x [foo()]: any; + @x [foo()]: any = null; + [fieldNameA]: any; + @x [fieldNameB]: any; + @x [fieldNameC]: any = null; +} + +void class B { + @x ["property"]: any; + @x [Symbol.toStringTag]: any; + @x ["property2"]: any = 2; + @x [Symbol.iterator]: any = null; + ["property3"]: any; + [Symbol.isConcatSpreadable]: any; + ["property4"]: any = 2; + [Symbol.match]: any = null; + [foo()]: any; + @x [foo()]: any; + @x [foo()]: any = null; + [fieldNameA]: any; + @x [fieldNameB]: any; + @x [fieldNameC]: any = null; +}; + +class C { + @x ["property"]: any; + @x [Symbol.toStringTag]: any; + @x ["property2"]: any = 2; + @x [Symbol.iterator]: any = null; + ["property3"]: any; + [Symbol.isConcatSpreadable]: any; + ["property4"]: any = 2; + [Symbol.match]: any = null; + [foo()]: any; + @x [foo()]: any; + @x [foo()]: any = null; + [fieldNameA]: any; + @x [fieldNameB]: any; + @x [fieldNameC]: any = null; + ["some" + "method"]() {} +} + +void class D { + @x ["property"]: any; + @x [Symbol.toStringTag]: any; + @x ["property2"]: any = 2; + @x [Symbol.iterator]: any = null; + ["property3"]: any; + [Symbol.isConcatSpreadable]: any; + ["property4"]: any = 2; + [Symbol.match]: any = null; + [foo()]: any; + @x [foo()]: any; + @x [foo()]: any = null; + [fieldNameA]: any; + @x [fieldNameB]: any; + @x [fieldNameC]: any = null; + ["some" + "method"]() {} +}; + +class E { + @x ["property"]: any; + @x [Symbol.toStringTag]: any; + @x ["property2"]: any = 2; + @x [Symbol.iterator]: any = null; + ["property3"]: any; + [Symbol.isConcatSpreadable]: any; + ["property4"]: any = 2; + [Symbol.match]: any = null; + [foo()]: any; + @x [foo()]: any; + @x [foo()]: any = null; + ["some" + "method"]() {} + [fieldNameA]: any; + @x [fieldNameB]: any; + @x [fieldNameC]: any = null; +} + +void class F { + @x ["property"]: any; + @x [Symbol.toStringTag]: any; + @x ["property2"]: any = 2; + @x [Symbol.iterator]: any = null; + ["property3"]: any; + [Symbol.isConcatSpreadable]: any; + ["property4"]: any = 2; + [Symbol.match]: any = null; + [foo()]: any; + @x [foo()]: any; + @x [foo()]: any = null; + ["some" + "method"]() {} + [fieldNameA]: any; + @x [fieldNameB]: any; + @x [fieldNameC]: any = null; +}; + +class G { + @x ["property"]: any; + @x [Symbol.toStringTag]: any; + @x ["property2"]: any = 2; + @x [Symbol.iterator]: any = null; + ["property3"]: any; + [Symbol.isConcatSpreadable]: any; + ["property4"]: any = 2; + [Symbol.match]: any = null; + [foo()]: any; + @x [foo()]: any; + @x [foo()]: any = null; + ["some" + "method"]() {} + [fieldNameA]: any; + @x [fieldNameB]: any; + ["some" + "method2"]() {} + @x [fieldNameC]: any = null; +} + +void class H { + @x ["property"]: any; + @x [Symbol.toStringTag]: any; + @x ["property2"]: any = 2; + @x [Symbol.iterator]: any = null; + ["property3"]: any; + [Symbol.isConcatSpreadable]: any; + ["property4"]: any = 2; + [Symbol.match]: any = null; + [foo()]: any; + @x [foo()]: any; + @x [foo()]: any = null; + ["some" + "method"]() {} + [fieldNameA]: any; + @x [fieldNameB]: any; + ["some" + "method2"]() {} + @x [fieldNameC]: any = null; +}; + +class I { + @x ["property"]: any; + @x [Symbol.toStringTag]: any; + @x ["property2"]: any = 2; + @x [Symbol.iterator]: any = null; + ["property3"]: any; + [Symbol.isConcatSpreadable]: any; + ["property4"]: any = 2; + [Symbol.match]: any = null; + [foo()]: any; + @x [foo()]: any; + @x [foo()]: any = null; + @x ["some" + "method"]() {} + [fieldNameA]: any; + @x [fieldNameB]: any; + ["some" + "method2"]() {} + @x [fieldNameC]: any = null; +} + +void class J { + @x ["property"]: any; + @x [Symbol.toStringTag]: any; + @x ["property2"]: any = 2; + @x [Symbol.iterator]: any = null; + ["property3"]: any; + [Symbol.isConcatSpreadable]: any; + ["property4"]: any = 2; + [Symbol.match]: any = null; + [foo()]: any; + @x [foo()]: any; + @x [foo()]: any = null; + @x ["some" + "method"]() {} + [fieldNameA]: any; + @x [fieldNameB]: any; + ["some" + "method2"]() {} + @x [fieldNameC]: any = null; +}; \ No newline at end of file From 0593ba27d8ccc8fac551aade40985f086d264954 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Mon, 6 Nov 2017 12:52:33 -0800 Subject: [PATCH 05/12] Make getContextualTypeOfApparentType mapType over unions (#17668) * Instantiate contextual types while in an inferrential context * Limit scope of instantiation to only when likely needed * Still get aparent type * Expand test * Fix nit * Handle JSX and array * Tests for the JSX and Array cases * After much deliberation and inspection, much simpler fix After much deliberation and inspection, much simpler fix Undo Redo --- src/compiler/checker.ts | 2 +- ...ntextualTypingOfOptionalMembers.errors.txt | 80 ++++++ .../contextualTypingOfOptionalMembers.js | 103 +++++++ .../contextualTypingOfOptionalMembers.symbols | 235 ++++++++++++++++ .../contextualTypingOfOptionalMembers.types | 261 ++++++++++++++++++ .../contextualTypingOfOptionalMembers.tsx | 77 ++++++ 6 files changed, 757 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/contextualTypingOfOptionalMembers.errors.txt create mode 100644 tests/baselines/reference/contextualTypingOfOptionalMembers.js create mode 100644 tests/baselines/reference/contextualTypingOfOptionalMembers.symbols create mode 100644 tests/baselines/reference/contextualTypingOfOptionalMembers.types create mode 100644 tests/cases/compiler/contextualTypingOfOptionalMembers.tsx diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index eb5442a7996..39b0dc18569 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -13691,7 +13691,7 @@ namespace ts { // be "pushed" onto a node using the contextualType property. function getApparentTypeOfContextualType(node: Expression): Type { const type = getContextualType(node); - return type && getApparentType(type); + return type && mapType(type, getApparentType); } /** diff --git a/tests/baselines/reference/contextualTypingOfOptionalMembers.errors.txt b/tests/baselines/reference/contextualTypingOfOptionalMembers.errors.txt new file mode 100644 index 00000000000..02c94400e21 --- /dev/null +++ b/tests/baselines/reference/contextualTypingOfOptionalMembers.errors.txt @@ -0,0 +1,80 @@ +tests/cases/compiler/index.tsx(73,34): error TS7006: Parameter 's' implicitly has an 'any' type. + + +==== tests/cases/compiler/index.tsx (1 errors) ==== + interface ActionsObject { + [prop: string]: (state: State) => State; + } + + interface Options { + state?: State; + view?: (state: State, actions: Actions) => any; + actions: string | Actions; + } + + declare function app>(obj: Options): void; + + app({ + state: 100, + actions: { + foo: s => s // Should be typed number => number + }, + view: (s, a) => undefined as any, + }); + + + interface Bar { + bar: (a: number) => void; + } + + declare function foo(x: string | T): T; + + const y = foo({ + bar(x) { // Should be typed number => void + } + }); + + interface Options2 { + state?: State; + view?: (state: State, actions: Actions) => any; + actions?: Actions; + } + + declare function app2>(obj: Options2): void; + + app2({ + state: 100, + actions: { + foo: s => s // Should be typed number => number + }, + view: (s, a) => undefined as any, + }); + + + type ActionsArray = ((state: State) => State)[]; + + declare function app3>(obj: Options): void; + + app3({ + state: 100, + actions: [ + s => s // Should be typed number => number + ], + view: (s, a) => undefined as any, + }); + + namespace JSX { + export interface Element {} + export interface IntrinsicElements {} + } + + interface ActionsObjectOr { + [prop: string]: ((state: State) => State) | State; + } + + declare function App4>(props: Options["actions"] & { state: State }): JSX.Element; + + const a = s} />; // TODO: should be number => number, but JSX resolution is missing an inferential pass + ~ +!!! error TS7006: Parameter 's' implicitly has an 'any' type. + \ No newline at end of file diff --git a/tests/baselines/reference/contextualTypingOfOptionalMembers.js b/tests/baselines/reference/contextualTypingOfOptionalMembers.js new file mode 100644 index 00000000000..289d64546e8 --- /dev/null +++ b/tests/baselines/reference/contextualTypingOfOptionalMembers.js @@ -0,0 +1,103 @@ +//// [index.tsx] +interface ActionsObject { + [prop: string]: (state: State) => State; +} + +interface Options { + state?: State; + view?: (state: State, actions: Actions) => any; + actions: string | Actions; +} + +declare function app>(obj: Options): void; + +app({ + state: 100, + actions: { + foo: s => s // Should be typed number => number + }, + view: (s, a) => undefined as any, +}); + + +interface Bar { + bar: (a: number) => void; +} + +declare function foo(x: string | T): T; + +const y = foo({ + bar(x) { // Should be typed number => void + } +}); + +interface Options2 { + state?: State; + view?: (state: State, actions: Actions) => any; + actions?: Actions; +} + +declare function app2>(obj: Options2): void; + +app2({ + state: 100, + actions: { + foo: s => s // Should be typed number => number + }, + view: (s, a) => undefined as any, +}); + + +type ActionsArray = ((state: State) => State)[]; + +declare function app3>(obj: Options): void; + +app3({ + state: 100, + actions: [ + s => s // Should be typed number => number + ], + view: (s, a) => undefined as any, +}); + +namespace JSX { + export interface Element {} + export interface IntrinsicElements {} +} + +interface ActionsObjectOr { + [prop: string]: ((state: State) => State) | State; +} + +declare function App4>(props: Options["actions"] & { state: State }): JSX.Element; + +const a = s} />; // TODO: should be number => number, but JSX resolution is missing an inferential pass + + +//// [index.jsx] +app({ + state: 100, + actions: { + foo: function (s) { return s; } // Should be typed number => number + }, + view: function (s, a) { return undefined; } +}); +var y = foo({ + bar: function (x) { + } +}); +app2({ + state: 100, + actions: { + foo: function (s) { return s; } // Should be typed number => number + }, + view: function (s, a) { return undefined; } +}); +app3({ + state: 100, + actions: [ + function (s) { return s; } // Should be typed number => number + ], + view: function (s, a) { return undefined; } +}); +var a = ; // TODO: should be number => number, but JSX resolution is missing an inferential pass diff --git a/tests/baselines/reference/contextualTypingOfOptionalMembers.symbols b/tests/baselines/reference/contextualTypingOfOptionalMembers.symbols new file mode 100644 index 00000000000..14d8ef41b3a --- /dev/null +++ b/tests/baselines/reference/contextualTypingOfOptionalMembers.symbols @@ -0,0 +1,235 @@ +=== tests/cases/compiler/index.tsx === +interface ActionsObject { +>ActionsObject : Symbol(ActionsObject, Decl(index.tsx, 0, 0)) +>State : Symbol(State, Decl(index.tsx, 0, 24)) + + [prop: string]: (state: State) => State; +>prop : Symbol(prop, Decl(index.tsx, 1, 5)) +>state : Symbol(state, Decl(index.tsx, 1, 21)) +>State : Symbol(State, Decl(index.tsx, 0, 24)) +>State : Symbol(State, Decl(index.tsx, 0, 24)) +} + +interface Options { +>Options : Symbol(Options, Decl(index.tsx, 2, 1)) +>State : Symbol(State, Decl(index.tsx, 4, 18)) +>Actions : Symbol(Actions, Decl(index.tsx, 4, 24)) + + state?: State; +>state : Symbol(Options.state, Decl(index.tsx, 4, 35)) +>State : Symbol(State, Decl(index.tsx, 4, 18)) + + view?: (state: State, actions: Actions) => any; +>view : Symbol(Options.view, Decl(index.tsx, 5, 18)) +>state : Symbol(state, Decl(index.tsx, 6, 12)) +>State : Symbol(State, Decl(index.tsx, 4, 18)) +>actions : Symbol(actions, Decl(index.tsx, 6, 25)) +>Actions : Symbol(Actions, Decl(index.tsx, 4, 24)) + + actions: string | Actions; +>actions : Symbol(Options.actions, Decl(index.tsx, 6, 51)) +>Actions : Symbol(Actions, Decl(index.tsx, 4, 24)) +} + +declare function app>(obj: Options): void; +>app : Symbol(app, Decl(index.tsx, 8, 1)) +>State : Symbol(State, Decl(index.tsx, 10, 21)) +>Actions : Symbol(Actions, Decl(index.tsx, 10, 27)) +>ActionsObject : Symbol(ActionsObject, Decl(index.tsx, 0, 0)) +>State : Symbol(State, Decl(index.tsx, 10, 21)) +>obj : Symbol(obj, Decl(index.tsx, 10, 66)) +>Options : Symbol(Options, Decl(index.tsx, 2, 1)) +>State : Symbol(State, Decl(index.tsx, 10, 21)) +>Actions : Symbol(Actions, Decl(index.tsx, 10, 27)) + +app({ +>app : Symbol(app, Decl(index.tsx, 8, 1)) + + state: 100, +>state : Symbol(state, Decl(index.tsx, 12, 5)) + + actions: { +>actions : Symbol(actions, Decl(index.tsx, 13, 15)) + + foo: s => s // Should be typed number => number +>foo : Symbol(foo, Decl(index.tsx, 14, 14)) +>s : Symbol(s, Decl(index.tsx, 15, 12)) +>s : Symbol(s, Decl(index.tsx, 15, 12)) + + }, + view: (s, a) => undefined as any, +>view : Symbol(view, Decl(index.tsx, 16, 6)) +>s : Symbol(s, Decl(index.tsx, 17, 11)) +>a : Symbol(a, Decl(index.tsx, 17, 13)) +>undefined : Symbol(undefined) + +}); + + +interface Bar { +>Bar : Symbol(Bar, Decl(index.tsx, 18, 3)) + + bar: (a: number) => void; +>bar : Symbol(Bar.bar, Decl(index.tsx, 21, 15)) +>a : Symbol(a, Decl(index.tsx, 22, 10)) +} + +declare function foo(x: string | T): T; +>foo : Symbol(foo, Decl(index.tsx, 23, 1)) +>T : Symbol(T, Decl(index.tsx, 25, 21)) +>Bar : Symbol(Bar, Decl(index.tsx, 18, 3)) +>x : Symbol(x, Decl(index.tsx, 25, 36)) +>T : Symbol(T, Decl(index.tsx, 25, 21)) +>T : Symbol(T, Decl(index.tsx, 25, 21)) + +const y = foo({ +>y : Symbol(y, Decl(index.tsx, 27, 5)) +>foo : Symbol(foo, Decl(index.tsx, 23, 1)) + + bar(x) { // Should be typed number => void +>bar : Symbol(bar, Decl(index.tsx, 27, 15)) +>x : Symbol(x, Decl(index.tsx, 28, 8)) + } +}); + +interface Options2 { +>Options2 : Symbol(Options2, Decl(index.tsx, 30, 3)) +>State : Symbol(State, Decl(index.tsx, 32, 19)) +>Actions : Symbol(Actions, Decl(index.tsx, 32, 25)) + + state?: State; +>state : Symbol(Options2.state, Decl(index.tsx, 32, 36)) +>State : Symbol(State, Decl(index.tsx, 32, 19)) + + view?: (state: State, actions: Actions) => any; +>view : Symbol(Options2.view, Decl(index.tsx, 33, 18)) +>state : Symbol(state, Decl(index.tsx, 34, 12)) +>State : Symbol(State, Decl(index.tsx, 32, 19)) +>actions : Symbol(actions, Decl(index.tsx, 34, 25)) +>Actions : Symbol(Actions, Decl(index.tsx, 32, 25)) + + actions?: Actions; +>actions : Symbol(Options2.actions, Decl(index.tsx, 34, 51)) +>Actions : Symbol(Actions, Decl(index.tsx, 32, 25)) +} + +declare function app2>(obj: Options2): void; +>app2 : Symbol(app2, Decl(index.tsx, 36, 1)) +>State : Symbol(State, Decl(index.tsx, 38, 22)) +>Actions : Symbol(Actions, Decl(index.tsx, 38, 28)) +>ActionsObject : Symbol(ActionsObject, Decl(index.tsx, 0, 0)) +>State : Symbol(State, Decl(index.tsx, 38, 22)) +>obj : Symbol(obj, Decl(index.tsx, 38, 67)) +>Options2 : Symbol(Options2, Decl(index.tsx, 30, 3)) +>State : Symbol(State, Decl(index.tsx, 38, 22)) +>Actions : Symbol(Actions, Decl(index.tsx, 38, 28)) + +app2({ +>app2 : Symbol(app2, Decl(index.tsx, 36, 1)) + + state: 100, +>state : Symbol(state, Decl(index.tsx, 40, 6)) + + actions: { +>actions : Symbol(actions, Decl(index.tsx, 41, 15)) + + foo: s => s // Should be typed number => number +>foo : Symbol(foo, Decl(index.tsx, 42, 14)) +>s : Symbol(s, Decl(index.tsx, 43, 12)) +>s : Symbol(s, Decl(index.tsx, 43, 12)) + + }, + view: (s, a) => undefined as any, +>view : Symbol(view, Decl(index.tsx, 44, 6)) +>s : Symbol(s, Decl(index.tsx, 45, 11)) +>a : Symbol(a, Decl(index.tsx, 45, 13)) +>undefined : Symbol(undefined) + +}); + + +type ActionsArray = ((state: State) => State)[]; +>ActionsArray : Symbol(ActionsArray, Decl(index.tsx, 46, 3)) +>State : Symbol(State, Decl(index.tsx, 49, 18)) +>state : Symbol(state, Decl(index.tsx, 49, 29)) +>State : Symbol(State, Decl(index.tsx, 49, 18)) +>State : Symbol(State, Decl(index.tsx, 49, 18)) + +declare function app3>(obj: Options): void; +>app3 : Symbol(app3, Decl(index.tsx, 49, 55)) +>State : Symbol(State, Decl(index.tsx, 51, 22)) +>Actions : Symbol(Actions, Decl(index.tsx, 51, 28)) +>ActionsArray : Symbol(ActionsArray, Decl(index.tsx, 46, 3)) +>State : Symbol(State, Decl(index.tsx, 51, 22)) +>obj : Symbol(obj, Decl(index.tsx, 51, 66)) +>Options : Symbol(Options, Decl(index.tsx, 2, 1)) +>State : Symbol(State, Decl(index.tsx, 51, 22)) +>Actions : Symbol(Actions, Decl(index.tsx, 51, 28)) + +app3({ +>app3 : Symbol(app3, Decl(index.tsx, 49, 55)) + + state: 100, +>state : Symbol(state, Decl(index.tsx, 53, 6)) + + actions: [ +>actions : Symbol(actions, Decl(index.tsx, 54, 15)) + + s => s // Should be typed number => number +>s : Symbol(s, Decl(index.tsx, 55, 14)) +>s : Symbol(s, Decl(index.tsx, 55, 14)) + + ], + view: (s, a) => undefined as any, +>view : Symbol(view, Decl(index.tsx, 57, 6)) +>s : Symbol(s, Decl(index.tsx, 58, 11)) +>a : Symbol(a, Decl(index.tsx, 58, 13)) +>undefined : Symbol(undefined) + +}); + +namespace JSX { +>JSX : Symbol(JSX, Decl(index.tsx, 59, 3)) + + export interface Element {} +>Element : Symbol(Element, Decl(index.tsx, 61, 15)) + + export interface IntrinsicElements {} +>IntrinsicElements : Symbol(IntrinsicElements, Decl(index.tsx, 62, 31)) +} + +interface ActionsObjectOr { +>ActionsObjectOr : Symbol(ActionsObjectOr, Decl(index.tsx, 64, 1)) +>State : Symbol(State, Decl(index.tsx, 66, 26)) + + [prop: string]: ((state: State) => State) | State; +>prop : Symbol(prop, Decl(index.tsx, 67, 5)) +>state : Symbol(state, Decl(index.tsx, 67, 22)) +>State : Symbol(State, Decl(index.tsx, 66, 26)) +>State : Symbol(State, Decl(index.tsx, 66, 26)) +>State : Symbol(State, Decl(index.tsx, 66, 26)) +} + +declare function App4>(props: Options["actions"] & { state: State }): JSX.Element; +>App4 : Symbol(App4, Decl(index.tsx, 68, 1)) +>State : Symbol(State, Decl(index.tsx, 70, 22)) +>Actions : Symbol(Actions, Decl(index.tsx, 70, 28)) +>ActionsObjectOr : Symbol(ActionsObjectOr, Decl(index.tsx, 64, 1)) +>State : Symbol(State, Decl(index.tsx, 70, 22)) +>props : Symbol(props, Decl(index.tsx, 70, 69)) +>Options : Symbol(Options, Decl(index.tsx, 2, 1)) +>State : Symbol(State, Decl(index.tsx, 70, 22)) +>Actions : Symbol(Actions, Decl(index.tsx, 70, 28)) +>state : Symbol(state, Decl(index.tsx, 70, 114)) +>State : Symbol(State, Decl(index.tsx, 70, 22)) +>JSX : Symbol(JSX, Decl(index.tsx, 59, 3)) +>Element : Symbol(JSX.Element, Decl(index.tsx, 61, 15)) + +const a = s} />; // TODO: should be number => number, but JSX resolution is missing an inferential pass +>a : Symbol(a, Decl(index.tsx, 72, 5)) +>App4 : Symbol(App4, Decl(index.tsx, 68, 1)) +>state : Symbol(state, Decl(index.tsx, 72, 15)) +>foo : Symbol(foo, Decl(index.tsx, 72, 27)) +>s : Symbol(s, Decl(index.tsx, 72, 33)) +>s : Symbol(s, Decl(index.tsx, 72, 33)) + diff --git a/tests/baselines/reference/contextualTypingOfOptionalMembers.types b/tests/baselines/reference/contextualTypingOfOptionalMembers.types new file mode 100644 index 00000000000..515685f5c53 --- /dev/null +++ b/tests/baselines/reference/contextualTypingOfOptionalMembers.types @@ -0,0 +1,261 @@ +=== tests/cases/compiler/index.tsx === +interface ActionsObject { +>ActionsObject : ActionsObject +>State : State + + [prop: string]: (state: State) => State; +>prop : string +>state : State +>State : State +>State : State +} + +interface Options { +>Options : Options +>State : State +>Actions : Actions + + state?: State; +>state : State | undefined +>State : State + + view?: (state: State, actions: Actions) => any; +>view : ((state: State, actions: Actions) => any) | undefined +>state : State +>State : State +>actions : Actions +>Actions : Actions + + actions: string | Actions; +>actions : string | Actions +>Actions : Actions +} + +declare function app>(obj: Options): void; +>app : >(obj: Options) => void +>State : State +>Actions : Actions +>ActionsObject : ActionsObject +>State : State +>obj : Options +>Options : Options +>State : State +>Actions : Actions + +app({ +>app({ state: 100, actions: { foo: s => s // Should be typed number => number }, view: (s, a) => undefined as any,}) : void +>app : >(obj: Options) => void +>{ state: 100, actions: { foo: s => s // Should be typed number => number }, view: (s, a) => undefined as any,} : { state: number; actions: { foo: (s: number) => number; }; view: (s: number, a: ActionsObject) => any; } + + state: 100, +>state : number +>100 : 100 + + actions: { +>actions : { foo: (s: number) => number; } +>{ foo: s => s // Should be typed number => number } : { foo: (s: number) => number; } + + foo: s => s // Should be typed number => number +>foo : (s: number) => number +>s => s : (s: number) => number +>s : number +>s : number + + }, + view: (s, a) => undefined as any, +>view : (s: number, a: ActionsObject) => any +>(s, a) => undefined as any : (s: number, a: ActionsObject) => any +>s : number +>a : ActionsObject +>undefined as any : any +>undefined : undefined + +}); + + +interface Bar { +>Bar : Bar + + bar: (a: number) => void; +>bar : (a: number) => void +>a : number +} + +declare function foo(x: string | T): T; +>foo : (x: string | T) => T +>T : T +>Bar : Bar +>x : string | T +>T : T +>T : T + +const y = foo({ +>y : { bar(x: number): void; } +>foo({ bar(x) { // Should be typed number => void }}) : { bar(x: number): void; } +>foo : (x: string | T) => T +>{ bar(x) { // Should be typed number => void }} : { bar(x: number): void; } + + bar(x) { // Should be typed number => void +>bar : (x: number) => void +>x : number + } +}); + +interface Options2 { +>Options2 : Options2 +>State : State +>Actions : Actions + + state?: State; +>state : State | undefined +>State : State + + view?: (state: State, actions: Actions) => any; +>view : ((state: State, actions: Actions) => any) | undefined +>state : State +>State : State +>actions : Actions +>Actions : Actions + + actions?: Actions; +>actions : Actions | undefined +>Actions : Actions +} + +declare function app2>(obj: Options2): void; +>app2 : >(obj: Options2) => void +>State : State +>Actions : Actions +>ActionsObject : ActionsObject +>State : State +>obj : Options2 +>Options2 : Options2 +>State : State +>Actions : Actions + +app2({ +>app2({ state: 100, actions: { foo: s => s // Should be typed number => number }, view: (s, a) => undefined as any,}) : void +>app2 : >(obj: Options2) => void +>{ state: 100, actions: { foo: s => s // Should be typed number => number }, view: (s, a) => undefined as any,} : { state: number; actions: { foo: (s: number) => number; }; view: (s: number, a: ActionsObject) => any; } + + state: 100, +>state : number +>100 : 100 + + actions: { +>actions : { foo: (s: number) => number; } +>{ foo: s => s // Should be typed number => number } : { foo: (s: number) => number; } + + foo: s => s // Should be typed number => number +>foo : (s: number) => number +>s => s : (s: number) => number +>s : number +>s : number + + }, + view: (s, a) => undefined as any, +>view : (s: number, a: ActionsObject) => any +>(s, a) => undefined as any : (s: number, a: ActionsObject) => any +>s : number +>a : ActionsObject +>undefined as any : any +>undefined : undefined + +}); + + +type ActionsArray = ((state: State) => State)[]; +>ActionsArray : ((state: State) => State)[] +>State : State +>state : State +>State : State +>State : State + +declare function app3>(obj: Options): void; +>app3 : State)[]>(obj: Options) => void +>State : State +>Actions : Actions +>ActionsArray : ((state: State) => State)[] +>State : State +>obj : Options +>Options : Options +>State : State +>Actions : Actions + +app3({ +>app3({ state: 100, actions: [ s => s // Should be typed number => number ], view: (s, a) => undefined as any,}) : void +>app3 : State)[]>(obj: Options) => void +>{ state: 100, actions: [ s => s // Should be typed number => number ], view: (s, a) => undefined as any,} : { state: number; actions: ((s: number) => number)[]; view: (s: number, a: ((state: number) => number)[]) => any; } + + state: 100, +>state : number +>100 : 100 + + actions: [ +>actions : ((s: number) => number)[] +>[ s => s // Should be typed number => number ] : ((s: number) => number)[] + + s => s // Should be typed number => number +>s => s : (s: number) => number +>s : number +>s : number + + ], + view: (s, a) => undefined as any, +>view : (s: number, a: ((state: number) => number)[]) => any +>(s, a) => undefined as any : (s: number, a: ((state: number) => number)[]) => any +>s : number +>a : ((state: number) => number)[] +>undefined as any : any +>undefined : undefined + +}); + +namespace JSX { +>JSX : any + + export interface Element {} +>Element : Element + + export interface IntrinsicElements {} +>IntrinsicElements : IntrinsicElements +} + +interface ActionsObjectOr { +>ActionsObjectOr : ActionsObjectOr +>State : State + + [prop: string]: ((state: State) => State) | State; +>prop : string +>state : State +>State : State +>State : State +>State : State +} + +declare function App4>(props: Options["actions"] & { state: State }): JSX.Element; +>App4 : >(props: (string & { state: State; }) | (Actions & { state: State; })) => JSX.Element +>State : State +>Actions : Actions +>ActionsObjectOr : ActionsObjectOr +>State : State +>props : (string & { state: State; }) | (Actions & { state: State; }) +>Options : Options +>State : State +>Actions : Actions +>state : State +>State : State +>JSX : any +>Element : JSX.Element + +const a = s} />; // TODO: should be number => number, but JSX resolution is missing an inferential pass +>a : JSX.Element +> s} /> : JSX.Element +>App4 : >(props: (string & { state: State; }) | (Actions & { state: State; })) => JSX.Element +>state : number +>100 : 100 +>foo : (s: any) => any +>s => s : (s: any) => any +>s : any +>s : any + diff --git a/tests/cases/compiler/contextualTypingOfOptionalMembers.tsx b/tests/cases/compiler/contextualTypingOfOptionalMembers.tsx new file mode 100644 index 00000000000..5e5a9c70c9b --- /dev/null +++ b/tests/cases/compiler/contextualTypingOfOptionalMembers.tsx @@ -0,0 +1,77 @@ +// @noImplicitAny: true +// @strictNullChecks: true +// @jsx: preserve +// @filename: index.tsx +interface ActionsObject { + [prop: string]: (state: State) => State; +} + +interface Options { + state?: State; + view?: (state: State, actions: Actions) => any; + actions: string | Actions; +} + +declare function app>(obj: Options): void; + +app({ + state: 100, + actions: { + foo: s => s // Should be typed number => number + }, + view: (s, a) => undefined as any, +}); + + +interface Bar { + bar: (a: number) => void; +} + +declare function foo(x: string | T): T; + +const y = foo({ + bar(x) { // Should be typed number => void + } +}); + +interface Options2 { + state?: State; + view?: (state: State, actions: Actions) => any; + actions?: Actions; +} + +declare function app2>(obj: Options2): void; + +app2({ + state: 100, + actions: { + foo: s => s // Should be typed number => number + }, + view: (s, a) => undefined as any, +}); + + +type ActionsArray = ((state: State) => State)[]; + +declare function app3>(obj: Options): void; + +app3({ + state: 100, + actions: [ + s => s // Should be typed number => number + ], + view: (s, a) => undefined as any, +}); + +namespace JSX { + export interface Element {} + export interface IntrinsicElements {} +} + +interface ActionsObjectOr { + [prop: string]: ((state: State) => State) | State; +} + +declare function App4>(props: Options["actions"] & { state: State }): JSX.Element; + +const a = s} />; // TODO: should be number => number, but JSX resolution is missing an inferential pass From 5b9905d5a41a55e49d2a8ca585dc936949ead71d Mon Sep 17 00:00:00 2001 From: Eugene Timokhov Date: Sat, 4 Nov 2017 11:08:00 +0300 Subject: [PATCH 06/12] Added empty constructors to TypedArrays from es2017 (#19680) --- Gulpfile.ts | 1 + Jakefile.js | 3 +- src/compiler/commandLineParser.ts | 1 + src/harness/unittests/commandLineParsing.ts | 6 +-- .../convertCompilerOptionsFromJson.ts | 8 ++-- src/lib/es2017.d.ts | 1 + src/lib/es2017.typedarrays.d.ts | 35 ++++++++++++++ tests/baselines/reference/useTypedArrays1.js | 22 +++++++++ .../reference/useTypedArrays1.symbols | 37 +++++++++++++++ .../baselines/reference/useTypedArrays1.types | 46 +++++++++++++++++++ .../conformance/es2017/useTypedArrays1.ts | 12 +++++ 11 files changed, 164 insertions(+), 8 deletions(-) create mode 100644 src/lib/es2017.typedarrays.d.ts create mode 100644 tests/baselines/reference/useTypedArrays1.js create mode 100644 tests/baselines/reference/useTypedArrays1.symbols create mode 100644 tests/baselines/reference/useTypedArrays1.types create mode 100644 tests/cases/conformance/es2017/useTypedArrays1.ts diff --git a/Gulpfile.ts b/Gulpfile.ts index fd353083433..a75882c5f46 100644 --- a/Gulpfile.ts +++ b/Gulpfile.ts @@ -138,6 +138,7 @@ const es2017LibrarySource = [ "es2017.sharedmemory.d.ts", "es2017.string.d.ts", "es2017.intl.d.ts", + "es2017.typedarrays.d.ts", ]; const es2017LibrarySourceMap = es2017LibrarySource.map(source => diff --git a/Jakefile.js b/Jakefile.js index 7f0915ad7e9..89fcb6500dd 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -197,7 +197,8 @@ var es2017LibrarySource = [ "es2017.object.d.ts", "es2017.sharedmemory.d.ts", "es2017.string.d.ts", - "es2017.intl.d.ts" + "es2017.intl.d.ts", + "es2017.typedarrays.d.ts", ]; var es2017LibrarySourceMap = es2017LibrarySource.map(function (source) { diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index b7003fbffd9..7ba9bd80843 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -141,6 +141,7 @@ namespace ts { "es2017.sharedmemory": "lib.es2017.sharedmemory.d.ts", "es2017.string": "lib.es2017.string.d.ts", "es2017.intl": "lib.es2017.intl.d.ts", + "es2017.typedarrays": "lib.es2017.typedarrays.d.ts", "esnext.asynciterable": "lib.esnext.asynciterable.d.ts", }), }, diff --git a/src/harness/unittests/commandLineParsing.ts b/src/harness/unittests/commandLineParsing.ts index 01a208aa330..18e867cb9ea 100644 --- a/src/harness/unittests/commandLineParsing.ts +++ b/src/harness/unittests/commandLineParsing.ts @@ -60,7 +60,7 @@ namespace ts { assertParseResult(["--lib", "es5,invalidOption", "0.ts"], { errors: [{ - messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'esnext.asynciterable'.", + messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'esnext.asynciterable'.", category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category, code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code, @@ -263,7 +263,7 @@ namespace ts { assertParseResult(["--lib", "es5,", "es7", "0.ts"], { errors: [{ - messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'esnext.asynciterable'.", + messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'esnext.asynciterable'.", category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category, code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code, @@ -283,7 +283,7 @@ namespace ts { assertParseResult(["--lib", "es5, ", "es7", "0.ts"], { errors: [{ - messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'esnext.asynciterable'.", + messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'esnext.asynciterable'.", category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category, code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code, diff --git a/src/harness/unittests/convertCompilerOptionsFromJson.ts b/src/harness/unittests/convertCompilerOptionsFromJson.ts index 09659762288..cbbe41ceadf 100644 --- a/src/harness/unittests/convertCompilerOptionsFromJson.ts +++ b/src/harness/unittests/convertCompilerOptionsFromJson.ts @@ -266,7 +266,7 @@ namespace ts { file: undefined, start: 0, length: 0, - messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'esnext.asynciterable'.", + messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'esnext.asynciterable'.", code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category }] @@ -297,7 +297,7 @@ namespace ts { file: undefined, start: 0, length: 0, - messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'esnext.asynciterable'.", + messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'esnext.asynciterable'.", code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category }] @@ -328,7 +328,7 @@ namespace ts { file: undefined, start: 0, length: 0, - messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'esnext.asynciterable'.", + messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'esnext.asynciterable'.", code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category }] @@ -359,7 +359,7 @@ namespace ts { file: undefined, start: 0, length: 0, - messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'esnext.asynciterable'.", + messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'es2017.intl', 'es2017.typedarrays', 'esnext.asynciterable'.", code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category }] diff --git a/src/lib/es2017.d.ts b/src/lib/es2017.d.ts index 80282355a45..87aa273140b 100644 --- a/src/lib/es2017.d.ts +++ b/src/lib/es2017.d.ts @@ -3,3 +3,4 @@ /// /// /// +/// diff --git a/src/lib/es2017.typedarrays.d.ts b/src/lib/es2017.typedarrays.d.ts new file mode 100644 index 00000000000..a0b64135a30 --- /dev/null +++ b/src/lib/es2017.typedarrays.d.ts @@ -0,0 +1,35 @@ +interface Int8ArrayConstructor { + new (): Int8Array; +} + +interface Uint8ArrayConstructor { + new (): Uint8Array; +} + +interface Uint8ClampedArrayConstructor { + new (): Uint8ClampedArray; +} + +interface Int16ArrayConstructor { + new (): Int16Array; +} + +interface Uint16ArrayConstructor { + new (): Uint16Array; +} + +interface Int32ArrayConstructor { + new (): Int32Array; +} + +interface Uint32ArrayConstructor { + new (): Uint32Array; +} + +interface Float32ArrayConstructor { + new (): Float32Array; +} + +interface Float64ArrayConstructor { + new (): Float64Array; +} diff --git a/tests/baselines/reference/useTypedArrays1.js b/tests/baselines/reference/useTypedArrays1.js new file mode 100644 index 00000000000..bbfcccec836 --- /dev/null +++ b/tests/baselines/reference/useTypedArrays1.js @@ -0,0 +1,22 @@ +//// [useTypedArrays1.ts] +var int8Array = new Int8Array(); +var uint8Array = new Uint8Array(); +var uint8ClampedArray = new Uint8ClampedArray(); +var int16Array = new Int16Array(); +var uint16Array = new Uint16Array(); +var int32Array = new Int32Array(); +var uint32Array = new Uint32Array(); +var float32Array = new Float32Array(); +var float64Array = new Float64Array(); + + +//// [useTypedArrays1.js] +var int8Array = new Int8Array(); +var uint8Array = new Uint8Array(); +var uint8ClampedArray = new Uint8ClampedArray(); +var int16Array = new Int16Array(); +var uint16Array = new Uint16Array(); +var int32Array = new Int32Array(); +var uint32Array = new Uint32Array(); +var float32Array = new Float32Array(); +var float64Array = new Float64Array(); diff --git a/tests/baselines/reference/useTypedArrays1.symbols b/tests/baselines/reference/useTypedArrays1.symbols new file mode 100644 index 00000000000..ed41b0c24bd --- /dev/null +++ b/tests/baselines/reference/useTypedArrays1.symbols @@ -0,0 +1,37 @@ +=== tests/cases/conformance/es2017/useTypedArrays1.ts === +var int8Array = new Int8Array(); +>int8Array : Symbol(int8Array, Decl(useTypedArrays1.ts, 0, 3)) +>Int8Array : Symbol(Int8Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + +var uint8Array = new Uint8Array(); +>uint8Array : Symbol(uint8Array, Decl(useTypedArrays1.ts, 1, 3)) +>Uint8Array : Symbol(Uint8Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + +var uint8ClampedArray = new Uint8ClampedArray(); +>uint8ClampedArray : Symbol(uint8ClampedArray, Decl(useTypedArrays1.ts, 2, 3)) +>Uint8ClampedArray : Symbol(Uint8ClampedArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + +var int16Array = new Int16Array(); +>int16Array : Symbol(int16Array, Decl(useTypedArrays1.ts, 3, 3)) +>Int16Array : Symbol(Int16Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + +var uint16Array = new Uint16Array(); +>uint16Array : Symbol(uint16Array, Decl(useTypedArrays1.ts, 4, 3)) +>Uint16Array : Symbol(Uint16Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + +var int32Array = new Int32Array(); +>int32Array : Symbol(int32Array, Decl(useTypedArrays1.ts, 5, 3)) +>Int32Array : Symbol(Int32Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + +var uint32Array = new Uint32Array(); +>uint32Array : Symbol(uint32Array, Decl(useTypedArrays1.ts, 6, 3)) +>Uint32Array : Symbol(Uint32Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + +var float32Array = new Float32Array(); +>float32Array : Symbol(float32Array, Decl(useTypedArrays1.ts, 7, 3)) +>Float32Array : Symbol(Float32Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + +var float64Array = new Float64Array(); +>float64Array : Symbol(float64Array, Decl(useTypedArrays1.ts, 8, 3)) +>Float64Array : Symbol(Float64Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + diff --git a/tests/baselines/reference/useTypedArrays1.types b/tests/baselines/reference/useTypedArrays1.types new file mode 100644 index 00000000000..f3f27383a3e --- /dev/null +++ b/tests/baselines/reference/useTypedArrays1.types @@ -0,0 +1,46 @@ +=== tests/cases/conformance/es2017/useTypedArrays1.ts === +var int8Array = new Int8Array(); +>int8Array : Int8Array +>new Int8Array() : Int8Array +>Int8Array : Int8ArrayConstructor + +var uint8Array = new Uint8Array(); +>uint8Array : Uint8Array +>new Uint8Array() : Uint8Array +>Uint8Array : Uint8ArrayConstructor + +var uint8ClampedArray = new Uint8ClampedArray(); +>uint8ClampedArray : Uint8ClampedArray +>new Uint8ClampedArray() : Uint8ClampedArray +>Uint8ClampedArray : Uint8ClampedArrayConstructor + +var int16Array = new Int16Array(); +>int16Array : Int16Array +>new Int16Array() : Int16Array +>Int16Array : Int16ArrayConstructor + +var uint16Array = new Uint16Array(); +>uint16Array : Uint16Array +>new Uint16Array() : Uint16Array +>Uint16Array : Uint16ArrayConstructor + +var int32Array = new Int32Array(); +>int32Array : Int32Array +>new Int32Array() : Int32Array +>Int32Array : Int32ArrayConstructor + +var uint32Array = new Uint32Array(); +>uint32Array : Uint32Array +>new Uint32Array() : Uint32Array +>Uint32Array : Uint32ArrayConstructor + +var float32Array = new Float32Array(); +>float32Array : Float32Array +>new Float32Array() : Float32Array +>Float32Array : Float32ArrayConstructor + +var float64Array = new Float64Array(); +>float64Array : Float64Array +>new Float64Array() : Float64Array +>Float64Array : Float64ArrayConstructor + diff --git a/tests/cases/conformance/es2017/useTypedArrays1.ts b/tests/cases/conformance/es2017/useTypedArrays1.ts new file mode 100644 index 00000000000..e06bf91f317 --- /dev/null +++ b/tests/cases/conformance/es2017/useTypedArrays1.ts @@ -0,0 +1,12 @@ +// @target: es5 +// @lib: es5,es2017.typedarrays + +var int8Array = new Int8Array(); +var uint8Array = new Uint8Array(); +var uint8ClampedArray = new Uint8ClampedArray(); +var int16Array = new Int16Array(); +var uint16Array = new Uint16Array(); +var int32Array = new Int32Array(); +var uint32Array = new Uint32Array(); +var float32Array = new Float32Array(); +var float64Array = new Float64Array(); From 5c173f4436703aa6a75ac2fb93d3785905cb72fa Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Mon, 6 Nov 2017 12:51:52 -0800 Subject: [PATCH 07/12] Remove test --- tests/baselines/reference/useTypedArrays1.js | 22 --------- .../reference/useTypedArrays1.symbols | 37 --------------- .../baselines/reference/useTypedArrays1.types | 46 ------------------- .../conformance/es2017/useTypedArrays1.ts | 12 ----- 4 files changed, 117 deletions(-) delete mode 100644 tests/baselines/reference/useTypedArrays1.js delete mode 100644 tests/baselines/reference/useTypedArrays1.symbols delete mode 100644 tests/baselines/reference/useTypedArrays1.types delete mode 100644 tests/cases/conformance/es2017/useTypedArrays1.ts diff --git a/tests/baselines/reference/useTypedArrays1.js b/tests/baselines/reference/useTypedArrays1.js deleted file mode 100644 index bbfcccec836..00000000000 --- a/tests/baselines/reference/useTypedArrays1.js +++ /dev/null @@ -1,22 +0,0 @@ -//// [useTypedArrays1.ts] -var int8Array = new Int8Array(); -var uint8Array = new Uint8Array(); -var uint8ClampedArray = new Uint8ClampedArray(); -var int16Array = new Int16Array(); -var uint16Array = new Uint16Array(); -var int32Array = new Int32Array(); -var uint32Array = new Uint32Array(); -var float32Array = new Float32Array(); -var float64Array = new Float64Array(); - - -//// [useTypedArrays1.js] -var int8Array = new Int8Array(); -var uint8Array = new Uint8Array(); -var uint8ClampedArray = new Uint8ClampedArray(); -var int16Array = new Int16Array(); -var uint16Array = new Uint16Array(); -var int32Array = new Int32Array(); -var uint32Array = new Uint32Array(); -var float32Array = new Float32Array(); -var float64Array = new Float64Array(); diff --git a/tests/baselines/reference/useTypedArrays1.symbols b/tests/baselines/reference/useTypedArrays1.symbols deleted file mode 100644 index ed41b0c24bd..00000000000 --- a/tests/baselines/reference/useTypedArrays1.symbols +++ /dev/null @@ -1,37 +0,0 @@ -=== tests/cases/conformance/es2017/useTypedArrays1.ts === -var int8Array = new Int8Array(); ->int8Array : Symbol(int8Array, Decl(useTypedArrays1.ts, 0, 3)) ->Int8Array : Symbol(Int8Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) - -var uint8Array = new Uint8Array(); ->uint8Array : Symbol(uint8Array, Decl(useTypedArrays1.ts, 1, 3)) ->Uint8Array : Symbol(Uint8Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) - -var uint8ClampedArray = new Uint8ClampedArray(); ->uint8ClampedArray : Symbol(uint8ClampedArray, Decl(useTypedArrays1.ts, 2, 3)) ->Uint8ClampedArray : Symbol(Uint8ClampedArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) - -var int16Array = new Int16Array(); ->int16Array : Symbol(int16Array, Decl(useTypedArrays1.ts, 3, 3)) ->Int16Array : Symbol(Int16Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) - -var uint16Array = new Uint16Array(); ->uint16Array : Symbol(uint16Array, Decl(useTypedArrays1.ts, 4, 3)) ->Uint16Array : Symbol(Uint16Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) - -var int32Array = new Int32Array(); ->int32Array : Symbol(int32Array, Decl(useTypedArrays1.ts, 5, 3)) ->Int32Array : Symbol(Int32Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) - -var uint32Array = new Uint32Array(); ->uint32Array : Symbol(uint32Array, Decl(useTypedArrays1.ts, 6, 3)) ->Uint32Array : Symbol(Uint32Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) - -var float32Array = new Float32Array(); ->float32Array : Symbol(float32Array, Decl(useTypedArrays1.ts, 7, 3)) ->Float32Array : Symbol(Float32Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) - -var float64Array = new Float64Array(); ->float64Array : Symbol(float64Array, Decl(useTypedArrays1.ts, 8, 3)) ->Float64Array : Symbol(Float64Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) - diff --git a/tests/baselines/reference/useTypedArrays1.types b/tests/baselines/reference/useTypedArrays1.types deleted file mode 100644 index f3f27383a3e..00000000000 --- a/tests/baselines/reference/useTypedArrays1.types +++ /dev/null @@ -1,46 +0,0 @@ -=== tests/cases/conformance/es2017/useTypedArrays1.ts === -var int8Array = new Int8Array(); ->int8Array : Int8Array ->new Int8Array() : Int8Array ->Int8Array : Int8ArrayConstructor - -var uint8Array = new Uint8Array(); ->uint8Array : Uint8Array ->new Uint8Array() : Uint8Array ->Uint8Array : Uint8ArrayConstructor - -var uint8ClampedArray = new Uint8ClampedArray(); ->uint8ClampedArray : Uint8ClampedArray ->new Uint8ClampedArray() : Uint8ClampedArray ->Uint8ClampedArray : Uint8ClampedArrayConstructor - -var int16Array = new Int16Array(); ->int16Array : Int16Array ->new Int16Array() : Int16Array ->Int16Array : Int16ArrayConstructor - -var uint16Array = new Uint16Array(); ->uint16Array : Uint16Array ->new Uint16Array() : Uint16Array ->Uint16Array : Uint16ArrayConstructor - -var int32Array = new Int32Array(); ->int32Array : Int32Array ->new Int32Array() : Int32Array ->Int32Array : Int32ArrayConstructor - -var uint32Array = new Uint32Array(); ->uint32Array : Uint32Array ->new Uint32Array() : Uint32Array ->Uint32Array : Uint32ArrayConstructor - -var float32Array = new Float32Array(); ->float32Array : Float32Array ->new Float32Array() : Float32Array ->Float32Array : Float32ArrayConstructor - -var float64Array = new Float64Array(); ->float64Array : Float64Array ->new Float64Array() : Float64Array ->Float64Array : Float64ArrayConstructor - diff --git a/tests/cases/conformance/es2017/useTypedArrays1.ts b/tests/cases/conformance/es2017/useTypedArrays1.ts deleted file mode 100644 index e06bf91f317..00000000000 --- a/tests/cases/conformance/es2017/useTypedArrays1.ts +++ /dev/null @@ -1,12 +0,0 @@ -// @target: es5 -// @lib: es5,es2017.typedarrays - -var int8Array = new Int8Array(); -var uint8Array = new Uint8Array(); -var uint8ClampedArray = new Uint8ClampedArray(); -var int16Array = new Int16Array(); -var uint16Array = new Uint16Array(); -var int32Array = new Int32Array(); -var uint32Array = new Uint32Array(); -var float32Array = new Float32Array(); -var float64Array = new Float64Array(); From ed38889ca66991d02728c3ed60ba3bf9d914d55e Mon Sep 17 00:00:00 2001 From: Andy Date: Mon, 6 Nov 2017 13:01:07 -0800 Subject: [PATCH 08/12] Enable 'no-unused-expression' tslint rule (#19734) --- src/compiler/checker.ts | 100 +++++++++--------- src/harness/fourslash.ts | 8 +- src/harness/parallel/worker.ts | 8 +- src/harness/unittests/languageService.ts | 2 +- src/harness/unittests/session.ts | 8 +- .../unittests/tsserverProjectSystem.ts | 12 +-- src/services/utilities.ts | 8 +- tslint.json | 1 - 8 files changed, 77 insertions(+), 70 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 39b0dc18569..649deef7e3a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1904,8 +1904,9 @@ namespace ts { * Extends one symbol table with another while collecting information on name collisions for error message generation into the `lookupTable` argument * Not passing `lookupTable` and `exportNode` disables this collection, and just extends the tables */ - function extendExportSymbols(target: SymbolTable, source: SymbolTable, lookupTable?: ExportCollisionTrackerTable, exportNode?: ExportDeclaration) { - source && source.forEach((sourceSymbol, id) => { + function extendExportSymbols(target: SymbolTable, source: SymbolTable | undefined, lookupTable?: ExportCollisionTrackerTable, exportNode?: ExportDeclaration) { + if (!source) return; + source.forEach((sourceSymbol, id) => { if (id === "default") return; const targetSymbol = target.get(id); @@ -17016,8 +17017,7 @@ namespace ts { * @returns On success, the expression's signature's return type. On failure, anyType. */ function checkCallExpression(node: CallExpression | NewExpression): Type { - // Grammar checking; stop grammar-checking if checkGrammarTypeArguments return true - checkGrammarTypeArguments(node, node.typeArguments) || checkGrammarArguments(node.arguments); + if (!checkGrammarTypeArguments(node, node.typeArguments)) checkGrammarArguments(node.arguments); const signature = getResolvedSignature(node); @@ -17064,7 +17064,7 @@ namespace ts { function checkImportCallExpression(node: ImportCall): Type { // Check grammar of dynamic import - checkGrammarArguments(node.arguments) || checkGrammarImportCallExpression(node); + if (!checkGrammarArguments(node.arguments)) checkGrammarImportCallExpression(node); if (node.arguments.length === 0) { return createPromiseReturnType(node, anyType); @@ -18739,9 +18739,7 @@ namespace ts { // It is a SyntaxError if the Identifier "eval" or the Identifier "arguments" occurs as the // Identifier in a PropertySetParameterList of a PropertyAssignment that is contained in strict code // or if its FunctionBody is strict code(11.1.5). - - // Grammar checking - checkGrammarDecorators(node) || checkGrammarModifiers(node); + checkGrammarDecoratorsAndModifiers(node); checkVariableLikeDeclaration(node); const func = getContainingFunction(node); @@ -19131,14 +19129,13 @@ namespace ts { function checkPropertyDeclaration(node: PropertyDeclaration) { // Grammar checking - checkGrammarDecorators(node) || checkGrammarModifiers(node) || checkGrammarProperty(node) || checkGrammarComputedPropertyName(node.name); - + if (!checkGrammarDecoratorsAndModifiers(node) && !checkGrammarProperty(node)) checkGrammarComputedPropertyName(node.name); checkVariableLikeDeclaration(node); } function checkMethodDeclaration(node: MethodDeclaration) { // Grammar checking - checkGrammarMethod(node) || checkGrammarComputedPropertyName(node.name); + if (!checkGrammarMethod(node)) checkGrammarComputedPropertyName(node.name); // Grammar checking for modifiers is done inside the function checkGrammarFunctionLikeDeclaration checkFunctionOrMethodDeclaration(node); @@ -19154,7 +19151,7 @@ namespace ts { // Grammar check on signature of constructor and modifier of the constructor is done in checkSignatureDeclaration function. checkSignatureDeclaration(node); // Grammar check for checking only related to constructorDeclaration - checkGrammarConstructorTypeParameters(node) || checkGrammarConstructorTypeAnnotation(node); + if (!checkGrammarConstructorTypeParameters(node)) checkGrammarConstructorTypeAnnotation(node); checkSourceElement(node.body); registerForUnusedIdentifiersCheck(node); @@ -19251,7 +19248,7 @@ namespace ts { function checkAccessorDeclaration(node: AccessorDeclaration) { if (produceDiagnostics) { // Grammar checking accessors - checkGrammarFunctionLikeDeclaration(node) || checkGrammarAccessor(node) || checkGrammarComputedPropertyName(node.name); + if (!checkGrammarFunctionLikeDeclaration(node) && !checkGrammarAccessor(node)) checkGrammarComputedPropertyName(node.name); checkDecorators(node); checkSignatureDeclaration(node); @@ -21013,8 +21010,7 @@ namespace ts { function checkVariableStatement(node: VariableStatement) { // Grammar checking - checkGrammarDecorators(node) || checkGrammarModifiers(node) || checkGrammarVariableDeclarationList(node.declarationList) || checkGrammarForDisallowedLetOrConstStatement(node); - + if (!checkGrammarDecoratorsAndModifiers(node) && !checkGrammarVariableDeclarationList(node.declarationList)) checkGrammarForDisallowedLetOrConstStatement(node); forEach(node.declarationList.declarations, checkSourceElement); } @@ -21522,7 +21518,7 @@ namespace ts { function checkBreakOrContinueStatement(node: BreakOrContinueStatement) { // Grammar checking - checkGrammarStatementInAmbientContext(node) || checkGrammarBreakOrContinueStatement(node); + if (!checkGrammarStatementInAmbientContext(node)) checkGrammarBreakOrContinueStatement(node); // TODO: Check that target label is valid } @@ -22203,7 +22199,7 @@ namespace ts { function checkInterfaceDeclaration(node: InterfaceDeclaration) { // Grammar checking - checkGrammarDecorators(node) || checkGrammarModifiers(node) || checkGrammarInterfaceDeclaration(node); + if (!checkGrammarDecoratorsAndModifiers(node)) checkGrammarInterfaceDeclaration(node); checkTypeParameters(node.typeParameters); if (produceDiagnostics) { @@ -22245,7 +22241,7 @@ namespace ts { function checkTypeAliasDeclaration(node: TypeAliasDeclaration) { // Grammar checking - checkGrammarDecorators(node) || checkGrammarModifiers(node); + checkGrammarDecoratorsAndModifiers(node); checkTypeNameIsReserved(node.name, Diagnostics.Type_alias_name_cannot_be_0); checkTypeParameters(node.typeParameters); @@ -22415,7 +22411,7 @@ namespace ts { } // Grammar checking - checkGrammarDecorators(node) || checkGrammarModifiers(node); + checkGrammarDecoratorsAndModifiers(node); checkTypeNameIsReserved(node.name, Diagnostics.Enum_name_cannot_be_0); checkCollisionWithCapturedThisVariable(node, node.name); @@ -22518,7 +22514,7 @@ namespace ts { return; } - if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node)) { + if (!checkGrammarDecoratorsAndModifiers(node)) { if (!inAmbientContext && node.name.kind === SyntaxKind.StringLiteral) { grammarErrorOnNode(node.name, Diagnostics.Only_ambient_modules_can_use_quoted_names); } @@ -22741,7 +22737,7 @@ namespace ts { // If we hit an import declaration in an illegal context, just bail out to avoid cascading errors. return; } - if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && hasModifiers(node)) { + if (!checkGrammarDecoratorsAndModifiers(node) && hasModifiers(node)) { grammarErrorOnFirstToken(node, Diagnostics.An_import_declaration_cannot_have_modifiers); } if (checkExternalImportOrExportDeclaration(node)) { @@ -22768,7 +22764,7 @@ namespace ts { return; } - checkGrammarDecorators(node) || checkGrammarModifiers(node); + checkGrammarDecoratorsAndModifiers(node); if (isInternalModuleImportEqualsDeclaration(node) || checkExternalImportOrExportDeclaration(node)) { checkImportBinding(node); if (hasModifier(node, ModifierFlags.Export)) { @@ -22804,7 +22800,7 @@ namespace ts { return; } - if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && hasModifiers(node)) { + if (!checkGrammarDecoratorsAndModifiers(node) && hasModifiers(node)) { grammarErrorOnFirstToken(node, Diagnostics.An_export_declaration_cannot_have_modifiers); } @@ -22877,7 +22873,7 @@ namespace ts { return; } // Grammar checking - if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && hasModifiers(node)) { + if (!checkGrammarDecoratorsAndModifiers(node) && hasModifiers(node)) { grammarErrorOnFirstToken(node, Diagnostics.An_export_assignment_cannot_have_modifiers); } if (node.expression.kind === SyntaxKind.Identifier) { @@ -22922,29 +22918,31 @@ namespace ts { } // Checks for export * conflicts const exports = getExportsOfModule(moduleSymbol); - exports && exports.forEach(({ declarations, flags }, id) => { - if (id === "__export") { - return; - } - // ECMA262: 15.2.1.1 It is a Syntax Error if the ExportedNames of ModuleItemList contains any duplicate entries. - // (TS Exceptions: namespaces, function overloads, enums, and interfaces) - if (flags & (SymbolFlags.Namespace | SymbolFlags.Interface | SymbolFlags.Enum)) { - return; - } - const exportedDeclarationsCount = countWhere(declarations, isNotOverloadAndNotAccessor); - if (flags & SymbolFlags.TypeAlias && exportedDeclarationsCount <= 2) { - // it is legal to merge type alias with other values - // so count should be either 1 (just type alias) or 2 (type alias + merged value) - return; - } - if (exportedDeclarationsCount > 1) { - for (const declaration of declarations) { - if (isNotOverload(declaration)) { - diagnostics.add(createDiagnosticForNode(declaration, Diagnostics.Cannot_redeclare_exported_variable_0, unescapeLeadingUnderscores(id))); + if (exports) { + exports.forEach(({ declarations, flags }, id) => { + if (id === "__export") { + return; + } + // ECMA262: 15.2.1.1 It is a Syntax Error if the ExportedNames of ModuleItemList contains any duplicate entries. + // (TS Exceptions: namespaces, function overloads, enums, and interfaces) + if (flags & (SymbolFlags.Namespace | SymbolFlags.Interface | SymbolFlags.Enum)) { + return; + } + const exportedDeclarationsCount = countWhere(declarations, isNotOverloadAndNotAccessor); + if (flags & SymbolFlags.TypeAlias && exportedDeclarationsCount <= 2) { + // it is legal to merge type alias with other values + // so count should be either 1 (just type alias) or 2 (type alias + merged value) + return; + } + if (exportedDeclarationsCount > 1) { + for (const declaration of declarations) { + if (isNotOverload(declaration)) { + diagnostics.add(createDiagnosticForNode(declaration, Diagnostics.Cannot_redeclare_exported_variable_0, unescapeLeadingUnderscores(id))); + } } } - } - }); + }); + } links.exportsChecked = true; } } @@ -24577,12 +24575,16 @@ namespace ts { } // GRAMMAR CHECKING + function checkGrammarDecoratorsAndModifiers(node: Node): boolean { + return checkGrammarDecorators(node) || checkGrammarModifiers(node); + } + function checkGrammarDecorators(node: Node): boolean { if (!node.decorators) { return false; } if (!nodeCanBeDecorated(node)) { - if (node.kind === SyntaxKind.MethodDeclaration && !ts.nodeIsPresent((node).body)) { + if (node.kind === SyntaxKind.MethodDeclaration && !nodeIsPresent((node).body)) { return grammarErrorOnFirstToken(node, Diagnostics.A_decorator_can_only_decorate_a_method_implementation_not_an_overload); } else { @@ -24932,7 +24934,7 @@ namespace ts { function checkGrammarFunctionLikeDeclaration(node: FunctionLikeDeclaration): boolean { // Prevent cascading error by short-circuit const file = getSourceFileOfNode(node); - return checkGrammarDecorators(node) || checkGrammarModifiers(node) || checkGrammarTypeParameterList(node.typeParameters, file) || + return checkGrammarDecoratorsAndModifiers(node) || checkGrammarTypeParameterList(node.typeParameters, file) || checkGrammarParameterList(node.parameters) || checkGrammarArrowFunction(node, file); } @@ -24988,7 +24990,7 @@ namespace ts { function checkGrammarIndexSignature(node: SignatureDeclaration) { // Prevent cascading error by short-circuit - return checkGrammarDecorators(node) || checkGrammarModifiers(node) || checkGrammarIndexSignatureParameters(node); + return checkGrammarDecoratorsAndModifiers(node) || checkGrammarIndexSignatureParameters(node); } function checkGrammarForAtLeastOneTypeArgument(node: Node, typeArguments: NodeArray): boolean { @@ -25039,7 +25041,7 @@ namespace ts { let seenExtendsClause = false; let seenImplementsClause = false; - if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && node.heritageClauses) { + if (!checkGrammarDecoratorsAndModifiers(node) && node.heritageClauses) { for (const heritageClause of node.heritageClauses) { if (heritageClause.token === SyntaxKind.ExtendsKeyword) { if (seenExtendsClause) { diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index dac8f7b8413..85011525d52 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -221,11 +221,9 @@ namespace FourSlash { private addMatchedInputFile(referenceFilePath: string, extensions: ReadonlyArray) { const inputFiles = this.inputFiles; const languageServiceAdapterHost = this.languageServiceAdapterHost; - if (!extensions) { - tryAdd(referenceFilePath); - } - else { - tryAdd(referenceFilePath) || ts.forEach(extensions, ext => tryAdd(referenceFilePath + ext)); + const didAdd = tryAdd(referenceFilePath); + if (extensions && !didAdd) { + ts.forEach(extensions, ext => tryAdd(referenceFilePath + ext)); } function tryAdd(path: string) { diff --git a/src/harness/parallel/worker.ts b/src/harness/parallel/worker.ts index c32b9660a39..953ed5aeb21 100644 --- a/src/harness/parallel/worker.ts +++ b/src/harness/parallel/worker.ts @@ -57,7 +57,9 @@ namespace Harness.Parallel.Worker { return cleanup(); } try { - beforeFunc && beforeFunc(); + if (beforeFunc) { + beforeFunc(); + } } catch (e) { errors.push({ error: `Error executing before function: ${e.message}`, stack: e.stack, name: [...namestack] }); @@ -69,7 +71,9 @@ namespace Harness.Parallel.Worker { testList.forEach(({ name, callback, kind }) => executeCallback(name, callback, kind)); try { - afterFunc && afterFunc(); + if (afterFunc) { + afterFunc(); + } } catch (e) { errors.push({ error: `Error executing after function: ${e.message}`, stack: e.stack, name: [...namestack] }); diff --git a/src/harness/unittests/languageService.ts b/src/harness/unittests/languageService.ts index fd0a95c167f..1407a518617 100644 --- a/src/harness/unittests/languageService.ts +++ b/src/harness/unittests/languageService.ts @@ -45,7 +45,7 @@ export function Component(x: Config): any;` readDirectory: noop as any, }); const definitions = languageService.getDefinitionAtPosition("foo.ts", 160); // 160 is the latter `vueTemplateHtml` position - expect(definitions).to.exist; + expect(definitions).to.exist; // tslint:disable-line no-unused-expression }); }); } \ No newline at end of file diff --git a/src/harness/unittests/session.ts b/src/harness/unittests/session.ts index e40e7d11b1a..871d4a37b9a 100644 --- a/src/harness/unittests/session.ts +++ b/src/harness/unittests/session.ts @@ -317,7 +317,7 @@ namespace ts.server { session.send = Session.prototype.send; assert(session.send); - expect(session.send(msg)).to.not.exist; + expect(session.send(msg)).to.not.exist; // tslint:disable-line no-unused-expression expect(lastWrittenToHost).to.equal(resultMsg); }); }); @@ -524,14 +524,14 @@ namespace ts.server { }); }); it("has access to the project service", () => { - class ServiceSession extends TestSession { + // tslint:disable-next-line no-unused-expression + new class extends TestSession { constructor() { super(); assert(this.projectService); expect(this.projectService).to.be.instanceOf(ProjectService); } - } - new ServiceSession(); + }(); }); }); diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index c09a1bcb5da..55d767d24a7 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -1870,7 +1870,7 @@ namespace ts.projectSystem { // Specify .html extension as mixed content const extraFileExtensions = [{ extension: ".html", scriptKind: ScriptKind.JS, isMixedContent: true }]; const configureHostRequest = makeSessionRequest(CommandNames.Configure, { extraFileExtensions }); - session.executeCommand(configureHostRequest).response; + session.executeCommand(configureHostRequest); // The configured project should now be updated to include html file checkNumberOfProjects(projectService, { configuredProjects: 1 }); @@ -1929,7 +1929,7 @@ namespace ts.projectSystem { // Specify .html extension as mixed content in a configure host request const extraFileExtensions = [{ extension: ".html", scriptKind: ScriptKind.JS, isMixedContent: true }]; const configureHostRequest = makeSessionRequest(CommandNames.Configure, { extraFileExtensions }); - session.executeCommand(configureHostRequest).response; + session.executeCommand(configureHostRequest); openFilesForSession([file1], session); let projectService = session.getProjectService(); @@ -1948,7 +1948,7 @@ namespace ts.projectSystem { host = createServerHost([file1, file2, config2, libFile], { executingFilePath: combinePaths(getDirectoryPath(libFile.path), "tsc.js") }); session = createSession(host); - session.executeCommand(configureHostRequest).response; + session.executeCommand(configureHostRequest); openFilesForSession([file1], session); projectService = session.getProjectService(); @@ -1967,7 +1967,7 @@ namespace ts.projectSystem { host = createServerHost([file1, file2, config3, libFile], { executingFilePath: combinePaths(getDirectoryPath(libFile.path), "tsc.js") }); session = createSession(host); - session.executeCommand(configureHostRequest).response; + session.executeCommand(configureHostRequest); openFilesForSession([file1], session); projectService = session.getProjectService(); @@ -1986,7 +1986,7 @@ namespace ts.projectSystem { host = createServerHost([file1, file2, config4, libFile], { executingFilePath: combinePaths(getDirectoryPath(libFile.path), "tsc.js") }); session = createSession(host); - session.executeCommand(configureHostRequest).response; + session.executeCommand(configureHostRequest); openFilesForSession([file1], session); projectService = session.getProjectService(); @@ -2005,7 +2005,7 @@ namespace ts.projectSystem { host = createServerHost([file1, file2, config5, libFile], { executingFilePath: combinePaths(getDirectoryPath(libFile.path), "tsc.js") }); session = createSession(host); - session.executeCommand(configureHostRequest).response; + session.executeCommand(configureHostRequest); openFilesForSession([file1], session); projectService = session.getProjectService(); diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 9397c40ff8a..36089f94f73 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1398,7 +1398,9 @@ namespace ts { addEmitFlags(node, EmitFlags.NoLeadingComments); const firstChild = forEachChild(node, child => child); - firstChild && suppressLeading(firstChild); + if (firstChild) { + suppressLeading(firstChild); + } } function suppressTrailing(node: Node) { @@ -1415,7 +1417,9 @@ namespace ts { } return undefined; }); - lastChild && suppressTrailing(lastChild); + if (lastChild) { + suppressTrailing(lastChild); + } } } } diff --git a/tslint.json b/tslint.json index 9ad752e6094..497bd5e787a 100644 --- a/tslint.json +++ b/tslint.json @@ -93,7 +93,6 @@ "no-object-literal-type-assertion": false, "no-shadowed-variable": false, "no-submodule-imports": false, - "no-unused-expression": false, "no-unnecessary-initializer": false, "no-var-requires": false, "object-literal-key-quotes": false, From 28ed9b307b06bdf09dcad4cb10b31d82b19fc7c7 Mon Sep 17 00:00:00 2001 From: falsandtru Date: Tue, 7 Nov 2017 06:12:47 +0900 Subject: [PATCH 09/12] Update DOM iterable interfaces (#19752) * Make HTMLCollections Iterable * Sort definitions --- src/lib/dom.iterable.d.ts | 42 +++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/src/lib/dom.iterable.d.ts b/src/lib/dom.iterable.d.ts index e89a22f2c14..6ca728444f2 100644 --- a/src/lib/dom.iterable.d.ts +++ b/src/lib/dom.iterable.d.ts @@ -4,23 +4,6 @@ interface DOMTokenList { [Symbol.iterator](): IterableIterator; } -interface FormData { - /** - * Returns an array of key, value pairs for every entry in the list - */ - entries(): IterableIterator<[string, string | File]>; - /** - * Returns a list of keys in the list - */ - keys(): IterableIterator; - /** - * Returns a list of values in the list - */ - values(): IterableIterator; - - [Symbol.iterator](): IterableIterator; -} - interface Headers { [Symbol.iterator](): IterableIterator<[string, string]>; /** @@ -87,6 +70,31 @@ interface NodeListOf { [Symbol.iterator](): IterableIterator; } +interface HTMLCollectionBase { + [Symbol.iterator](): IterableIterator; +} + +interface HTMLCollectionOf { + [Symbol.iterator](): IterableIterator; +} + +interface FormData { + /** + * Returns an array of key, value pairs for every entry in the list + */ + entries(): IterableIterator<[string, string | File]>; + /** + * Returns a list of keys in the list + */ + keys(): IterableIterator; + /** + * Returns a list of values in the list + */ + values(): IterableIterator; + + [Symbol.iterator](): IterableIterator; +} + interface URLSearchParams { /** * Returns an array of key, value pairs for every entry in the search params From a46d2705ef872a1c4f86a9dc5d7384b412e8ba5a Mon Sep 17 00:00:00 2001 From: Sean Barag Date: Mon, 6 Nov 2017 13:18:21 -0800 Subject: [PATCH 10/12] Use documentation comments from inherited properties when @inheritDoc is present (#18804) * Use documentation comments from inherited properties when @inheritDoc is present The JSDoc `@ineheritDoc` [tag](http://usejsdoc.org/tags-inheritdoc.html) "indicates that a symbol should inherit its documentation from its parent class". In the case of a TypeScript file, this also includes implemented interfaces and parent interfaces. With this change, a class method or property (or an interface property) with the `@inheritDoc` tag in its JSDoc comment will automatically use the comments from its nearest ancestor that has no `@inheritDoc` tag. To prevent breaking backwards compatibility, `Symbol.getDocumentationComment` now accepts an optional `TypeChecker` instance to support this feature. fixes #8912 * Use ts.getJSDocTags as per @andy-ms 's recommendation * Convert @inheritDoc tests to verify.quickInfoAt * Concatenate inherited and local docs when @inheritDoc is present * Make typeChecker param explicitly `TypeChecker | undefined` * Re-accept baseline after switch to explicit `| undefined` * Update APISample_jsodc.ts to match new getDocumentationComment signature * Re-accept baselines after rebasing --- src/services/jsDoc.ts | 1 + src/services/services.ts | 96 ++++++++++++++++++- src/services/signatureHelp.ts | 6 +- src/services/symbolDisplay.ts | 6 +- src/services/types.ts | 4 +- tests/baselines/reference/APISample_jsdoc.js | 4 +- .../reference/api/tsserverlibrary.d.ts | 4 +- tests/baselines/reference/api/typescript.d.ts | 4 +- tests/cases/compiler/APISample_jsdoc.ts | 2 +- tests/cases/fourslash/commentsInheritance.ts | 10 +- tests/cases/fourslash/jsDocInheritDoc.ts | 57 +++++++++++ 11 files changed, 170 insertions(+), 24 deletions(-) create mode 100644 tests/cases/fourslash/jsDocInheritDoc.ts diff --git a/src/services/jsDoc.ts b/src/services/jsDoc.ts index b8e94857aa7..79b08780226 100644 --- a/src/services/jsDoc.ts +++ b/src/services/jsDoc.ts @@ -20,6 +20,7 @@ namespace ts.JsDoc { "fileOverview", "function", "ignore", + "inheritDoc", "inner", "lends", "link", diff --git a/src/services/services.ts b/src/services/services.ts index 0dbdb57f309..237a9ce8d5b 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -346,9 +346,29 @@ namespace ts { return this.declarations; } - getDocumentationComment(): SymbolDisplayPart[] { + getDocumentationComment(checker: TypeChecker | undefined): SymbolDisplayPart[] { if (this.documentationComment === undefined) { - this.documentationComment = JsDoc.getJsDocCommentsFromDeclarations(this.declarations); + if (this.declarations) { + this.documentationComment = JsDoc.getJsDocCommentsFromDeclarations(this.declarations); + + if (this.documentationComment.length === 0 || this.declarations.some(hasJSDocInheritDocTag)) { + if (checker) { + for (const declaration of this.declarations) { + const inheritedDocs = findInheritedJSDocComments(declaration, this.getName(), checker); + if (inheritedDocs.length > 0) { + if (this.documentationComment.length > 0) { + inheritedDocs.push(ts.lineBreakPart()); + } + this.documentationComment = concatenate(inheritedDocs, this.documentationComment); + break; + } + } + } + } + } + else { + this.documentationComment = []; + } } return this.documentationComment; @@ -477,7 +497,23 @@ namespace ts { getDocumentationComment(): SymbolDisplayPart[] { if (this.documentationComment === undefined) { - this.documentationComment = this.declaration ? JsDoc.getJsDocCommentsFromDeclarations([this.declaration]) : []; + if (this.declaration) { + this.documentationComment = JsDoc.getJsDocCommentsFromDeclarations([this.declaration]); + + if (this.documentationComment.length === 0 || hasJSDocInheritDocTag(this.declaration)) { + const inheritedDocs = findInheritedJSDocComments(this.declaration, this.declaration.symbol.getName(), this.checker); + if (this.documentationComment.length > 0) { + inheritedDocs.push(ts.lineBreakPart()); + } + this.documentationComment = concatenate( + inheritedDocs, + this.documentationComment + ); + } + } + else { + this.documentationComment = []; + } } return this.documentationComment; @@ -492,6 +528,58 @@ namespace ts { } } + /** + * Returns whether or not the given node has a JSDoc "inheritDoc" tag on it. + * @param node the Node in question. + * @returns `true` if `node` has a JSDoc "inheritDoc" tag on it, otherwise `false`. + */ + function hasJSDocInheritDocTag(node: Node) { + return ts.getJSDocTags(node).some(tag => tag.tagName.text === "inheritDoc"); + } + + /** + * Attempts to find JSDoc comments for possibly-inherited properties. Checks superclasses then traverses + * implemented interfaces until a symbol is found with the same name and with documentation. + * @param declaration The possibly-inherited declaration to find comments for. + * @param propertyName The name of the possibly-inherited property. + * @param typeChecker A TypeChecker, used to find inherited properties. + * @returns A filled array of documentation comments if any were found, otherwise an empty array. + */ + function findInheritedJSDocComments(declaration: Declaration, propertyName: string, typeChecker: TypeChecker): SymbolDisplayPart[] { + let foundDocs = false; + return flatMap(getAllSuperTypeNodes(declaration), superTypeNode => { + if (foundDocs) { + return emptyArray; + } + const superType = typeChecker.getTypeAtLocation(superTypeNode); + if (!superType) { + return emptyArray; + } + const baseProperty = typeChecker.getPropertyOfType(superType, propertyName); + if (!baseProperty) { + return emptyArray; + } + const inheritedDocs = baseProperty.getDocumentationComment(typeChecker); + foundDocs = inheritedDocs.length > 0; + return inheritedDocs; + }); + } + + /** + * Finds and returns the `TypeNode` for all super classes and implemented interfaces given a declaration. + * @param declaration The possibly-inherited declaration. + * @returns A filled array of `TypeNode`s containing all super classes and implemented interfaces if any exist, otherwise an empty array. + */ + function getAllSuperTypeNodes(declaration: Declaration): ReadonlyArray { + const container = declaration.parent; + if (!container || (!isClassDeclaration(container) && !isInterfaceDeclaration(container))) { + return emptyArray; + } + const extended = getClassExtendsHeritageClauseElement(container); + const types = extended ? [extended] : emptyArray; + return isClassLike(container) ? concatenate(types, getClassImplementsHeritageClauseElements(container)) : types; + } + class SourceFileObject extends NodeObject implements SourceFile { public kind: SyntaxKind.SourceFile; public _declarationBrand: any; @@ -1399,7 +1487,7 @@ namespace ts { kindModifiers: ScriptElementKindModifier.none, textSpan: createTextSpan(node.getStart(), node.getWidth()), displayParts: typeToDisplayParts(typeChecker, type, getContainerNode(node)), - documentation: type.symbol ? type.symbol.getDocumentationComment() : undefined, + documentation: type.symbol ? type.symbol.getDocumentationComment(typeChecker) : undefined, tags: type.symbol ? type.symbol.getJsDocTags() : undefined }; } diff --git a/src/services/signatureHelp.ts b/src/services/signatureHelp.ts index 7e8e748bb17..36c83f5f4af 100644 --- a/src/services/signatureHelp.ts +++ b/src/services/signatureHelp.ts @@ -400,7 +400,7 @@ namespace ts.SignatureHelp { suffixDisplayParts, separatorDisplayParts: [punctuationPart(SyntaxKind.CommaToken), spacePart()], parameters: signatureHelpParameters, - documentation: candidateSignature.getDocumentationComment(), + documentation: candidateSignature.getDocumentationComment(typeChecker), tags: candidateSignature.getJsDocTags() }; }); @@ -420,7 +420,7 @@ namespace ts.SignatureHelp { return { name: parameter.name, - documentation: parameter.getDocumentationComment(), + documentation: parameter.getDocumentationComment(typeChecker), displayParts, isOptional: typeChecker.isOptionalParameter(parameter.valueDeclaration) }; @@ -438,4 +438,4 @@ namespace ts.SignatureHelp { }; } } -} \ No newline at end of file +} diff --git a/src/services/symbolDisplay.ts b/src/services/symbolDisplay.ts index 0465ec2aa70..e3ef4d3e495 100644 --- a/src/services/symbolDisplay.ts +++ b/src/services/symbolDisplay.ts @@ -438,7 +438,7 @@ namespace ts.SymbolDisplay { } if (!documentation) { - documentation = symbol.getDocumentationComment(); + documentation = symbol.getDocumentationComment(typeChecker); tags = symbol.getJsDocTags(); if (documentation.length === 0 && symbolFlags & SymbolFlags.Property) { // For some special property access expressions like `exports.foo = foo` or `module.exports.foo = foo` @@ -455,7 +455,7 @@ namespace ts.SymbolDisplay { continue; } - documentation = rhsSymbol.getDocumentationComment(); + documentation = rhsSymbol.getDocumentationComment(typeChecker); tags = rhsSymbol.getJsDocTags(); if (documentation.length > 0) { break; @@ -524,7 +524,7 @@ namespace ts.SymbolDisplay { displayParts.push(textPart(allSignatures.length === 2 ? "overload" : "overloads")); displayParts.push(punctuationPart(SyntaxKind.CloseParenToken)); } - documentation = signature.getDocumentationComment(); + documentation = signature.getDocumentationComment(typeChecker); tags = signature.getJsDocTags(); } diff --git a/src/services/types.ts b/src/services/types.ts index a3af3dbdf63..e93ae9686d7 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -32,7 +32,7 @@ namespace ts { getEscapedName(): __String; getName(): string; getDeclarations(): Declaration[] | undefined; - getDocumentationComment(): SymbolDisplayPart[]; + getDocumentationComment(typeChecker: TypeChecker | undefined): SymbolDisplayPart[]; getJsDocTags(): JSDocTagInfo[]; } @@ -55,7 +55,7 @@ namespace ts { getTypeParameters(): TypeParameter[] | undefined; getParameters(): Symbol[]; getReturnType(): Type; - getDocumentationComment(): SymbolDisplayPart[]; + getDocumentationComment(typeChecker: TypeChecker | undefined): SymbolDisplayPart[]; getJsDocTags(): JSDocTagInfo[]; } diff --git a/tests/baselines/reference/APISample_jsdoc.js b/tests/baselines/reference/APISample_jsdoc.js index c74e188f38b..f28b16d88b6 100644 --- a/tests/baselines/reference/APISample_jsdoc.js +++ b/tests/baselines/reference/APISample_jsdoc.js @@ -21,7 +21,7 @@ function parseCommentsIntoDefinition(this: any, } // the comments for a symbol - let comments = symbol.getDocumentationComment(); + let comments = symbol.getDocumentationComment(undefined); if (comments.length) { definition.description = comments.map(comment => comment.kind === "lineBreak" ? comment.text : comment.text.trim().replace(/\r\n/g, "\n")).join(""); @@ -131,7 +131,7 @@ function parseCommentsIntoDefinition(symbol, definition, otherAnnotations) { return; } // the comments for a symbol - var comments = symbol.getDocumentationComment(); + var comments = symbol.getDocumentationComment(undefined); if (comments.length) { definition.description = comments.map(function (comment) { return comment.kind === "lineBreak" ? comment.text : comment.text.trim().replace(/\r\n/g, "\n"); }).join(""); } diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 663aa27a1b6..85895ffbce4 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -3813,7 +3813,7 @@ declare namespace ts { getEscapedName(): __String; getName(): string; getDeclarations(): Declaration[] | undefined; - getDocumentationComment(): SymbolDisplayPart[]; + getDocumentationComment(typeChecker: TypeChecker | undefined): SymbolDisplayPart[]; getJsDocTags(): JSDocTagInfo[]; } interface Type { @@ -3834,7 +3834,7 @@ declare namespace ts { getTypeParameters(): TypeParameter[] | undefined; getParameters(): Symbol[]; getReturnType(): Type; - getDocumentationComment(): SymbolDisplayPart[]; + getDocumentationComment(typeChecker: TypeChecker | undefined): SymbolDisplayPart[]; getJsDocTags(): JSDocTagInfo[]; } interface SourceFile { diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 62b7d4e885b..fd58e72181a 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -3813,7 +3813,7 @@ declare namespace ts { getEscapedName(): __String; getName(): string; getDeclarations(): Declaration[] | undefined; - getDocumentationComment(): SymbolDisplayPart[]; + getDocumentationComment(typeChecker: TypeChecker | undefined): SymbolDisplayPart[]; getJsDocTags(): JSDocTagInfo[]; } interface Type { @@ -3834,7 +3834,7 @@ declare namespace ts { getTypeParameters(): TypeParameter[] | undefined; getParameters(): Symbol[]; getReturnType(): Type; - getDocumentationComment(): SymbolDisplayPart[]; + getDocumentationComment(typeChecker: TypeChecker | undefined): SymbolDisplayPart[]; getJsDocTags(): JSDocTagInfo[]; } interface SourceFile { diff --git a/tests/cases/compiler/APISample_jsdoc.ts b/tests/cases/compiler/APISample_jsdoc.ts index 2f4e08931d6..d40673f1d9e 100644 --- a/tests/cases/compiler/APISample_jsdoc.ts +++ b/tests/cases/compiler/APISample_jsdoc.ts @@ -25,7 +25,7 @@ function parseCommentsIntoDefinition(this: any, } // the comments for a symbol - let comments = symbol.getDocumentationComment(); + let comments = symbol.getDocumentationComment(undefined); if (comments.length) { definition.description = comments.map(comment => comment.kind === "lineBreak" ? comment.text : comment.text.trim().replace(/\r\n/g, "\n")).join(""); diff --git a/tests/cases/fourslash/commentsInheritance.ts b/tests/cases/fourslash/commentsInheritance.ts index 7afe18f400c..985c55c7947 100644 --- a/tests/cases/fourslash/commentsInheritance.ts +++ b/tests/cases/fourslash/commentsInheritance.ts @@ -263,8 +263,8 @@ verify.quickInfos({ }); goTo.marker('6'); -verify.completionListContains("i1_p1", "(property) c1.i1_p1: number", ""); -verify.completionListContains("i1_f1", "(method) c1.i1_f1(): void", ""); +verify.completionListContains("i1_p1", "(property) c1.i1_p1: number", "i1_p1"); +verify.completionListContains("i1_f1", "(method) c1.i1_f1(): void", "i1_f1"); verify.completionListContains("i1_l1", "(property) c1.i1_l1: () => void", ""); verify.completionListContains("i1_nc_p1", "(property) c1.i1_nc_p1: number", ""); verify.completionListContains("i1_nc_f1", "(method) c1.i1_nc_f1(): void", ""); @@ -276,7 +276,7 @@ verify.completionListContains("nc_p1", "(property) c1.nc_p1: number", "c1_nc_p1" verify.completionListContains("nc_f1", "(method) c1.nc_f1(): void", "c1_nc_f1"); verify.completionListContains("nc_l1", "(property) c1.nc_l1: () => void", ""); goTo.marker('7'); -verify.currentSignatureHelpDocCommentIs(""); +verify.currentSignatureHelpDocCommentIs("i1_f1"); goTo.marker('8'); verify.currentSignatureHelpDocCommentIs(""); goTo.marker('9'); @@ -294,7 +294,7 @@ verify.currentSignatureHelpDocCommentIs(""); verify.quickInfos({ "6iq": "var c1_i: c1", - "7q": "(method) c1.i1_f1(): void", + "7q": ["(method) c1.i1_f1(): void", "i1_f1"], "8q": "(method) c1.i1_nc_f1(): void", "9q": ["(method) c1.f1(): void", "c1_f1"], "10q": ["(method) c1.nc_f1(): void", "c1_nc_f1"], @@ -515,7 +515,7 @@ verify.quickInfos({ "39q": ["(method) i2.f1(): void", "i2 f1"], "40q": "(method) i2.nc_f1(): void", "l37q": "(property) i2.i2_l1: () => void", - "l38q": "(property) i2.i2_nc_l1: () => void", + "l38q": "(property) i2.i2_nc_l1: () => void", "l39q": "(property) i2.l1: () => void", "l40q": "(property) i2.nc_l1: () => void", }); diff --git a/tests/cases/fourslash/jsDocInheritDoc.ts b/tests/cases/fourslash/jsDocInheritDoc.ts new file mode 100644 index 00000000000..8a19bd0c14e --- /dev/null +++ b/tests/cases/fourslash/jsDocInheritDoc.ts @@ -0,0 +1,57 @@ +/// +// @Filename: inheritDoc.ts +////class Foo { +//// /** +//// * Foo constructor documentation +//// */ +//// constructor(value: number) {} +//// /** +//// * Foo#method1 documentation +//// */ +//// static method1() {} +//// /** +//// * Foo#method2 documentation +//// */ +//// method2() {} +//// /** +//// * Foo#property1 documentation +//// */ +//// property1: string; +////} +////interface Baz { +//// /** Baz#property1 documentation */ +//// property1: string; +//// /** +//// * Baz#property2 documentation +//// */ +//// property2: object; +////} +////class Bar extends Foo implements Baz { +//// ctorValue: number; +//// /** @inheritDoc */ +//// constructor(value: number) { +//// super(value); +//// this.ctorValue = value; +//// } +//// /** @inheritDoc */ +//// static method1() {} +//// method2() {} +//// /** @inheritDoc */ +//// property1: string; +//// /** +//// * Bar#property2 +//// * @inheritDoc +//// */ +//// property2: object; +////} +////const b = new Bar/*1*/(5); +////b.method2/*2*/(); +////Bar.method1/*3*/(); +////const p1 = b.property1/*4*/; +////const p2 = b.property2/*5*/; + +verify.quickInfoAt("1", "constructor Bar(value: number): Bar", undefined); // constructors aren't actually inherited +verify.quickInfoAt("2", "(method) Bar.method2(): void", "Foo#method2 documentation"); // use inherited docs only +verify.quickInfoAt("3", "(method) Bar.method1(): void", undefined); // statics aren't actually inherited +verify.quickInfoAt("4", "(property) Bar.property1: string", "Foo#property1 documentation"); // use inherited docs only +verify.quickInfoAt("5", "(property) Bar.property2: object", "Baz#property2 documentation\nBar#property2"); // include local and inherited docs From fd64322a6372b17d442c95aadce95ff6115883fd Mon Sep 17 00:00:00 2001 From: csigs Date: Mon, 6 Nov 2017 23:10:47 +0000 Subject: [PATCH 11/12] LEGO: check in for master to temporary branch. --- .../diagnosticMessages.generated.json.lcl | 36 +++++++++++++++++++ .../diagnosticMessages.generated.json.lcl | 36 +++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl index 94bbc474495..c59e9c20060 100644 --- a/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -2241,6 +2241,15 @@ + + + + + + + + + @@ -2970,6 +2979,15 @@ + + + + + + + + + @@ -4212,6 +4230,24 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl index 83a8d7cace7..31f3bfdefd5 100644 --- a/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -2241,6 +2241,15 @@ + + + + + + + + + @@ -2970,6 +2979,15 @@ + + + + + + + + + @@ -4212,6 +4230,24 @@ + + + + + + + + + + + + + + + + + + From d79c37cd191a5d10ad678f2a1379c6267e914bf2 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Mon, 6 Nov 2017 16:09:35 -0800 Subject: [PATCH 12/12] Discriminate contextual types (#19733) * Discriminate contextual types * Invert conditional * Update findMatchingDiscriminantType and baselines --- src/compiler/checker.ts | 59 ++++++++++++---- .../contextuallyTypedByDiscriminableUnion.js | 42 +++++++++++ ...textuallyTypedByDiscriminableUnion.symbols | 60 ++++++++++++++++ ...ontextuallyTypedByDiscriminableUnion.types | 70 +++++++++++++++++++ .../excessPropertyCheckWithUnions.errors.txt | 18 +++-- .../excessPropertyCheckWithUnions.js | 4 +- .../excessPropertyCheckWithUnions.symbols | 2 +- .../excessPropertyCheckWithUnions.types | 6 +- .../contextuallyTypedByDiscriminableUnion.ts | 25 +++++++ .../compiler/excessPropertyCheckWithUnions.ts | 2 +- 10 files changed, 262 insertions(+), 26 deletions(-) create mode 100644 tests/baselines/reference/contextuallyTypedByDiscriminableUnion.js create mode 100644 tests/baselines/reference/contextuallyTypedByDiscriminableUnion.symbols create mode 100644 tests/baselines/reference/contextuallyTypedByDiscriminableUnion.types create mode 100644 tests/cases/compiler/contextuallyTypedByDiscriminableUnion.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 649deef7e3a..7d9a32a8f92 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -9269,20 +9269,24 @@ namespace ts { return Ternary.False; } + // Keep this up-to-date with the same logic within `getApparentTypeOfContextualType`, since they should behave similarly function findMatchingDiscriminantType(source: Type, target: UnionOrIntersectionType) { let match: Type; const sourceProperties = getPropertiesOfObjectType(source); if (sourceProperties) { - const sourceProperty = findSingleDiscriminantProperty(sourceProperties, target); - if (sourceProperty) { - const sourceType = getTypeOfSymbol(sourceProperty); - for (const type of target.types) { - const targetType = getTypeOfPropertyOfType(type, sourceProperty.escapedName); - if (targetType && isRelatedTo(sourceType, targetType)) { - if (match) { - return undefined; + const sourcePropertiesFiltered = findDiscriminantProperties(sourceProperties, target); + if (sourcePropertiesFiltered) { + for (const sourceProperty of sourcePropertiesFiltered) { + const sourceType = getTypeOfSymbol(sourceProperty); + for (const type of target.types) { + const targetType = getTypeOfPropertyOfType(type, sourceProperty.escapedName); + if (targetType && isRelatedTo(sourceType, targetType)) { + if (type === match) continue; // Finding multiple fields which discriminate to the same type is fine + if (match) { + return undefined; + } + match = type; } - match = type; } } } @@ -11396,14 +11400,15 @@ namespace ts { return false; } - function findSingleDiscriminantProperty(sourceProperties: Symbol[], target: Type): Symbol | undefined { - let result: Symbol; + function findDiscriminantProperties(sourceProperties: Symbol[], target: Type): Symbol[] | undefined { + let result: Symbol[]; for (const sourceProperty of sourceProperties) { if (isDiscriminantProperty(target, sourceProperty.escapedName)) { if (result) { - return undefined; + result.push(sourceProperty); + continue; } - result = sourceProperty; + result = [sourceProperty]; } } return result; @@ -13691,8 +13696,32 @@ namespace ts { // Return the contextual type for a given expression node. During overload resolution, a contextual type may temporarily // be "pushed" onto a node using the contextualType property. function getApparentTypeOfContextualType(node: Expression): Type { - const type = getContextualType(node); - return type && mapType(type, getApparentType); + let contextualType = getContextualType(node); + contextualType = contextualType && mapType(contextualType, getApparentType); + if (!(contextualType && contextualType.flags & TypeFlags.Union && isObjectLiteralExpression(node))) { + return contextualType; + } + // Keep the below up-to-date with the work done within `isRelatedTo` by `findMatchingDiscriminantType` + let match: Type | undefined; + propLoop: for (const prop of node.properties) { + if (!prop.symbol) continue; + if (prop.kind !== SyntaxKind.PropertyAssignment) continue; + if (isDiscriminantProperty(contextualType, prop.symbol.escapedName)) { + const discriminatingType = getTypeOfNode(prop.initializer); + for (const type of (contextualType as UnionType).types) { + const targetType = getTypeOfPropertyOfType(type, prop.symbol.escapedName); + if (targetType && checkTypeAssignableTo(discriminatingType, targetType, /*errorNode*/ undefined)) { + if (match) { + if (type === match) continue; // Finding multiple fields which discriminate to the same type is fine + match = undefined; + break propLoop; + } + match = type; + } + } + } + } + return match || contextualType; } /** diff --git a/tests/baselines/reference/contextuallyTypedByDiscriminableUnion.js b/tests/baselines/reference/contextuallyTypedByDiscriminableUnion.js new file mode 100644 index 00000000000..b61c235dee9 --- /dev/null +++ b/tests/baselines/reference/contextuallyTypedByDiscriminableUnion.js @@ -0,0 +1,42 @@ +//// [contextuallyTypedByDiscriminableUnion.ts] +type ADT = { + kind: "a", + method(x: string): number; +} | { + kind: "b", + method(x: number): string; +}; + + +function invoke(item: ADT) { + if (item.kind === "a") { + item.method(""); + } + else { + item.method(42); + } +} + +invoke({ + kind: "a", + method(a) { + return +a; + } +}); + + +//// [contextuallyTypedByDiscriminableUnion.js] +function invoke(item) { + if (item.kind === "a") { + item.method(""); + } + else { + item.method(42); + } +} +invoke({ + kind: "a", + method: function (a) { + return +a; + } +}); diff --git a/tests/baselines/reference/contextuallyTypedByDiscriminableUnion.symbols b/tests/baselines/reference/contextuallyTypedByDiscriminableUnion.symbols new file mode 100644 index 00000000000..e4ef8ee73e7 --- /dev/null +++ b/tests/baselines/reference/contextuallyTypedByDiscriminableUnion.symbols @@ -0,0 +1,60 @@ +=== tests/cases/compiler/contextuallyTypedByDiscriminableUnion.ts === +type ADT = { +>ADT : Symbol(ADT, Decl(contextuallyTypedByDiscriminableUnion.ts, 0, 0)) + + kind: "a", +>kind : Symbol(kind, Decl(contextuallyTypedByDiscriminableUnion.ts, 0, 12)) + + method(x: string): number; +>method : Symbol(method, Decl(contextuallyTypedByDiscriminableUnion.ts, 1, 14)) +>x : Symbol(x, Decl(contextuallyTypedByDiscriminableUnion.ts, 2, 11)) + +} | { + kind: "b", +>kind : Symbol(kind, Decl(contextuallyTypedByDiscriminableUnion.ts, 3, 5)) + + method(x: number): string; +>method : Symbol(method, Decl(contextuallyTypedByDiscriminableUnion.ts, 4, 14)) +>x : Symbol(x, Decl(contextuallyTypedByDiscriminableUnion.ts, 5, 11)) + +}; + + +function invoke(item: ADT) { +>invoke : Symbol(invoke, Decl(contextuallyTypedByDiscriminableUnion.ts, 6, 2)) +>item : Symbol(item, Decl(contextuallyTypedByDiscriminableUnion.ts, 9, 16)) +>ADT : Symbol(ADT, Decl(contextuallyTypedByDiscriminableUnion.ts, 0, 0)) + + if (item.kind === "a") { +>item.kind : Symbol(kind, Decl(contextuallyTypedByDiscriminableUnion.ts, 0, 12), Decl(contextuallyTypedByDiscriminableUnion.ts, 3, 5)) +>item : Symbol(item, Decl(contextuallyTypedByDiscriminableUnion.ts, 9, 16)) +>kind : Symbol(kind, Decl(contextuallyTypedByDiscriminableUnion.ts, 0, 12), Decl(contextuallyTypedByDiscriminableUnion.ts, 3, 5)) + + item.method(""); +>item.method : Symbol(method, Decl(contextuallyTypedByDiscriminableUnion.ts, 1, 14)) +>item : Symbol(item, Decl(contextuallyTypedByDiscriminableUnion.ts, 9, 16)) +>method : Symbol(method, Decl(contextuallyTypedByDiscriminableUnion.ts, 1, 14)) + } + else { + item.method(42); +>item.method : Symbol(method, Decl(contextuallyTypedByDiscriminableUnion.ts, 4, 14)) +>item : Symbol(item, Decl(contextuallyTypedByDiscriminableUnion.ts, 9, 16)) +>method : Symbol(method, Decl(contextuallyTypedByDiscriminableUnion.ts, 4, 14)) + } +} + +invoke({ +>invoke : Symbol(invoke, Decl(contextuallyTypedByDiscriminableUnion.ts, 6, 2)) + + kind: "a", +>kind : Symbol(kind, Decl(contextuallyTypedByDiscriminableUnion.ts, 18, 8)) + + method(a) { +>method : Symbol(method, Decl(contextuallyTypedByDiscriminableUnion.ts, 19, 14)) +>a : Symbol(a, Decl(contextuallyTypedByDiscriminableUnion.ts, 20, 11)) + + return +a; +>a : Symbol(a, Decl(contextuallyTypedByDiscriminableUnion.ts, 20, 11)) + } +}); + diff --git a/tests/baselines/reference/contextuallyTypedByDiscriminableUnion.types b/tests/baselines/reference/contextuallyTypedByDiscriminableUnion.types new file mode 100644 index 00000000000..d62dc4b5e0c --- /dev/null +++ b/tests/baselines/reference/contextuallyTypedByDiscriminableUnion.types @@ -0,0 +1,70 @@ +=== tests/cases/compiler/contextuallyTypedByDiscriminableUnion.ts === +type ADT = { +>ADT : ADT + + kind: "a", +>kind : "a" + + method(x: string): number; +>method : (x: string) => number +>x : string + +} | { + kind: "b", +>kind : "b" + + method(x: number): string; +>method : (x: number) => string +>x : number + +}; + + +function invoke(item: ADT) { +>invoke : (item: ADT) => void +>item : ADT +>ADT : ADT + + if (item.kind === "a") { +>item.kind === "a" : boolean +>item.kind : "a" | "b" +>item : ADT +>kind : "a" | "b" +>"a" : "a" + + item.method(""); +>item.method("") : number +>item.method : (x: string) => number +>item : { kind: "a"; method(x: string): number; } +>method : (x: string) => number +>"" : "" + } + else { + item.method(42); +>item.method(42) : string +>item.method : (x: number) => string +>item : { kind: "b"; method(x: number): string; } +>method : (x: number) => string +>42 : 42 + } +} + +invoke({ +>invoke({ kind: "a", method(a) { return +a; }}) : void +>invoke : (item: ADT) => void +>{ kind: "a", method(a) { return +a; }} : { kind: "a"; method(a: string): number; } + + kind: "a", +>kind : string +>"a" : "a" + + method(a) { +>method : (a: string) => number +>a : string + + return +a; +>+a : number +>a : string + } +}); + diff --git a/tests/baselines/reference/excessPropertyCheckWithUnions.errors.txt b/tests/baselines/reference/excessPropertyCheckWithUnions.errors.txt index 9fbbb001605..d802733354e 100644 --- a/tests/baselines/reference/excessPropertyCheckWithUnions.errors.txt +++ b/tests/baselines/reference/excessPropertyCheckWithUnions.errors.txt @@ -1,6 +1,6 @@ tests/cases/compiler/excessPropertyCheckWithUnions.ts(10,30): error TS2322: Type '{ tag: "T"; a1: string; }' is not assignable to type 'ADT'. Object literal may only specify known properties, and 'a1' does not exist in type '{ tag: "T"; }'. -tests/cases/compiler/excessPropertyCheckWithUnions.ts(11,21): error TS2322: Type '{ tag: "A"; d20: 12; }' is not assignable to type 'ADT'. +tests/cases/compiler/excessPropertyCheckWithUnions.ts(11,21): error TS2322: Type '{ tag: "A"; d20: number; }' is not assignable to type 'ADT'. Object literal may only specify known properties, and 'd20' does not exist in type '{ tag: "A"; a1: string; }'. tests/cases/compiler/excessPropertyCheckWithUnions.ts(12,1): error TS2322: Type '{ tag: "D"; }' is not assignable to type 'ADT'. Type '{ tag: "D"; }' is not assignable to type '{ tag: "D"; d20: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20; }'. @@ -17,9 +17,13 @@ tests/cases/compiler/excessPropertyCheckWithUnions.ts(40,1): error TS2322: Type Type '{ tag: "A"; z: true; }' is not assignable to type '{ tag: "C"; }'. Types of property 'tag' are incompatible. Type '"A"' is not assignable to type '"C"'. +tests/cases/compiler/excessPropertyCheckWithUnions.ts(49,35): error TS2322: Type '{ a: 1; b: 1; first: string; second: string; }' is not assignable to type 'Overlapping'. + Object literal may only specify known properties, and 'second' does not exist in type '{ a: 1; b: 1; first: string; }'. +tests/cases/compiler/excessPropertyCheckWithUnions.ts(50,35): error TS2322: Type '{ a: 1; b: 1; first: string; third: string; }' is not assignable to type 'Overlapping'. + Object literal may only specify known properties, and 'third' does not exist in type '{ a: 1; b: 1; first: string; }'. -==== tests/cases/compiler/excessPropertyCheckWithUnions.ts (7 errors) ==== +==== tests/cases/compiler/excessPropertyCheckWithUnions.ts (9 errors) ==== type ADT = { tag: "A", a1: string @@ -35,7 +39,7 @@ tests/cases/compiler/excessPropertyCheckWithUnions.ts(40,1): error TS2322: Type !!! error TS2322: Object literal may only specify known properties, and 'a1' does not exist in type '{ tag: "T"; }'. wrong = { tag: "A", d20: 12 } ~~~~~~~ -!!! error TS2322: Type '{ tag: "A"; d20: 12; }' is not assignable to type 'ADT'. +!!! error TS2322: Type '{ tag: "A"; d20: number; }' is not assignable to type 'ADT'. !!! error TS2322: Object literal may only specify known properties, and 'd20' does not exist in type '{ tag: "A"; a1: string; }'. wrong = { tag: "D" } ~~~~~ @@ -93,9 +97,15 @@ tests/cases/compiler/excessPropertyCheckWithUnions.ts(40,1): error TS2322: Type | { b: 3, third: string } let over: Overlapping - // these two are not reported because there are two discriminant properties + // these two are still errors despite their doubled up discriminants over = { a: 1, b: 1, first: "ok", second: "error" } + ~~~~~~~~~~~~~~~ +!!! error TS2322: Type '{ a: 1; b: 1; first: string; second: string; }' is not assignable to type 'Overlapping'. +!!! error TS2322: Object literal may only specify known properties, and 'second' does not exist in type '{ a: 1; b: 1; first: string; }'. over = { a: 1, b: 1, first: "ok", third: "error" } + ~~~~~~~~~~~~~~ +!!! error TS2322: Type '{ a: 1; b: 1; first: string; third: string; }' is not assignable to type 'Overlapping'. +!!! error TS2322: Object literal may only specify known properties, and 'third' does not exist in type '{ a: 1; b: 1; first: string; }'. // Freshness disappears after spreading a union declare let t0: { a: any, b: any } | { d: any, e: any } diff --git a/tests/baselines/reference/excessPropertyCheckWithUnions.js b/tests/baselines/reference/excessPropertyCheckWithUnions.js index c6b45123cce..a20983e4b08 100644 --- a/tests/baselines/reference/excessPropertyCheckWithUnions.js +++ b/tests/baselines/reference/excessPropertyCheckWithUnions.js @@ -46,7 +46,7 @@ type Overlapping = | { b: 3, third: string } let over: Overlapping -// these two are not reported because there are two discriminant properties +// these two are still errors despite their doubled up discriminants over = { a: 1, b: 1, first: "ok", second: "error" } over = { a: 1, b: 1, first: "ok", third: "error" } @@ -84,7 +84,7 @@ amb = { tag: "A", y: 12, extra: 12 }; amb = { tag: "A" }; amb = { tag: "A", z: true }; var over; -// these two are not reported because there are two discriminant properties +// these two are still errors despite their doubled up discriminants over = { a: 1, b: 1, first: "ok", second: "error" }; over = { a: 1, b: 1, first: "ok", third: "error" }; var t2 = __assign({}, t1); diff --git a/tests/baselines/reference/excessPropertyCheckWithUnions.symbols b/tests/baselines/reference/excessPropertyCheckWithUnions.symbols index 7778c6bf216..381681de384 100644 --- a/tests/baselines/reference/excessPropertyCheckWithUnions.symbols +++ b/tests/baselines/reference/excessPropertyCheckWithUnions.symbols @@ -127,7 +127,7 @@ let over: Overlapping >over : Symbol(over, Decl(excessPropertyCheckWithUnions.ts, 45, 3)) >Overlapping : Symbol(Overlapping, Decl(excessPropertyCheckWithUnions.ts, 39, 27)) -// these two are not reported because there are two discriminant properties +// these two are still errors despite their doubled up discriminants over = { a: 1, b: 1, first: "ok", second: "error" } >over : Symbol(over, Decl(excessPropertyCheckWithUnions.ts, 45, 3)) >a : Symbol(a, Decl(excessPropertyCheckWithUnions.ts, 48, 8)) diff --git a/tests/baselines/reference/excessPropertyCheckWithUnions.types b/tests/baselines/reference/excessPropertyCheckWithUnions.types index 78f5c025b38..212eccbe2ff 100644 --- a/tests/baselines/reference/excessPropertyCheckWithUnions.types +++ b/tests/baselines/reference/excessPropertyCheckWithUnions.types @@ -29,9 +29,9 @@ let wrong: ADT = { tag: "T", a1: "extra" } >"extra" : "extra" wrong = { tag: "A", d20: 12 } ->wrong = { tag: "A", d20: 12 } : { tag: "A"; d20: 12; } +>wrong = { tag: "A", d20: 12 } : { tag: "A"; d20: number; } >wrong : ADT ->{ tag: "A", d20: 12 } : { tag: "A"; d20: 12; } +>{ tag: "A", d20: 12 } : { tag: "A"; d20: number; } >tag : string >"A" : "A" >d20 : number @@ -167,7 +167,7 @@ let over: Overlapping >over : Overlapping >Overlapping : Overlapping -// these two are not reported because there are two discriminant properties +// these two are still errors despite their doubled up discriminants over = { a: 1, b: 1, first: "ok", second: "error" } >over = { a: 1, b: 1, first: "ok", second: "error" } : { a: 1; b: 1; first: string; second: string; } >over : Overlapping diff --git a/tests/cases/compiler/contextuallyTypedByDiscriminableUnion.ts b/tests/cases/compiler/contextuallyTypedByDiscriminableUnion.ts new file mode 100644 index 00000000000..5fbcd2dbbc5 --- /dev/null +++ b/tests/cases/compiler/contextuallyTypedByDiscriminableUnion.ts @@ -0,0 +1,25 @@ +// @noImplicitAny: true +type ADT = { + kind: "a", + method(x: string): number; +} | { + kind: "b", + method(x: number): string; +}; + + +function invoke(item: ADT) { + if (item.kind === "a") { + item.method(""); + } + else { + item.method(42); + } +} + +invoke({ + kind: "a", + method(a) { + return +a; + } +}); diff --git a/tests/cases/compiler/excessPropertyCheckWithUnions.ts b/tests/cases/compiler/excessPropertyCheckWithUnions.ts index d5a2327380e..240af391cf5 100644 --- a/tests/cases/compiler/excessPropertyCheckWithUnions.ts +++ b/tests/cases/compiler/excessPropertyCheckWithUnions.ts @@ -46,7 +46,7 @@ type Overlapping = | { b: 3, third: string } let over: Overlapping -// these two are not reported because there are two discriminant properties +// these two are still errors despite their doubled up discriminants over = { a: 1, b: 1, first: "ok", second: "error" } over = { a: 1, b: 1, first: "ok", third: "error" }