From c87ca2f1ab8caab05c6085c0135bdcf7a61ac042 Mon Sep 17 00:00:00 2001 From: christian Date: Mon, 3 Sep 2018 22:57:26 -0400 Subject: [PATCH 01/83] Fix diagnostic reporting for empty files in tsconfig --- src/compiler/commandLineParser.ts | 16 ++++--- src/compiler/tsbuild.ts | 16 +++++-- src/testRunner/unittests/tsbuild.ts | 42 +++++++++++++++++++ src/testRunner/unittests/tsconfigParsing.ts | 39 +++++++++++++++++ tests/projects/empty-files/core/index.ts | 1 + tests/projects/empty-files/core/tsconfig.json | 7 ++++ .../empty-files/no-references/tsconfig.json | 9 ++++ .../empty-files/with-references/tsconfig.json | 11 +++++ 8 files changed, 132 insertions(+), 9 deletions(-) create mode 100644 tests/projects/empty-files/core/index.ts create mode 100644 tests/projects/empty-files/core/tsconfig.json create mode 100644 tests/projects/empty-files/no-references/tsconfig.json create mode 100644 tests/projects/empty-files/with-references/tsconfig.json diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index e4c4edcb4db..5d87525073f 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -1843,7 +1843,9 @@ namespace ts { if (hasProperty(raw, "files") && !isNullOrUndefined(raw.files)) { if (isArray(raw.files)) { filesSpecs = >raw.files; - if (filesSpecs.length === 0) { + const hasReferences = hasProperty(raw, "references") && !isNullOrUndefined(raw.references); + const hasZeroOrNoReferences = !hasReferences || raw.references.length === 0; + if (filesSpecs.length === 0 && hasZeroOrNoReferences) { createCompilerDiagnosticOnlyIfJson(Diagnostics.The_files_list_in_config_file_0_is_empty, configFileName || "tsconfig.json"); } } @@ -2067,11 +2069,6 @@ namespace ts { createDiagnosticForNodeInSourceFile(sourceFile, valueNode, message, arg0) ); return; - case "files": - if ((>value).length === 0) { - errors.push(createDiagnosticForNodeInSourceFile(sourceFile, valueNode, Diagnostics.The_files_list_in_config_file_0_is_empty, configFileName || "tsconfig.json")); - } - return; } }, onSetUnknownOptionKeyValueInRoot(key: string, keyNode: PropertyName, _value: CompilerOptionsValue, _valueNode: Expression) { @@ -2081,6 +2078,13 @@ namespace ts { } }; const json = convertToObjectWorker(sourceFile, errors, /*returnValue*/ true, getTsconfigRootOptionsMap(), optionsIterator); + const hasZeroFiles = json && json.files && json.files.length === 0; + const hasZeroOrNoReferences = !(json && json.references) || json.references.length === 0; + + if (hasZeroFiles && hasZeroOrNoReferences) { + errors.push(createCompilerDiagnostic(Diagnostics.The_files_list_in_config_file_0_is_empty, sourceFile.fileName)); + } + if (!typeAcquisition) { if (typingOptionstypeAcquisition) { typeAcquisition = (typingOptionstypeAcquisition.enableAutoDiscovery !== undefined) ? diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts index 4ddda98a41f..418185b4c16 100644 --- a/src/compiler/tsbuild.ts +++ b/src/compiler/tsbuild.ts @@ -946,7 +946,6 @@ namespace ts { context.projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Config file errors" }); return resultFlags; } - if (configFile.fileNames.length === 0) { // Nothing to build - must be a solution file, basically return BuildResultFlags.None; @@ -956,7 +955,8 @@ namespace ts { projectReferences: configFile.projectReferences, host, rootNames: configFile.fileNames, - options: configFile.options + options: configFile.options, + configFileParsingDiagnostics: configFile.errors, }; const program = createProgram(programOptions); @@ -1149,7 +1149,6 @@ namespace ts { const queue = graph.buildQueue; reportBuildQueue(graph); - let anyFailed = false; for (const next of queue) { const proj = configFileCache.parseConfigFile(next); @@ -1157,11 +1156,15 @@ namespace ts { anyFailed = true; break; } + + // report errors early when using continue or break statements + const errors = proj.errors; const status = getUpToDateStatus(proj); verboseReportProjectStatus(next, status); const projName = proj.options.configFilePath!; if (status.type === UpToDateStatusType.UpToDate && !context.options.force) { + reportErrors(errors); // Up to date, skip if (defaultOptions.dry) { // In a dry build, inform the user of this fact @@ -1171,17 +1174,20 @@ namespace ts { } if (status.type === UpToDateStatusType.UpToDateWithUpstreamTypes && !context.options.force) { + reportErrors(errors); // Fake build updateOutputTimestamps(proj); continue; } if (status.type === UpToDateStatusType.UpstreamBlocked) { + reportErrors(errors); if (context.options.verbose) reportStatus(Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors, projName, status.upstreamProjectName); continue; } if (status.type === UpToDateStatusType.ContainerOnly) { + reportErrors(errors); // Do nothing continue; } @@ -1193,6 +1199,10 @@ namespace ts { return anyFailed ? ExitStatus.DiagnosticsPresent_OutputsSkipped : ExitStatus.Success; } + function reportErrors(errors: Diagnostic[]) { + errors.forEach((err) => host.reportDiagnostic(err)); + } + /** * Report the build ordering inferred from the current project graph if we're in verbose mode */ diff --git a/src/testRunner/unittests/tsbuild.ts b/src/testRunner/unittests/tsbuild.ts index ea99ee92457..6d6f95ce19c 100644 --- a/src/testRunner/unittests/tsbuild.ts +++ b/src/testRunner/unittests/tsbuild.ts @@ -292,6 +292,48 @@ namespace ts { }); } + export namespace EmptyFiles { + const projFs = loadProjectFromDisk("tests/projects/empty-files"); + + const allExpectedOutputs = [ + "/src/core/index.js", + "/src/core/index.d.ts", + "/src/core/index.d.ts.map", + ]; + + describe("tsbuild - empty files option in tsconfig", () => { + it("has empty files diagnostic when files is empty and no references are provided", () => { + const fs = projFs.shadow(); + const host = new fakes.SolutionBuilderHost(fs); + const builder = createSolutionBuilder(host, ["/src/no-references"], { dry: false, force: false, verbose: false }); + + host.clearDiagnostics(); + builder.buildAllProjects(); + host.assertDiagnosticMessages(Diagnostics.The_files_list_in_config_file_0_is_empty); + + // Check for outputs to not be written. + for (const output of allExpectedOutputs) { + assert(!fs.existsSync(output), `Expect file ${output} to not exist`); + } + }); + + it("does not have empty files diagnostic when files is empty and references are provided", () => { + const fs = projFs.shadow(); + const host = new fakes.SolutionBuilderHost(fs); + const builder = createSolutionBuilder(host, ["/src/with-references"], { dry: false, force: false, verbose: false }); + + host.clearDiagnostics(); + builder.buildAllProjects(); + host.assertDiagnosticMessages(/*empty*/); + + // Check for outputs to be written. + for (const output of allExpectedOutputs) { + assert(fs.existsSync(output), `Expect file ${output} to exist`); + } + }); + }); + } + describe("tsbuild - graph-ordering", () => { let host: fakes.SolutionBuilderHost | undefined; const deps: [string, string][] = [ diff --git a/src/testRunner/unittests/tsconfigParsing.ts b/src/testRunner/unittests/tsconfigParsing.ts index 6ef5697046f..c2e8f0eb10d 100644 --- a/src/testRunner/unittests/tsconfigParsing.ts +++ b/src/testRunner/unittests/tsconfigParsing.ts @@ -61,6 +61,19 @@ namespace ts { } } + function assertParseFileDiagnosticsExclusion(jsonText: string, configFileName: string, basePath: string, allFileList: string[], expectedExcludedDiagnosticCode: number) { + { + const parsed = getParsedCommandJson(jsonText, configFileName, basePath, allFileList); + assert.isTrue(parsed.errors.length >= 0); + assert.isTrue(parsed.errors.findIndex(e => e.code === expectedExcludedDiagnosticCode) === -1, `Expected error code ${expectedExcludedDiagnosticCode} to not be in ${JSON.stringify(parsed.errors)}`); + } + { + const parsed = getParsedCommandJsonNode(jsonText, configFileName, basePath, allFileList); + assert.isTrue(parsed.errors.length >= 0); + assert.isTrue(parsed.errors.findIndex(e => e.code === expectedExcludedDiagnosticCode) === -1, `Expected error code ${expectedExcludedDiagnosticCode} to not be in ${JSON.stringify(parsed.errors)}`); + } + } + it("returns empty config for file with only whitespaces", () => { assertParseResult("", { config : {} }); assertParseResult(" ", { config : {} }); @@ -274,6 +287,32 @@ namespace ts { "files": [] }`; assertParseFileDiagnostics(content, + "/apath/tsconfig.json", + "tests/cases/unittests", + ["/apath/a.ts"], + Diagnostics.The_files_list_in_config_file_0_is_empty.code, + /*noLocation*/ true); + }); + + it("generates errors for empty files list when no references are provided", () => { + const content = `{ + "files": [], + "references": [] + }`; + assertParseFileDiagnostics(content, + "/apath/tsconfig.json", + "tests/cases/unittests", + ["/apath/a.ts"], + Diagnostics.The_files_list_in_config_file_0_is_empty.code, + /*noLocation*/ true); + }); + + it("does not generate errors for empty files list when one or more references are provided", () => { + const content = `{ + "files": [], + "references": [{ "path": "/apath" }] + }`; + assertParseFileDiagnosticsExclusion(content, "/apath/tsconfig.json", "tests/cases/unittests", ["/apath/a.ts"], diff --git a/tests/projects/empty-files/core/index.ts b/tests/projects/empty-files/core/index.ts new file mode 100644 index 00000000000..3da69271e97 --- /dev/null +++ b/tests/projects/empty-files/core/index.ts @@ -0,0 +1 @@ +export function multiply(a: number, b: number) { return a * b; } diff --git a/tests/projects/empty-files/core/tsconfig.json b/tests/projects/empty-files/core/tsconfig.json new file mode 100644 index 00000000000..24b64bc7b2c --- /dev/null +++ b/tests/projects/empty-files/core/tsconfig.json @@ -0,0 +1,7 @@ +{ + "compilerOptions": { + "composite": true, + "declaration": true, + "declarationMap": true + } +} \ No newline at end of file diff --git a/tests/projects/empty-files/no-references/tsconfig.json b/tests/projects/empty-files/no-references/tsconfig.json new file mode 100644 index 00000000000..9b02f3654e3 --- /dev/null +++ b/tests/projects/empty-files/no-references/tsconfig.json @@ -0,0 +1,9 @@ +{ + "references": [], + "files": [], + "compilerOptions": { + "composite": true, + "declaration": true, + "forceConsistentCasingInFileNames": true + } +} \ No newline at end of file diff --git a/tests/projects/empty-files/with-references/tsconfig.json b/tests/projects/empty-files/with-references/tsconfig.json new file mode 100644 index 00000000000..bf5e2690064 --- /dev/null +++ b/tests/projects/empty-files/with-references/tsconfig.json @@ -0,0 +1,11 @@ +{ + "references": [ + { "path": "../core" }, + ], + "files": [], + "compilerOptions": { + "composite": true, + "declaration": true, + "forceConsistentCasingInFileNames": true + } +} \ No newline at end of file From 959dbbba2821c63bcb1de9d4422a80aeab6b5156 Mon Sep 17 00:00:00 2001 From: christian Date: Mon, 3 Sep 2018 23:16:53 -0400 Subject: [PATCH 02/83] Add newline to bottom of tsconfig files --- tests/projects/empty-files/core/tsconfig.json | 2 +- tests/projects/empty-files/no-references/tsconfig.json | 2 +- tests/projects/empty-files/with-references/tsconfig.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/projects/empty-files/core/tsconfig.json b/tests/projects/empty-files/core/tsconfig.json index 24b64bc7b2c..0e8205977dd 100644 --- a/tests/projects/empty-files/core/tsconfig.json +++ b/tests/projects/empty-files/core/tsconfig.json @@ -4,4 +4,4 @@ "declaration": true, "declarationMap": true } -} \ No newline at end of file +} diff --git a/tests/projects/empty-files/no-references/tsconfig.json b/tests/projects/empty-files/no-references/tsconfig.json index 9b02f3654e3..c6b8f1a43d7 100644 --- a/tests/projects/empty-files/no-references/tsconfig.json +++ b/tests/projects/empty-files/no-references/tsconfig.json @@ -6,4 +6,4 @@ "declaration": true, "forceConsistentCasingInFileNames": true } -} \ No newline at end of file +} diff --git a/tests/projects/empty-files/with-references/tsconfig.json b/tests/projects/empty-files/with-references/tsconfig.json index bf5e2690064..3a55cad1b1c 100644 --- a/tests/projects/empty-files/with-references/tsconfig.json +++ b/tests/projects/empty-files/with-references/tsconfig.json @@ -8,4 +8,4 @@ "declaration": true, "forceConsistentCasingInFileNames": true } -} \ No newline at end of file +} From 5a72da76c28044e7b19e22bda98dcaa09d108762 Mon Sep 17 00:00:00 2001 From: Benjamin Lichtman Date: Wed, 5 Sep 2018 16:26:20 -0700 Subject: [PATCH 03/83] Only perform async refactor if it won't delete code --- .../codefixes/convertToAsyncFunction.ts | 11 +- .../unittests/convertToAsyncFunction.ts | 210 +++++++----------- ...yncFunction_NestedFunctionRightLocation.js | 24 ++ ...yncFunction_NestedFunctionRightLocation.ts | 24 ++ .../convertToAsyncFunction_NoRes4.js | 16 ++ .../convertToAsyncFunction_NoRes4.ts | 16 ++ 6 files changed, 176 insertions(+), 125 deletions(-) create mode 100644 tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_NestedFunctionRightLocation.js create mode 100644 tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_NestedFunctionRightLocation.ts create mode 100644 tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_NoRes4.js create mode 100644 tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_NoRes4.ts diff --git a/src/services/codefixes/convertToAsyncFunction.ts b/src/services/codefixes/convertToAsyncFunction.ts index 76cdf471466..944bb06505d 100644 --- a/src/services/codefixes/convertToAsyncFunction.ts +++ b/src/services/codefixes/convertToAsyncFunction.ts @@ -2,11 +2,13 @@ namespace ts.codefix { const fixId = "convertToAsyncFunction"; const errorCodes = [Diagnostics.This_may_be_converted_to_an_async_function.code]; + let codeActionSucceeded = true; registerCodeFix({ errorCodes, getCodeActions(context: CodeFixContext) { + codeActionSucceeded = true; const changes = textChanges.ChangeTracker.with(context, (t) => convertToAsyncFunction(t, context.sourceFile, context.span.start, context.program.getTypeChecker(), context)); - return [createCodeFixAction(fixId, changes, Diagnostics.Convert_to_async_function, fixId, Diagnostics.Convert_all_to_async_functions)]; + return codeActionSucceeded ? [createCodeFixAction(fixId, changes, Diagnostics.Convert_to_async_function, fixId, Diagnostics.Convert_all_to_async_functions)] : []; }, fixIds: [fixId], getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, err) => convertToAsyncFunction(changes, err.file, err.start, context.program.getTypeChecker(), context)), @@ -387,6 +389,10 @@ namespace ts.codefix { const hasArgName = argName && argName.identifier.text.length > 0; const shouldReturn = transformer.setOfExpressionsToReturn.get(getNodeId(parent).toString()); switch (func.kind) { + case SyntaxKind.NullKeyword: + case SyntaxKind.UndefinedKeyword: + // do not produce a transformed statement for a null or undefined argument + break; case SyntaxKind.Identifier: if (!hasArgName) break; @@ -443,6 +449,9 @@ namespace ts.codefix { return createNodeArray([createReturn(getSynthesizedDeepClone(funcBody) as Expression)]); } } + default: + // We've found a transformation body we don't know how to handle, so the refactoring should no-op to avoid deleting code. + codeActionSucceeded = false; break; } return createNodeArray([]); diff --git a/src/testRunner/unittests/convertToAsyncFunction.ts b/src/testRunner/unittests/convertToAsyncFunction.ts index 99788e1310e..9fac9e59e92 100644 --- a/src/testRunner/unittests/convertToAsyncFunction.ts +++ b/src/testRunner/unittests/convertToAsyncFunction.ts @@ -1,66 +1,8 @@ namespace ts { - interface Range { - pos: number; - end: number; - name: string; - } - - interface Test { - source: string; - ranges: Map; - } - - function getTest(source: string): Test { - const activeRanges: Range[] = []; - let text = ""; - let lastPos = 0; - let pos = 0; - const ranges = createMap(); - - while (pos < source.length) { - if (source.charCodeAt(pos) === CharacterCodes.openBracket && - (source.charCodeAt(pos + 1) === CharacterCodes.hash || source.charCodeAt(pos + 1) === CharacterCodes.$)) { - const saved = pos; - pos += 2; - const s = pos; - consumeIdentifier(); - const e = pos; - if (source.charCodeAt(pos) === CharacterCodes.bar) { - pos++; - text += source.substring(lastPos, saved); - const name = s === e - ? source.charCodeAt(saved + 1) === CharacterCodes.hash ? "selection" : "extracted" - : source.substring(s, e); - activeRanges.push({ name, pos: text.length, end: undefined! }); - lastPos = pos; - continue; - } - else { - pos = saved; - } - } - else if (source.charCodeAt(pos) === CharacterCodes.bar && source.charCodeAt(pos + 1) === CharacterCodes.closeBracket) { - text += source.substring(lastPos, pos); - activeRanges[activeRanges.length - 1].end = text.length; - const range = activeRanges.pop()!; - if (range.name in ranges) { - throw new Error(`Duplicate name of range ${range.name}`); - } - ranges.set(range.name, range); - pos += 2; - lastPos = pos; - continue; - } - pos++; - } - text += source.substring(lastPos, pos); - - function consumeIdentifier() { - while (isIdentifierPart(source.charCodeAt(pos), ScriptTarget.Latest)) { - pos++; - } - } - return { source: text, ranges }; + const enum TestExpectation { + Normal, + NoDiagnostic, + NoAction } const libFile: TestFSWithWatch.File = { @@ -319,19 +261,22 @@ interface String { charAt: any; } interface Array {}` }; - function testConvertToAsyncFunction(caption: string, text: string, baselineFolder: string, diagnosticDescription: DiagnosticMessage, codeFixDescription: DiagnosticMessage, includeLib?: boolean) { - const t = getTest(text); + function testConvertToAsyncFunction(caption: string, text: string, baselineFolder: string, includeLib?: boolean, expectedResult: TestExpectation = TestExpectation.Normal) { + const t = extractTest(text); const selectionRange = t.ranges.get("selection")!; if (!selectionRange) { throw new Error(`Test ${caption} does not specify selection range`); } - [Extension.Ts, Extension.Js].forEach(extension => + const extensions = expectedResult === TestExpectation.Normal ? [Extension.Ts, Extension.Js] : [Extension.Ts]; + + extensions.forEach(extension => it(`${caption} [${extension}]`, () => runBaseline(extension))); function runBaseline(extension: Extension) { const path = "/a" + extension; - const program = makeProgram({ path, content: t.source }, includeLib)!; + const languageService = makeLanguageService({ path, content: t.source }, includeLib); + const program = languageService.getProgram()!; if (hasSyntacticDiagnostics(program)) { // Don't bother generating JS baselines for inputs that aren't valid JS. @@ -345,10 +290,6 @@ interface Array {}` }; const sourceFile = program.getSourceFile(path)!; - const host = projectSystem.createServerHost([f, libFile]); - const projectService = projectSystem.createProjectService(host); - projectService.openClientFile(f.path); - const languageService = projectService.inferredProjects[0].getLanguageService(); const context: CodeFixContext = { errorCode: 80006, span: { start: selectionRange.pos, length: selectionRange.end - selectionRange.pos }, @@ -361,37 +302,45 @@ interface Array {}` }; const diagnostics = languageService.getSuggestionDiagnostics(f.path); - const diagnostic = find(diagnostics, diagnostic => diagnostic.messageText === diagnosticDescription.message); + const diagnostic = find(diagnostics, diagnostic => diagnostic.messageText === Diagnostics.This_may_be_converted_to_an_async_function.message && + diagnostic.start === context.span.start && diagnostic.length === context.span.length); + if (expectedResult === TestExpectation.NoDiagnostic) { + assert.isUndefined(diagnostic); + return; + } + assert.exists(diagnostic); - assert.equal(diagnostic!.start, context.span.start); - assert.equal(diagnostic!.length, context.span.length); const actions = codefix.getFixes(context); - const action = find(actions, action => action.description === codeFixDescription.message)!; + const action = find(actions, action => action.description === Diagnostics.Convert_to_async_function.message); + if (expectedResult === TestExpectation.NoAction) { + assert.isUndefined(action); + return; + } + assert.exists(action); const data: string[] = []; data.push(`// ==ORIGINAL==`); data.push(text.replace("[#|", "/*[#|*/").replace("|]", "/*|]*/")); - const changes = action.changes; + const changes = action!.changes; assert.lengthOf(changes, 1); - data.push(`// ==ASYNC FUNCTION::${action.description}==`); + data.push(`// ==ASYNC FUNCTION::${action!.description}==`); const newText = textChanges.applyChanges(sourceFile.text, changes[0].textChanges); data.push(newText); - const diagProgram = makeProgram({ path, content: newText }, includeLib)!; + const diagProgram = makeLanguageService({ path, content: newText }, includeLib).getProgram()!; assert.isFalse(hasSyntacticDiagnostics(diagProgram)); Harness.Baseline.runBaseline(`${baselineFolder}/${caption}${extension}`, data.join(newLineCharacter)); } - function makeProgram(f: { path: string, content: string }, includeLib?: boolean) { + function makeLanguageService(f: { path: string, content: string }, includeLib?: boolean) { const host = projectSystem.createServerHost(includeLib ? [f, libFile] : [f]); // libFile is expensive to parse repeatedly - only test when required const projectService = projectSystem.createProjectService(host); projectService.openClientFile(f.path); - const program = projectService.inferredProjects[0].getLanguageService().getProgram(); - return program; + return projectService.inferredProjects[0].getLanguageService(); } function hasSyntacticDiagnostics(program: Program) { @@ -400,27 +349,6 @@ interface Array {}` } } - function testConvertToAsyncFunctionFailed(caption: string, text: string, description: DiagnosticMessage) { - it(caption, () => { - const t = extractTest(text); - const selectionRange = t.ranges.get("selection"); - if (!selectionRange) { - throw new Error(`Test ${caption} does not specify selection range`); - } - const f = { - path: "/a.ts", - content: t.source - }; - const host = projectSystem.createServerHost([f, libFile]); - const projectService = projectSystem.createProjectService(host); - projectService.openClientFile(f.path); - const languageService = projectService.inferredProjects[0].getLanguageService(); - - const actions = languageService.getSuggestionDiagnostics(f.path); - assert.isUndefined(find(actions, action => action.messageText === description.message)); - }); - } - describe("convertToAsyncFunctions", () => { _testConvertToAsyncFunction("convertToAsyncFunction_basic", ` function [#|f|](): Promise{ @@ -547,7 +475,13 @@ function [#|f|]():Promise { } ` ); - _testConvertToAsyncFunctionFailed("convertToAsyncFunction_NoSuggestion", ` + _testConvertToAsyncFunction("convertToAsyncFunction_NoRes4", ` +function [#|f|]() { + return fetch('https://typescriptlang.org').then(undefined, rejection => console.log("rejected:", rejection)); +} +` + ); + _testConvertToAsyncFunctionNoDiagnostic("convertToAsyncFunction_NoSuggestion", ` function [#|f|]():Promise { return fetch('https://typescriptlang.org'); } @@ -561,7 +495,7 @@ function [#|f|]():Promise{ } ` ); - _testConvertToAsyncFunctionFailed("convertToAsyncFunction_NoSuggestionNoPromise", ` + _testConvertToAsyncFunctionNoDiagnostic("convertToAsyncFunction_NoSuggestionNoPromise", ` function [#|f|]():void{ } ` @@ -614,21 +548,21 @@ function [#|f|]():Promise { } ` ); - _testConvertToAsyncFunctionFailed("convertToAsyncFunction_Finally1", ` + _testConvertToAsyncFunctionNoDiagnostic("convertToAsyncFunction_Finally1", ` function [#|finallyTest|](): Promise { return fetch("https://typescriptlang.org").then(res => console.log(res)).catch(rej => console.log("error", rej)).finally(console.log("finally!")); } ` ); - _testConvertToAsyncFunctionFailed("convertToAsyncFunction_Finally2", ` + _testConvertToAsyncFunctionNoDiagnostic("convertToAsyncFunction_Finally2", ` function [#|finallyTest|](): Promise { return fetch("https://typescriptlang.org").then(res => console.log(res)).finally(console.log("finally!")); } ` ); - _testConvertToAsyncFunctionFailed("convertToAsyncFunction_Finally3", ` + _testConvertToAsyncFunctionNoDiagnostic("convertToAsyncFunction_Finally3", ` function [#|finallyTest|](): Promise { return fetch("https://typescriptlang.org").finally(console.log("finally!")); } @@ -656,14 +590,14 @@ function [#|innerPromise|](): Promise { ` ); - _testConvertToAsyncFunctionFailed("convertToAsyncFunction_VarReturn01", ` + _testConvertToAsyncFunctionNoDiagnostic("convertToAsyncFunction_VarReturn01", ` function [#|f|]() { let blob = fetch("https://typescriptlang.org").then(resp => console.log(resp)); return blob; } ` ); - _testConvertToAsyncFunctionFailed("convertToAsyncFunction_VarReturn02", ` + _testConvertToAsyncFunctionNoDiagnostic("convertToAsyncFunction_VarReturn02", ` function [#|f|]() { let blob = fetch("https://typescriptlang.org"); blob.then(resp => console.log(resp)); @@ -671,7 +605,7 @@ function [#|f|]() { } ` ); - _testConvertToAsyncFunctionFailed("convertToAsyncFunction_VarReturn03", ` + _testConvertToAsyncFunctionNoDiagnostic("convertToAsyncFunction_VarReturn03", ` function [#|f|]() { let blob = fetch("https://typescriptlang.org") let blob2 = blob.then(resp => console.log(resp)); @@ -684,7 +618,7 @@ function err (rej) { } ` ); - _testConvertToAsyncFunctionFailed("convertToAsyncFunction_VarReturn04", ` + _testConvertToAsyncFunctionNoDiagnostic("convertToAsyncFunction_VarReturn04", ` function [#|f|]() { var blob = fetch("https://typescriptlang.org").then(res => console.log(res)), blob2 = fetch("https://microsoft.com").then(res => res.ok).catch(err); return blob; @@ -695,7 +629,7 @@ function err (rej) { ` ); - _testConvertToAsyncFunctionFailed("convertToAsyncFunction_VarReturn05", ` + _testConvertToAsyncFunctionNoDiagnostic("convertToAsyncFunction_VarReturn05", ` function [#|f|]() { var blob = fetch("https://typescriptlang.org").then(res => console.log(res)); blob.then(x => x); @@ -704,7 +638,7 @@ function [#|f|]() { ` ); - _testConvertToAsyncFunctionFailed("convertToAsyncFunction_VarReturn06", ` + _testConvertToAsyncFunctionNoDiagnostic("convertToAsyncFunction_VarReturn06", ` function [#|f|]() { var blob = fetch("https://typescriptlang.org"); return blob; @@ -712,7 +646,7 @@ function [#|f|]() { ` ); - _testConvertToAsyncFunctionFailed("convertToAsyncFunction_VarReturn07", ` + _testConvertToAsyncFunctionNoDiagnostic("convertToAsyncFunction_VarReturn07", ` function [#|f|]() { let blob = fetch("https://typescriptlang.org"); let blob2 = fetch("https://microsoft.com"); @@ -723,7 +657,7 @@ function [#|f|]() { ` ); - _testConvertToAsyncFunctionFailed("convertToAsyncFunction_VarReturn08", ` + _testConvertToAsyncFunctionNoDiagnostic("convertToAsyncFunction_VarReturn08", ` function [#|f|]() { let blob = fetch("https://typescriptlang.org"); if (!blob.ok){ @@ -735,7 +669,7 @@ function [#|f|]() { ` ); - _testConvertToAsyncFunctionFailed("convertToAsyncFunction_VarReturn09", ` + _testConvertToAsyncFunctionNoDiagnostic("convertToAsyncFunction_VarReturn09", ` function [#|f|]() { let blob3; let blob = fetch("https://typescriptlang.org"); @@ -749,7 +683,7 @@ function [#|f|]() { ); - _testConvertToAsyncFunctionFailed("convertToAsyncFunction_VarReturn10", ` + _testConvertToAsyncFunctionNoDiagnostic("convertToAsyncFunction_VarReturn10", ` function [#|f|]() { let blob3; let blob = fetch("https://typescriptlang.org"); @@ -763,7 +697,7 @@ function [#|f|]() { ` ); - _testConvertToAsyncFunctionFailed("convertToAsyncFunction_VarReturn11", ` + _testConvertToAsyncFunctionNoDiagnostic("convertToAsyncFunction_VarReturn11", ` function [#|f|]() { let blob; return blob; @@ -773,7 +707,7 @@ function [#|f|]() { - _testConvertToAsyncFunctionFailed("convertToAsyncFunction_Param1", ` + _testConvertToAsyncFunctionNoDiagnostic("convertToAsyncFunction_Param1", ` function [#|f|]() { return my_print(fetch("https://typescriptlang.org").then(res => console.log(res))); } @@ -830,7 +764,7 @@ function [#|f|](): Promise { ); - _testConvertToAsyncFunctionFailed("convertToAsyncFunction_SeperateLines", ` + _testConvertToAsyncFunctionNoDiagnostic("convertToAsyncFunction_SeperateLines", ` function [#|f|](): Promise { var blob = fetch("https://typescriptlang.org") blob.then(resp => { @@ -1093,7 +1027,7 @@ function [#|f|]() { } `); -_testConvertToAsyncFunctionFailed("convertToAsyncFunction_CatchFollowedByCall", ` +_testConvertToAsyncFunctionNoDiagnostic("convertToAsyncFunction_CatchFollowedByCall", ` function [#|f|](){ return fetch("https://typescriptlang.org").then(res).catch(rej).toString(); } @@ -1157,7 +1091,7 @@ function [#|f|]() { ` ); - _testConvertToAsyncFunctionFailed("convertToAsyncFunction_NestedFunction", ` + _testConvertToAsyncFunctionNoDiagnostic("convertToAsyncFunction_NestedFunctionWrongLocation", ` function [#|f|]() { function fn2(){ function fn3(){ @@ -1167,6 +1101,18 @@ function [#|f|]() { } return fn2(); } +`); + + _testConvertToAsyncFunction("convertToAsyncFunction_NestedFunctionRightLocation", ` +function f() { + function fn2(){ + function [#|fn3|](){ + return fetch("https://typescriptlang.org").then(res => console.log(res)); + } + return fn3(); + } + return fn2(); +} `); _testConvertToAsyncFunction("convertToAsyncFunction_UntypedFunction", ` @@ -1194,14 +1140,30 @@ const [#|foo|] = function () { } `); + _testConvertToAsyncFunctionNoAction("convertToAsyncFunction_thenArgumentNotFunction", ` +function [#|f|]() { + return Promise.resolve().then(f ? (x => x) : (y => y)); +} +`); + +_testConvertToAsyncFunctionNoAction("convertToAsyncFunction_thenArgumentNotFunctionNotLastInChain", ` +function [#|f|]() { + return Promise.resolve().then(f ? (x => x) : (y => y)).then(q => q); +} +`); + }); function _testConvertToAsyncFunction(caption: string, text: string) { - testConvertToAsyncFunction(caption, text, "convertToAsyncFunction", Diagnostics.This_may_be_converted_to_an_async_function, Diagnostics.Convert_to_async_function, /*includeLib*/ true); + testConvertToAsyncFunction(caption, text, "convertToAsyncFunction", /*includeLib*/ true); } - function _testConvertToAsyncFunctionFailed(caption: string, text: string) { - testConvertToAsyncFunctionFailed(caption, text, Diagnostics.Convert_to_async_function); + function _testConvertToAsyncFunctionNoDiagnostic(caption: string, text: string) { + testConvertToAsyncFunction(caption, text, "convertToAsyncFunction", /*includeLib*/ true, TestExpectation.NoDiagnostic); + } + + function _testConvertToAsyncFunctionNoAction(caption: string, text: string) { + testConvertToAsyncFunction(caption, text, "convertToAsyncFunction", /*includeLib*/ true, TestExpectation.NoAction); } } \ No newline at end of file diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_NestedFunctionRightLocation.js b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_NestedFunctionRightLocation.js new file mode 100644 index 00000000000..fa55fb8ca22 --- /dev/null +++ b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_NestedFunctionRightLocation.js @@ -0,0 +1,24 @@ +// ==ORIGINAL== + +function f() { + function fn2(){ + function /*[#|*/fn3/*|]*/(){ + return fetch("https://typescriptlang.org").then(res => console.log(res)); + } + return fn3(); + } + return fn2(); +} + +// ==ASYNC FUNCTION::Convert to async function== + +function f() { + function fn2(){ + async function fn3(){ + const res = await fetch("https://typescriptlang.org"); + return console.log(res); + } + return fn3(); + } + return fn2(); +} diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_NestedFunctionRightLocation.ts b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_NestedFunctionRightLocation.ts new file mode 100644 index 00000000000..fa55fb8ca22 --- /dev/null +++ b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_NestedFunctionRightLocation.ts @@ -0,0 +1,24 @@ +// ==ORIGINAL== + +function f() { + function fn2(){ + function /*[#|*/fn3/*|]*/(){ + return fetch("https://typescriptlang.org").then(res => console.log(res)); + } + return fn3(); + } + return fn2(); +} + +// ==ASYNC FUNCTION::Convert to async function== + +function f() { + function fn2(){ + async function fn3(){ + const res = await fetch("https://typescriptlang.org"); + return console.log(res); + } + return fn3(); + } + return fn2(); +} diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_NoRes4.js b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_NoRes4.js new file mode 100644 index 00000000000..2bbf32e46a6 --- /dev/null +++ b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_NoRes4.js @@ -0,0 +1,16 @@ +// ==ORIGINAL== + +function /*[#|*/f/*|]*/() { + return fetch('https://typescriptlang.org').then(undefined, rejection => console.log("rejected:", rejection)); +} + +// ==ASYNC FUNCTION::Convert to async function== + +async function f() { + try { + await fetch('https://typescriptlang.org'); + } + catch (rejection) { + return console.log("rejected:", rejection); + } +} diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_NoRes4.ts b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_NoRes4.ts new file mode 100644 index 00000000000..2bbf32e46a6 --- /dev/null +++ b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_NoRes4.ts @@ -0,0 +1,16 @@ +// ==ORIGINAL== + +function /*[#|*/f/*|]*/() { + return fetch('https://typescriptlang.org').then(undefined, rejection => console.log("rejected:", rejection)); +} + +// ==ASYNC FUNCTION::Convert to async function== + +async function f() { + try { + await fetch('https://typescriptlang.org'); + } + catch (rejection) { + return console.log("rejected:", rejection); + } +} From f7f5b1ac87e88ba3a3b809de606b2eaf269e7136 Mon Sep 17 00:00:00 2001 From: Benjamin Lichtman Date: Wed, 5 Sep 2018 16:28:53 -0700 Subject: [PATCH 04/83] Don't case on type node --- src/services/codefixes/convertToAsyncFunction.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/services/codefixes/convertToAsyncFunction.ts b/src/services/codefixes/convertToAsyncFunction.ts index 944bb06505d..61e142a8a08 100644 --- a/src/services/codefixes/convertToAsyncFunction.ts +++ b/src/services/codefixes/convertToAsyncFunction.ts @@ -390,7 +390,6 @@ namespace ts.codefix { const shouldReturn = transformer.setOfExpressionsToReturn.get(getNodeId(parent).toString()); switch (func.kind) { case SyntaxKind.NullKeyword: - case SyntaxKind.UndefinedKeyword: // do not produce a transformed statement for a null or undefined argument break; case SyntaxKind.Identifier: From ea984d7b64fc7b57d643ffc2792eac01baccddc2 Mon Sep 17 00:00:00 2001 From: christian Date: Wed, 5 Sep 2018 23:18:39 -0400 Subject: [PATCH 05/83] Centralize diagnostic reporting for empty files diagnostic --- src/compiler/commandLineParser.ts | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 5d87525073f..a2dac4e7d33 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -1846,7 +1846,7 @@ namespace ts { const hasReferences = hasProperty(raw, "references") && !isNullOrUndefined(raw.references); const hasZeroOrNoReferences = !hasReferences || raw.references.length === 0; if (filesSpecs.length === 0 && hasZeroOrNoReferences) { - createCompilerDiagnosticOnlyIfJson(Diagnostics.The_files_list_in_config_file_0_is_empty, configFileName || "tsconfig.json"); + errors.push(createCompilerDiagnostic(Diagnostics.The_files_list_in_config_file_0_is_empty, configFileName || "tsconfig.json")); } } else { @@ -2078,12 +2078,6 @@ namespace ts { } }; const json = convertToObjectWorker(sourceFile, errors, /*returnValue*/ true, getTsconfigRootOptionsMap(), optionsIterator); - const hasZeroFiles = json && json.files && json.files.length === 0; - const hasZeroOrNoReferences = !(json && json.references) || json.references.length === 0; - - if (hasZeroFiles && hasZeroOrNoReferences) { - errors.push(createCompilerDiagnostic(Diagnostics.The_files_list_in_config_file_0_is_empty, sourceFile.fileName)); - } if (!typeAcquisition) { if (typingOptionstypeAcquisition) { From ec72f4751d0986690440dad7be2d6b8d86a65da9 Mon Sep 17 00:00:00 2001 From: christian Date: Thu, 6 Sep 2018 20:40:02 -0400 Subject: [PATCH 06/83] Add location info to empty lists diagnostics when tsconfig file exists --- src/compiler/commandLineParser.ts | 9 ++++++++- src/testRunner/unittests/tsconfigParsing.ts | 6 ++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index a2dac4e7d33..ecc69fccf86 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -1846,7 +1846,14 @@ namespace ts { const hasReferences = hasProperty(raw, "references") && !isNullOrUndefined(raw.references); const hasZeroOrNoReferences = !hasReferences || raw.references.length === 0; if (filesSpecs.length === 0 && hasZeroOrNoReferences) { - errors.push(createCompilerDiagnostic(Diagnostics.The_files_list_in_config_file_0_is_empty, configFileName || "tsconfig.json")); + if (sourceFile) { + const nodeValue = firstDefined(getTsConfigPropArray(sourceFile, "files"), property => property.initializer); + const error = createDiagnosticForNodeInSourceFile(sourceFile, nodeValue!, Diagnostics.The_files_list_in_config_file_0_is_empty, configFileName || "tsconfig.json"); + errors.push(error); + } + else { + createCompilerDiagnosticOnlyIfJson(Diagnostics.The_files_list_in_config_file_0_is_empty, configFileName || "tsconfig.json"); + } } } else { diff --git a/src/testRunner/unittests/tsconfigParsing.ts b/src/testRunner/unittests/tsconfigParsing.ts index c2e8f0eb10d..6909e260d2a 100644 --- a/src/testRunner/unittests/tsconfigParsing.ts +++ b/src/testRunner/unittests/tsconfigParsing.ts @@ -290,8 +290,7 @@ namespace ts { "/apath/tsconfig.json", "tests/cases/unittests", ["/apath/a.ts"], - Diagnostics.The_files_list_in_config_file_0_is_empty.code, - /*noLocation*/ true); + Diagnostics.The_files_list_in_config_file_0_is_empty.code); }); it("generates errors for empty files list when no references are provided", () => { @@ -303,8 +302,7 @@ namespace ts { "/apath/tsconfig.json", "tests/cases/unittests", ["/apath/a.ts"], - Diagnostics.The_files_list_in_config_file_0_is_empty.code, - /*noLocation*/ true); + Diagnostics.The_files_list_in_config_file_0_is_empty.code); }); it("does not generate errors for empty files list when one or more references are provided", () => { From 95d57885c5efd05d3cb35fb8f7816a98bf56f1c6 Mon Sep 17 00:00:00 2001 From: Benjamin Lichtman Date: Fri, 7 Sep 2018 14:14:01 -0700 Subject: [PATCH 07/83] Ensure diagnostic reporting matches code fix ability --- .../codefixes/convertToAsyncFunction.ts | 11 +-- src/services/suggestionDiagnostics.ts | 39 +++++++++- src/services/utilities.ts | 8 ++ .../unittests/convertToAsyncFunction.ts | 76 ++++++++----------- 4 files changed, 79 insertions(+), 55 deletions(-) diff --git a/src/services/codefixes/convertToAsyncFunction.ts b/src/services/codefixes/convertToAsyncFunction.ts index 61e142a8a08..ba230aa95e4 100644 --- a/src/services/codefixes/convertToAsyncFunction.ts +++ b/src/services/codefixes/convertToAsyncFunction.ts @@ -254,6 +254,7 @@ namespace ts.codefix { } // dispatch function to recursively build the refactoring + // should be kept up to date with isFixablePromiseHandler in suggestionDiagnostics.ts function transformExpression(node: Expression, transformer: Transformer, outermostParent: CallExpression, prevArgName?: SynthIdentifier): Statement[] { if (!node) { return []; @@ -275,6 +276,7 @@ namespace ts.codefix { return transformPromiseCall(node, transformer, prevArgName); } + codeActionSucceeded = false; return []; } @@ -383,6 +385,7 @@ namespace ts.codefix { (createVariableDeclarationList([createVariableDeclaration(getSynthesizedDeepClone(prevArgName.identifier), /*type*/ undefined, rightHandSide)], getFlagOfIdentifier(prevArgName.identifier, transformer.constIdentifiers))))]); } + // should be kept up to date with isFixablePromiseArgument in suggestionDiagnostics.ts function getTransformationBody(func: Node, prevArgName: SynthIdentifier | undefined, argName: SynthIdentifier, parent: CallExpression, transformer: Transformer): NodeArray { const hasPrevArgName = prevArgName && prevArgName.identifier.text.length > 0; @@ -500,14 +503,6 @@ namespace ts.codefix { return innerCbBody; } - function hasPropertyAccessExpressionWithName(node: CallExpression, funcName: string): boolean { - if (!isPropertyAccessExpression(node.expression)) { - return false; - } - - return node.expression.name.text === funcName; - } - function getArgName(funcNode: Node, transformer: Transformer): SynthIdentifier { const numberOfAssignmentsOriginal = 0; diff --git a/src/services/suggestionDiagnostics.ts b/src/services/suggestionDiagnostics.ts index 167bcb6bbac..3df40c8d9df 100644 --- a/src/services/suggestionDiagnostics.ts +++ b/src/services/suggestionDiagnostics.ts @@ -160,7 +160,7 @@ namespace ts { } function addHandlers(returnChild: Node) { - if (isPromiseHandler(returnChild)) { + if (isFixablePromiseHandler(returnChild)) { returnStatements.push(child as ReturnStatement); } } @@ -170,8 +170,39 @@ namespace ts { return returnStatements; } - function isPromiseHandler(node: Node): boolean { - return (isCallExpression(node) && isPropertyAccessExpression(node.expression) && - (node.expression.name.text === "then" || node.expression.name.text === "catch")); + // Should be kept up to date with transformExpression in convertToAsyncFunction.ts + function isFixablePromiseHandler(node: Node): boolean { + // ensure outermost call exists and is a promise handler + if (!isPromiseHandler(node) || !node.arguments.every(isFixablePromiseArgument)) { + return false; + } + + // ensure all chained calls are valid + let currentNode = node.expression; + while (isPromiseHandler(currentNode) || isPropertyAccessExpression(currentNode)) { + if (isCallExpression(currentNode) && !currentNode.arguments.every(isFixablePromiseArgument)) { + return false; + } + currentNode = currentNode.expression; + } + return true; + } + + function isPromiseHandler(node: Node): node is CallExpression { + return isCallExpression(node) && (hasPropertyAccessExpressionWithName(node, "then") || hasPropertyAccessExpressionWithName(node, "catch")); + } + + // should be kept up to date with getTransformationBody in convertToAsyncFunction.ts + function isFixablePromiseArgument(arg: Expression): boolean { + switch (arg.kind) { + case SyntaxKind.NullKeyword: + case SyntaxKind.Identifier: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionExpression: + case SyntaxKind.ArrowFunction: + return true; + default: + return false; + } } } diff --git a/src/services/utilities.ts b/src/services/utilities.ts index b8a235bbeb4..19bc029e855 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -224,6 +224,14 @@ namespace ts { return undefined; } + export function hasPropertyAccessExpressionWithName(node: CallExpression, funcName: string): boolean { + if (!isPropertyAccessExpression(node.expression)) { + return false; + } + + return node.expression.name.text === funcName; + } + export function isJumpStatementTarget(node: Node): node is Identifier & { parent: BreakOrContinueStatement } { return node.kind === SyntaxKind.Identifier && isBreakOrContinueStatement(node.parent) && node.parent.label === node; } diff --git a/src/testRunner/unittests/convertToAsyncFunction.ts b/src/testRunner/unittests/convertToAsyncFunction.ts index 9fac9e59e92..9f675f1c89a 100644 --- a/src/testRunner/unittests/convertToAsyncFunction.ts +++ b/src/testRunner/unittests/convertToAsyncFunction.ts @@ -1,10 +1,4 @@ namespace ts { - const enum TestExpectation { - Normal, - NoDiagnostic, - NoAction - } - const libFile: TestFSWithWatch.File = { path: "/a/lib/lib.d.ts", content: `/// @@ -261,14 +255,14 @@ interface String { charAt: any; } interface Array {}` }; - function testConvertToAsyncFunction(caption: string, text: string, baselineFolder: string, includeLib?: boolean, expectedResult: TestExpectation = TestExpectation.Normal) { + function testConvertToAsyncFunction(caption: string, text: string, baselineFolder: string, includeLib?: boolean, expectFailure = false) { const t = extractTest(text); const selectionRange = t.ranges.get("selection")!; if (!selectionRange) { throw new Error(`Test ${caption} does not specify selection range`); } - const extensions = expectedResult === TestExpectation.Normal ? [Extension.Ts, Extension.Js] : [Extension.Ts]; + const extensions = expectFailure ? [Extension.Ts] : [Extension.Ts, Extension.Js]; extensions.forEach(extension => it(`${caption} [${extension}]`, () => runBaseline(extension))); @@ -304,21 +298,21 @@ interface Array {}` const diagnostics = languageService.getSuggestionDiagnostics(f.path); const diagnostic = find(diagnostics, diagnostic => diagnostic.messageText === Diagnostics.This_may_be_converted_to_an_async_function.message && diagnostic.start === context.span.start && diagnostic.length === context.span.length); - if (expectedResult === TestExpectation.NoDiagnostic) { + if (expectFailure) { assert.isUndefined(diagnostic); - return; } - - assert.exists(diagnostic); + else { + assert.exists(diagnostic); + } const actions = codefix.getFixes(context); const action = find(actions, action => action.description === Diagnostics.Convert_to_async_function.message); - if (expectedResult === TestExpectation.NoAction) { - assert.isUndefined(action); + if (expectFailure) { + assert.isNotTrue(action && action.changes.length > 0); return; } - assert.exists(action); + assert.isTrue(action && action.changes.length > 0); const data: string[] = []; data.push(`// ==ORIGINAL==`); @@ -481,7 +475,7 @@ function [#|f|]() { } ` ); - _testConvertToAsyncFunctionNoDiagnostic("convertToAsyncFunction_NoSuggestion", ` + _testConvertToAsyncFunctionFailed("convertToAsyncFunction_NoSuggestion", ` function [#|f|]():Promise { return fetch('https://typescriptlang.org'); } @@ -495,7 +489,7 @@ function [#|f|]():Promise{ } ` ); - _testConvertToAsyncFunctionNoDiagnostic("convertToAsyncFunction_NoSuggestionNoPromise", ` + _testConvertToAsyncFunctionFailed("convertToAsyncFunction_NoSuggestionNoPromise", ` function [#|f|]():void{ } ` @@ -548,21 +542,21 @@ function [#|f|]():Promise { } ` ); - _testConvertToAsyncFunctionNoDiagnostic("convertToAsyncFunction_Finally1", ` + _testConvertToAsyncFunctionFailed("convertToAsyncFunction_Finally1", ` function [#|finallyTest|](): Promise { return fetch("https://typescriptlang.org").then(res => console.log(res)).catch(rej => console.log("error", rej)).finally(console.log("finally!")); } ` ); - _testConvertToAsyncFunctionNoDiagnostic("convertToAsyncFunction_Finally2", ` + _testConvertToAsyncFunctionFailed("convertToAsyncFunction_Finally2", ` function [#|finallyTest|](): Promise { return fetch("https://typescriptlang.org").then(res => console.log(res)).finally(console.log("finally!")); } ` ); - _testConvertToAsyncFunctionNoDiagnostic("convertToAsyncFunction_Finally3", ` + _testConvertToAsyncFunctionFailed("convertToAsyncFunction_Finally3", ` function [#|finallyTest|](): Promise { return fetch("https://typescriptlang.org").finally(console.log("finally!")); } @@ -590,14 +584,14 @@ function [#|innerPromise|](): Promise { ` ); - _testConvertToAsyncFunctionNoDiagnostic("convertToAsyncFunction_VarReturn01", ` + _testConvertToAsyncFunctionFailed("convertToAsyncFunction_VarReturn01", ` function [#|f|]() { let blob = fetch("https://typescriptlang.org").then(resp => console.log(resp)); return blob; } ` ); - _testConvertToAsyncFunctionNoDiagnostic("convertToAsyncFunction_VarReturn02", ` + _testConvertToAsyncFunctionFailed("convertToAsyncFunction_VarReturn02", ` function [#|f|]() { let blob = fetch("https://typescriptlang.org"); blob.then(resp => console.log(resp)); @@ -605,7 +599,7 @@ function [#|f|]() { } ` ); - _testConvertToAsyncFunctionNoDiagnostic("convertToAsyncFunction_VarReturn03", ` + _testConvertToAsyncFunctionFailed("convertToAsyncFunction_VarReturn03", ` function [#|f|]() { let blob = fetch("https://typescriptlang.org") let blob2 = blob.then(resp => console.log(resp)); @@ -618,7 +612,7 @@ function err (rej) { } ` ); - _testConvertToAsyncFunctionNoDiagnostic("convertToAsyncFunction_VarReturn04", ` + _testConvertToAsyncFunctionFailed("convertToAsyncFunction_VarReturn04", ` function [#|f|]() { var blob = fetch("https://typescriptlang.org").then(res => console.log(res)), blob2 = fetch("https://microsoft.com").then(res => res.ok).catch(err); return blob; @@ -629,7 +623,7 @@ function err (rej) { ` ); - _testConvertToAsyncFunctionNoDiagnostic("convertToAsyncFunction_VarReturn05", ` + _testConvertToAsyncFunctionFailed("convertToAsyncFunction_VarReturn05", ` function [#|f|]() { var blob = fetch("https://typescriptlang.org").then(res => console.log(res)); blob.then(x => x); @@ -638,7 +632,7 @@ function [#|f|]() { ` ); - _testConvertToAsyncFunctionNoDiagnostic("convertToAsyncFunction_VarReturn06", ` + _testConvertToAsyncFunctionFailed("convertToAsyncFunction_VarReturn06", ` function [#|f|]() { var blob = fetch("https://typescriptlang.org"); return blob; @@ -646,7 +640,7 @@ function [#|f|]() { ` ); - _testConvertToAsyncFunctionNoDiagnostic("convertToAsyncFunction_VarReturn07", ` + _testConvertToAsyncFunctionFailed("convertToAsyncFunction_VarReturn07", ` function [#|f|]() { let blob = fetch("https://typescriptlang.org"); let blob2 = fetch("https://microsoft.com"); @@ -657,7 +651,7 @@ function [#|f|]() { ` ); - _testConvertToAsyncFunctionNoDiagnostic("convertToAsyncFunction_VarReturn08", ` + _testConvertToAsyncFunctionFailed("convertToAsyncFunction_VarReturn08", ` function [#|f|]() { let blob = fetch("https://typescriptlang.org"); if (!blob.ok){ @@ -669,7 +663,7 @@ function [#|f|]() { ` ); - _testConvertToAsyncFunctionNoDiagnostic("convertToAsyncFunction_VarReturn09", ` + _testConvertToAsyncFunctionFailed("convertToAsyncFunction_VarReturn09", ` function [#|f|]() { let blob3; let blob = fetch("https://typescriptlang.org"); @@ -683,7 +677,7 @@ function [#|f|]() { ); - _testConvertToAsyncFunctionNoDiagnostic("convertToAsyncFunction_VarReturn10", ` + _testConvertToAsyncFunctionFailed("convertToAsyncFunction_VarReturn10", ` function [#|f|]() { let blob3; let blob = fetch("https://typescriptlang.org"); @@ -697,7 +691,7 @@ function [#|f|]() { ` ); - _testConvertToAsyncFunctionNoDiagnostic("convertToAsyncFunction_VarReturn11", ` + _testConvertToAsyncFunctionFailed("convertToAsyncFunction_VarReturn11", ` function [#|f|]() { let blob; return blob; @@ -707,7 +701,7 @@ function [#|f|]() { - _testConvertToAsyncFunctionNoDiagnostic("convertToAsyncFunction_Param1", ` + _testConvertToAsyncFunctionFailed("convertToAsyncFunction_Param1", ` function [#|f|]() { return my_print(fetch("https://typescriptlang.org").then(res => console.log(res))); } @@ -764,7 +758,7 @@ function [#|f|](): Promise { ); - _testConvertToAsyncFunctionNoDiagnostic("convertToAsyncFunction_SeperateLines", ` + _testConvertToAsyncFunctionFailed("convertToAsyncFunction_SeperateLines", ` function [#|f|](): Promise { var blob = fetch("https://typescriptlang.org") blob.then(resp => { @@ -1027,7 +1021,7 @@ function [#|f|]() { } `); -_testConvertToAsyncFunctionNoDiagnostic("convertToAsyncFunction_CatchFollowedByCall", ` +_testConvertToAsyncFunctionFailed("convertToAsyncFunction_CatchFollowedByCall", ` function [#|f|](){ return fetch("https://typescriptlang.org").then(res).catch(rej).toString(); } @@ -1091,7 +1085,7 @@ function [#|f|]() { ` ); - _testConvertToAsyncFunctionNoDiagnostic("convertToAsyncFunction_NestedFunctionWrongLocation", ` + _testConvertToAsyncFunctionFailed("convertToAsyncFunction_NestedFunctionWrongLocation", ` function [#|f|]() { function fn2(){ function fn3(){ @@ -1140,13 +1134,13 @@ const [#|foo|] = function () { } `); - _testConvertToAsyncFunctionNoAction("convertToAsyncFunction_thenArgumentNotFunction", ` + _testConvertToAsyncFunctionFailed("convertToAsyncFunction_thenArgumentNotFunction", ` function [#|f|]() { return Promise.resolve().then(f ? (x => x) : (y => y)); } `); -_testConvertToAsyncFunctionNoAction("convertToAsyncFunction_thenArgumentNotFunctionNotLastInChain", ` + _testConvertToAsyncFunctionFailed("convertToAsyncFunction_thenArgumentNotFunctionNotLastInChain", ` function [#|f|]() { return Promise.resolve().then(f ? (x => x) : (y => y)).then(q => q); } @@ -1159,11 +1153,7 @@ function [#|f|]() { testConvertToAsyncFunction(caption, text, "convertToAsyncFunction", /*includeLib*/ true); } - function _testConvertToAsyncFunctionNoDiagnostic(caption: string, text: string) { - testConvertToAsyncFunction(caption, text, "convertToAsyncFunction", /*includeLib*/ true, TestExpectation.NoDiagnostic); - } - - function _testConvertToAsyncFunctionNoAction(caption: string, text: string) { - testConvertToAsyncFunction(caption, text, "convertToAsyncFunction", /*includeLib*/ true, TestExpectation.NoAction); + function _testConvertToAsyncFunctionFailed(caption: string, text: string) { + testConvertToAsyncFunction(caption, text, "convertToAsyncFunction", /*includeLib*/ true, /*expectFailure*/ true); } } \ No newline at end of file From 16477b65067d7e4b3d71eeb1300ae03d7723fe2d Mon Sep 17 00:00:00 2001 From: christian Date: Sat, 8 Sep 2018 00:06:07 -0400 Subject: [PATCH 08/83] Take into account undefined nodeValue when recording diagnostic --- src/compiler/commandLineParser.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index ecc69fccf86..edee847019a 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -1847,8 +1847,12 @@ namespace ts { const hasZeroOrNoReferences = !hasReferences || raw.references.length === 0; if (filesSpecs.length === 0 && hasZeroOrNoReferences) { if (sourceFile) { + const fileName = configFileName || "tsconfig.json"; + const diagnosticMessage = Diagnostics.The_files_list_in_config_file_0_is_empty; const nodeValue = firstDefined(getTsConfigPropArray(sourceFile, "files"), property => property.initializer); - const error = createDiagnosticForNodeInSourceFile(sourceFile, nodeValue!, Diagnostics.The_files_list_in_config_file_0_is_empty, configFileName || "tsconfig.json"); + const error = nodeValue + ? createDiagnosticForNodeInSourceFile(sourceFile, nodeValue, diagnosticMessage, fileName) + : createCompilerDiagnostic(diagnosticMessage, fileName); errors.push(error); } else { From 745f5be2cbf0bda18310ad14ad68974b42d9b9e4 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Sat, 8 Sep 2018 13:12:09 -0700 Subject: [PATCH 09/83] Invert gutter instead of setting colors Fixes #26850 --- src/compiler/program.ts | 2 +- .../deeplyNestedAssignabilityIssue.errors.txt | 16 +++--- ...uplicateIdentifierRelatedSpans1.errors.txt | 56 +++++++++---------- ...uplicateIdentifierRelatedSpans2.errors.txt | 16 +++--- ...uplicateIdentifierRelatedSpans3.errors.txt | 48 ++++++++-------- ...uplicateIdentifierRelatedSpans4.errors.txt | 16 +++--- ...uplicateIdentifierRelatedSpans5.errors.txt | 48 ++++++++-------- ...uplicateIdentifierRelatedSpans6.errors.txt | 48 ++++++++-------- ...uplicateIdentifierRelatedSpans7.errors.txt | 16 +++--- ...opPrettyErrorRelatedInformation.errors.txt | 8 +-- ...LineContextDiagnosticWithPretty.errors.txt | 12 ++-- .../prettyContextNotDebugAssertion.errors.txt | 4 +- .../reference/typedefCrossModule5.errors.txt | 32 +++++------ 13 files changed, 161 insertions(+), 161 deletions(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index c97f1a61d27..c24f570819e 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -250,7 +250,7 @@ namespace ts { Blue = "\u001b[94m", Cyan = "\u001b[96m" } - const gutterStyleSequence = "\u001b[30;47m"; + const gutterStyleSequence = "\u001b[7m"; const gutterSeparator = " "; const resetEscapeSequence = "\u001b[0m"; const ellipsis = "..."; diff --git a/tests/baselines/reference/deeplyNestedAssignabilityIssue.errors.txt b/tests/baselines/reference/deeplyNestedAssignabilityIssue.errors.txt index cf243a1e5bd..772d1e4f5a3 100644 --- a/tests/baselines/reference/deeplyNestedAssignabilityIssue.errors.txt +++ b/tests/baselines/reference/deeplyNestedAssignabilityIssue.errors.txt @@ -1,22 +1,22 @@ tests/cases/compiler/deeplyNestedAssignabilityIssue.ts:22:17 - error TS2322: Type '{}' is not assignable to type 'A'. Property 'a' is missing in type '{}'. -22 thing: {} -   ~~~~~ +22 thing: {} +   ~~~~~ tests/cases/compiler/deeplyNestedAssignabilityIssue.ts:9:17 - 9 thing: A; -    ~~~~~ + 9 thing: A; +    ~~~~~ The expected type comes from property 'thing' which is declared here on type '{ thing: A; }' tests/cases/compiler/deeplyNestedAssignabilityIssue.ts:25:17 - error TS2322: Type '{}' is not assignable to type 'A'. Property 'a' is missing in type '{}'. -25 another: {} -   ~~~~~~~ +25 another: {} +   ~~~~~~~ tests/cases/compiler/deeplyNestedAssignabilityIssue.ts:12:17 - 12 another: A; -    ~~~~~~~ + 12 another: A; +    ~~~~~~~ The expected type comes from property 'another' which is declared here on type '{ another: A; }' diff --git a/tests/baselines/reference/duplicateIdentifierRelatedSpans1.errors.txt b/tests/baselines/reference/duplicateIdentifierRelatedSpans1.errors.txt index 62b4774f4f7..9a963614b61 100644 --- a/tests/baselines/reference/duplicateIdentifierRelatedSpans1.errors.txt +++ b/tests/baselines/reference/duplicateIdentifierRelatedSpans1.errors.txt @@ -1,64 +1,64 @@ tests/cases/compiler/file1.ts:1:7 - error TS2300: Duplicate identifier 'Foo'. -1 class Foo { } -   ~~~ +1 class Foo { } +   ~~~ tests/cases/compiler/file2.ts:1:6 - 1 type Foo = number; -    ~~~ + 1 type Foo = number; +    ~~~ 'Foo' was also declared here. tests/cases/compiler/file3.ts:1:6 - 1 type Foo = 54; -    ~~~ + 1 type Foo = 54; +    ~~~ and here. tests/cases/compiler/file1.ts:2:7 - error TS2451: Cannot redeclare block-scoped variable 'Bar'. -2 const Bar = 3; -   ~~~ +2 const Bar = 3; +   ~~~ tests/cases/compiler/file2.ts:2:7 - 2 class Bar {} -    ~~~ + 2 class Bar {} +    ~~~ 'Bar' was also declared here. tests/cases/compiler/file3.ts:2:5 - 2 let Bar = 42 -    ~~~ + 2 let Bar = 42 +    ~~~ and here. tests/cases/compiler/file2.ts:1:6 - error TS2300: Duplicate identifier 'Foo'. -1 type Foo = number; -   ~~~ +1 type Foo = number; +   ~~~ tests/cases/compiler/file1.ts:1:7 - 1 class Foo { } -    ~~~ + 1 class Foo { } +    ~~~ 'Foo' was also declared here. tests/cases/compiler/file2.ts:2:7 - error TS2451: Cannot redeclare block-scoped variable 'Bar'. -2 class Bar {} -   ~~~ +2 class Bar {} +   ~~~ tests/cases/compiler/file1.ts:2:7 - 2 const Bar = 3; -    ~~~ + 2 const Bar = 3; +    ~~~ 'Bar' was also declared here. tests/cases/compiler/file3.ts:1:6 - error TS2300: Duplicate identifier 'Foo'. -1 type Foo = 54; -   ~~~ +1 type Foo = 54; +   ~~~ tests/cases/compiler/file1.ts:1:7 - 1 class Foo { } -    ~~~ + 1 class Foo { } +    ~~~ 'Foo' was also declared here. tests/cases/compiler/file3.ts:2:5 - error TS2451: Cannot redeclare block-scoped variable 'Bar'. -2 let Bar = 42 -   ~~~ +2 let Bar = 42 +   ~~~ tests/cases/compiler/file1.ts:2:7 - 2 const Bar = 3; -    ~~~ + 2 const Bar = 3; +    ~~~ 'Bar' was also declared here. diff --git a/tests/baselines/reference/duplicateIdentifierRelatedSpans2.errors.txt b/tests/baselines/reference/duplicateIdentifierRelatedSpans2.errors.txt index 2925b636d2d..c6d6291e66a 100644 --- a/tests/baselines/reference/duplicateIdentifierRelatedSpans2.errors.txt +++ b/tests/baselines/reference/duplicateIdentifierRelatedSpans2.errors.txt @@ -1,20 +1,20 @@ tests/cases/compiler/file1.ts:1:1 - error TS6200: Definitions of the following identifiers conflict with those in another file: A, B, C, D, E, F, G, H, I -1 class A { } -  ~~~~~ +1 class A { } +  ~~~~~ tests/cases/compiler/file2.ts:1:1 - 1 class A { } -   ~~~~~ + 1 class A { } +   ~~~~~ Conflicts are in this file. tests/cases/compiler/file2.ts:1:1 - error TS6200: Definitions of the following identifiers conflict with those in another file: A, B, C, D, E, F, G, H, I -1 class A { } -  ~~~~~ +1 class A { } +  ~~~~~ tests/cases/compiler/file1.ts:1:1 - 1 class A { } -   ~~~~~ + 1 class A { } +   ~~~~~ Conflicts are in this file. diff --git a/tests/baselines/reference/duplicateIdentifierRelatedSpans3.errors.txt b/tests/baselines/reference/duplicateIdentifierRelatedSpans3.errors.txt index a97ce217928..2fb1879933c 100644 --- a/tests/baselines/reference/duplicateIdentifierRelatedSpans3.errors.txt +++ b/tests/baselines/reference/duplicateIdentifierRelatedSpans3.errors.txt @@ -1,56 +1,56 @@ tests/cases/compiler/file1.ts:2:5 - error TS2300: Duplicate identifier 'duplicate1'. -2 duplicate1: () => string; -   ~~~~~~~~~~ +2 duplicate1: () => string; +   ~~~~~~~~~~ tests/cases/compiler/file2.ts:2:5 - 2 duplicate1(): number; -    ~~~~~~~~~~ + 2 duplicate1(): number; +    ~~~~~~~~~~ 'duplicate1' was also declared here. tests/cases/compiler/file1.ts:3:5 - error TS2300: Duplicate identifier 'duplicate2'. -3 duplicate2: () => string; -   ~~~~~~~~~~ +3 duplicate2: () => string; +   ~~~~~~~~~~ tests/cases/compiler/file2.ts:3:5 - 3 duplicate2(): number; -    ~~~~~~~~~~ + 3 duplicate2(): number; +    ~~~~~~~~~~ 'duplicate2' was also declared here. tests/cases/compiler/file1.ts:4:5 - error TS2300: Duplicate identifier 'duplicate3'. -4 duplicate3: () => string; -   ~~~~~~~~~~ +4 duplicate3: () => string; +   ~~~~~~~~~~ tests/cases/compiler/file2.ts:4:5 - 4 duplicate3(): number; -    ~~~~~~~~~~ + 4 duplicate3(): number; +    ~~~~~~~~~~ 'duplicate3' was also declared here. tests/cases/compiler/file2.ts:2:5 - error TS2300: Duplicate identifier 'duplicate1'. -2 duplicate1(): number; -   ~~~~~~~~~~ +2 duplicate1(): number; +   ~~~~~~~~~~ tests/cases/compiler/file1.ts:2:5 - 2 duplicate1: () => string; -    ~~~~~~~~~~ + 2 duplicate1: () => string; +    ~~~~~~~~~~ 'duplicate1' was also declared here. tests/cases/compiler/file2.ts:3:5 - error TS2300: Duplicate identifier 'duplicate2'. -3 duplicate2(): number; -   ~~~~~~~~~~ +3 duplicate2(): number; +   ~~~~~~~~~~ tests/cases/compiler/file1.ts:3:5 - 3 duplicate2: () => string; -    ~~~~~~~~~~ + 3 duplicate2: () => string; +    ~~~~~~~~~~ 'duplicate2' was also declared here. tests/cases/compiler/file2.ts:4:5 - error TS2300: Duplicate identifier 'duplicate3'. -4 duplicate3(): number; -   ~~~~~~~~~~ +4 duplicate3(): number; +   ~~~~~~~~~~ tests/cases/compiler/file1.ts:4:5 - 4 duplicate3: () => string; -    ~~~~~~~~~~ + 4 duplicate3: () => string; +    ~~~~~~~~~~ 'duplicate3' was also declared here. diff --git a/tests/baselines/reference/duplicateIdentifierRelatedSpans4.errors.txt b/tests/baselines/reference/duplicateIdentifierRelatedSpans4.errors.txt index da50e3ad4a3..9512e55733e 100644 --- a/tests/baselines/reference/duplicateIdentifierRelatedSpans4.errors.txt +++ b/tests/baselines/reference/duplicateIdentifierRelatedSpans4.errors.txt @@ -1,20 +1,20 @@ tests/cases/compiler/file1.ts:1:1 - error TS6200: Definitions of the following identifiers conflict with those in another file: duplicate1, duplicate2, duplicate3, duplicate4, duplicate5, duplicate6, duplicate7, duplicate8 -1 interface TopLevel { -  ~~~~~~~~~ +1 interface TopLevel { +  ~~~~~~~~~ tests/cases/compiler/file2.ts:1:1 - 1 interface TopLevel { -   ~~~~~~~~~ + 1 interface TopLevel { +   ~~~~~~~~~ Conflicts are in this file. tests/cases/compiler/file2.ts:1:1 - error TS6200: Definitions of the following identifiers conflict with those in another file: duplicate1, duplicate2, duplicate3, duplicate4, duplicate5, duplicate6, duplicate7, duplicate8 -1 interface TopLevel { -  ~~~~~~~~~ +1 interface TopLevel { +  ~~~~~~~~~ tests/cases/compiler/file1.ts:1:1 - 1 interface TopLevel { -   ~~~~~~~~~ + 1 interface TopLevel { +   ~~~~~~~~~ Conflicts are in this file. diff --git a/tests/baselines/reference/duplicateIdentifierRelatedSpans5.errors.txt b/tests/baselines/reference/duplicateIdentifierRelatedSpans5.errors.txt index 2cbd4fa9629..497a0642296 100644 --- a/tests/baselines/reference/duplicateIdentifierRelatedSpans5.errors.txt +++ b/tests/baselines/reference/duplicateIdentifierRelatedSpans5.errors.txt @@ -1,56 +1,56 @@ tests/cases/compiler/file1.ts:3:9 - error TS2300: Duplicate identifier 'duplicate1'. -3 duplicate1: () => string; -   ~~~~~~~~~~ +3 duplicate1: () => string; +   ~~~~~~~~~~ tests/cases/compiler/file2.ts:4:9 - 4 duplicate1(): number; -    ~~~~~~~~~~ + 4 duplicate1(): number; +    ~~~~~~~~~~ 'duplicate1' was also declared here. tests/cases/compiler/file1.ts:4:9 - error TS2300: Duplicate identifier 'duplicate2'. -4 duplicate2: () => string; -   ~~~~~~~~~~ +4 duplicate2: () => string; +   ~~~~~~~~~~ tests/cases/compiler/file2.ts:5:9 - 5 duplicate2(): number; -    ~~~~~~~~~~ + 5 duplicate2(): number; +    ~~~~~~~~~~ 'duplicate2' was also declared here. tests/cases/compiler/file1.ts:5:9 - error TS2300: Duplicate identifier 'duplicate3'. -5 duplicate3: () => string; -   ~~~~~~~~~~ +5 duplicate3: () => string; +   ~~~~~~~~~~ tests/cases/compiler/file2.ts:6:9 - 6 duplicate3(): number; -    ~~~~~~~~~~ + 6 duplicate3(): number; +    ~~~~~~~~~~ 'duplicate3' was also declared here. tests/cases/compiler/file2.ts:4:9 - error TS2300: Duplicate identifier 'duplicate1'. -4 duplicate1(): number; -   ~~~~~~~~~~ +4 duplicate1(): number; +   ~~~~~~~~~~ tests/cases/compiler/file1.ts:3:9 - 3 duplicate1: () => string; -    ~~~~~~~~~~ + 3 duplicate1: () => string; +    ~~~~~~~~~~ 'duplicate1' was also declared here. tests/cases/compiler/file2.ts:5:9 - error TS2300: Duplicate identifier 'duplicate2'. -5 duplicate2(): number; -   ~~~~~~~~~~ +5 duplicate2(): number; +   ~~~~~~~~~~ tests/cases/compiler/file1.ts:4:9 - 4 duplicate2: () => string; -    ~~~~~~~~~~ + 4 duplicate2: () => string; +    ~~~~~~~~~~ 'duplicate2' was also declared here. tests/cases/compiler/file2.ts:6:9 - error TS2300: Duplicate identifier 'duplicate3'. -6 duplicate3(): number; -   ~~~~~~~~~~ +6 duplicate3(): number; +   ~~~~~~~~~~ tests/cases/compiler/file1.ts:5:9 - 5 duplicate3: () => string; -    ~~~~~~~~~~ + 5 duplicate3: () => string; +    ~~~~~~~~~~ 'duplicate3' was also declared here. diff --git a/tests/baselines/reference/duplicateIdentifierRelatedSpans6.errors.txt b/tests/baselines/reference/duplicateIdentifierRelatedSpans6.errors.txt index afe6ebe9f42..db980204718 100644 --- a/tests/baselines/reference/duplicateIdentifierRelatedSpans6.errors.txt +++ b/tests/baselines/reference/duplicateIdentifierRelatedSpans6.errors.txt @@ -1,56 +1,56 @@ tests/cases/compiler/file1.ts:3:9 - error TS2300: Duplicate identifier 'duplicate1'. -3 duplicate1: () => string; -   ~~~~~~~~~~ +3 duplicate1: () => string; +   ~~~~~~~~~~ tests/cases/compiler/file2.ts:5:9 - 5 duplicate1(): number; -    ~~~~~~~~~~ + 5 duplicate1(): number; +    ~~~~~~~~~~ 'duplicate1' was also declared here. tests/cases/compiler/file1.ts:4:9 - error TS2300: Duplicate identifier 'duplicate2'. -4 duplicate2: () => string; -   ~~~~~~~~~~ +4 duplicate2: () => string; +   ~~~~~~~~~~ tests/cases/compiler/file2.ts:6:9 - 6 duplicate2(): number; -    ~~~~~~~~~~ + 6 duplicate2(): number; +    ~~~~~~~~~~ 'duplicate2' was also declared here. tests/cases/compiler/file1.ts:5:9 - error TS2300: Duplicate identifier 'duplicate3'. -5 duplicate3: () => string; -   ~~~~~~~~~~ +5 duplicate3: () => string; +   ~~~~~~~~~~ tests/cases/compiler/file2.ts:7:9 - 7 duplicate3(): number; -    ~~~~~~~~~~ + 7 duplicate3(): number; +    ~~~~~~~~~~ 'duplicate3' was also declared here. tests/cases/compiler/file2.ts:5:9 - error TS2300: Duplicate identifier 'duplicate1'. -5 duplicate1(): number; -   ~~~~~~~~~~ +5 duplicate1(): number; +   ~~~~~~~~~~ tests/cases/compiler/file1.ts:3:9 - 3 duplicate1: () => string; -    ~~~~~~~~~~ + 3 duplicate1: () => string; +    ~~~~~~~~~~ 'duplicate1' was also declared here. tests/cases/compiler/file2.ts:6:9 - error TS2300: Duplicate identifier 'duplicate2'. -6 duplicate2(): number; -   ~~~~~~~~~~ +6 duplicate2(): number; +   ~~~~~~~~~~ tests/cases/compiler/file1.ts:4:9 - 4 duplicate2: () => string; -    ~~~~~~~~~~ + 4 duplicate2: () => string; +    ~~~~~~~~~~ 'duplicate2' was also declared here. tests/cases/compiler/file2.ts:7:9 - error TS2300: Duplicate identifier 'duplicate3'. -7 duplicate3(): number; -   ~~~~~~~~~~ +7 duplicate3(): number; +   ~~~~~~~~~~ tests/cases/compiler/file1.ts:5:9 - 5 duplicate3: () => string; -    ~~~~~~~~~~ + 5 duplicate3: () => string; +    ~~~~~~~~~~ 'duplicate3' was also declared here. diff --git a/tests/baselines/reference/duplicateIdentifierRelatedSpans7.errors.txt b/tests/baselines/reference/duplicateIdentifierRelatedSpans7.errors.txt index 76bb3d9c750..7b568736ff3 100644 --- a/tests/baselines/reference/duplicateIdentifierRelatedSpans7.errors.txt +++ b/tests/baselines/reference/duplicateIdentifierRelatedSpans7.errors.txt @@ -1,20 +1,20 @@ tests/cases/compiler/file1.ts:1:1 - error TS6200: Definitions of the following identifiers conflict with those in another file: duplicate1, duplicate2, duplicate3, duplicate4, duplicate5, duplicate6, duplicate7, duplicate8, duplicate9 -1 declare module "someMod" { -  ~~~~~~~ +1 declare module "someMod" { +  ~~~~~~~ tests/cases/compiler/file2.ts:3:1 - 3 declare module "someMod" { -   ~~~~~~~ + 3 declare module "someMod" { +   ~~~~~~~ Conflicts are in this file. tests/cases/compiler/file2.ts:3:1 - error TS6200: Definitions of the following identifiers conflict with those in another file: duplicate1, duplicate2, duplicate3, duplicate4, duplicate5, duplicate6, duplicate7, duplicate8, duplicate9 -3 declare module "someMod" { -  ~~~~~~~ +3 declare module "someMod" { +  ~~~~~~~ tests/cases/compiler/file1.ts:1:1 - 1 declare module "someMod" { -   ~~~~~~~ + 1 declare module "someMod" { +   ~~~~~~~ Conflicts are in this file. diff --git a/tests/baselines/reference/esModuleInteropPrettyErrorRelatedInformation.errors.txt b/tests/baselines/reference/esModuleInteropPrettyErrorRelatedInformation.errors.txt index 1d1c983162f..14c054c466c 100644 --- a/tests/baselines/reference/esModuleInteropPrettyErrorRelatedInformation.errors.txt +++ b/tests/baselines/reference/esModuleInteropPrettyErrorRelatedInformation.errors.txt @@ -1,12 +1,12 @@ tests/cases/compiler/index.ts:3:8 - error TS2345: Argument of type '{ default: () => void; }' is not assignable to parameter of type '() => void'. Type '{ default: () => void; }' provides no match for the signature '(): void'. -3 invoke(foo); -   ~~~ +3 invoke(foo); +   ~~~ tests/cases/compiler/index.ts:1:1 - 1 import * as foo from "./foo"; -   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 1 import * as foo from "./foo"; +   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Type originates at this import. A namespace-style import cannot be called or constructed, and will cause a failure at runtime. Consider using a default import or import require here instead. diff --git a/tests/baselines/reference/multiLineContextDiagnosticWithPretty.errors.txt b/tests/baselines/reference/multiLineContextDiagnosticWithPretty.errors.txt index c6b8095d15b..525f30415d1 100644 --- a/tests/baselines/reference/multiLineContextDiagnosticWithPretty.errors.txt +++ b/tests/baselines/reference/multiLineContextDiagnosticWithPretty.errors.txt @@ -1,12 +1,12 @@ tests/cases/compiler/multiLineContextDiagnosticWithPretty.ts:2:5 - error TS2322: Type '{ a: { b: string; }; }' is not assignable to type '{ c: string; }'. Object literal may only specify known properties, and 'a' does not exist in type '{ c: string; }'. -2 a: { -   ~~~~ -3 b: '', -  ~~~~~~~~~~~~~~ -4 } -  ~~~~~ +2 a: { +   ~~~~ +3 b: '', +  ~~~~~~~~~~~~~~ +4 } +  ~~~~~ ==== tests/cases/compiler/multiLineContextDiagnosticWithPretty.ts (1 errors) ==== diff --git a/tests/baselines/reference/prettyContextNotDebugAssertion.errors.txt b/tests/baselines/reference/prettyContextNotDebugAssertion.errors.txt index 57b4f5d62f7..d983f0d973e 100644 --- a/tests/baselines/reference/prettyContextNotDebugAssertion.errors.txt +++ b/tests/baselines/reference/prettyContextNotDebugAssertion.errors.txt @@ -1,7 +1,7 @@ tests/cases/compiler/index.ts:2:1 - error TS1005: '}' expected. -2 -   +2 +   ==== tests/cases/compiler/index.ts (1 errors) ==== diff --git a/tests/baselines/reference/typedefCrossModule5.errors.txt b/tests/baselines/reference/typedefCrossModule5.errors.txt index b75652a31d5..2784f0e1896 100644 --- a/tests/baselines/reference/typedefCrossModule5.errors.txt +++ b/tests/baselines/reference/typedefCrossModule5.errors.txt @@ -1,38 +1,38 @@ tests/cases/conformance/jsdoc/mod1.js:1:23 - error TS2300: Duplicate identifier 'Foo'. -1 /** @typedef {number} Foo */ -   ~~~ +1 /** @typedef {number} Foo */ +   ~~~ tests/cases/conformance/jsdoc/mod2.js:1:7 - 1 class Foo { } // should error -    ~~~ + 1 class Foo { } // should error +    ~~~ 'Foo' was also declared here. tests/cases/conformance/jsdoc/mod1.js:2:7 - error TS2451: Cannot redeclare block-scoped variable 'Bar'. -2 class Bar {} -   ~~~ +2 class Bar {} +   ~~~ tests/cases/conformance/jsdoc/mod2.js:2:7 - 2 const Bar = 3; -    ~~~ + 2 const Bar = 3; +    ~~~ 'Bar' was also declared here. tests/cases/conformance/jsdoc/mod2.js:1:7 - error TS2300: Duplicate identifier 'Foo'. -1 class Foo { } // should error -   ~~~ +1 class Foo { } // should error +   ~~~ tests/cases/conformance/jsdoc/mod1.js:1:23 - 1 /** @typedef {number} Foo */ -    ~~~ + 1 /** @typedef {number} Foo */ +    ~~~ 'Foo' was also declared here. tests/cases/conformance/jsdoc/mod2.js:2:7 - error TS2451: Cannot redeclare block-scoped variable 'Bar'. -2 const Bar = 3; -   ~~~ +2 const Bar = 3; +   ~~~ tests/cases/conformance/jsdoc/mod1.js:2:7 - 2 class Bar {} -    ~~~ + 2 class Bar {} +    ~~~ 'Bar' was also declared here. From 95ba73e16b5b417a7a9c5d664b4c092677231937 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Mon, 10 Sep 2018 10:37:44 -0700 Subject: [PATCH 10/83] Don't offer module completions in non-module JS files --- src/services/completions.ts | 4 +-- .../fourslash/completionsImport_importType.ts | 13 +++++--- ...oImportCompletionsInOtherJavaScriptFile.ts | 31 +++++++++++++++++++ 3 files changed, 41 insertions(+), 7 deletions(-) create mode 100644 tests/cases/fourslash/noImportCompletionsInOtherJavaScriptFile.ts diff --git a/src/services/completions.ts b/src/services/completions.ts index 16e48dc56b6..61e424c43ec 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -1268,10 +1268,10 @@ namespace ts.Completions { if (sourceFile.externalModuleIndicator) return true; // If already using commonjs, don't introduce ES6. if (sourceFile.commonJsModuleIndicator) return false; - // If some file is using ES6 modules, assume that it's OK to add more. - if (programContainsEs6Modules(program)) return true; // For JS, stay on the safe side. if (isUncheckedFile) return false; + // If some file is using ES6 modules, assume that it's OK to add more. + if (programContainsEs6Modules(program)) return true; // If module transpilation is enabled or we're targeting es6 or above, or not emitting, OK. return compilerOptionsIndicateEs6Modules(program.getCompilerOptions()); } diff --git a/tests/cases/fourslash/completionsImport_importType.ts b/tests/cases/fourslash/completionsImport_importType.ts index b1b69a9a8d0..3c371980b90 100644 --- a/tests/cases/fourslash/completionsImport_importType.ts +++ b/tests/cases/fourslash/completionsImport_importType.ts @@ -3,13 +3,14 @@ // @allowJs: true // @Filename: /a.js -////export const x = 0; -////export class C {} -/////** @typedef {number} T */ +//// export const x = 0; +//// export class C {} +//// /** @typedef {number} T */ // @Filename: /b.js -/////** @type {/*0*/} */ -/////** @type {/*1*/} */ +//// export const m = 0; +//// /** @type {/*0*/} */ +//// /** @type {/*1*/} */ verify.completions({ marker: ["0", "1"], @@ -43,6 +44,7 @@ verify.applyCodeActionFromCompletion("0", { newFileContent: `import { C } from "./a"; +export const m = 0; /** @type {} */ /** @type {} */`, }); @@ -55,6 +57,7 @@ verify.applyCodeActionFromCompletion("1", { newFileContent: `import { C } from "./a"; +export const m = 0; /** @type {} */ /** @type {import("./a").} */`, }); diff --git a/tests/cases/fourslash/noImportCompletionsInOtherJavaScriptFile.ts b/tests/cases/fourslash/noImportCompletionsInOtherJavaScriptFile.ts new file mode 100644 index 00000000000..3493c4c2cff --- /dev/null +++ b/tests/cases/fourslash/noImportCompletionsInOtherJavaScriptFile.ts @@ -0,0 +1,31 @@ +/// + +// @allowJs: true +// @module: esnext + +// @Filename: /node_modules/foo/index.d.ts +//// export const fail: number; + +// @Filename: /a.js +//// export const x = 0; +//// export class C {} +//// + +// @Filename: /b.js +//// /**/ + +goTo.file("/b.js"); +goTo.marker(); +verify.not.completionListContains("fail", undefined, undefined, undefined, undefined, undefined, { includeCompletionsForModuleExports: true }); +edit.insert("export const k = 10;\r\nf"); +verify.completionListContains( + { name: "fail", source: "/node_modules/foo/index" }, + "const fail: number", + "", + "const", + undefined, + true, + { + includeCompletionsForModuleExports: true, + sourceDisplay: "./node_modules/foo/index" + }); From 59060a1b9064c5ece4e2219ac6404ac45f5c1316 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Thu, 6 Sep 2018 16:03:34 -0700 Subject: [PATCH 11/83] Remove unnecessary projectReferences from ExpandResult and referenceSpecs from ConfigFileSpecs --- src/compiler/commandLineParser.ts | 16 ++++------------ src/compiler/types.ts | 2 -- .../baselines/reference/api/tsserverlibrary.d.ts | 1 - tests/baselines/reference/api/typescript.d.ts | 1 - 4 files changed, 4 insertions(+), 16 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index e4c4edcb4db..e7269acfa5b 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -1825,7 +1825,8 @@ namespace ts { const options = extend(existingOptions, parsedConfig.options || {}); options.configFilePath = configFileName && normalizeSlashes(configFileName); setConfigFileInOptions(options, sourceFile); - const { fileNames, wildcardDirectories, spec, projectReferences } = getFileNames(); + let projectReferences: ProjectReference[] | undefined; + const { fileNames, wildcardDirectories, spec } = getFileNames(); return { options, fileNames, @@ -1891,13 +1892,12 @@ namespace ts { if (hasProperty(raw, "references") && !isNullOrUndefined(raw.references)) { if (isArray(raw.references)) { - const references: ProjectReference[] = []; for (const ref of raw.references) { if (typeof ref.path !== "string") { createCompilerDiagnosticOnlyIfJson(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, "reference.path", "string"); } else { - references.push({ + (projectReferences || (projectReferences = [])).push({ path: getNormalizedAbsolutePath(ref.path, basePath), originalPath: ref.path, prepend: ref.prepend, @@ -1905,7 +1905,6 @@ namespace ts { }); } } - result.projectReferences = references; } else { createCompilerDiagnosticOnlyIfJson(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, "references", "Array"); @@ -2398,7 +2397,7 @@ namespace ts { // new entries in these paths. const wildcardDirectories = getWildcardDirectories(validatedIncludeSpecs, validatedExcludeSpecs, basePath, host.useCaseSensitiveFileNames); - const spec: ConfigFileSpecs = { filesSpecs, referencesSpecs: undefined, includeSpecs, excludeSpecs, validatedIncludeSpecs, validatedExcludeSpecs, wildcardDirectories }; + const spec: ConfigFileSpecs = { filesSpecs, includeSpecs, excludeSpecs, validatedIncludeSpecs, validatedExcludeSpecs, wildcardDirectories }; return getFileNamesFromConfigSpecs(spec, basePath, options, host, extraFileExtensions); } @@ -2469,16 +2468,9 @@ namespace ts { const literalFiles = arrayFrom(literalFileMap.values()); const wildcardFiles = arrayFrom(wildcardFileMap.values()); - const projectReferences = spec.referencesSpecs && spec.referencesSpecs.map((r): ProjectReference => { - return { - ...r, - path: getNormalizedAbsolutePath(r.path, basePath) - }; - }); return { fileNames: literalFiles.concat(wildcardFiles), - projectReferences, wildcardDirectories, spec }; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 279fef73d5e..27622b9ec4f 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -4516,7 +4516,6 @@ namespace ts { /* @internal */ export interface ConfigFileSpecs { filesSpecs: ReadonlyArray | undefined; - referencesSpecs: ReadonlyArray | undefined; /** * Present to report errors (user specified specs), validatedIncludeSpecs are used for file name matching */ @@ -4532,7 +4531,6 @@ namespace ts { export interface ExpandResult { fileNames: string[]; - projectReferences: ReadonlyArray | undefined; wildcardDirectories: MapLike; /* @internal */ spec: ConfigFileSpecs; } diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 672b93e55da..a2fbf9ac944 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -2584,7 +2584,6 @@ declare namespace ts { } interface ExpandResult { fileNames: string[]; - projectReferences: ReadonlyArray | undefined; wildcardDirectories: MapLike; } interface CreateProgramOptions { diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 5d093382f54..6ab352033f3 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -2584,7 +2584,6 @@ declare namespace ts { } interface ExpandResult { fileNames: string[]; - projectReferences: ReadonlyArray | undefined; wildcardDirectories: MapLike; } interface CreateProgramOptions { From 50bcfb63280155dfd5f9ca51e366b7edf7c6b9ff Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Fri, 7 Sep 2018 12:59:38 -0700 Subject: [PATCH 12/83] Try the ParsedCommandLine from cache instead of re-reading contents of tsconfig file --- src/compiler/tsbuild.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts index 4ddda98a41f..b5a95039a02 100644 --- a/src/compiler/tsbuild.ts +++ b/src/compiler/tsbuild.ts @@ -356,10 +356,19 @@ namespace ts { } function createConfigFileCache(host: CompilerHost) { - const cache = createFileMap(); + const cache = createFileMap(); const configParseHost = parseConfigHostFromCompilerHost(host); + function isParsedCommandLine(value: ParsedCommandLine | "error"): value is ParsedCommandLine { + return !(value as "error").length; + } + function parseConfigFile(configFilePath: ResolvedConfigFileName) { + const value = cache.getValueOrUndefined(configFilePath); + if (value) { + return isParsedCommandLine(value) ? value : undefined; + } + const sourceFile = host.getSourceFile(configFilePath, ScriptTarget.JSON) as JsonSourceFile; if (sourceFile === undefined) { return undefined; From 521edc1c80cc2d1bcca4024e20625b69f7fb15d2 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Fri, 7 Sep 2018 13:36:45 -0700 Subject: [PATCH 13/83] Refactoring to handle case sensitivity of the host when caching --- src/compiler/tsbuild.ts | 126 +++++++++++++++++++--------------------- 1 file changed, 60 insertions(+), 66 deletions(-) diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts index b5a95039a02..e72e9d1903e 100644 --- a/src/compiler/tsbuild.ts +++ b/src/compiler/tsbuild.ts @@ -34,8 +34,8 @@ namespace ts { /** * Map from config file name to up-to-date status */ - projectStatus: FileMap; - diagnostics?: FileMap; // TODO(shkamat): this should be really be diagnostics but thats for later time + projectStatus: ConfigFileMap; + diagnostics?: ConfigFileMap; // TODO(shkamat): this should be really be diagnostics but thats for later time invalidateProject(project: ResolvedConfigFileName, dependencyGraph: DependencyGraph | undefined): void; getNextInvalidatedProject(): ResolvedConfigFileName | undefined; @@ -189,62 +189,56 @@ namespace ts { } } - interface FileMap { - setValue(fileName: string, value: T): void; - getValue(fileName: string): T | never; - getValueOrUndefined(fileName: string): T | undefined; - hasKey(fileName: string): boolean; - removeKey(fileName: string): void; - getKeys(): string[]; + interface FileMap { + setValue(fileName: U, value: T): void; + getValue(fileName: U): T | undefined; + hasKey(fileName: U): boolean; + removeKey(fileName: U): void; + forEach(action: (value: T, key: V) => void): void; getSize(): number; } + type ResolvedConfigFilePath = ResolvedConfigFileName & Path; + type ConfigFileMap = FileMap; + type ToResolvedConfigFilePath = (fileName: ResolvedConfigFileName) => ResolvedConfigFilePath; + type ToPath = (fileName: string) => Path; + /** * A FileMap maintains a normalized-key to value relationship */ - function createFileMap(): FileMap { + function createFileMap(toPath: ToResolvedConfigFilePath): ConfigFileMap; + function createFileMap(toPath: ToPath): FileMap; + function createFileMap(toPath: (fileName: U) => V): FileMap { // tslint:disable-next-line:no-null-keyword const lookup = createMap(); return { setValue, getValue, - getValueOrUndefined, removeKey, - getKeys, + forEach, hasKey, getSize }; - function getKeys(): string[] { - return Object.keys(lookup); + function forEach(action: (value: T, key: V) => void) { + lookup.forEach(action); } - function hasKey(fileName: string) { - return lookup.has(normalizePath(fileName)); + function hasKey(fileName: U) { + return lookup.has(toPath(fileName)); } - function removeKey(fileName: string) { - lookup.delete(normalizePath(fileName)); + function removeKey(fileName: U) { + lookup.delete(toPath(fileName)); } - function setValue(fileName: string, value: T) { - lookup.set(normalizePath(fileName), value); + function setValue(fileName: U, value: T) { + lookup.set(toPath(fileName), value); } - function getValue(fileName: string): T | never { - const f = normalizePath(fileName); - if (lookup.has(f)) { - return lookup.get(f)!; - } - else { - throw new Error(`No value corresponding to ${fileName} exists in this map`); - } - } - - function getValueOrUndefined(fileName: string): T | undefined { - const f = normalizePath(fileName); - return lookup.get(f); + function getValue(fileName: U): T | undefined { + return lookup.get(toPath(fileName)); } function getSize() { @@ -252,10 +246,9 @@ namespace ts { } } - function createDependencyMapper() { - const childToParents = createFileMap(); - const parentToChildren = createFileMap(); - const allKeys = createFileMap(); + function createDependencyMapper(toPath: ToResolvedConfigFilePath) { + const childToParents = createFileMap(toPath); + const parentToChildren = createFileMap(toPath); function addReference(childConfigFileName: ResolvedConfigFileName, parentConfigFileName: ResolvedConfigFileName): void { addEntry(childToParents, childConfigFileName, parentConfigFileName); @@ -263,36 +256,29 @@ namespace ts { } function getReferencesTo(parentConfigFileName: ResolvedConfigFileName): ResolvedConfigFileName[] { - return parentToChildren.getValueOrUndefined(parentConfigFileName) || []; + return parentToChildren.getValue(parentConfigFileName) || []; } function getReferencesOf(childConfigFileName: ResolvedConfigFileName): ResolvedConfigFileName[] { - return childToParents.getValueOrUndefined(childConfigFileName) || []; - } - - function getKeys(): ReadonlyArray { - return allKeys.getKeys() as ResolvedConfigFileName[]; + return childToParents.getValue(childConfigFileName) || []; } function addEntry(mapToAddTo: typeof childToParents | typeof parentToChildren, key: ResolvedConfigFileName, element: ResolvedConfigFileName) { key = normalizePath(key) as ResolvedConfigFileName; element = normalizePath(element) as ResolvedConfigFileName; - let arr = mapToAddTo.getValueOrUndefined(key); + let arr = mapToAddTo.getValue(key); if (arr === undefined) { mapToAddTo.setValue(key, arr = []); } if (arr.indexOf(element) < 0) { arr.push(element); } - allKeys.setValue(key, true); - allKeys.setValue(element, true); } return { addReference, getReferencesTo, getReferencesOf, - getKeys }; } @@ -355,8 +341,8 @@ namespace ts { return opts.rootDir || getDirectoryPath(configFileName); } - function createConfigFileCache(host: CompilerHost) { - const cache = createFileMap(); + function createConfigFileCache(host: CompilerHost, toPath: ToResolvedConfigFilePath) { + const cache = createFileMap(toPath); const configParseHost = parseConfigHostFromCompilerHost(host); function isParsedCommandLine(value: ParsedCommandLine | "error"): value is ParsedCommandLine { @@ -364,7 +350,7 @@ namespace ts { } function parseConfigFile(configFilePath: ResolvedConfigFileName) { - const value = cache.getValueOrUndefined(configFilePath); + const value = cache.getValue(configFilePath); if (value) { return isParsedCommandLine(value) ? value : undefined; } @@ -398,18 +384,18 @@ namespace ts { return fileExtensionIs(fileName, Extension.Dts); } - export function createBuildContext(options: BuildOptions): BuildContext { + export function createBuildContext(options: BuildOptions, toPath: ToResolvedConfigFilePath): BuildContext { const invalidatedProjectQueue = [] as ResolvedConfigFileName[]; let nextIndex = 0; - const projectPendingBuild = createFileMap(); + const projectPendingBuild = createFileMap(toPath); const missingRoots = createMap(); - const diagnostics = options.watch ? createFileMap() : undefined; + const diagnostics = options.watch ? createFileMap(toPath) : undefined; return { options, - projectStatus: createFileMap(), + projectStatus: createFileMap(toPath), diagnostics, - unchangedOutputs: createFileMap(), + unchangedOutputs: createFileMap(toPath as ToPath), invalidateProject, getNextInvalidatedProject, hasPendingInvalidatedProjects, @@ -513,8 +499,10 @@ namespace ts { */ export function createSolutionBuilder(host: SolutionBuilderHost, rootNames: ReadonlyArray, defaultOptions: BuildOptions) { const hostWithWatch = host as SolutionBuilderWithWatchHost; - const configFileCache = createConfigFileCache(host); - let context = createBuildContext(defaultOptions); + const currentDirectory = host.getCurrentDirectory(); + const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames()); + const configFileCache = createConfigFileCache(host, toPath); + let context = createBuildContext(defaultOptions, toPath); let timerToBuildInvalidatedProject: any; let reportFileChangeDetected = false; @@ -535,6 +523,12 @@ namespace ts { startWatching }; + function toPath(fileName: ResolvedConfigFileName): ResolvedConfigFilePath; + function toPath(fileName: string): Path; + function toPath(fileName: string) { + return ts.toPath(fileName, currentDirectory, getCanonicalFileName); + } + function reportStatus(message: DiagnosticMessage, ...args: string[]) { host.reportSolutionBuilderStatus(createCompilerDiagnostic(message, ...args)); } @@ -600,7 +594,7 @@ namespace ts { } function resetBuildContext(opts = defaultOptions) { - context = createBuildContext(opts); + context = createBuildContext(opts, toPath); } function getUpToDateStatusOfFile(configFileName: ResolvedConfigFileName): UpToDateStatus { @@ -623,13 +617,13 @@ namespace ts { return { type: UpToDateStatusType.Unbuildable, reason: "File deleted mid-build" }; } - const prior = context.projectStatus.getValueOrUndefined(project.options.configFilePath!); + const prior = context.projectStatus.getValue(project.options.configFilePath as ResolvedConfigFilePath); if (prior !== undefined) { return prior; } const actual = getUpToDateStatusWorker(project); - context.projectStatus.setValue(project.options.configFilePath!, actual); + context.projectStatus.setValue(project.options.configFilePath as ResolvedConfigFilePath, actual); return actual; } @@ -700,7 +694,7 @@ namespace ts { // had its file touched but not had its contents changed - this allows us // to skip a downstream typecheck if (isDeclarationFile(output)) { - const unchangedTime = context.unchangedOutputs.getValueOrUndefined(output); + const unchangedTime = context.unchangedOutputs.getValue(output); if (unchangedTime !== undefined) { newestDeclarationFileContentChangedTime = newer(unchangedTime, newestDeclarationFileContentChangedTime); } @@ -845,9 +839,9 @@ namespace ts { function reportErrorSummary() { if (context.options.watch) { - let errorCount = 0; - context.diagnostics!.getKeys().forEach(resolved => errorCount += context.diagnostics!.getValue(resolved)); - reportWatchStatus(errorCount === 1 ? Diagnostics.Found_1_error_Watching_for_file_changes : Diagnostics.Found_0_errors_Watching_for_file_changes, errorCount); + let totalErrors = 0; + context.diagnostics!.forEach(singleProjectErrors => totalErrors += singleProjectErrors); + reportWatchStatus(totalErrors === 1 ? Diagnostics.Found_1_error_Watching_for_file_changes : Diagnostics.Found_0_errors_Watching_for_file_changes, totalErrors); } } @@ -881,7 +875,7 @@ namespace ts { const permanentMarks: { [path: string]: true } = {}; const circularityReportStack: string[] = []; const buildOrder: ResolvedConfigFileName[] = []; - const graph = createDependencyMapper(); + const graph = createDependencyMapper(toPath); let hadError = false; @@ -1061,7 +1055,7 @@ namespace ts { host.setModifiedTime(file, now); } - context.projectStatus.setValue(proj.options.configFilePath!, { type: UpToDateStatusType.UpToDate, newestDeclarationFileContentChangedTime: priorNewestUpdateTime } as UpToDateStatus); + context.projectStatus.setValue(proj.options.configFilePath as ResolvedConfigFilePath, { type: UpToDateStatusType.UpToDate, newestDeclarationFileContentChangedTime: priorNewestUpdateTime } as UpToDateStatus); } function getFilesToClean(configFileNames: ReadonlyArray): string[] | undefined { From 82041eb300260d06da720a47d6f660ae2ace1db2 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Fri, 7 Sep 2018 15:22:10 -0700 Subject: [PATCH 14/83] Add partial reload support also watch wild cards correctly. Partially fixes #26524 --- src/compiler/tsbuild.ts | 250 +++++++++++-------- src/testRunner/unittests/tsbuildWatchMode.ts | 8 +- 2 files changed, 158 insertions(+), 100 deletions(-) diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts index e72e9d1903e..55af0080983 100644 --- a/src/compiler/tsbuild.ts +++ b/src/compiler/tsbuild.ts @@ -37,8 +37,8 @@ namespace ts { projectStatus: ConfigFileMap; diagnostics?: ConfigFileMap; // TODO(shkamat): this should be really be diagnostics but thats for later time - invalidateProject(project: ResolvedConfigFileName, dependencyGraph: DependencyGraph | undefined): void; - getNextInvalidatedProject(): ResolvedConfigFileName | undefined; + invalidateProject(project: ResolvedConfigFileName, reloadLevel: ConfigFileProgramReloadLevel | undefined, dependencyGraph: DependencyGraph | undefined): void; + getNextInvalidatedProject(): { project: ResolvedConfigFileName, reloadLevel: ConfigFileProgramReloadLevel } | undefined; hasPendingInvalidatedProjects(): boolean; missingRoots: Map; } @@ -341,40 +341,6 @@ namespace ts { return opts.rootDir || getDirectoryPath(configFileName); } - function createConfigFileCache(host: CompilerHost, toPath: ToResolvedConfigFilePath) { - const cache = createFileMap(toPath); - const configParseHost = parseConfigHostFromCompilerHost(host); - - function isParsedCommandLine(value: ParsedCommandLine | "error"): value is ParsedCommandLine { - return !(value as "error").length; - } - - function parseConfigFile(configFilePath: ResolvedConfigFileName) { - const value = cache.getValue(configFilePath); - if (value) { - return isParsedCommandLine(value) ? value : undefined; - } - - const sourceFile = host.getSourceFile(configFilePath, ScriptTarget.JSON) as JsonSourceFile; - if (sourceFile === undefined) { - return undefined; - } - - const parsed = parseJsonSourceFileConfigFileContent(sourceFile, configParseHost, getDirectoryPath(configFilePath)); - parsed.options.configFilePath = configFilePath; - cache.setValue(configFilePath, parsed); - return parsed; - } - - function removeKey(configFilePath: ResolvedConfigFileName) { - cache.removeKey(configFilePath); - } - - return { - parseConfigFile, - removeKey - }; - } function newer(date1: Date, date2: Date): Date { return date2 > date1 ? date2 : date1; @@ -387,7 +353,7 @@ namespace ts { export function createBuildContext(options: BuildOptions, toPath: ToResolvedConfigFilePath): BuildContext { const invalidatedProjectQueue = [] as ResolvedConfigFileName[]; let nextIndex = 0; - const projectPendingBuild = createFileMap(toPath); + const projectPendingBuild = createFileMap(toPath); const missingRoots = createMap(); const diagnostics = options.watch ? createFileMap(toPath) : undefined; @@ -402,31 +368,39 @@ namespace ts { missingRoots }; - function invalidateProject(proj: ResolvedConfigFileName, dependencyGraph: DependencyGraph | undefined) { - if (!projectPendingBuild.hasKey(proj)) { - addProjToQueue(proj); - if (dependencyGraph) { - queueBuildForDownstreamReferences(proj, dependencyGraph); - } + function invalidateProject(proj: ResolvedConfigFileName, reloadLevel: ConfigFileProgramReloadLevel | undefined, dependencyGraph: DependencyGraph | undefined) { + if (addProjToQueue(proj, reloadLevel) && dependencyGraph) { + queueBuildForDownstreamReferences(proj, dependencyGraph); } } - function addProjToQueue(proj: ResolvedConfigFileName) { - Debug.assert(!projectPendingBuild.hasKey(proj)); - projectPendingBuild.setValue(proj, true); - invalidatedProjectQueue.push(proj); + /** + * return true if new addition + */ + function addProjToQueue(proj: ResolvedConfigFileName, reloadLevel?: ConfigFileProgramReloadLevel) { + const value = projectPendingBuild.getValue(proj); + if (value === undefined) { + projectPendingBuild.setValue(proj, reloadLevel || ConfigFileProgramReloadLevel.None); + invalidatedProjectQueue.push(proj); + return true; + } + + if (value < (reloadLevel || ConfigFileProgramReloadLevel.None)) { + projectPendingBuild.setValue(proj, reloadLevel || ConfigFileProgramReloadLevel.None); + } } function getNextInvalidatedProject() { if (nextIndex < invalidatedProjectQueue.length) { - const proj = invalidatedProjectQueue[nextIndex]; + const project = invalidatedProjectQueue[nextIndex]; nextIndex++; - projectPendingBuild.removeKey(proj); + const reloadLevel = projectPendingBuild.getValue(project)!; + projectPendingBuild.removeKey(project); if (!projectPendingBuild.getSize()) { invalidatedProjectQueue.length = 0; nextIndex = 0; } - return proj; + return { project, reloadLevel }; } } @@ -439,8 +413,7 @@ namespace ts { const deps = dependencyGraph.dependencyMap.getReferencesTo(root); for (const ref of deps) { // Can skip circular references - if (!projectPendingBuild.hasKey(ref)) { - addProjToQueue(ref); + if (addProjToQueue(ref)) { queueBuildForDownstreamReferences(ref, dependencyGraph); } } @@ -501,12 +474,15 @@ namespace ts { const hostWithWatch = host as SolutionBuilderWithWatchHost; const currentDirectory = host.getCurrentDirectory(); const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames()); - const configFileCache = createConfigFileCache(host, toPath); + const parseConfigFileHost = parseConfigHostFromCompilerHost(host); + type ConfigFileCacheEntry = ParsedCommandLine | Diagnostic; + const configFileCache = createFileMap(toPath); let context = createBuildContext(defaultOptions, toPath); let timerToBuildInvalidatedProject: any; let reportFileChangeDetected = false; - const existingWatchersForWildcards = createMap(); + const existingWatchersForWildcards = createFileMap>(toPath); + return { buildAllProjects, getUpToDateStatus, @@ -529,6 +505,24 @@ namespace ts { return ts.toPath(fileName, currentDirectory, getCanonicalFileName); } + function isParsedCommandLine(entry: ConfigFileCacheEntry): entry is ParsedCommandLine { + return !!(entry as ParsedCommandLine).options; + } + + function parseConfigFile(configFilePath: ResolvedConfigFileName): ParsedCommandLine | undefined { + const value = configFileCache.getValue(configFilePath); + if (value) { + return isParsedCommandLine(value) ? value : undefined; + } + + let diagnostic: Diagnostic | undefined; + parseConfigFileHost.onUnRecoverableConfigFileDiagnostic = d => diagnostic = d; + const parsed = getParsedCommandLineOfConfigFile(configFilePath, {}, parseConfigFileHost); + parseConfigFileHost.onUnRecoverableConfigFileDiagnostic = noop; + configFileCache.setValue(configFilePath, parsed || diagnostic!); + return parsed; + } + function reportStatus(message: DiagnosticMessage, ...args: string[]) { host.reportSolutionBuilderStatus(createCompilerDiagnostic(message, ...args)); } @@ -559,19 +553,36 @@ namespace ts { } for (const resolved of graph.buildQueue) { - const cfg = configFileCache.parseConfigFile(resolved); + const cfg = parseConfigFile(resolved); if (cfg) { // Watch this file hostWithWatch.watchFile(resolved, () => { configFileCache.removeKey(resolved); - invalidateProjectAndScheduleBuilds(resolved); + invalidateProjectAndScheduleBuilds(resolved, ConfigFileProgramReloadLevel.Full); }); // Update watchers for wildcard directories if (cfg.configFileSpecs) { - updateWatchingWildcardDirectories(existingWatchersForWildcards, createMapFromTemplate(cfg.configFileSpecs.wildcardDirectories), (dir, flags) => { - return hostWithWatch.watchDirectory(dir, () => { - invalidateProjectAndScheduleBuilds(resolved); + const existingWatches = existingWatchersForWildcards.getValue(resolved); + let newWatches: Map | undefined; + if (!existingWatches) { + newWatches = createMap(); + existingWatchersForWildcards.setValue(resolved, newWatches); + } + updateWatchingWildcardDirectories(existingWatches || newWatches!, createMapFromTemplate(cfg.configFileSpecs.wildcardDirectories), (dir, flags) => { + return hostWithWatch.watchDirectory(dir, fileOrDirectory => { + const fileOrDirectoryPath = toPath(fileOrDirectory); + if (fileOrDirectoryPath !== toPath(dir) && hasExtension(fileOrDirectoryPath) && !isSupportedSourceFileName(fileOrDirectory, cfg.options)) { + // writeLog(`Project: ${configFileName} Detected file add/remove of non supported extension: ${fileOrDirectory}`); + return; + } + + if (isOutputFile(fileOrDirectory, cfg)) { + // writeLog(`${fileOrDirectory} is output file`); + return; + } + + invalidateProjectAndScheduleBuilds(resolved, ConfigFileProgramReloadLevel.Partial); }, !!(flags & WatchDirectoryFlags.Recursive)); }); } @@ -579,7 +590,7 @@ namespace ts { // Watch input files for (const input of cfg.fileNames) { hostWithWatch.watchFile(input, () => { - invalidateProjectAndScheduleBuilds(resolved); + invalidateProjectAndScheduleBuilds(resolved, ConfigFileProgramReloadLevel.None); }); } } @@ -587,9 +598,41 @@ namespace ts { } - function invalidateProjectAndScheduleBuilds(resolved: ResolvedConfigFileName) { + function isOutputFile(fileName: string, configFile: ParsedCommandLine) { + if (configFile.options.noEmit) return false; + + // ts or tsx files are not output + if (!fileExtensionIs(fileName, Extension.Dts) && + (fileExtensionIs(fileName, Extension.Ts) || fileExtensionIs(fileName, Extension.Tsx))) { + return false; + } + + // If options have --outFile or --out, check if its that + const out = configFile.options.outFile || configFile.options.out; + if (out && (isSameFile(fileName, out) || isSameFile(fileName, removeFileExtension(out) + Extension.Dts))) { + return true; + } + + // If declarationDir is specified, return if its a file in that directory + if (configFile.options.declarationDir && containsPath(configFile.options.declarationDir, fileName, currentDirectory, !host.useCaseSensitiveFileNames())) { + return true; + } + + // If --outDir, check if file is in that directory + if (configFile.options.outDir && containsPath(configFile.options.outDir, fileName, currentDirectory, !host.useCaseSensitiveFileNames())) { + return true; + } + + return !forEach(configFile.fileNames, inputFile => isSameFile(fileName, inputFile)); + } + + function isSameFile(file1: string, file2: string) { + return comparePaths(file1, file2, currentDirectory, !host.useCaseSensitiveFileNames()) === Comparison.EqualTo; + } + + function invalidateProjectAndScheduleBuilds(resolved: ResolvedConfigFileName, reloadLevel: ConfigFileProgramReloadLevel) { reportFileChangeDetected = true; - invalidateProject(resolved); + invalidateProject(resolved, reloadLevel); scheduleBuildInvalidatedProject(); } @@ -598,7 +641,7 @@ namespace ts { } function getUpToDateStatusOfFile(configFileName: ResolvedConfigFileName): UpToDateStatus { - return getUpToDateStatus(configFileCache.parseConfigFile(configFileName)); + return getUpToDateStatus(parseConfigFile(configFileName)); } function getBuildGraph(configFileNames: ReadonlyArray) { @@ -712,7 +755,7 @@ namespace ts { for (const ref of project.projectReferences) { usesPrepend = usesPrepend || !!(ref.prepend); const resolvedRef = resolveProjectReferencePath(host, ref); - const refStatus = getUpToDateStatus(configFileCache.parseConfigFile(resolvedRef)); + const refStatus = getUpToDateStatus(parseConfigFile(resolvedRef)); // An upstream project is blocked if (refStatus.type === UpToDateStatusType.Unbuildable) { @@ -789,7 +832,7 @@ namespace ts { }; } - function invalidateProject(configFileName: string) { + function invalidateProject(configFileName: string, reloadLevel?: ConfigFileProgramReloadLevel) { const resolved = resolveProjectName(configFileName); if (resolved === undefined) { // If this was a rootName, we need to track it as missing. @@ -800,13 +843,12 @@ namespace ts { return; } - configFileCache.removeKey(resolved); context.projectStatus.removeKey(resolved); if (context.options.watch) { context.diagnostics!.removeKey(resolved); } - context.invalidateProject(resolved, getGlobalDependencyGraph()); + context.invalidateProject(resolved, reloadLevel, getGlobalDependencyGraph()); } function scheduleBuildInvalidatedProject() { @@ -826,14 +868,16 @@ namespace ts { reportWatchStatus(Diagnostics.File_change_detected_Starting_incremental_compilation); } const buildProject = context.getNextInvalidatedProject(); - buildSomeProjects(p => p === buildProject); - if (context.hasPendingInvalidatedProjects()) { - if (!timerToBuildInvalidatedProject) { - scheduleBuildInvalidatedProject(); + if (buildProject) { + buildSingleInvalidatedProject(buildProject.project, buildProject.reloadLevel); + if (context.hasPendingInvalidatedProjects()) { + if (!timerToBuildInvalidatedProject) { + scheduleBuildInvalidatedProject(); + } + } + else { + reportErrorSummary(); } - } - else { - reportErrorSummary(); } } @@ -845,29 +889,37 @@ namespace ts { } } - function buildSomeProjects(predicate: (projName: ResolvedConfigFileName) => boolean) { - const resolvedNames: ResolvedConfigFileName[] | undefined = resolveProjectNames(rootNames); - if (resolvedNames === undefined) return; + function buildSingleInvalidatedProject(project: ResolvedConfigFileName, reloadLevel: ConfigFileProgramReloadLevel) { + // TODO:: handle this in better way later - const graph = createDependencyGraph(resolvedNames)!; - for (const next of graph.buildQueue) { - if (!predicate(next)) continue; + const resolved = resolveProjectName(project); + if (!resolved) return; // ?? + const proj = parseConfigFile(resolved); + if (!proj) return; // ? + // TODO:: If full reload , update watch for wild cards + // TODO:: If full or partial reload, update watch for input files - const resolved = resolveProjectName(next); - if (!resolved) continue; // ?? - const proj = configFileCache.parseConfigFile(resolved); - if (!proj) continue; // ? - - const status = getUpToDateStatus(proj); - verboseReportProjectStatus(next, status); - - if (status.type === UpToDateStatusType.UpstreamBlocked) { - if (context.options.verbose) reportStatus(Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors, resolved, status.upstreamProjectName); - continue; + if (reloadLevel === ConfigFileProgramReloadLevel.Partial) { + // Update file names + const result = getFileNamesFromConfigSpecs(proj.configFileSpecs!, getDirectoryPath(project), proj.options, parseConfigFileHost); + if (result.fileNames.length !== 0) { + filterMutate(proj.errors, error => !isErrorNoInputFiles(error)); } - - buildSingleProject(next); + else if (!proj.configFileSpecs!.filesSpecs && !some(proj.errors, isErrorNoInputFiles)) { + proj.errors.push(getErrorForNoInputFiles(proj.configFileSpecs!, resolved)); + } + proj.fileNames = result.fileNames; } + + const status = getUpToDateStatus(proj); + verboseReportProjectStatus(project, status); + + if (status.type === UpToDateStatusType.UpstreamBlocked) { + if (context.options.verbose) reportStatus(Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors, resolved, status.upstreamProjectName); + return; + } + + buildSingleProject(project); } function createDependencyGraph(roots: ResolvedConfigFileName[]): DependencyGraph | undefined { @@ -907,7 +959,7 @@ namespace ts { temporaryMarks[projPath] = true; circularityReportStack.push(projPath); - const parsed = configFileCache.parseConfigFile(projPath); + const parsed = parseConfigFile(projPath); if (parsed === undefined) { hadError = true; return; @@ -941,10 +993,11 @@ namespace ts { let resultFlags = BuildResultFlags.None; resultFlags |= BuildResultFlags.DeclarationOutputUnchanged; - const configFile = configFileCache.parseConfigFile(proj); + const configFile = parseConfigFile(proj); if (!configFile) { // Failed to read the config file resultFlags |= BuildResultFlags.ConfigFileErrors; + host.reportDiagnostic(configFileCache.getValue(proj) as Diagnostic); storeErrorSummary(proj, 1); context.projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Config file errors" }); return resultFlags; @@ -959,7 +1012,8 @@ namespace ts { projectReferences: configFile.projectReferences, host, rootNames: configFile.fileNames, - options: configFile.options + options: configFile.options, + configFileParsingDiagnostics: configFile.errors }; const program = createProgram(programOptions); @@ -1068,7 +1122,7 @@ namespace ts { const filesToDelete: string[] = []; for (const proj of graph.buildQueue) { - const parsed = configFileCache.parseConfigFile(proj); + const parsed = parseConfigFile(proj); if (parsed === undefined) { // File has gone missing; fine to ignore here continue; @@ -1155,7 +1209,7 @@ namespace ts { let anyFailed = false; for (const next of queue) { - const proj = configFileCache.parseConfigFile(next); + const proj = parseConfigFile(next); if (proj === undefined) { anyFailed = true; break; diff --git a/src/testRunner/unittests/tsbuildWatchMode.ts b/src/testRunner/unittests/tsbuildWatchMode.ts index daa1276e023..c9c57379ec2 100644 --- a/src/testRunner/unittests/tsbuildWatchMode.ts +++ b/src/testRunner/unittests/tsbuildWatchMode.ts @@ -26,8 +26,12 @@ namespace ts.tscWatch { type SubProjectFiles = [ReadonlyFile, ReadonlyFile] | [ReadonlyFile, ReadonlyFile, ReadonlyFile, ReadonlyFile]; const root = Harness.IO.getWorkspaceRoot(); + function projectPath(subProject: SubProject) { + return `${projectsLocation}/${project}/${subProject}`; + } + function projectFilePath(subProject: SubProject, baseFileName: string) { - return `${projectsLocation}/${project}/${subProject}/${baseFileName.toLowerCase()}`; + return `${projectPath(subProject)}/${baseFileName.toLowerCase()}`; } function projectFile(subProject: SubProject, baseFileName: string): File { @@ -92,7 +96,7 @@ namespace ts.tscWatch { createSolutionBuilderWithWatch(host, [`${project}/${SubProject.tests}`]); checkWatchedFiles(host, testProjectExpectedWatchedFiles); checkWatchedDirectories(host, emptyArray, /*recursive*/ false); - checkWatchedDirectories(host, emptyArray, /*recursive*/ true); // TODO: #26524 + checkWatchedDirectories(host, [projectPath(SubProject.core), projectPath(SubProject.logic)], /*recursive*/ true); checkOutputErrorsInitial(host, emptyArray); const outputFileStamps = getOutputFileStamps(host); for (const stamp of outputFileStamps) { From 228858f36c04bdfaab4303a4a826791a6e2b7cae Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 10 Sep 2018 15:46:33 -0700 Subject: [PATCH 15/83] Inline builder context instead of it being outside for easier access and resetting --- src/compiler/tsbuild.ts | 271 +++++++++++++++++++--------------------- 1 file changed, 127 insertions(+), 144 deletions(-) diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts index 55af0080983..fd0f7350abe 100644 --- a/src/compiler/tsbuild.ts +++ b/src/compiler/tsbuild.ts @@ -11,38 +11,6 @@ namespace ts { message(diag: DiagnosticMessage, ...args: string[]): void; } - /** - * A BuildContext tracks what's going on during the course of a build. - * - * Callers may invoke any number of build requests within the same context; - * until the context is reset, each project will only be built at most once. - * - * Example: In a standard setup where project B depends on project A, and both are out of date, - * a failed build of A will result in A remaining out of date. When we try to build - * B, we should immediately bail instead of recomputing A's up-to-date status again. - * - * This also matters for performing fast (i.e. fake) downstream builds of projects - * when their upstream .d.ts files haven't changed content (but have newer timestamps) - */ - export interface BuildContext { - options: BuildOptions; - /** - * Map from output file name to its pre-build timestamp - */ - unchangedOutputs: FileMap; - - /** - * Map from config file name to up-to-date status - */ - projectStatus: ConfigFileMap; - diagnostics?: ConfigFileMap; // TODO(shkamat): this should be really be diagnostics but thats for later time - - invalidateProject(project: ResolvedConfigFileName, reloadLevel: ConfigFileProgramReloadLevel | undefined, dependencyGraph: DependencyGraph | undefined): void; - getNextInvalidatedProject(): { project: ResolvedConfigFileName, reloadLevel: ConfigFileProgramReloadLevel } | undefined; - hasPendingInvalidatedProjects(): boolean; - missingRoots: Map; - } - type Mapper = ReturnType; interface DependencyGraph { buildQueue: ResolvedConfigFileName[]; @@ -196,6 +164,7 @@ namespace ts { removeKey(fileName: U): void; forEach(action: (value: T, key: V) => void): void; getSize(): number; + clear(): void; } type ResolvedConfigFilePath = ResolvedConfigFileName & Path; @@ -218,7 +187,8 @@ namespace ts { removeKey, forEach, hasKey, - getSize + getSize, + clear }; function forEach(action: (value: T, key: V) => void) { @@ -244,6 +214,10 @@ namespace ts { function getSize() { return lookup.size; } + + function clear() { + lookup.clear(); + } } function createDependencyMapper(toPath: ToResolvedConfigFilePath) { @@ -341,7 +315,6 @@ namespace ts { return opts.rootDir || getDirectoryPath(configFileName); } - function newer(date1: Date, date2: Date): Date { return date2 > date1 ? date2 : date1; } @@ -350,76 +323,6 @@ namespace ts { return fileExtensionIs(fileName, Extension.Dts); } - export function createBuildContext(options: BuildOptions, toPath: ToResolvedConfigFilePath): BuildContext { - const invalidatedProjectQueue = [] as ResolvedConfigFileName[]; - let nextIndex = 0; - const projectPendingBuild = createFileMap(toPath); - const missingRoots = createMap(); - const diagnostics = options.watch ? createFileMap(toPath) : undefined; - - return { - options, - projectStatus: createFileMap(toPath), - diagnostics, - unchangedOutputs: createFileMap(toPath as ToPath), - invalidateProject, - getNextInvalidatedProject, - hasPendingInvalidatedProjects, - missingRoots - }; - - function invalidateProject(proj: ResolvedConfigFileName, reloadLevel: ConfigFileProgramReloadLevel | undefined, dependencyGraph: DependencyGraph | undefined) { - if (addProjToQueue(proj, reloadLevel) && dependencyGraph) { - queueBuildForDownstreamReferences(proj, dependencyGraph); - } - } - - /** - * return true if new addition - */ - function addProjToQueue(proj: ResolvedConfigFileName, reloadLevel?: ConfigFileProgramReloadLevel) { - const value = projectPendingBuild.getValue(proj); - if (value === undefined) { - projectPendingBuild.setValue(proj, reloadLevel || ConfigFileProgramReloadLevel.None); - invalidatedProjectQueue.push(proj); - return true; - } - - if (value < (reloadLevel || ConfigFileProgramReloadLevel.None)) { - projectPendingBuild.setValue(proj, reloadLevel || ConfigFileProgramReloadLevel.None); - } - } - - function getNextInvalidatedProject() { - if (nextIndex < invalidatedProjectQueue.length) { - const project = invalidatedProjectQueue[nextIndex]; - nextIndex++; - const reloadLevel = projectPendingBuild.getValue(project)!; - projectPendingBuild.removeKey(project); - if (!projectPendingBuild.getSize()) { - invalidatedProjectQueue.length = 0; - nextIndex = 0; - } - return { project, reloadLevel }; - } - } - - function hasPendingInvalidatedProjects() { - return !!projectPendingBuild.getSize(); - } - - // Mark all downstream projects of this one needing to be built "later" - function queueBuildForDownstreamReferences(root: ResolvedConfigFileName, dependencyGraph: DependencyGraph) { - const deps = dependencyGraph.dependencyMap.getReferencesTo(root); - for (const ref of deps) { - // Can skip circular references - if (addProjToQueue(ref)) { - queueBuildForDownstreamReferences(ref, dependencyGraph); - } - } - } - } - export interface SolutionBuilderHost extends CompilerHost { getModifiedTime(fileName: string): Date | undefined; setModifiedTime(fileName: string, date: Date): void; @@ -475,12 +378,27 @@ namespace ts { const currentDirectory = host.getCurrentDirectory(); const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames()); const parseConfigFileHost = parseConfigHostFromCompilerHost(host); + + // State of the solution + let options = defaultOptions; type ConfigFileCacheEntry = ParsedCommandLine | Diagnostic; const configFileCache = createFileMap(toPath); - let context = createBuildContext(defaultOptions, toPath); + /** Map from output file name to its pre-build timestamp */ + const unchangedOutputs = createFileMap(toPath as ToPath); + /** Map from config file name to up-to-date status */ + const projectStatus = createFileMap(toPath); + const missingRoots = createMap(); + + // Watch state + // TODO(shkamat): this should be really be diagnostics but thats for later time + const diagnostics = createFileMap(toPath); + const projectPendingBuild = createFileMap(toPath); + const invalidatedProjectQueue = [] as ResolvedConfigFileName[]; + let nextProjectToBuild = 0; let timerToBuildInvalidatedProject: any; let reportFileChangeDetected = false; + // Watches for the solution const existingWatchersForWildcards = createFileMap>(toPath); return { @@ -505,6 +423,25 @@ namespace ts { return ts.toPath(fileName, currentDirectory, getCanonicalFileName); } + function resetBuildContext(opts = defaultOptions) { + options = opts; + configFileCache.clear(); + unchangedOutputs.clear(); + projectStatus.clear(); + missingRoots.clear(); + + diagnostics.clear(); + projectPendingBuild.clear(); + invalidatedProjectQueue.length = 0; + nextProjectToBuild = 0; + if (timerToBuildInvalidatedProject) { + clearTimeout(timerToBuildInvalidatedProject); + timerToBuildInvalidatedProject = undefined; + } + reportFileChangeDetected = false; + existingWatchersForWildcards.forEach(wildCardWatches => clearMap(wildCardWatches, closeFileWatcherOf)); + } + function isParsedCommandLine(entry: ConfigFileCacheEntry): entry is ParsedCommandLine { return !!(entry as ParsedCommandLine).options; } @@ -528,20 +465,20 @@ namespace ts { } function storeErrors(proj: ResolvedConfigFileName, diagnostics: ReadonlyArray) { - if (context.options.watch) { + if (options.watch) { storeErrorSummary(proj, diagnostics.filter(diagnostic => diagnostic.category === DiagnosticCategory.Error).length); } } function storeErrorSummary(proj: ResolvedConfigFileName, errorCount: number) { - if (context.options.watch) { - context.diagnostics!.setValue(proj, errorCount); + if (options.watch) { + diagnostics.setValue(proj, errorCount); } } function reportWatchStatus(message: DiagnosticMessage, ...args: (string | number | undefined)[]) { if (hostWithWatch.onWatchStatusChange) { - hostWithWatch.onWatchStatusChange(createCompilerDiagnostic(message, ...args), host.getNewLine(), { preserveWatchOutput: context.options.preserveWatchOutput }); + hostWithWatch.onWatchStatusChange(createCompilerDiagnostic(message, ...args), host.getNewLine(), { preserveWatchOutput: options.preserveWatchOutput }); } } @@ -636,10 +573,6 @@ namespace ts { scheduleBuildInvalidatedProject(); } - function resetBuildContext(opts = defaultOptions) { - context = createBuildContext(opts, toPath); - } - function getUpToDateStatusOfFile(configFileName: ResolvedConfigFileName): UpToDateStatus { return getUpToDateStatus(parseConfigFile(configFileName)); } @@ -660,13 +593,13 @@ namespace ts { return { type: UpToDateStatusType.Unbuildable, reason: "File deleted mid-build" }; } - const prior = context.projectStatus.getValue(project.options.configFilePath as ResolvedConfigFilePath); + const prior = projectStatus.getValue(project.options.configFilePath as ResolvedConfigFilePath); if (prior !== undefined) { return prior; } const actual = getUpToDateStatusWorker(project); - context.projectStatus.setValue(project.options.configFilePath as ResolvedConfigFilePath, actual); + projectStatus.setValue(project.options.configFilePath as ResolvedConfigFilePath, actual); return actual; } @@ -737,7 +670,7 @@ namespace ts { // had its file touched but not had its contents changed - this allows us // to skip a downstream typecheck if (isDeclarationFile(output)) { - const unchangedTime = context.unchangedOutputs.getValue(output); + const unchangedTime = unchangedOutputs.getValue(output); if (unchangedTime !== undefined) { newestDeclarationFileContentChangedTime = newer(unchangedTime, newestDeclarationFileContentChangedTime); } @@ -843,12 +776,62 @@ namespace ts { return; } - context.projectStatus.removeKey(resolved); - if (context.options.watch) { - context.diagnostics!.removeKey(resolved); + projectStatus.removeKey(resolved); + if (options.watch) { + diagnostics.removeKey(resolved); } - context.invalidateProject(resolved, reloadLevel, getGlobalDependencyGraph()); + if (addProjToQueue(resolved, reloadLevel)) { + const dependencyGraph = getGlobalDependencyGraph(); + if (dependencyGraph) { + queueBuildForDownstreamReferences(resolved, dependencyGraph); + } + } + } + + /** + * return true if new addition + */ + function addProjToQueue(proj: ResolvedConfigFileName, reloadLevel?: ConfigFileProgramReloadLevel) { + const value = projectPendingBuild.getValue(proj); + if (value === undefined) { + projectPendingBuild.setValue(proj, reloadLevel || ConfigFileProgramReloadLevel.None); + invalidatedProjectQueue.push(proj); + return true; + } + + if (value < (reloadLevel || ConfigFileProgramReloadLevel.None)) { + projectPendingBuild.setValue(proj, reloadLevel || ConfigFileProgramReloadLevel.None); + } + } + + function getNextInvalidatedProject() { + if (nextProjectToBuild < invalidatedProjectQueue.length) { + const project = invalidatedProjectQueue[nextProjectToBuild]; + nextProjectToBuild++; + const reloadLevel = projectPendingBuild.getValue(project)!; + projectPendingBuild.removeKey(project); + if (!projectPendingBuild.getSize()) { + invalidatedProjectQueue.length = 0; + nextProjectToBuild = 0; + } + return { project, reloadLevel }; + } + } + + function hasPendingInvalidatedProjects() { + return !!projectPendingBuild.getSize(); + } + + // Mark all downstream projects of this one needing to be built "later" + function queueBuildForDownstreamReferences(root: ResolvedConfigFileName, dependencyGraph: DependencyGraph) { + const deps = dependencyGraph.dependencyMap.getReferencesTo(root); + for (const ref of deps) { + // Can skip circular references + if (addProjToQueue(ref)) { + queueBuildForDownstreamReferences(ref, dependencyGraph); + } + } } function scheduleBuildInvalidatedProject() { @@ -867,10 +850,10 @@ namespace ts { reportFileChangeDetected = false; reportWatchStatus(Diagnostics.File_change_detected_Starting_incremental_compilation); } - const buildProject = context.getNextInvalidatedProject(); + const buildProject = getNextInvalidatedProject(); if (buildProject) { buildSingleInvalidatedProject(buildProject.project, buildProject.reloadLevel); - if (context.hasPendingInvalidatedProjects()) { + if (hasPendingInvalidatedProjects()) { if (!timerToBuildInvalidatedProject) { scheduleBuildInvalidatedProject(); } @@ -882,9 +865,9 @@ namespace ts { } function reportErrorSummary() { - if (context.options.watch) { + if (options.watch) { let totalErrors = 0; - context.diagnostics!.forEach(singleProjectErrors => totalErrors += singleProjectErrors); + diagnostics.forEach(singleProjectErrors => totalErrors += singleProjectErrors); reportWatchStatus(totalErrors === 1 ? Diagnostics.Found_1_error_Watching_for_file_changes : Diagnostics.Found_0_errors_Watching_for_file_changes, totalErrors); } } @@ -915,7 +898,7 @@ namespace ts { verboseReportProjectStatus(project, status); if (status.type === UpToDateStatusType.UpstreamBlocked) { - if (context.options.verbose) reportStatus(Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors, resolved, status.upstreamProjectName); + if (options.verbose) reportStatus(Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors, resolved, status.upstreamProjectName); return; } @@ -983,12 +966,12 @@ namespace ts { } function buildSingleProject(proj: ResolvedConfigFileName): BuildResultFlags { - if (context.options.dry) { + if (options.dry) { reportStatus(Diagnostics.A_non_dry_build_would_build_project_0, proj); return BuildResultFlags.Success; } - if (context.options.verbose) reportStatus(Diagnostics.Building_project_0, proj); + if (options.verbose) reportStatus(Diagnostics.Building_project_0, proj); let resultFlags = BuildResultFlags.None; resultFlags |= BuildResultFlags.DeclarationOutputUnchanged; @@ -999,7 +982,7 @@ namespace ts { resultFlags |= BuildResultFlags.ConfigFileErrors; host.reportDiagnostic(configFileCache.getValue(proj) as Diagnostic); storeErrorSummary(proj, 1); - context.projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Config file errors" }); + projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Config file errors" }); return resultFlags; } @@ -1028,7 +1011,7 @@ namespace ts { host.reportDiagnostic(diag); } storeErrors(proj, syntaxDiagnostics); - context.projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Syntactic errors" }); + projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Syntactic errors" }); return resultFlags; } @@ -1041,7 +1024,7 @@ namespace ts { host.reportDiagnostic(diag); } storeErrors(proj, declDiagnostics); - context.projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Declaration file errors" }); + projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Declaration file errors" }); return resultFlags; } } @@ -1054,7 +1037,7 @@ namespace ts { host.reportDiagnostic(diag); } storeErrors(proj, semanticDiagnostics); - context.projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Semantic errors" }); + projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Semantic errors" }); return resultFlags; } @@ -1077,7 +1060,7 @@ namespace ts { host.writeFile(fileName, content, writeBom, onError, emptyArray); if (priorChangeTime !== undefined) { newestDeclarationFileContentChangedTime = newer(priorChangeTime, newestDeclarationFileContentChangedTime); - context.unchangedOutputs.setValue(fileName, priorChangeTime); + unchangedOutputs.setValue(fileName, priorChangeTime); } }); @@ -1085,16 +1068,16 @@ namespace ts { type: UpToDateStatusType.UpToDate, newestDeclarationFileContentChangedTime: anyDtsChanged ? maximumDate : newestDeclarationFileContentChangedTime }; - context.projectStatus.setValue(proj, status); + projectStatus.setValue(proj, status); return resultFlags; } function updateOutputTimestamps(proj: ParsedCommandLine) { - if (context.options.dry) { + if (options.dry) { return reportStatus(Diagnostics.A_non_dry_build_would_build_project_0, proj.options.configFilePath!); } - if (context.options.verbose) { + if (options.verbose) { reportStatus(Diagnostics.Updating_output_timestamps_of_project_0, proj.options.configFilePath!); } @@ -1109,7 +1092,7 @@ namespace ts { host.setModifiedTime(file, now); } - context.projectStatus.setValue(proj.options.configFilePath as ResolvedConfigFilePath, { type: UpToDateStatusType.UpToDate, newestDeclarationFileContentChangedTime: priorNewestUpdateTime } as UpToDateStatus); + projectStatus.setValue(proj.options.configFilePath as ResolvedConfigFilePath, { type: UpToDateStatusType.UpToDate, newestDeclarationFileContentChangedTime: priorNewestUpdateTime } as UpToDateStatus); } function getFilesToClean(configFileNames: ReadonlyArray): string[] | undefined { @@ -1158,7 +1141,7 @@ namespace ts { return ExitStatus.DiagnosticsPresent_OutputsSkipped; } - if (context.options.dry) { + if (options.dry) { reportStatus(Diagnostics.A_non_dry_build_would_delete_the_following_files_Colon_0, filesToDelete.map(f => `\r\n * ${f}`).join("")); return ExitStatus.Success; } @@ -1197,7 +1180,7 @@ namespace ts { } function buildAllProjects(): ExitStatus { - if (context.options.watch) { reportWatchStatus(Diagnostics.Starting_compilation_in_watch_mode); } + if (options.watch) { reportWatchStatus(Diagnostics.Starting_compilation_in_watch_mode); } const graph = getGlobalDependencyGraph(); if (graph === undefined) { reportErrorSummary(); @@ -1218,7 +1201,7 @@ namespace ts { verboseReportProjectStatus(next, status); const projName = proj.options.configFilePath!; - if (status.type === UpToDateStatusType.UpToDate && !context.options.force) { + if (status.type === UpToDateStatusType.UpToDate && !options.force) { // Up to date, skip if (defaultOptions.dry) { // In a dry build, inform the user of this fact @@ -1227,14 +1210,14 @@ namespace ts { continue; } - if (status.type === UpToDateStatusType.UpToDateWithUpstreamTypes && !context.options.force) { + if (status.type === UpToDateStatusType.UpToDateWithUpstreamTypes && !options.force) { // Fake build updateOutputTimestamps(proj); continue; } if (status.type === UpToDateStatusType.UpstreamBlocked) { - if (context.options.verbose) reportStatus(Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors, projName, status.upstreamProjectName); + if (options.verbose) reportStatus(Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors, projName, status.upstreamProjectName); continue; } @@ -1254,13 +1237,13 @@ namespace ts { * Report the build ordering inferred from the current project graph if we're in verbose mode */ function reportBuildQueue(graph: DependencyGraph) { - if (!context.options.verbose) return; + if (!options.verbose) return; const names: string[] = []; for (const name of graph.buildQueue) { names.push(name); } - if (context.options.verbose) reportStatus(Diagnostics.Projects_in_this_build_Colon_0, names.map(s => "\r\n * " + relName(s)).join("")); + if (options.verbose) reportStatus(Diagnostics.Projects_in_this_build_Colon_0, names.map(s => "\r\n * " + relName(s)).join("")); } function relName(path: string): string { @@ -1271,7 +1254,7 @@ namespace ts { * Report the up-to-date status of a project if we're in verbose mode */ function verboseReportProjectStatus(configFileName: string, status: UpToDateStatus) { - if (!context.options.verbose) return; + if (!options.verbose) return; return formatUpToDateStatus(configFileName, status, relName, reportStatus); } } From 6c57ebd00b6e84dba3059832b8a8e466aef783cf Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 10 Sep 2018 16:17:52 -0700 Subject: [PATCH 16/83] Update watches to wild card directories, input files, config files when project invalidates --- src/compiler/tsbuild.ts | 110 +++++++++++------ src/compiler/utilities.ts | 2 +- src/testRunner/unittests/tsbuildWatchMode.ts | 122 +++++++++++++------ 3 files changed, 155 insertions(+), 79 deletions(-) diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts index fd0f7350abe..9eada3eeb6f 100644 --- a/src/compiler/tsbuild.ts +++ b/src/compiler/tsbuild.ts @@ -399,7 +399,9 @@ namespace ts { let reportFileChangeDetected = false; // Watches for the solution - const existingWatchersForWildcards = createFileMap>(toPath); + const allWatchedWildcardDirectories = createFileMap>(toPath); + const allWatchedInputFiles = createFileMap>(toPath); + const allWatchedConfigFiles = createFileMap(toPath); return { buildAllProjects, @@ -439,7 +441,9 @@ namespace ts { timerToBuildInvalidatedProject = undefined; } reportFileChangeDetected = false; - existingWatchersForWildcards.forEach(wildCardWatches => clearMap(wildCardWatches, closeFileWatcherOf)); + clearMap(allWatchedWildcardDirectories, wildCardWatches => clearMap(wildCardWatches, closeFileWatcherOf)); + clearMap(allWatchedInputFiles, inputFileWatches => clearMap(inputFileWatches, closeFileWatcher)); + clearMap(allWatchedConfigFiles, closeFileWatcher); } function isParsedCommandLine(entry: ConfigFileCacheEntry): entry is ParsedCommandLine { @@ -493,48 +497,73 @@ namespace ts { const cfg = parseConfigFile(resolved); if (cfg) { // Watch this file - hostWithWatch.watchFile(resolved, () => { - configFileCache.removeKey(resolved); - invalidateProjectAndScheduleBuilds(resolved, ConfigFileProgramReloadLevel.Full); - }); + watchConfigFile(resolved); // Update watchers for wildcard directories - if (cfg.configFileSpecs) { - const existingWatches = existingWatchersForWildcards.getValue(resolved); - let newWatches: Map | undefined; - if (!existingWatches) { - newWatches = createMap(); - existingWatchersForWildcards.setValue(resolved, newWatches); - } - updateWatchingWildcardDirectories(existingWatches || newWatches!, createMapFromTemplate(cfg.configFileSpecs.wildcardDirectories), (dir, flags) => { - return hostWithWatch.watchDirectory(dir, fileOrDirectory => { - const fileOrDirectoryPath = toPath(fileOrDirectory); - if (fileOrDirectoryPath !== toPath(dir) && hasExtension(fileOrDirectoryPath) && !isSupportedSourceFileName(fileOrDirectory, cfg.options)) { - // writeLog(`Project: ${configFileName} Detected file add/remove of non supported extension: ${fileOrDirectory}`); - return; - } - - if (isOutputFile(fileOrDirectory, cfg)) { - // writeLog(`${fileOrDirectory} is output file`); - return; - } - - invalidateProjectAndScheduleBuilds(resolved, ConfigFileProgramReloadLevel.Partial); - }, !!(flags & WatchDirectoryFlags.Recursive)); - }); - } + watchWildCardDirectories(resolved, cfg); // Watch input files - for (const input of cfg.fileNames) { - hostWithWatch.watchFile(input, () => { - invalidateProjectAndScheduleBuilds(resolved, ConfigFileProgramReloadLevel.None); - }); - } + watchInputFiles(resolved, cfg); } } } + function watchConfigFile(resolved: ResolvedConfigFileName) { + if (!allWatchedConfigFiles.hasKey(resolved)) { + allWatchedConfigFiles.setValue(resolved, hostWithWatch.watchFile(resolved, () => { + configFileCache.removeKey(resolved); + invalidateProjectAndScheduleBuilds(resolved, ConfigFileProgramReloadLevel.Full); + })); + } + } + + function getOrCreateExistingWatches(resolved: ResolvedConfigFileName, allWatches: ConfigFileMap>) { + const existingWatches = allWatches.getValue(resolved); + let newWatches: Map | undefined; + if (!existingWatches) { + newWatches = createMap(); + allWatches.setValue(resolved, newWatches); + } + return existingWatches || newWatches!; + } + + function watchWildCardDirectories(resolved: ResolvedConfigFileName, parsed: ParsedCommandLine) { + updateWatchingWildcardDirectories( + getOrCreateExistingWatches(resolved, allWatchedWildcardDirectories), + createMapFromTemplate(parsed.configFileSpecs!.wildcardDirectories), + (dir, flags) => { + return hostWithWatch.watchDirectory(dir, fileOrDirectory => { + const fileOrDirectoryPath = toPath(fileOrDirectory); + if (fileOrDirectoryPath !== toPath(dir) && hasExtension(fileOrDirectoryPath) && !isSupportedSourceFileName(fileOrDirectory, parsed.options)) { + // writeLog(`Project: ${configFileName} Detected file add/remove of non supported extension: ${fileOrDirectory}`); + return; + } + + if (isOutputFile(fileOrDirectory, parsed)) { + // writeLog(`${fileOrDirectory} is output file`); + return; + } + + invalidateProjectAndScheduleBuilds(resolved, ConfigFileProgramReloadLevel.Partial); + }, !!(flags & WatchDirectoryFlags.Recursive)); + } + ); + } + + function watchInputFiles(resolved: ResolvedConfigFileName, parsed: ParsedCommandLine) { + mutateMap( + getOrCreateExistingWatches(resolved, allWatchedInputFiles), + arrayToMap(parsed.fileNames, toPath), + { + createNewValue: (_key, input) => hostWithWatch.watchFile(input, () => { + invalidateProjectAndScheduleBuilds(resolved, ConfigFileProgramReloadLevel.None); + }), + onDeleteValue: closeFileWatcher, + } + ); + } + function isOutputFile(fileName: string, configFile: ParsedCommandLine) { if (configFile.options.noEmit) return false; @@ -879,10 +908,12 @@ namespace ts { if (!resolved) return; // ?? const proj = parseConfigFile(resolved); if (!proj) return; // ? - // TODO:: If full reload , update watch for wild cards - // TODO:: If full or partial reload, update watch for input files - - if (reloadLevel === ConfigFileProgramReloadLevel.Partial) { + if (reloadLevel === ConfigFileProgramReloadLevel.Full) { + watchConfigFile(resolved); + watchWildCardDirectories(resolved, proj); + watchInputFiles(resolved, proj); + } + else if (reloadLevel === ConfigFileProgramReloadLevel.Partial) { // Update file names const result = getFileNamesFromConfigSpecs(proj.configFileSpecs!, getDirectoryPath(project), proj.options, parseConfigFileHost); if (result.fileNames.length !== 0) { @@ -892,6 +923,7 @@ namespace ts { proj.errors.push(getErrorForNoInputFiles(proj.configFileSpecs!, resolved)); } proj.fileNames = result.fileNames; + watchInputFiles(resolved, proj); } const status = getUpToDateStatus(proj); diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 5191fe1cc47..baf45da1516 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -4329,7 +4329,7 @@ namespace ts { /** * clears already present map by calling onDeleteExistingValue callback before deleting that key/value */ - export function clearMap(map: Map, onDeleteValue: (valueInMap: T, key: string) => void) { + export function clearMap(map: { forEach: Map["forEach"]; clear: Map["clear"]; }, onDeleteValue: (valueInMap: T, key: string) => void) { // Remove all map.forEach(onDeleteValue); map.clear(); diff --git a/src/testRunner/unittests/tsbuildWatchMode.ts b/src/testRunner/unittests/tsbuildWatchMode.ts index c9c57379ec2..bc1bc4f373d 100644 --- a/src/testRunner/unittests/tsbuildWatchMode.ts +++ b/src/testRunner/unittests/tsbuildWatchMode.ts @@ -62,13 +62,17 @@ namespace ts.tscWatch { return getOutputFileNames(subProject, baseFileNameWithoutExtension).map(f => [f, host.getModifiedTime(f)] as OutputFileStamp); } - function getOutputFileStamps(host: WatchedSystem): OutputFileStamp[] { - return [ + function getOutputFileStamps(host: WatchedSystem, additionalFiles?: ReadonlyArray<[SubProject, string]>): OutputFileStamp[] { + const result = [ ...getOutputStamps(host, SubProject.core, "anotherModule"), ...getOutputStamps(host, SubProject.core, "index"), ...getOutputStamps(host, SubProject.logic, "index"), ...getOutputStamps(host, SubProject.tests, "index"), ]; + if (additionalFiles) { + additionalFiles.forEach(([subProject, baseFileNameWithoutExtension]) => result.push(...getOutputStamps(host, subProject, baseFileNameWithoutExtension))); + } + return result; } function verifyChangedFiles(actualStamps: OutputFileStamp[], oldTimeStamps: OutputFileStamp[], changedFiles: string[]) { @@ -108,49 +112,89 @@ namespace ts.tscWatch { createSolutionInWatchMode(); }); - it("change builds changes and reports found errors message", () => { - const host = createSolutionInWatchMode(); - verifyChange(`${core[1].content} + describe("validates the changes and watched files", () => { + const newFileWithoutExtension = "newFile"; + const newFile: File = { + path: projectFilePath(SubProject.core, `${newFileWithoutExtension}.ts`), + content: `export const newFileConst = 30;` + }; + + function createSolutionInWatchModeToVerifyChanges(additionalFiles?: ReadonlyArray<[SubProject, string]>) { + const host = createSolutionInWatchMode(); + return { host, verifyChangeWithFile, verifyChangeAfterTimeout, verifyWatches }; + + function verifyChangeWithFile(fileName: string, content: string) { + const outputFileStamps = getOutputFileStamps(host, additionalFiles); + host.writeFile(fileName, content); + verifyChangeAfterTimeout(outputFileStamps); + } + + function verifyChangeAfterTimeout(outputFileStamps: OutputFileStamp[]) { + host.checkTimeoutQueueLengthAndRun(1); // Builds core + const changedCore = getOutputFileStamps(host, additionalFiles); + verifyChangedFiles(changedCore, outputFileStamps, [ + ...getOutputFileNames(SubProject.core, "anotherModule"), // This should not be written really + ...getOutputFileNames(SubProject.core, "index"), + ...(additionalFiles ? getOutputFileNames(SubProject.core, newFileWithoutExtension) : emptyArray) + ]); + host.checkTimeoutQueueLengthAndRun(1); // Builds tests + const changedTests = getOutputFileStamps(host, additionalFiles); + verifyChangedFiles(changedTests, changedCore, [ + ...getOutputFileNames(SubProject.tests, "index") // Again these need not be written + ]); + host.checkTimeoutQueueLengthAndRun(1); // Builds logic + const changedLogic = getOutputFileStamps(host, additionalFiles); + verifyChangedFiles(changedLogic, changedTests, [ + ...getOutputFileNames(SubProject.logic, "index") // Again these need not be written + ]); + host.checkTimeoutQueueLength(0); + checkOutputErrorsIncremental(host, emptyArray); + verifyWatches(); + } + + function verifyWatches() { + checkWatchedFiles(host, additionalFiles ? testProjectExpectedWatchedFiles.concat(newFile.path) : testProjectExpectedWatchedFiles); + checkWatchedDirectories(host, emptyArray, /*recursive*/ false); + checkWatchedDirectories(host, [projectPath(SubProject.core), projectPath(SubProject.logic)], /*recursive*/ true); + } + } + + it("change builds changes and reports found errors message", () => { + const { host, verifyChangeWithFile, verifyChangeAfterTimeout } = createSolutionInWatchModeToVerifyChanges(); + verifyChange(`${core[1].content} export class someClass { }`); - // Another change requeues and builds it - verifyChange(core[1].content); + // Another change requeues and builds it + verifyChange(core[1].content); - // Two changes together report only single time message: File change detected. Starting incremental compilation... - const outputFileStamps = getOutputFileStamps(host); - const change1 = `${core[1].content} -export class someClass { }`; - host.writeFile(core[1].path, change1); - host.writeFile(core[1].path, `${change1} -export class someClass2 { }`); - verifyChangeAfterTimeout(outputFileStamps); - - function verifyChange(coreContent: string) { + // Two changes together report only single time message: File change detected. Starting incremental compilation... const outputFileStamps = getOutputFileStamps(host); - host.writeFile(core[1].path, coreContent); + const change1 = `${core[1].content} +export class someClass { }`; + host.writeFile(core[1].path, change1); + host.writeFile(core[1].path, `${change1} +export class someClass2 { }`); verifyChangeAfterTimeout(outputFileStamps); - } - function verifyChangeAfterTimeout(outputFileStamps: OutputFileStamp[]) { - host.checkTimeoutQueueLengthAndRun(1); // Builds core - const changedCore = getOutputFileStamps(host); - verifyChangedFiles(changedCore, outputFileStamps, [ - ...getOutputFileNames(SubProject.core, "anotherModule"), // This should not be written really - ...getOutputFileNames(SubProject.core, "index") - ]); - host.checkTimeoutQueueLengthAndRun(1); // Builds tests - const changedTests = getOutputFileStamps(host); - verifyChangedFiles(changedTests, changedCore, [ - ...getOutputFileNames(SubProject.tests, "index") // Again these need not be written - ]); - host.checkTimeoutQueueLengthAndRun(1); // Builds logic - const changedLogic = getOutputFileStamps(host); - verifyChangedFiles(changedLogic, changedTests, [ - ...getOutputFileNames(SubProject.logic, "index") // Again these need not be written - ]); - host.checkTimeoutQueueLength(0); - checkOutputErrorsIncremental(host, emptyArray); - } + function verifyChange(coreContent: string) { + verifyChangeWithFile(core[1].path, coreContent); + } + }); + + it("builds when new file is added, and its subsequent updates", () => { + const additinalFiles: ReadonlyArray<[SubProject, string]> = [[SubProject.core, newFileWithoutExtension]]; + const { verifyChangeWithFile } = createSolutionInWatchModeToVerifyChanges(additinalFiles); + verifyChange(newFile.content); + + // Another change requeues and builds it + verifyChange(`${newFile.content} +export class someClass2 { }`); + + function verifyChange(newFileContent: string) { + verifyChangeWithFile(newFile.path, newFileContent); + } + }); + }); // TODO: write tests reporting errors but that will have more involved work since file From 6b2ea463b2251d0452029f4b108e502d7f3030f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E6=96=87=E7=92=90?= Date: Tue, 11 Sep 2018 14:35:01 +0800 Subject: [PATCH 17/83] improve Diagnostics for accidentally calling type-assertion expressions --- src/compiler/checker.ts | 7 +++ src/compiler/diagnosticMessages.json | 4 ++ ...CallingTypeAssertionExpressions.errors.txt | 35 ++++++++++++++ ...dentallyCallingTypeAssertionExpressions.js | 19 ++++++++ ...llyCallingTypeAssertionExpressions.symbols | 20 ++++++++ ...tallyCallingTypeAssertionExpressions.types | 48 +++++++++++++++++++ ...dentallyCallingTypeAssertionExpressions.ts | 11 +++++ 7 files changed, 144 insertions(+) create mode 100644 tests/baselines/reference/betterErrorForAccidentallyCallingTypeAssertionExpressions.errors.txt create mode 100644 tests/baselines/reference/betterErrorForAccidentallyCallingTypeAssertionExpressions.js create mode 100644 tests/baselines/reference/betterErrorForAccidentallyCallingTypeAssertionExpressions.symbols create mode 100644 tests/baselines/reference/betterErrorForAccidentallyCallingTypeAssertionExpressions.types create mode 100644 tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ae0124616a4..2b146e230ff 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -19655,6 +19655,13 @@ namespace ts { error(node, Diagnostics.Value_of_type_0_is_not_callable_Did_you_mean_to_include_new, typeToString(funcType)); } else { + if (node.arguments.length === 1 && isTypeAssertion(first(node.arguments))) { + const text = getSourceFileOfNode(node).text; + const pos = skipTrivia(text, node.expression.end, /* stepAfterLineBreak */ true) - 1; + if (isLineBreak(text.charCodeAt(pos))) { + error(node.expression, Diagnostics.It_is_highly_likely_that_you_are_missing_a_semicolon); + } + } invocationError(node, apparentType, SignatureKind.Call); } return resolveErrorCall(node); diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 4384167a4e0..399afb4ebc6 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2457,6 +2457,10 @@ "category": "Error", "code": 2733 }, + "It is highly likely that you are missing a semicolon.": { + "category": "Error", + "code": 2734 + }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", diff --git a/tests/baselines/reference/betterErrorForAccidentallyCallingTypeAssertionExpressions.errors.txt b/tests/baselines/reference/betterErrorForAccidentallyCallingTypeAssertionExpressions.errors.txt new file mode 100644 index 00000000000..b27c6b06d48 --- /dev/null +++ b/tests/baselines/reference/betterErrorForAccidentallyCallingTypeAssertionExpressions.errors.txt @@ -0,0 +1,35 @@ +tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts(3,1): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures. +tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts(5,1): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures. +tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts(7,1): error TS2734: It is highly likely that you are missing a semicolon. +tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts(7,1): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures. +tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts(10,1): error TS2734: It is highly likely that you are missing a semicolon. +tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts(10,1): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures. + + +==== tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts (6 errors) ==== + declare function foo(): string; + + foo()(1 as number).toString(); + ~~~~~~~~~~~~~~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures. + + foo() (1 as number).toString(); + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures. + + foo() + ~~~~~ +!!! error TS2734: It is highly likely that you are missing a semicolon. + ~~~~~ + (1 as number).toString(); + ~~~~~~~~~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures. + + foo() + ~~~~~ +!!! error TS2734: It is highly likely that you are missing a semicolon. + ~~~~~~~~ + (1 as number).toString(); + ~~~~~~~~~~~~~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures. + \ No newline at end of file diff --git a/tests/baselines/reference/betterErrorForAccidentallyCallingTypeAssertionExpressions.js b/tests/baselines/reference/betterErrorForAccidentallyCallingTypeAssertionExpressions.js new file mode 100644 index 00000000000..ff22844b48b --- /dev/null +++ b/tests/baselines/reference/betterErrorForAccidentallyCallingTypeAssertionExpressions.js @@ -0,0 +1,19 @@ +//// [betterErrorForAccidentallyCallingTypeAssertionExpressions.ts] +declare function foo(): string; + +foo()(1 as number).toString(); + +foo() (1 as number).toString(); + +foo() +(1 as number).toString(); + +foo() + (1 as number).toString(); + + +//// [betterErrorForAccidentallyCallingTypeAssertionExpressions.js] +foo()(1).toString(); +foo()(1).toString(); +foo()(1).toString(); +foo()(1).toString(); diff --git a/tests/baselines/reference/betterErrorForAccidentallyCallingTypeAssertionExpressions.symbols b/tests/baselines/reference/betterErrorForAccidentallyCallingTypeAssertionExpressions.symbols new file mode 100644 index 00000000000..fb49ecd070a --- /dev/null +++ b/tests/baselines/reference/betterErrorForAccidentallyCallingTypeAssertionExpressions.symbols @@ -0,0 +1,20 @@ +=== tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts === +declare function foo(): string; +>foo : Symbol(foo, Decl(betterErrorForAccidentallyCallingTypeAssertionExpressions.ts, 0, 0)) + +foo()(1 as number).toString(); +>foo : Symbol(foo, Decl(betterErrorForAccidentallyCallingTypeAssertionExpressions.ts, 0, 0)) + +foo() (1 as number).toString(); +>foo : Symbol(foo, Decl(betterErrorForAccidentallyCallingTypeAssertionExpressions.ts, 0, 0)) + +foo() +>foo : Symbol(foo, Decl(betterErrorForAccidentallyCallingTypeAssertionExpressions.ts, 0, 0)) + +(1 as number).toString(); + +foo() +>foo : Symbol(foo, Decl(betterErrorForAccidentallyCallingTypeAssertionExpressions.ts, 0, 0)) + + (1 as number).toString(); + diff --git a/tests/baselines/reference/betterErrorForAccidentallyCallingTypeAssertionExpressions.types b/tests/baselines/reference/betterErrorForAccidentallyCallingTypeAssertionExpressions.types new file mode 100644 index 00000000000..a9569a9dadf --- /dev/null +++ b/tests/baselines/reference/betterErrorForAccidentallyCallingTypeAssertionExpressions.types @@ -0,0 +1,48 @@ +=== tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts === +declare function foo(): string; +>foo : () => string + +foo()(1 as number).toString(); +>foo()(1 as number).toString() : any +>foo()(1 as number).toString : any +>foo()(1 as number) : any +>foo() : string +>foo : () => string +>1 as number : number +>1 : 1 +>toString : any + +foo() (1 as number).toString(); +>foo() (1 as number).toString() : any +>foo() (1 as number).toString : any +>foo() (1 as number) : any +>foo() : string +>foo : () => string +>1 as number : number +>1 : 1 +>toString : any + +foo() +>foo()(1 as number).toString() : any +>foo()(1 as number).toString : any +>foo()(1 as number) : any +>foo() : string +>foo : () => string + +(1 as number).toString(); +>1 as number : number +>1 : 1 +>toString : any + +foo() +>foo() (1 as number).toString() : any +>foo() (1 as number).toString : any +>foo() (1 as number) : any +>foo() : string +>foo : () => string + + (1 as number).toString(); +>1 as number : number +>1 : 1 +>toString : any + diff --git a/tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts b/tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts new file mode 100644 index 00000000000..957dc5cab75 --- /dev/null +++ b/tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts @@ -0,0 +1,11 @@ +declare function foo(): string; + +foo()(1 as number).toString(); + +foo() (1 as number).toString(); + +foo() +(1 as number).toString(); + +foo() + (1 as number).toString(); From 66a401ae648b51e0553dcf5a208a849dadf05b83 Mon Sep 17 00:00:00 2001 From: Klaus Meinhardt Date: Tue, 11 Sep 2018 09:39:11 +0200 Subject: [PATCH 18/83] Fix FunctionType emit when only parameter has no type Fixes: #27018 --- src/compiler/emitter.ts | 3 ++- .../reference/printerApi/printsNodeCorrectly.functionTypes.js | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 8cb1d4f34a9..55e690f8ae8 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -2818,7 +2818,8 @@ namespace ts { const parameter = singleOrUndefined(parameters); return parameter && parameter.pos === parentNode.pos // may not have parsed tokens between parent and parameter - && !(isArrowFunction(parentNode) && parentNode.type) // arrow function may not have return type annotation + && isArrowFunction(parentNode) // only arrow functions may have simple arrow head + && !parentNode.type // arrow function may not have return type annotation && !some(parentNode.decorators) // parent may not have decorators && !some(parentNode.modifiers) // parent may not have modifiers && !some(parentNode.typeParameters) // parent may not have type parameters diff --git a/tests/baselines/reference/printerApi/printsNodeCorrectly.functionTypes.js b/tests/baselines/reference/printerApi/printsNodeCorrectly.functionTypes.js index 5bfda3ba7c9..10ca78d89c8 100644 --- a/tests/baselines/reference/printerApi/printsNodeCorrectly.functionTypes.js +++ b/tests/baselines/reference/printerApi/printsNodeCorrectly.functionTypes.js @@ -1 +1 @@ -[args => any, (args) => any, (...args) => any, (args?) => any, (args: any) => any, ({}) => any] \ No newline at end of file +[(args) => any, (args) => any, (...args) => any, (args?) => any, (args: any) => any, ({}) => any] \ No newline at end of file From 2cf2bbd5f77a7756e6861fd2942e68e279046b28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E6=96=87=E7=92=90?= Date: Tue, 11 Sep 2018 16:20:38 +0800 Subject: [PATCH 19/83] improve test case and add related diagnostic --- src/compiler/checker.ts | 19 ++++++++++--------- ...CallingTypeAssertionExpressions.errors.txt | 18 +++++++++++------- ...dentallyCallingTypeAssertionExpressions.js | 4 ++++ ...llyCallingTypeAssertionExpressions.symbols | 5 +++++ ...tallyCallingTypeAssertionExpressions.types | 12 ++++++++++++ ...dentallyCallingTypeAssertionExpressions.ts | 3 +++ 6 files changed, 45 insertions(+), 16 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2b146e230ff..96e72a9e07e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -19655,14 +19655,14 @@ namespace ts { error(node, Diagnostics.Value_of_type_0_is_not_callable_Did_you_mean_to_include_new, typeToString(funcType)); } else { + let relatedInformation: DiagnosticRelatedInformation | undefined; if (node.arguments.length === 1 && isTypeAssertion(first(node.arguments))) { const text = getSourceFileOfNode(node).text; - const pos = skipTrivia(text, node.expression.end, /* stepAfterLineBreak */ true) - 1; - if (isLineBreak(text.charCodeAt(pos))) { - error(node.expression, Diagnostics.It_is_highly_likely_that_you_are_missing_a_semicolon); + if (isLineBreak(text.charCodeAt(skipTrivia(text, node.expression.end, /* stopAfterLineBreak */ true) - 1))) { + relatedInformation = createDiagnosticForNode(node.expression, Diagnostics.It_is_highly_likely_that_you_are_missing_a_semicolon); } } - invocationError(node, apparentType, SignatureKind.Call); + invocationError(node, apparentType, SignatureKind.Call, relatedInformation); } return resolveErrorCall(node); } @@ -19832,11 +19832,12 @@ namespace ts { return true; } - function invocationError(node: Node, apparentType: Type, kind: SignatureKind) { - invocationErrorRecovery(apparentType, kind, error(node, kind === SignatureKind.Call - ? Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures - : Diagnostics.Cannot_use_new_with_an_expression_whose_type_lacks_a_call_or_construct_signature - , typeToString(apparentType))); + function invocationError(node: Node, apparentType: Type, kind: SignatureKind, relatedInformation?: DiagnosticRelatedInformation) { + const diagnostic = error(node, (kind === SignatureKind.Call ? + Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures : + Diagnostics.Cannot_use_new_with_an_expression_whose_type_lacks_a_call_or_construct_signature + ), typeToString(apparentType)); + invocationErrorRecovery(apparentType, kind, relatedInformation ? addRelatedInfo(diagnostic, relatedInformation) : diagnostic); } function invocationErrorRecovery(apparentType: Type, kind: SignatureKind, diagnostic: Diagnostic) { diff --git a/tests/baselines/reference/betterErrorForAccidentallyCallingTypeAssertionExpressions.errors.txt b/tests/baselines/reference/betterErrorForAccidentallyCallingTypeAssertionExpressions.errors.txt index b27c6b06d48..023e40a70da 100644 --- a/tests/baselines/reference/betterErrorForAccidentallyCallingTypeAssertionExpressions.errors.txt +++ b/tests/baselines/reference/betterErrorForAccidentallyCallingTypeAssertionExpressions.errors.txt @@ -1,12 +1,11 @@ tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts(3,1): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures. tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts(5,1): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures. -tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts(7,1): error TS2734: It is highly likely that you are missing a semicolon. tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts(7,1): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures. -tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts(10,1): error TS2734: It is highly likely that you are missing a semicolon. tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts(10,1): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures. +tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts(13,1): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures. -==== tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts (6 errors) ==== +==== tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts (5 errors) ==== declare function foo(): string; foo()(1 as number).toString(); @@ -19,17 +18,22 @@ tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.t foo() ~~~~~ -!!! error TS2734: It is highly likely that you are missing a semicolon. - ~~~~~ (1 as number).toString(); ~~~~~~~~~~~~~ !!! error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures. +!!! related TS2734 tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts:7:1: It is highly likely that you are missing a semicolon. foo() - ~~~~~ -!!! error TS2734: It is highly likely that you are missing a semicolon. ~~~~~~~~ (1 as number).toString(); ~~~~~~~~~~~~~~~~~ !!! error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures. +!!! related TS2734 tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts:10:1: It is highly likely that you are missing a semicolon. + + foo() + ~~~~~~~~ + (1).toString(); + ~~~~~~~~~~~~~~~ +!!! error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures. +!!! related TS2734 tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts:13:1: It is highly likely that you are missing a semicolon. \ No newline at end of file diff --git a/tests/baselines/reference/betterErrorForAccidentallyCallingTypeAssertionExpressions.js b/tests/baselines/reference/betterErrorForAccidentallyCallingTypeAssertionExpressions.js index ff22844b48b..877ed539e71 100644 --- a/tests/baselines/reference/betterErrorForAccidentallyCallingTypeAssertionExpressions.js +++ b/tests/baselines/reference/betterErrorForAccidentallyCallingTypeAssertionExpressions.js @@ -10,6 +10,9 @@ foo() foo() (1 as number).toString(); + +foo() + (1).toString(); //// [betterErrorForAccidentallyCallingTypeAssertionExpressions.js] @@ -17,3 +20,4 @@ foo()(1).toString(); foo()(1).toString(); foo()(1).toString(); foo()(1).toString(); +foo()(1).toString(); diff --git a/tests/baselines/reference/betterErrorForAccidentallyCallingTypeAssertionExpressions.symbols b/tests/baselines/reference/betterErrorForAccidentallyCallingTypeAssertionExpressions.symbols index fb49ecd070a..9dc2e676937 100644 --- a/tests/baselines/reference/betterErrorForAccidentallyCallingTypeAssertionExpressions.symbols +++ b/tests/baselines/reference/betterErrorForAccidentallyCallingTypeAssertionExpressions.symbols @@ -18,3 +18,8 @@ foo() (1 as number).toString(); +foo() +>foo : Symbol(foo, Decl(betterErrorForAccidentallyCallingTypeAssertionExpressions.ts, 0, 0)) + + (1).toString(); + diff --git a/tests/baselines/reference/betterErrorForAccidentallyCallingTypeAssertionExpressions.types b/tests/baselines/reference/betterErrorForAccidentallyCallingTypeAssertionExpressions.types index a9569a9dadf..54564d7462c 100644 --- a/tests/baselines/reference/betterErrorForAccidentallyCallingTypeAssertionExpressions.types +++ b/tests/baselines/reference/betterErrorForAccidentallyCallingTypeAssertionExpressions.types @@ -46,3 +46,15 @@ foo() >1 : 1 >toString : any +foo() +>foo() (1).toString() : any +>foo() (1).toString : any +>foo() (1) : any +>foo() : string +>foo : () => string + + (1).toString(); +>1 : number +>1 : 1 +>toString : any + diff --git a/tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts b/tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts index 957dc5cab75..42c3025c8e3 100644 --- a/tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts +++ b/tests/cases/compiler/betterErrorForAccidentallyCallingTypeAssertionExpressions.ts @@ -9,3 +9,6 @@ foo() foo() (1 as number).toString(); + +foo() + (1).toString(); From 8c9e8666ed6f02b5f7c29430e475cbe4a4ad4444 Mon Sep 17 00:00:00 2001 From: Benjamin Lichtman Date: Thu, 6 Sep 2018 15:53:05 -0700 Subject: [PATCH 20/83] Miscellaneous cleanup --- .../codefixes/convertToAsyncFunction.ts | 27 +++++++------------ src/services/suggestionDiagnostics.ts | 14 +++------- src/services/utilities.ts | 2 +- 3 files changed, 15 insertions(+), 28 deletions(-) diff --git a/src/services/codefixes/convertToAsyncFunction.ts b/src/services/codefixes/convertToAsyncFunction.ts index 76cdf471466..9d4d6f74be4 100644 --- a/src/services/codefixes/convertToAsyncFunction.ts +++ b/src/services/codefixes/convertToAsyncFunction.ts @@ -81,19 +81,14 @@ namespace ts.codefix { } for (const statement of returnStatements) { - if (isCallExpression(statement)) { - startTransformation(statement, statement); - } - else { - forEachChild(statement, function visit(node: Node) { - if (isCallExpression(node)) { - startTransformation(node, statement); - } - else if (!isFunctionLike(node)) { - forEachChild(node, visit); - } - }); - } + forEachChild(statement, function visit(node: Node) { + if (isCallExpression(node)) { + startTransformation(node, statement); + } + else if (!isFunctionLike(node)) { + forEachChild(node, visit); + } + }); } } @@ -344,11 +339,8 @@ namespace ts.codefix { return [createTry(tryBlock, catchClause, /* finallyBlock */ undefined) as Statement]; } - else { - return transformExpression(node.expression, transformer, node, argNameRes).concat(transformationBody); - } - return []; + return transformExpression(node.expression, transformer, node, argNameRes).concat(transformationBody); } function getFlagOfIdentifier(node: Identifier, constIdentifiers: Identifier[]): NodeFlags { @@ -513,6 +505,7 @@ namespace ts.codefix { name = getMapEntryIfExists(param); } } + // currently not relevant, since we don't produce a valid transformation if the argument to a promise operation is a CallExpression else if (isCallExpression(funcNode) && funcNode.arguments.length > 0 && isIdentifier(funcNode.arguments[0])) { name = { identifier: funcNode.arguments[0] as Identifier, types, numberOfAssignmentsOriginal }; } diff --git a/src/services/suggestionDiagnostics.ts b/src/services/suggestionDiagnostics.ts index 167bcb6bbac..c1af35eefa8 100644 --- a/src/services/suggestionDiagnostics.ts +++ b/src/services/suggestionDiagnostics.ts @@ -141,8 +141,8 @@ namespace ts { } /** @internal */ - export function getReturnStatementsWithPromiseHandlers(node: Node): Node[] { - const returnStatements: Node[] = []; + export function getReturnStatementsWithPromiseHandlers(node: Node): ReturnStatement[] { + const returnStatements: ReturnStatement[] = []; if (isFunctionLike(node)) { forEachChild(node, visit); } @@ -155,14 +155,8 @@ namespace ts { return; } - if (isReturnStatement(child)) { - forEachChild(child, addHandlers); - } - - function addHandlers(returnChild: Node) { - if (isPromiseHandler(returnChild)) { - returnStatements.push(child as ReturnStatement); - } + if (isReturnStatement(child) && child.expression && isPromiseHandler(child.expression)) { + returnStatements.push(child); } forEachChild(child, visit); diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 1c10bc983fd..4559a88881e 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1671,7 +1671,7 @@ namespace ts { } if (clone && !includeTrivia) suppressLeadingAndTrailingTrivia(clone); - if (callback && node) callback(node!, clone); + if (callback && node && clone) callback(node!, clone); return clone as T; } From 7466ac1cd58b102547833f2a7c0b9037c2315d2b Mon Sep 17 00:00:00 2001 From: Benjamin Lichtman Date: Thu, 6 Sep 2018 15:53:13 -0700 Subject: [PATCH 21/83] [WIP] add test --- src/testRunner/unittests/convertToAsyncFunction.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/testRunner/unittests/convertToAsyncFunction.ts b/src/testRunner/unittests/convertToAsyncFunction.ts index 99788e1310e..d1655824216 100644 --- a/src/testRunner/unittests/convertToAsyncFunction.ts +++ b/src/testRunner/unittests/convertToAsyncFunction.ts @@ -1194,6 +1194,11 @@ const [#|foo|] = function () { } `); + _testConvertToAsyncFunction("convertToAsyncFunction_catchBlockUniqueParams", ` +function [#|f|]() { + return Promise.resolve().then(x => 1).catch(x => "a").then(x => !!x); +} +`); }); From a4c87df821259ef03fd92b9993b93e10aee7fab8 Mon Sep 17 00:00:00 2001 From: Benjamin Lichtman Date: Fri, 7 Sep 2018 16:28:47 -0700 Subject: [PATCH 22/83] [WIP] Use original identifier name to count up from when renaming collisions --- src/services/codefixes/convertToAsyncFunction.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/services/codefixes/convertToAsyncFunction.ts b/src/services/codefixes/convertToAsyncFunction.ts index 9d4d6f74be4..97658fd3e2f 100644 --- a/src/services/codefixes/convertToAsyncFunction.ts +++ b/src/services/codefixes/convertToAsyncFunction.ts @@ -240,7 +240,7 @@ namespace ts.codefix { } function getNewNameIfConflict(name: Identifier, allVarNames: SymbolAndIdentifier[]): SynthIdentifier { - const numVarsSameName = allVarNames.filter(elem => elem.identifier.text === name.text).length; + const numVarsSameName = allVarNames.filter(elem => elem.symbol.name === name.text).length; const numberOfAssignmentsOriginal = 0; const identifier = numVarsSameName === 0 ? name : createIdentifier(name.text + "_" + numVarsSameName); return { identifier, types: [], numberOfAssignmentsOriginal }; @@ -426,7 +426,7 @@ namespace ts.codefix { if (hasPrevArgName && !shouldReturn) { const type = transformer.checker.getTypeAtLocation(func); - const returnType = getLastCallSignature(type, transformer.checker).getReturnType(); + const returnType = getLastCallSignature(type, transformer.checker)!.getReturnType(); const varDeclOrAssignment = createVariableDeclarationOrAssignment(prevArgName!, getSynthesizedDeepClone(funcBody) as Expression, transformer); prevArgName!.types.push(returnType); return varDeclOrAssignment; @@ -440,7 +440,7 @@ namespace ts.codefix { return createNodeArray([]); } - function getLastCallSignature(type: Type, checker: TypeChecker): Signature { + function getLastCallSignature(type: Type, checker: TypeChecker): Signature | undefined { const callSignatures = type && checker.getSignaturesOfType(type, SignatureKind.Call); return callSignatures && callSignatures[callSignatures.length - 1]; } From 92edc2db56693186d7acf405c279c2e1898fecb5 Mon Sep 17 00:00:00 2001 From: Benjamin Lichtman Date: Fri, 7 Sep 2018 17:04:34 -0700 Subject: [PATCH 23/83] [WIP] Record original name of renamed variable --- .../codefixes/convertToAsyncFunction.ts | 22 ++++++++++--------- ...tToAsyncFunction_catchBlockUniqueParams.js | 19 ++++++++++++++++ ...tToAsyncFunction_catchBlockUniqueParams.ts | 19 ++++++++++++++++ 3 files changed, 50 insertions(+), 10 deletions(-) create mode 100644 tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_catchBlockUniqueParams.js create mode 100644 tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_catchBlockUniqueParams.ts diff --git a/src/services/codefixes/convertToAsyncFunction.ts b/src/services/codefixes/convertToAsyncFunction.ts index 97658fd3e2f..d8d6fa05d1f 100644 --- a/src/services/codefixes/convertToAsyncFunction.ts +++ b/src/services/codefixes/convertToAsyncFunction.ts @@ -25,15 +25,16 @@ namespace ts.codefix { numberOfAssignmentsOriginal: number; } - interface SymbolAndIdentifier { + interface SymbolAndIdentifierAndOriginalName { identifier: Identifier; symbol: Symbol; + originalName: string; } interface Transformer { checker: TypeChecker; synthNamesMap: Map; // keys are the symbol id of the identifier - allVarNames: SymbolAndIdentifier[]; + allVarNames: SymbolAndIdentifierAndOriginalName[]; setOfExpressionsToReturn: Map; // keys are the node ids of the expressions constIdentifiers: Identifier[]; originalTypeMap: Map; // keys are the node id of the identifier @@ -60,7 +61,7 @@ namespace ts.codefix { const synthNamesMap: Map = createMap(); const originalTypeMap: Map = createMap(); - const allVarNames: SymbolAndIdentifier[] = []; + const allVarNames: SymbolAndIdentifierAndOriginalName[] = []; const isInJSFile = isInJavaScriptFile(functionToConvert); const setOfExpressionsToReturn = getAllPromiseExpressionsToReturn(functionToConvert, checker); const functionToConvertRenamed: FunctionLikeDeclaration = renameCollidingVarNames(functionToConvert, checker, synthNamesMap, context, setOfExpressionsToReturn, originalTypeMap, allVarNames); @@ -157,7 +158,7 @@ namespace ts.codefix { This function collects all existing identifier names and names of identifiers that will be created in the refactor. It then checks for any collisions and renames them through getSynthesizedDeepClone */ - function renameCollidingVarNames(nodeToRename: FunctionLikeDeclaration, checker: TypeChecker, synthNamesMap: Map, context: CodeFixContextBase, setOfAllExpressionsToReturn: Map, originalType: Map, allVarNames: SymbolAndIdentifier[]): FunctionLikeDeclaration { + function renameCollidingVarNames(nodeToRename: FunctionLikeDeclaration, checker: TypeChecker, synthNamesMap: Map, context: CodeFixContextBase, setOfAllExpressionsToReturn: Map, originalType: Map, allVarNames: SymbolAndIdentifierAndOriginalName[]): FunctionLikeDeclaration { const identsToRenameMap: Map = createMap(); // key is the symbol id forEachChild(nodeToRename, function visit(node: Node) { @@ -177,26 +178,27 @@ namespace ts.codefix { // if the identifier refers to a function we want to add the new synthesized variable for the declaration (ex. blob in let blob = res(arg)) // Note - the choice of the last call signature is arbitrary if (lastCallSignature && lastCallSignature.parameters.length && !synthNamesMap.has(symbolIdString)) { + const name = lastCallSignature.parameters[0].name; const synthName = getNewNameIfConflict(createIdentifier(lastCallSignature.parameters[0].name), allVarNames); synthNamesMap.set(symbolIdString, synthName); - allVarNames.push({ identifier: synthName.identifier, symbol }); + allVarNames.push({ identifier: synthName.identifier, symbol, originalName: name }); } // we only care about identifiers that are parameters and declarations (don't care about other uses) else if (node.parent && (isParameter(node.parent) || isVariableDeclaration(node.parent))) { // if the identifier name conflicts with a different identifier that we've already seen - if (allVarNames.some(ident => ident.identifier.text === node.text && ident.symbol !== symbol)) { + if (allVarNames.some(ident => ident.originalName === node.text && ident.symbol !== symbol)) { const newName = getNewNameIfConflict(node, allVarNames); identsToRenameMap.set(symbolIdString, newName.identifier); synthNamesMap.set(symbolIdString, newName); - allVarNames.push({ identifier: newName.identifier, symbol }); + allVarNames.push({ identifier: newName.identifier, symbol, originalName: node.text }); } else { const identifier = getSynthesizedDeepClone(node); identsToRenameMap.set(symbolIdString, identifier); synthNamesMap.set(symbolIdString, { identifier, types: [], numberOfAssignmentsOriginal: allVarNames.filter(elem => elem.identifier.text === node.text).length/*, numberOfAssignmentsSynthesized: 0*/ }); if ((isParameter(node.parent) && isExpressionOrCallOnTypePromise(node.parent.parent)) || isVariableDeclaration(node.parent)) { - allVarNames.push({ identifier, symbol }); + allVarNames.push({ identifier, symbol, originalName: node.text }); } } } @@ -239,8 +241,8 @@ namespace ts.codefix { } - function getNewNameIfConflict(name: Identifier, allVarNames: SymbolAndIdentifier[]): SynthIdentifier { - const numVarsSameName = allVarNames.filter(elem => elem.symbol.name === name.text).length; + function getNewNameIfConflict(name: Identifier, allVarNames: SymbolAndIdentifierAndOriginalName[]): SynthIdentifier { + const numVarsSameName = allVarNames.filter(elem => elem.originalName === name.text).length; const numberOfAssignmentsOriginal = 0; const identifier = numVarsSameName === 0 ? name : createIdentifier(name.text + "_" + numVarsSameName); return { identifier, types: [], numberOfAssignmentsOriginal }; diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_catchBlockUniqueParams.js b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_catchBlockUniqueParams.js new file mode 100644 index 00000000000..2600adec16b --- /dev/null +++ b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_catchBlockUniqueParams.js @@ -0,0 +1,19 @@ +// ==ORIGINAL== + +function /*[#|*/f/*|]*/() { + return Promise.resolve().then(x => 1).catch(x => "a").then(x => !!x); +} + +// ==ASYNC FUNCTION::Convert to async function== + +async function f() { + let x_2; + try { + const x = await Promise.resolve(); + x_2 = 1; + } + catch (x_1) { + x_2 = "a"; + } + return !!x_2; +} diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_catchBlockUniqueParams.ts b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_catchBlockUniqueParams.ts new file mode 100644 index 00000000000..5c4daf076a0 --- /dev/null +++ b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_catchBlockUniqueParams.ts @@ -0,0 +1,19 @@ +// ==ORIGINAL== + +function /*[#|*/f/*|]*/() { + return Promise.resolve().then(x => 1).catch(x => "a").then(x => !!x); +} + +// ==ASYNC FUNCTION::Convert to async function== + +async function f() { + let x_2: string | number; + try { + const x = await Promise.resolve(); + x_2 = 1; + } + catch (x_1) { + x_2 = "a"; + } + return !!x_2; +} From 9079df1a4d3f6c67990674545079a1fa13eafc67 Mon Sep 17 00:00:00 2001 From: Benjamin Lichtman Date: Tue, 11 Sep 2018 11:09:31 -0700 Subject: [PATCH 24/83] Update baselines --- .../convertToAsyncFunction_InnerVarNameConflict.ts | 2 +- .../convertToAsyncFunction_MultipleReturns2.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_InnerVarNameConflict.ts b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_InnerVarNameConflict.ts index 3570a90a0b1..119d9d408bb 100644 --- a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_InnerVarNameConflict.ts +++ b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_InnerVarNameConflict.ts @@ -13,5 +13,5 @@ function /*[#|*/f/*|]*/(): Promise { async function f(): Promise { const resp = await fetch("https://typescriptlang.org"); var blob = resp.blob().then(blob_1 => blob_1.byteOffset).catch(err => 'Error'); - return blob_1.toString(); + return blob_2.toString(); } diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_MultipleReturns2.ts b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_MultipleReturns2.ts index 6569c1fb0ef..389faf61891 100644 --- a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_MultipleReturns2.ts +++ b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_MultipleReturns2.ts @@ -21,6 +21,6 @@ async function f(): Promise { } const resp = await x; var blob = resp.blob().then(blob_1 => blob_1.byteOffset).catch(err => 'Error'); - const res_1 = await fetch("https://micorosft.com"); + const res_2 = await fetch("https://micorosft.com"); return console.log("Another one!"); } From a172751bf9cf16a4652ed03f44858a73ff13bc32 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 11 Sep 2018 12:56:23 -0700 Subject: [PATCH 25/83] Always resolve the config file to ResolvedConfigFile if its json, otherwise combine tsconfig.json --- src/compiler/program.ts | 13 ++-- src/compiler/tsbuild.ts | 62 ++++++------------- src/testRunner/unittests/tsbuild.ts | 2 +- src/tsc/tsc.ts | 12 +--- .../reference/api/tsserverlibrary.d.ts | 5 +- tests/baselines/reference/api/typescript.d.ts | 5 +- 6 files changed, 28 insertions(+), 71 deletions(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index c24f570819e..c6cdceeb550 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -2341,7 +2341,7 @@ namespace ts { function parseProjectReferenceConfigFile(ref: ProjectReference): { commandLine: ParsedCommandLine, sourceFile: SourceFile } | undefined { // The actual filename (i.e. add "/tsconfig.json" if necessary) - const refPath = resolveProjectReferencePath(host, ref); + const refPath = resolveProjectReferencePath(ref); // An absolute path pointing to the containing directory of the config file const basePath = getNormalizedAbsolutePath(getDirectoryPath(refPath), host.getCurrentDirectory()); const sourceFile = host.getSourceFile(refPath, ScriptTarget.JSON) as JsonSourceFile | undefined; @@ -2820,18 +2820,13 @@ namespace ts { }; } - export interface ResolveProjectReferencePathHost { - fileExists(fileName: string): boolean; - } /** * Returns the target config filename of a project reference. * Note: The file might not exist. */ - export function resolveProjectReferencePath(host: ResolveProjectReferencePathHost, ref: ProjectReference): ResolvedConfigFileName { - if (!host.fileExists(ref.path)) { - return combinePaths(ref.path, "tsconfig.json") as ResolvedConfigFileName; - } - return ref.path as ResolvedConfigFileName; + // TODO: Does this need to be exposed + export function resolveProjectReferencePath(ref: ProjectReference): ResolvedConfigFileName { + return resolveConfigFileProjectName(ref.path); } /* @internal */ diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts index 599b6ddd882..54cd97644f6 100644 --- a/src/compiler/tsbuild.ts +++ b/src/compiler/tsbuild.ts @@ -598,7 +598,7 @@ namespace ts { function invalidateProjectAndScheduleBuilds(resolved: ResolvedConfigFileName, reloadLevel: ConfigFileProgramReloadLevel) { reportFileChangeDetected = true; - invalidateProject(resolved, reloadLevel); + invalidateResolvedProject(resolved, reloadLevel); scheduleBuildInvalidatedProject(); } @@ -716,7 +716,7 @@ namespace ts { if (project.projectReferences) { for (const ref of project.projectReferences) { usesPrepend = usesPrepend || !!(ref.prepend); - const resolvedRef = resolveProjectReferencePath(host, ref); + const resolvedRef = resolveProjectReferencePath(ref); const refStatus = getUpToDateStatus(parseConfigFile(resolvedRef)); // An upstream project is blocked @@ -795,16 +795,10 @@ namespace ts { } function invalidateProject(configFileName: string, reloadLevel?: ConfigFileProgramReloadLevel) { - const resolved = resolveProjectName(configFileName); - if (resolved === undefined) { - // If this was a rootName, we need to track it as missing. - // Otherwise we can just ignore it and have it possibly surface as an error in any downstream projects, - // if they exist - - // TODO: do those things - return; - } + invalidateResolvedProject(resolveProjectName(configFileName), reloadLevel); + } + function invalidateResolvedProject(resolved: ResolvedConfigFileName, reloadLevel?: ConfigFileProgramReloadLevel) { projectStatus.removeKey(resolved); if (options.watch) { diagnostics.removeKey(resolved); @@ -901,11 +895,9 @@ namespace ts { } } - function buildSingleInvalidatedProject(project: ResolvedConfigFileName, reloadLevel: ConfigFileProgramReloadLevel) { + function buildSingleInvalidatedProject(resolved: ResolvedConfigFileName, reloadLevel: ConfigFileProgramReloadLevel) { // TODO:: handle this in better way later - const resolved = resolveProjectName(project); - if (!resolved) return; // ?? const proj = parseConfigFile(resolved); if (!proj) return; // ? if (reloadLevel === ConfigFileProgramReloadLevel.Full) { @@ -915,7 +907,7 @@ namespace ts { } else if (reloadLevel === ConfigFileProgramReloadLevel.Partial) { // Update file names - const result = getFileNamesFromConfigSpecs(proj.configFileSpecs!, getDirectoryPath(project), proj.options, parseConfigFileHost); + const result = getFileNamesFromConfigSpecs(proj.configFileSpecs!, getDirectoryPath(resolved), proj.options, parseConfigFileHost); if (result.fileNames.length !== 0) { filterMutate(proj.errors, error => !isErrorNoInputFiles(error)); } @@ -927,14 +919,14 @@ namespace ts { } const status = getUpToDateStatus(proj); - verboseReportProjectStatus(project, status); + verboseReportProjectStatus(resolved, status); if (status.type === UpToDateStatusType.UpstreamBlocked) { if (options.verbose) reportStatus(Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors, resolved, status.upstreamProjectName); return; } - buildSingleProject(project); + buildSingleProject(resolved); } function createDependencyGraph(roots: ResolvedConfigFileName[]): DependencyGraph | undefined { @@ -982,10 +974,6 @@ namespace ts { if (parsed.projectReferences) { for (const ref of parsed.projectReferences) { const resolvedRefPath = resolveProjectName(ref.path); - if (resolvedRefPath === undefined) { - hadError = true; - break; - } visit(resolvedRefPath, inCircularContext || ref.circular); graph.addReference(projPath, resolvedRefPath); } @@ -1184,30 +1172,12 @@ namespace ts { return ExitStatus.Success; } - function resolveProjectName(name: string): ResolvedConfigFileName | undefined { - const fullPath = resolvePath(host.getCurrentDirectory(), name); - if (host.fileExists(fullPath)) { - return fullPath as ResolvedConfigFileName; - } - const fullPathWithTsconfig = combinePaths(fullPath, "tsconfig.json"); - if (host.fileExists(fullPathWithTsconfig)) { - return fullPathWithTsconfig as ResolvedConfigFileName; - } - // TODO(shkamat): right now this is accounted as 1 error in config file, but we need to do better - host.reportDiagnostic(createCompilerDiagnostic(Diagnostics.File_0_not_found, relName(fullPath))); - return undefined; + function resolveProjectName(name: string): ResolvedConfigFileName { + return resolveConfigFileProjectName(resolvePath(host.getCurrentDirectory(), name)); } function resolveProjectNames(configFileNames: ReadonlyArray): ResolvedConfigFileName[] | undefined { - const resolvedNames: ResolvedConfigFileName[] = []; - for (const name of configFileNames) { - const resolved = resolveProjectName(name); - if (resolved === undefined) { - return undefined; - } - resolvedNames.push(resolved); - } - return resolvedNames; + return configFileNames.map(resolveProjectName); } function buildAllProjects(): ExitStatus { @@ -1300,6 +1270,14 @@ namespace ts { } } + export function resolveConfigFileProjectName(project: string): ResolvedConfigFileName { + if (fileExtensionIs(project, Extension.Json)) { + return project as ResolvedConfigFileName; + } + + return combinePaths(project, "tsconfig.json") as ResolvedConfigFileName; + } + export function getAllProjectOutputs(project: ParsedCommandLine): ReadonlyArray { if (project.options.outFile) { return getOutFileOutputs(project); diff --git a/src/testRunner/unittests/tsbuild.ts b/src/testRunner/unittests/tsbuild.ts index 6d6f95ce19c..bb620fc776b 100644 --- a/src/testRunner/unittests/tsbuild.ts +++ b/src/testRunner/unittests/tsbuild.ts @@ -199,7 +199,7 @@ namespace ts { tick(); touch(fs, "/src/logic/index.ts"); // Because we haven't reset the build context, the builder should assume there's nothing to do right now - const status = builder.getUpToDateStatusOfFile(builder.resolveProjectName("/src/logic")!); + const status = builder.getUpToDateStatusOfFile(builder.resolveProjectName("/src/logic")); assert.equal(status.type, UpToDateStatusType.UpToDate, "Project should be assumed to be up-to-date"); // Rebuild this project diff --git a/src/tsc/tsc.ts b/src/tsc/tsc.ts index d3966071265..523fcefd88c 100644 --- a/src/tsc/tsc.ts +++ b/src/tsc/tsc.ts @@ -165,7 +165,7 @@ namespace ts { } function performBuild(args: string[]): number | undefined { - const { buildOptions, projects: buildProjects, errors } = parseBuildCommand(args); + const { buildOptions, projects, errors } = parseBuildCommand(args); if (errors.length > 0) { errors.forEach(reportDiagnostic); return ExitStatus.DiagnosticsPresent_OutputsSkipped; @@ -179,16 +179,6 @@ namespace ts { // Update to pretty if host supports it updateReportDiagnostic(); - const projects = mapDefined(buildProjects, project => { - const fileName = resolvePath(sys.getCurrentDirectory(), project); - const refPath = resolveProjectReferencePath(sys, { path: fileName }); - if (!sys.fileExists(refPath)) { - reportDiagnostic(createCompilerDiagnostic(Diagnostics.File_0_does_not_exist, fileName)); - return undefined; - } - return refPath; - }); - if (projects.length === 0) { printVersion(); printHelp(buildOpts, "--build "); diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index a2fbf9ac944..1202a0847b6 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -4182,14 +4182,11 @@ declare namespace ts { * @returns A 'Program' object. */ function createProgram(rootNames: ReadonlyArray, options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: ReadonlyArray): Program; - interface ResolveProjectReferencePathHost { - fileExists(fileName: string): boolean; - } /** * Returns the target config filename of a project reference. * Note: The file might not exist. */ - function resolveProjectReferencePath(host: ResolveProjectReferencePathHost, ref: ProjectReference): ResolvedConfigFileName; + function resolveProjectReferencePath(ref: ProjectReference): ResolvedConfigFileName; } declare namespace ts { interface EmitOutput { diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 6ab352033f3..18293f58e0a 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -4182,14 +4182,11 @@ declare namespace ts { * @returns A 'Program' object. */ function createProgram(rootNames: ReadonlyArray, options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: ReadonlyArray): Program; - interface ResolveProjectReferencePathHost { - fileExists(fileName: string): boolean; - } /** * Returns the target config filename of a project reference. * Note: The file might not exist. */ - function resolveProjectReferencePath(host: ResolveProjectReferencePathHost, ref: ProjectReference): ResolvedConfigFileName; + function resolveProjectReferencePath(ref: ProjectReference): ResolvedConfigFileName; } declare namespace ts { interface EmitOutput { From 324073a1b28a15319b0704fa0720c9a0ce3ed8b4 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 11 Sep 2018 13:17:32 -0700 Subject: [PATCH 26/83] Remove dead code and rearrange code to handle resolveProjectNames always returns array of resolved config file name --- src/compiler/tsbuild.ts | 30 +++++------------------------- 1 file changed, 5 insertions(+), 25 deletions(-) diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts index 54cd97644f6..83a2794cfc8 100644 --- a/src/compiler/tsbuild.ts +++ b/src/compiler/tsbuild.ts @@ -607,10 +607,7 @@ namespace ts { } function getBuildGraph(configFileNames: ReadonlyArray) { - const resolvedNames: ResolvedConfigFileName[] | undefined = resolveProjectNames(configFileNames); - if (resolvedNames === undefined) return undefined; - - return createDependencyGraph(resolvedNames); + return createDependencyGraph(resolveProjectNames(configFileNames)); } function getGlobalDependencyGraph() { @@ -1114,12 +1111,9 @@ namespace ts { projectStatus.setValue(proj.options.configFilePath as ResolvedConfigFilePath, { type: UpToDateStatusType.UpToDate, newestDeclarationFileContentChangedTime: priorNewestUpdateTime } as UpToDateStatus); } - function getFilesToClean(configFileNames: ReadonlyArray): string[] | undefined { - const resolvedNames: ResolvedConfigFileName[] | undefined = resolveProjectNames(configFileNames); - if (resolvedNames === undefined) return undefined; - + function getFilesToClean(configFileNames: ReadonlyArray): string[] | undefined { // Get the same graph for cleaning we'd use for building - const graph = createDependencyGraph(resolvedNames); + const graph = getBuildGraph(configFileNames); if (graph === undefined) return undefined; const filesToDelete: string[] = []; @@ -1139,22 +1133,8 @@ namespace ts { return filesToDelete; } - function getAllProjectsInScope(): ReadonlyArray | undefined { - const resolvedNames = resolveProjectNames(rootNames); - if (resolvedNames === undefined) return undefined; - const graph = createDependencyGraph(resolvedNames); - if (graph === undefined) return undefined; - return graph.buildQueue; - } - function cleanAllProjects() { - const resolvedNames: ReadonlyArray | undefined = getAllProjectsInScope(); - if (resolvedNames === undefined) { - reportStatus(Diagnostics.Skipping_clean_because_not_all_projects_could_be_located); - return ExitStatus.DiagnosticsPresent_OutputsSkipped; - } - - const filesToDelete = getFilesToClean(resolvedNames); + const filesToDelete = getFilesToClean(rootNames); if (filesToDelete === undefined) { reportStatus(Diagnostics.Skipping_clean_because_not_all_projects_could_be_located); return ExitStatus.DiagnosticsPresent_OutputsSkipped; @@ -1176,7 +1156,7 @@ namespace ts { return resolveConfigFileProjectName(resolvePath(host.getCurrentDirectory(), name)); } - function resolveProjectNames(configFileNames: ReadonlyArray): ResolvedConfigFileName[] | undefined { + function resolveProjectNames(configFileNames: ReadonlyArray): ResolvedConfigFileName[] { return configFileNames.map(resolveProjectName); } From ec6c9ea00404d370058025e5861cc563278968df Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 11 Sep 2018 13:32:45 -0700 Subject: [PATCH 27/83] Start shaping SolutionBuilder API --- src/compiler/tsbuild.ts | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts index 83a2794cfc8..d138e43f9a1 100644 --- a/src/compiler/tsbuild.ts +++ b/src/compiler/tsbuild.ts @@ -335,6 +335,22 @@ namespace ts { export interface SolutionBuilderWithWatchHost extends SolutionBuilderHost, WatchHost { } + export interface SolutionBuilder { + buildAllProjects(): ExitStatus; + cleanAllProjects(): ExitStatus; + + /*@internal*/ resolveProjectName(name: string): ResolvedConfigFileName; + /*@internal*/ getUpToDateStatusOfFile(configFileName: ResolvedConfigFileName): UpToDateStatus; + /*@internal*/ getBuildGraph(configFileNames: ReadonlyArray): DependencyGraph | undefined; + + /*@internal*/ invalidateProject(configFileName: string, reloadLevel?: ConfigFileProgramReloadLevel): void; + /*@internal*/ buildInvalidatedProject(): void; + + /*@internal*/ resetBuildContext(opts?: BuildOptions): void; + + /*@internal*/ startWatching(): void; + } + /** * Create a function that reports watch status by writing to the system and handles the formating of the diagnostic */ @@ -373,7 +389,7 @@ namespace ts { * TODO: use SolutionBuilderWithWatchHost => watchedSolution * use SolutionBuilderHost => Solution */ - export function createSolutionBuilder(host: SolutionBuilderHost, rootNames: ReadonlyArray, defaultOptions: BuildOptions) { + export function createSolutionBuilder(host: SolutionBuilderHost, rootNames: ReadonlyArray, defaultOptions: BuildOptions): SolutionBuilder { const hostWithWatch = host as SolutionBuilderWithWatchHost; const currentDirectory = host.getCurrentDirectory(); const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames()); @@ -405,7 +421,6 @@ namespace ts { return { buildAllProjects, - getUpToDateStatus, getUpToDateStatusOfFile, cleanAllProjects, resetBuildContext, From 5029a61983ec80bbfa15976414b78c3aca10d8b6 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 11 Sep 2018 13:52:26 -0700 Subject: [PATCH 28/83] Cache global dependency graph and invalidate it only if doing full reload of the project or resetting builder context --- src/compiler/tsbuild.ts | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts index d138e43f9a1..65dfa88256f 100644 --- a/src/compiler/tsbuild.ts +++ b/src/compiler/tsbuild.ts @@ -404,6 +404,7 @@ namespace ts { /** Map from config file name to up-to-date status */ const projectStatus = createFileMap(toPath); const missingRoots = createMap(); + let globalDependencyGraph: DependencyGraph | false | undefined; // Watch state // TODO(shkamat): this should be really be diagnostics but thats for later time @@ -446,6 +447,7 @@ namespace ts { unchangedOutputs.clear(); projectStatus.clear(); missingRoots.clear(); + globalDependencyGraph = undefined; diagnostics.clear(); projectPendingBuild.clear(); @@ -527,7 +529,6 @@ namespace ts { function watchConfigFile(resolved: ResolvedConfigFileName) { if (!allWatchedConfigFiles.hasKey(resolved)) { allWatchedConfigFiles.setValue(resolved, hostWithWatch.watchFile(resolved, () => { - configFileCache.removeKey(resolved); invalidateProjectAndScheduleBuilds(resolved, ConfigFileProgramReloadLevel.Full); })); } @@ -626,7 +627,10 @@ namespace ts { } function getGlobalDependencyGraph() { - return getBuildGraph(rootNames); + if (globalDependencyGraph === undefined) { + globalDependencyGraph = getBuildGraph(rootNames) || false; + } + return globalDependencyGraph || undefined; } function getUpToDateStatus(project: ParsedCommandLine | undefined): UpToDateStatus { @@ -811,12 +815,17 @@ namespace ts { } function invalidateResolvedProject(resolved: ResolvedConfigFileName, reloadLevel?: ConfigFileProgramReloadLevel) { + if (reloadLevel === ConfigFileProgramReloadLevel.Full) { + configFileCache.removeKey(resolved); + globalDependencyGraph = undefined; + } projectStatus.removeKey(resolved); if (options.watch) { diagnostics.removeKey(resolved); } if (addProjToQueue(resolved, reloadLevel)) { + // TODO: instead of adding the dependent project to queue right away postpone this const dependencyGraph = getGlobalDependencyGraph(); if (dependencyGraph) { queueBuildForDownstreamReferences(resolved, dependencyGraph); @@ -1126,9 +1135,9 @@ namespace ts { projectStatus.setValue(proj.options.configFilePath as ResolvedConfigFilePath, { type: UpToDateStatusType.UpToDate, newestDeclarationFileContentChangedTime: priorNewestUpdateTime } as UpToDateStatus); } - function getFilesToClean(configFileNames: ReadonlyArray): string[] | undefined { + function getFilesToClean(): string[] | undefined { // Get the same graph for cleaning we'd use for building - const graph = getBuildGraph(configFileNames); + const graph = getGlobalDependencyGraph(); if (graph === undefined) return undefined; const filesToDelete: string[] = []; @@ -1149,7 +1158,7 @@ namespace ts { } function cleanAllProjects() { - const filesToDelete = getFilesToClean(rootNames); + const filesToDelete = getFilesToClean(); if (filesToDelete === undefined) { reportStatus(Diagnostics.Skipping_clean_because_not_all_projects_could_be_located); return ExitStatus.DiagnosticsPresent_OutputsSkipped; From 1c1379252ea60dfab715d40c83cb238826fdc0c7 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 11 Sep 2018 14:11:31 -0700 Subject: [PATCH 29/83] Prefer elaborating on expressions which could be called to produce a correct type by suggesting such (#27016) * Prefer elaborating on expressions which could be called to produce a correct type by suggesting such * Pass relation through elaboration machinery --- src/compiler/checker.ts | 58 +++++++++---- src/compiler/diagnosticMessages.json | 8 ++ ...orExpressionsWhichCouldBeCalled.errors.txt | 51 +++++++++++ ...rationsForExpressionsWhichCouldBeCalled.js | 52 +++++++++++ ...nsForExpressionsWhichCouldBeCalled.symbols | 71 +++++++++++++++ ...ionsForExpressionsWhichCouldBeCalled.types | 86 +++++++++++++++++++ ...ctionSignatureAssignmentCompat1.errors.txt | 5 +- .../invalidAssignmentsToVoid.errors.txt | 7 +- .../reference/invalidVoidValues.errors.txt | 7 +- .../optionalParamAssignmentCompat.errors.txt | 5 +- .../reference/parser536727.errors.txt | 14 +-- ...cMemberOfAnotherClassAssignment.errors.txt | 10 ++- ...ConstrainsPropertyDeclarations2.errors.txt | 12 +-- .../baselines/reference/typeMatch1.errors.txt | 5 +- tests/baselines/reference/weakType.errors.txt | 3 + ...rationsForExpressionsWhichCouldBeCalled.ts | 27 ++++++ 16 files changed, 376 insertions(+), 45 deletions(-) create mode 100644 tests/baselines/reference/didYouMeanElaborationsForExpressionsWhichCouldBeCalled.errors.txt create mode 100644 tests/baselines/reference/didYouMeanElaborationsForExpressionsWhichCouldBeCalled.js create mode 100644 tests/baselines/reference/didYouMeanElaborationsForExpressionsWhichCouldBeCalled.symbols create mode 100644 tests/baselines/reference/didYouMeanElaborationsForExpressionsWhichCouldBeCalled.types create mode 100644 tests/cases/compiler/didYouMeanElaborationsForExpressionsWhichCouldBeCalled.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ff7306855ce..19ca10e83be 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10573,7 +10573,7 @@ namespace ts { function checkTypeRelatedToAndOptionallyElaborate(source: Type, target: Type, relation: Map, errorNode: Node | undefined, expr: Expression | undefined, headMessage?: DiagnosticMessage, containingMessageChain?: () => DiagnosticMessageChain | undefined): boolean { if (isTypeRelatedTo(source, target, relation)) return true; - if (!errorNode || !elaborateError(expr, source, target)) { + if (!errorNode || !elaborateError(expr, source, target, relation)) { return checkTypeRelatedTo(source, target, relation, errorNode, headMessage, containingMessageChain); } return false; @@ -10583,25 +10583,49 @@ namespace ts { return !!(type.flags & TypeFlags.Conditional || (type.flags & TypeFlags.Intersection && some((type as IntersectionType).types, isOrHasGenericConditional))); } - function elaborateError(node: Expression | undefined, source: Type, target: Type): boolean { + function elaborateError(node: Expression | undefined, source: Type, target: Type, relation: Map): boolean { if (!node || isOrHasGenericConditional(target)) return false; + if (!checkTypeRelatedTo(source, target, relation, /*errorNode*/ undefined) && elaborateDidYouMeanToCallOrConstruct(node, source, target, relation)) { + return true; + } switch (node.kind) { case SyntaxKind.JsxExpression: case SyntaxKind.ParenthesizedExpression: - return elaborateError((node as ParenthesizedExpression | JsxExpression).expression, source, target); + return elaborateError((node as ParenthesizedExpression | JsxExpression).expression, source, target, relation); case SyntaxKind.BinaryExpression: switch ((node as BinaryExpression).operatorToken.kind) { case SyntaxKind.EqualsToken: case SyntaxKind.CommaToken: - return elaborateError((node as BinaryExpression).right, source, target); + return elaborateError((node as BinaryExpression).right, source, target, relation); } break; case SyntaxKind.ObjectLiteralExpression: - return elaborateObjectLiteral(node as ObjectLiteralExpression, source, target); + return elaborateObjectLiteral(node as ObjectLiteralExpression, source, target, relation); case SyntaxKind.ArrayLiteralExpression: - return elaborateArrayLiteral(node as ArrayLiteralExpression, source, target); + return elaborateArrayLiteral(node as ArrayLiteralExpression, source, target, relation); case SyntaxKind.JsxAttributes: - return elaborateJsxAttributes(node as JsxAttributes, source, target); + return elaborateJsxAttributes(node as JsxAttributes, source, target, relation); + } + return false; + } + + function elaborateDidYouMeanToCallOrConstruct(node: Expression, source: Type, target: Type, relation: Map): boolean { + const callSignatures = getSignaturesOfType(source, SignatureKind.Call); + const constructSignatures = getSignaturesOfType(source, SignatureKind.Construct); + for (const signatures of [constructSignatures, callSignatures]) { + if (some(signatures, s => { + const returnType = getReturnTypeOfSignature(s); + return !(returnType.flags & (TypeFlags.Any | TypeFlags.Never)) && checkTypeRelatedTo(returnType, target, relation, /*errorNode*/ undefined); + })) { + const resultObj: { error?: Diagnostic } = {}; + checkTypeAssignableTo(source, target, node, /*errorMessage*/ undefined, /*containingChain*/ undefined, resultObj); + const diagnostic = resultObj.error!; + addRelatedInfo(diagnostic, createDiagnosticForNode( + node, + signatures === constructSignatures ? Diagnostics.Did_you_mean_to_use_new_with_this_expression : Diagnostics.Did_you_mean_to_call_this_expression + )); + return true; + } } return false; } @@ -10612,7 +10636,7 @@ namespace ts { * If that element would issue an error, we first attempt to dive into that element's inner expression and issue a more specific error by recuring into `elaborateError` * Otherwise, we issue an error on _every_ element which fail the assignability check */ - function elaborateElementwise(iterator: ElaborationIterator, source: Type, target: Type) { + function elaborateElementwise(iterator: ElaborationIterator, source: Type, target: Type, relation: Map) { // Assignability failure - check each prop individually, and if that fails, fall back on the bad error span let reportedError = false; for (let status = iterator.next(); !status.done; status = iterator.next()) { @@ -10620,7 +10644,7 @@ namespace ts { const sourcePropType = getIndexedAccessType(source, nameType, /*accessNode*/ undefined, errorType); const targetPropType = getIndexedAccessType(target, nameType, /*accessNode*/ undefined, errorType); if (sourcePropType !== errorType && targetPropType !== errorType && !isTypeAssignableTo(sourcePropType, targetPropType)) { - const elaborated = next && elaborateError(next, sourcePropType, targetPropType); + const elaborated = next && elaborateError(next, sourcePropType, targetPropType, relation); if (elaborated) { reportedError = true; } @@ -10629,10 +10653,10 @@ namespace ts { const resultObj: { error?: Diagnostic } = {}; // Use the expression type, if available const specificSource = next ? checkExpressionForMutableLocation(next, CheckMode.Normal, sourcePropType) : sourcePropType; - const result = checkTypeAssignableTo(specificSource, targetPropType, prop, errorMessage, /*containingChain*/ undefined, resultObj); + const result = checkTypeRelatedTo(specificSource, targetPropType, relation, prop, errorMessage, /*containingChain*/ undefined, resultObj); if (result && specificSource !== sourcePropType) { // If for whatever reason the expression type doesn't yield an error, make sure we still issue an error on the sourcePropType - checkTypeAssignableTo(sourcePropType, targetPropType, prop, errorMessage, /*containingChain*/ undefined, resultObj); + checkTypeRelatedTo(sourcePropType, targetPropType, relation, prop, errorMessage, /*containingChain*/ undefined, resultObj); } if (resultObj.error) { const reportedDiag = resultObj.error; @@ -10674,8 +10698,8 @@ namespace ts { } } - function elaborateJsxAttributes(node: JsxAttributes, source: Type, target: Type) { - return elaborateElementwise(generateJsxAttributes(node), source, target); + function elaborateJsxAttributes(node: JsxAttributes, source: Type, target: Type, relation: Map) { + return elaborateElementwise(generateJsxAttributes(node), source, target, relation); } function *generateLimitedTupleElements(node: ArrayLiteralExpression, target: Type): ElaborationIterator { @@ -10691,9 +10715,9 @@ namespace ts { } } - function elaborateArrayLiteral(node: ArrayLiteralExpression, source: Type, target: Type) { + function elaborateArrayLiteral(node: ArrayLiteralExpression, source: Type, target: Type, relation: Map) { if (isTupleLikeType(source)) { - return elaborateElementwise(generateLimitedTupleElements(node, target), source, target); + return elaborateElementwise(generateLimitedTupleElements(node, target), source, target, relation); } return false; } @@ -10722,8 +10746,8 @@ namespace ts { } } - function elaborateObjectLiteral(node: ObjectLiteralExpression, source: Type, target: Type) { - return elaborateElementwise(generateObjectLiteralElements(node), source, target); + function elaborateObjectLiteral(node: ObjectLiteralExpression, source: Type, target: Type, relation: Map) { + return elaborateElementwise(generateObjectLiteralElements(node), source, target, relation); } /** diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 2bc47138d80..f3dec7287d5 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3720,6 +3720,14 @@ "category": "Message", "code": 6211 }, + "Did you mean to call this expression?": { + "category": "Message", + "code": 6212 + }, + "Did you mean to use `new` with this expression?": { + "category": "Message", + "code": 6213 + }, "Projects to reference": { "category": "Message", diff --git a/tests/baselines/reference/didYouMeanElaborationsForExpressionsWhichCouldBeCalled.errors.txt b/tests/baselines/reference/didYouMeanElaborationsForExpressionsWhichCouldBeCalled.errors.txt new file mode 100644 index 00000000000..9f1f60b9d1e --- /dev/null +++ b/tests/baselines/reference/didYouMeanElaborationsForExpressionsWhichCouldBeCalled.errors.txt @@ -0,0 +1,51 @@ +tests/cases/compiler/didYouMeanElaborationsForExpressionsWhichCouldBeCalled.ts(10,8): error TS2322: Type 'typeof Bar' is not assignable to type 'Bar'. + Property 'x' is missing in type 'typeof Bar'. +tests/cases/compiler/didYouMeanElaborationsForExpressionsWhichCouldBeCalled.ts(11,8): error TS2322: Type 'DateConstructor' is not assignable to type 'Date'. + Property 'toDateString' is missing in type 'DateConstructor'. +tests/cases/compiler/didYouMeanElaborationsForExpressionsWhichCouldBeCalled.ts(17,4): error TS2322: Type '() => number' is not assignable to type 'number'. +tests/cases/compiler/didYouMeanElaborationsForExpressionsWhichCouldBeCalled.ts(26,5): error TS2322: Type '() => number' is not assignable to type 'number'. + + +==== tests/cases/compiler/didYouMeanElaborationsForExpressionsWhichCouldBeCalled.ts (4 errors) ==== + class Bar { + x!: string; + } + + declare function getNum(): number; + + declare function foo(arg: { x: Bar, y: Date }, item: number, items?: [number, number, number]): void; + + foo({ + x: Bar, + ~~~ +!!! error TS2322: Type 'typeof Bar' is not assignable to type 'Bar'. +!!! error TS2322: Property 'x' is missing in type 'typeof Bar'. +!!! related TS6213 tests/cases/compiler/didYouMeanElaborationsForExpressionsWhichCouldBeCalled.ts:10:8: Did you mean to use `new` with this expression? + y: Date + ~~~~ +!!! error TS2322: Type 'DateConstructor' is not assignable to type 'Date'. +!!! error TS2322: Property 'toDateString' is missing in type 'DateConstructor'. +!!! related TS6213 tests/cases/compiler/didYouMeanElaborationsForExpressionsWhichCouldBeCalled.ts:11:8: Did you mean to use `new` with this expression? + }, getNum()); + + foo({ + x: new Bar(), + y: new Date() + }, getNum); + ~~~~~~ +!!! error TS2322: Type '() => number' is not assignable to type 'number'. +!!! related TS6212 tests/cases/compiler/didYouMeanElaborationsForExpressionsWhichCouldBeCalled.ts:17:4: Did you mean to call this expression? + + + foo({ + x: new Bar(), + y: new Date() + }, getNum(), [ + 1, + 2, + getNum + ~~~~~~ +!!! error TS2322: Type '() => number' is not assignable to type 'number'. +!!! related TS6212 tests/cases/compiler/didYouMeanElaborationsForExpressionsWhichCouldBeCalled.ts:26:5: Did you mean to call this expression? + ]); + \ No newline at end of file diff --git a/tests/baselines/reference/didYouMeanElaborationsForExpressionsWhichCouldBeCalled.js b/tests/baselines/reference/didYouMeanElaborationsForExpressionsWhichCouldBeCalled.js new file mode 100644 index 00000000000..3e2aaec27a4 --- /dev/null +++ b/tests/baselines/reference/didYouMeanElaborationsForExpressionsWhichCouldBeCalled.js @@ -0,0 +1,52 @@ +//// [didYouMeanElaborationsForExpressionsWhichCouldBeCalled.ts] +class Bar { + x!: string; +} + +declare function getNum(): number; + +declare function foo(arg: { x: Bar, y: Date }, item: number, items?: [number, number, number]): void; + +foo({ + x: Bar, + y: Date +}, getNum()); + +foo({ + x: new Bar(), + y: new Date() +}, getNum); + + +foo({ + x: new Bar(), + y: new Date() +}, getNum(), [ + 1, + 2, + getNum +]); + + +//// [didYouMeanElaborationsForExpressionsWhichCouldBeCalled.js] +var Bar = /** @class */ (function () { + function Bar() { + } + return Bar; +}()); +foo({ + x: Bar, + y: Date +}, getNum()); +foo({ + x: new Bar(), + y: new Date() +}, getNum); +foo({ + x: new Bar(), + y: new Date() +}, getNum(), [ + 1, + 2, + getNum +]); diff --git a/tests/baselines/reference/didYouMeanElaborationsForExpressionsWhichCouldBeCalled.symbols b/tests/baselines/reference/didYouMeanElaborationsForExpressionsWhichCouldBeCalled.symbols new file mode 100644 index 00000000000..d7f6457c262 --- /dev/null +++ b/tests/baselines/reference/didYouMeanElaborationsForExpressionsWhichCouldBeCalled.symbols @@ -0,0 +1,71 @@ +=== tests/cases/compiler/didYouMeanElaborationsForExpressionsWhichCouldBeCalled.ts === +class Bar { +>Bar : Symbol(Bar, Decl(didYouMeanElaborationsForExpressionsWhichCouldBeCalled.ts, 0, 0)) + + x!: string; +>x : Symbol(Bar.x, Decl(didYouMeanElaborationsForExpressionsWhichCouldBeCalled.ts, 0, 11)) +} + +declare function getNum(): number; +>getNum : Symbol(getNum, Decl(didYouMeanElaborationsForExpressionsWhichCouldBeCalled.ts, 2, 1)) + +declare function foo(arg: { x: Bar, y: Date }, item: number, items?: [number, number, number]): void; +>foo : Symbol(foo, Decl(didYouMeanElaborationsForExpressionsWhichCouldBeCalled.ts, 4, 34)) +>arg : Symbol(arg, Decl(didYouMeanElaborationsForExpressionsWhichCouldBeCalled.ts, 6, 21)) +>x : Symbol(x, Decl(didYouMeanElaborationsForExpressionsWhichCouldBeCalled.ts, 6, 27)) +>Bar : Symbol(Bar, Decl(didYouMeanElaborationsForExpressionsWhichCouldBeCalled.ts, 0, 0)) +>y : Symbol(y, Decl(didYouMeanElaborationsForExpressionsWhichCouldBeCalled.ts, 6, 35)) +>Date : Symbol(Date, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.scripthost.d.ts, --, --)) +>item : Symbol(item, Decl(didYouMeanElaborationsForExpressionsWhichCouldBeCalled.ts, 6, 46)) +>items : Symbol(items, Decl(didYouMeanElaborationsForExpressionsWhichCouldBeCalled.ts, 6, 60)) + +foo({ +>foo : Symbol(foo, Decl(didYouMeanElaborationsForExpressionsWhichCouldBeCalled.ts, 4, 34)) + + x: Bar, +>x : Symbol(x, Decl(didYouMeanElaborationsForExpressionsWhichCouldBeCalled.ts, 8, 5)) +>Bar : Symbol(Bar, Decl(didYouMeanElaborationsForExpressionsWhichCouldBeCalled.ts, 0, 0)) + + y: Date +>y : Symbol(y, Decl(didYouMeanElaborationsForExpressionsWhichCouldBeCalled.ts, 9, 11)) +>Date : Symbol(Date, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.scripthost.d.ts, --, --)) + +}, getNum()); +>getNum : Symbol(getNum, Decl(didYouMeanElaborationsForExpressionsWhichCouldBeCalled.ts, 2, 1)) + +foo({ +>foo : Symbol(foo, Decl(didYouMeanElaborationsForExpressionsWhichCouldBeCalled.ts, 4, 34)) + + x: new Bar(), +>x : Symbol(x, Decl(didYouMeanElaborationsForExpressionsWhichCouldBeCalled.ts, 13, 5)) +>Bar : Symbol(Bar, Decl(didYouMeanElaborationsForExpressionsWhichCouldBeCalled.ts, 0, 0)) + + y: new Date() +>y : Symbol(y, Decl(didYouMeanElaborationsForExpressionsWhichCouldBeCalled.ts, 14, 17)) +>Date : Symbol(Date, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.scripthost.d.ts, --, --)) + +}, getNum); +>getNum : Symbol(getNum, Decl(didYouMeanElaborationsForExpressionsWhichCouldBeCalled.ts, 2, 1)) + + +foo({ +>foo : Symbol(foo, Decl(didYouMeanElaborationsForExpressionsWhichCouldBeCalled.ts, 4, 34)) + + x: new Bar(), +>x : Symbol(x, Decl(didYouMeanElaborationsForExpressionsWhichCouldBeCalled.ts, 19, 5)) +>Bar : Symbol(Bar, Decl(didYouMeanElaborationsForExpressionsWhichCouldBeCalled.ts, 0, 0)) + + y: new Date() +>y : Symbol(y, Decl(didYouMeanElaborationsForExpressionsWhichCouldBeCalled.ts, 20, 17)) +>Date : Symbol(Date, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.scripthost.d.ts, --, --)) + +}, getNum(), [ +>getNum : Symbol(getNum, Decl(didYouMeanElaborationsForExpressionsWhichCouldBeCalled.ts, 2, 1)) + + 1, + 2, + getNum +>getNum : Symbol(getNum, Decl(didYouMeanElaborationsForExpressionsWhichCouldBeCalled.ts, 2, 1)) + +]); + diff --git a/tests/baselines/reference/didYouMeanElaborationsForExpressionsWhichCouldBeCalled.types b/tests/baselines/reference/didYouMeanElaborationsForExpressionsWhichCouldBeCalled.types new file mode 100644 index 00000000000..bd60a278645 --- /dev/null +++ b/tests/baselines/reference/didYouMeanElaborationsForExpressionsWhichCouldBeCalled.types @@ -0,0 +1,86 @@ +=== tests/cases/compiler/didYouMeanElaborationsForExpressionsWhichCouldBeCalled.ts === +class Bar { +>Bar : Bar + + x!: string; +>x : string +} + +declare function getNum(): number; +>getNum : () => number + +declare function foo(arg: { x: Bar, y: Date }, item: number, items?: [number, number, number]): void; +>foo : (arg: { x: Bar; y: Date; }, item: number, items?: [number, number, number]) => void +>arg : { x: Bar; y: Date; } +>x : Bar +>y : Date +>item : number +>items : [number, number, number] + +foo({ +>foo({ x: Bar, y: Date}, getNum()) : void +>foo : (arg: { x: Bar; y: Date; }, item: number, items?: [number, number, number]) => void +>{ x: Bar, y: Date} : { x: typeof Bar; y: DateConstructor; } + + x: Bar, +>x : typeof Bar +>Bar : typeof Bar + + y: Date +>y : DateConstructor +>Date : DateConstructor + +}, getNum()); +>getNum() : number +>getNum : () => number + +foo({ +>foo({ x: new Bar(), y: new Date()}, getNum) : void +>foo : (arg: { x: Bar; y: Date; }, item: number, items?: [number, number, number]) => void +>{ x: new Bar(), y: new Date()} : { x: Bar; y: Date; } + + x: new Bar(), +>x : Bar +>new Bar() : Bar +>Bar : typeof Bar + + y: new Date() +>y : Date +>new Date() : Date +>Date : DateConstructor + +}, getNum); +>getNum : () => number + + +foo({ +>foo({ x: new Bar(), y: new Date()}, getNum(), [ 1, 2, getNum]) : void +>foo : (arg: { x: Bar; y: Date; }, item: number, items?: [number, number, number]) => void +>{ x: new Bar(), y: new Date()} : { x: Bar; y: Date; } + + x: new Bar(), +>x : Bar +>new Bar() : Bar +>Bar : typeof Bar + + y: new Date() +>y : Date +>new Date() : Date +>Date : DateConstructor + +}, getNum(), [ +>getNum() : number +>getNum : () => number +>[ 1, 2, getNum] : (number | (() => number))[] + + 1, +>1 : 1 + + 2, +>2 : 2 + + getNum +>getNum : () => number + +]); + diff --git a/tests/baselines/reference/functionSignatureAssignmentCompat1.errors.txt b/tests/baselines/reference/functionSignatureAssignmentCompat1.errors.txt index f91a4f91547..bc2dc17dfbc 100644 --- a/tests/baselines/reference/functionSignatureAssignmentCompat1.errors.txt +++ b/tests/baselines/reference/functionSignatureAssignmentCompat1.errors.txt @@ -1,4 +1,4 @@ -tests/cases/compiler/functionSignatureAssignmentCompat1.ts(10,5): error TS2322: Type '(delimiter?: string) => ParserFunc' is not assignable to type 'ParserFunc'. +tests/cases/compiler/functionSignatureAssignmentCompat1.ts(10,21): error TS2322: Type '(delimiter?: string) => ParserFunc' is not assignable to type 'ParserFunc'. Types of parameters 'delimiter' and 'eventEmitter' are incompatible. Type 'number' is not assignable to type 'string'. @@ -14,8 +14,9 @@ tests/cases/compiler/functionSignatureAssignmentCompat1.ts(10,5): error TS2322: var parsers: Parsers; var c: ParserFunc = parsers.raw; // ok! var d: ParserFunc = parsers.readline; // not ok - ~ + ~~~~~~~~~~~~~~~~ !!! error TS2322: Type '(delimiter?: string) => ParserFunc' is not assignable to type 'ParserFunc'. !!! error TS2322: Types of parameters 'delimiter' and 'eventEmitter' are incompatible. !!! error TS2322: Type 'number' is not assignable to type 'string'. +!!! related TS6212 tests/cases/compiler/functionSignatureAssignmentCompat1.ts:10:21: Did you mean to call this expression? var e: ParserFunc = parsers.readline(); // ok \ No newline at end of file diff --git a/tests/baselines/reference/invalidAssignmentsToVoid.errors.txt b/tests/baselines/reference/invalidAssignmentsToVoid.errors.txt index 4b9b316e010..fd3fa48c01b 100644 --- a/tests/baselines/reference/invalidAssignmentsToVoid.errors.txt +++ b/tests/baselines/reference/invalidAssignmentsToVoid.errors.txt @@ -7,7 +7,7 @@ tests/cases/conformance/types/primitives/void/invalidAssignmentsToVoid.ts(10,1): tests/cases/conformance/types/primitives/void/invalidAssignmentsToVoid.ts(14,1): error TS2322: Type 'I' is not assignable to type 'void'. tests/cases/conformance/types/primitives/void/invalidAssignmentsToVoid.ts(17,1): error TS2322: Type 'typeof M' is not assignable to type 'void'. tests/cases/conformance/types/primitives/void/invalidAssignmentsToVoid.ts(20,5): error TS2322: Type 'T' is not assignable to type 'void'. -tests/cases/conformance/types/primitives/void/invalidAssignmentsToVoid.ts(22,1): error TS2322: Type '(a: T) => void' is not assignable to type 'void'. +tests/cases/conformance/types/primitives/void/invalidAssignmentsToVoid.ts(22,5): error TS2322: Type '(a: T) => void' is not assignable to type 'void'. ==== tests/cases/conformance/types/primitives/void/invalidAssignmentsToVoid.ts (10 errors) ==== @@ -51,5 +51,6 @@ tests/cases/conformance/types/primitives/void/invalidAssignmentsToVoid.ts(22,1): !!! error TS2322: Type 'T' is not assignable to type 'void'. } x = f; - ~ -!!! error TS2322: Type '(a: T) => void' is not assignable to type 'void'. \ No newline at end of file + ~ +!!! error TS2322: Type '(a: T) => void' is not assignable to type 'void'. +!!! related TS6212 tests/cases/conformance/types/primitives/void/invalidAssignmentsToVoid.ts:22:5: Did you mean to call this expression? \ No newline at end of file diff --git a/tests/baselines/reference/invalidVoidValues.errors.txt b/tests/baselines/reference/invalidVoidValues.errors.txt index 8fc015f692f..51155152864 100644 --- a/tests/baselines/reference/invalidVoidValues.errors.txt +++ b/tests/baselines/reference/invalidVoidValues.errors.txt @@ -8,7 +8,7 @@ tests/cases/conformance/types/primitives/void/invalidVoidValues.ts(16,1): error tests/cases/conformance/types/primitives/void/invalidVoidValues.ts(18,1): error TS2322: Type '{ f(): void; }' is not assignable to type 'void'. tests/cases/conformance/types/primitives/void/invalidVoidValues.ts(21,1): error TS2322: Type 'typeof M' is not assignable to type 'void'. tests/cases/conformance/types/primitives/void/invalidVoidValues.ts(24,5): error TS2322: Type 'T' is not assignable to type 'void'. -tests/cases/conformance/types/primitives/void/invalidVoidValues.ts(26,1): error TS2322: Type '(a: T) => void' is not assignable to type 'void'. +tests/cases/conformance/types/primitives/void/invalidVoidValues.ts(26,5): error TS2322: Type '(a: T) => void' is not assignable to type 'void'. ==== tests/cases/conformance/types/primitives/void/invalidVoidValues.ts (11 errors) ==== @@ -58,5 +58,6 @@ tests/cases/conformance/types/primitives/void/invalidVoidValues.ts(26,1): error !!! error TS2322: Type 'T' is not assignable to type 'void'. } x = f; - ~ -!!! error TS2322: Type '(a: T) => void' is not assignable to type 'void'. \ No newline at end of file + ~ +!!! error TS2322: Type '(a: T) => void' is not assignable to type 'void'. +!!! related TS6212 tests/cases/conformance/types/primitives/void/invalidVoidValues.ts:26:5: Did you mean to call this expression? \ No newline at end of file diff --git a/tests/baselines/reference/optionalParamAssignmentCompat.errors.txt b/tests/baselines/reference/optionalParamAssignmentCompat.errors.txt index 5ab492540ac..10222bc5d8f 100644 --- a/tests/baselines/reference/optionalParamAssignmentCompat.errors.txt +++ b/tests/baselines/reference/optionalParamAssignmentCompat.errors.txt @@ -1,4 +1,4 @@ -tests/cases/compiler/optionalParamAssignmentCompat.ts(10,5): error TS2322: Type '(p1?: string) => I1' is not assignable to type 'I1'. +tests/cases/compiler/optionalParamAssignmentCompat.ts(10,13): error TS2322: Type '(p1?: string) => I1' is not assignable to type 'I1'. Types of parameters 'p1' and 'p1' are incompatible. Type 'number' is not assignable to type 'string'. @@ -14,8 +14,9 @@ tests/cases/compiler/optionalParamAssignmentCompat.ts(10,5): error TS2322: Type var i2: I2; var c: I1 = i2.p1; // should be ok var d: I1 = i2.m1; // should error - ~ + ~~~~~ !!! error TS2322: Type '(p1?: string) => I1' is not assignable to type 'I1'. !!! error TS2322: Types of parameters 'p1' and 'p1' are incompatible. !!! error TS2322: Type 'number' is not assignable to type 'string'. +!!! related TS6212 tests/cases/compiler/optionalParamAssignmentCompat.ts:10:13: Did you mean to call this expression? \ No newline at end of file diff --git a/tests/baselines/reference/parser536727.errors.txt b/tests/baselines/reference/parser536727.errors.txt index 4204e62c93b..6cdf152582f 100644 --- a/tests/baselines/reference/parser536727.errors.txt +++ b/tests/baselines/reference/parser536727.errors.txt @@ -1,6 +1,6 @@ -tests/cases/conformance/parser/ecmascript5/RegressionTests/parser536727.ts(7,5): error TS2345: Argument of type '() => (x: string) => string' is not assignable to parameter of type '(x: string) => string'. +tests/cases/conformance/parser/ecmascript5/RegressionTests/parser536727.ts(7,5): error TS2322: Type '() => (x: string) => string' is not assignable to type '(x: string) => string'. Type '(x: string) => string' is not assignable to type 'string'. -tests/cases/conformance/parser/ecmascript5/RegressionTests/parser536727.ts(8,5): error TS2345: Argument of type '() => (x: string) => string' is not assignable to parameter of type '(x: string) => string'. +tests/cases/conformance/parser/ecmascript5/RegressionTests/parser536727.ts(8,5): error TS2322: Type '() => (x: string) => string' is not assignable to type '(x: string) => string'. Type '(x: string) => string' is not assignable to type 'string'. @@ -13,10 +13,12 @@ tests/cases/conformance/parser/ecmascript5/RegressionTests/parser536727.ts(8,5): foo(g); foo(() => g); ~~~~~~~ -!!! error TS2345: Argument of type '() => (x: string) => string' is not assignable to parameter of type '(x: string) => string'. -!!! error TS2345: Type '(x: string) => string' is not assignable to type 'string'. +!!! error TS2322: Type '() => (x: string) => string' is not assignable to type '(x: string) => string'. +!!! error TS2322: Type '(x: string) => string' is not assignable to type 'string'. +!!! related TS6212 tests/cases/conformance/parser/ecmascript5/RegressionTests/parser536727.ts:7:5: Did you mean to call this expression? foo(x); ~ -!!! error TS2345: Argument of type '() => (x: string) => string' is not assignable to parameter of type '(x: string) => string'. -!!! error TS2345: Type '(x: string) => string' is not assignable to type 'string'. +!!! error TS2322: Type '() => (x: string) => string' is not assignable to type '(x: string) => string'. +!!! error TS2322: Type '(x: string) => string' is not assignable to type 'string'. +!!! related TS6212 tests/cases/conformance/parser/ecmascript5/RegressionTests/parser536727.ts:8:5: Did you mean to call this expression? \ No newline at end of file diff --git a/tests/baselines/reference/staticMemberOfClassAndPublicMemberOfAnotherClassAssignment.errors.txt b/tests/baselines/reference/staticMemberOfClassAndPublicMemberOfAnotherClassAssignment.errors.txt index 36ead708331..734ef74c218 100644 --- a/tests/baselines/reference/staticMemberOfClassAndPublicMemberOfAnotherClassAssignment.errors.txt +++ b/tests/baselines/reference/staticMemberOfClassAndPublicMemberOfAnotherClassAssignment.errors.txt @@ -1,10 +1,10 @@ tests/cases/compiler/staticMemberOfClassAndPublicMemberOfAnotherClassAssignment.ts(12,1): error TS2322: Type 'C' is not assignable to type 'A'. Property 'prop' is missing in type 'C'. -tests/cases/compiler/staticMemberOfClassAndPublicMemberOfAnotherClassAssignment.ts(13,1): error TS2322: Type 'typeof B' is not assignable to type 'A'. +tests/cases/compiler/staticMemberOfClassAndPublicMemberOfAnotherClassAssignment.ts(13,5): error TS2322: Type 'typeof B' is not assignable to type 'A'. Property 'prop' is missing in type 'typeof B'. tests/cases/compiler/staticMemberOfClassAndPublicMemberOfAnotherClassAssignment.ts(16,5): error TS2322: Type 'C' is not assignable to type 'B'. Property 'prop' is missing in type 'C'. -tests/cases/compiler/staticMemberOfClassAndPublicMemberOfAnotherClassAssignment.ts(17,1): error TS2322: Type 'typeof B' is not assignable to type 'B'. +tests/cases/compiler/staticMemberOfClassAndPublicMemberOfAnotherClassAssignment.ts(17,5): error TS2322: Type 'typeof B' is not assignable to type 'B'. Property 'prop' is missing in type 'typeof B'. @@ -25,9 +25,10 @@ tests/cases/compiler/staticMemberOfClassAndPublicMemberOfAnotherClassAssignment. !!! error TS2322: Type 'C' is not assignable to type 'A'. !!! error TS2322: Property 'prop' is missing in type 'C'. a = B; // error prop is missing - ~ + ~ !!! error TS2322: Type 'typeof B' is not assignable to type 'A'. !!! error TS2322: Property 'prop' is missing in type 'typeof B'. +!!! related TS6213 tests/cases/compiler/staticMemberOfClassAndPublicMemberOfAnotherClassAssignment.ts:13:5: Did you mean to use `new` with this expression? a = C; var b: B = new C(); // error prop is missing @@ -35,9 +36,10 @@ tests/cases/compiler/staticMemberOfClassAndPublicMemberOfAnotherClassAssignment. !!! error TS2322: Type 'C' is not assignable to type 'B'. !!! error TS2322: Property 'prop' is missing in type 'C'. b = B; // error prop is missing - ~ + ~ !!! error TS2322: Type 'typeof B' is not assignable to type 'B'. !!! error TS2322: Property 'prop' is missing in type 'typeof B'. +!!! related TS6213 tests/cases/compiler/staticMemberOfClassAndPublicMemberOfAnotherClassAssignment.ts:17:5: Did you mean to use `new` with this expression? b = C; b = a; diff --git a/tests/baselines/reference/stringIndexerConstrainsPropertyDeclarations2.errors.txt b/tests/baselines/reference/stringIndexerConstrainsPropertyDeclarations2.errors.txt index 3a33fe74056..511a1ef68a8 100644 --- a/tests/baselines/reference/stringIndexerConstrainsPropertyDeclarations2.errors.txt +++ b/tests/baselines/reference/stringIndexerConstrainsPropertyDeclarations2.errors.txt @@ -4,9 +4,9 @@ tests/cases/conformance/types/objectTypeLiteral/indexSignatures/stringIndexerCon tests/cases/conformance/types/objectTypeLiteral/indexSignatures/stringIndexerConstrainsPropertyDeclarations2.ts(24,5): error TS2411: Property 'd' of type 'string' is not assignable to string index type 'A'. tests/cases/conformance/types/objectTypeLiteral/indexSignatures/stringIndexerConstrainsPropertyDeclarations2.ts(31,5): error TS2411: Property 'c' of type 'number' is not assignable to string index type 'A'. tests/cases/conformance/types/objectTypeLiteral/indexSignatures/stringIndexerConstrainsPropertyDeclarations2.ts(32,5): error TS2411: Property 'd' of type 'string' is not assignable to string index type 'A'. -tests/cases/conformance/types/objectTypeLiteral/indexSignatures/stringIndexerConstrainsPropertyDeclarations2.ts(37,5): error TS2322: Type 'typeof A' is not assignable to type 'A'. +tests/cases/conformance/types/objectTypeLiteral/indexSignatures/stringIndexerConstrainsPropertyDeclarations2.ts(37,8): error TS2322: Type 'typeof A' is not assignable to type 'A'. Property 'foo' is missing in type 'typeof A'. -tests/cases/conformance/types/objectTypeLiteral/indexSignatures/stringIndexerConstrainsPropertyDeclarations2.ts(38,5): error TS2322: Type 'typeof B' is not assignable to type 'A'. +tests/cases/conformance/types/objectTypeLiteral/indexSignatures/stringIndexerConstrainsPropertyDeclarations2.ts(38,8): error TS2322: Type 'typeof B' is not assignable to type 'A'. Property 'foo' is missing in type 'typeof B'. @@ -60,13 +60,13 @@ tests/cases/conformance/types/objectTypeLiteral/indexSignatures/stringIndexerCon // error var b: { [x: string]: A } = { a: A, - ~ + ~ !!! error TS2322: Type 'typeof A' is not assignable to type 'A'. !!! error TS2322: Property 'foo' is missing in type 'typeof A'. -!!! related TS6501 tests/cases/conformance/types/objectTypeLiteral/indexSignatures/stringIndexerConstrainsPropertyDeclarations2.ts:36:10: The expected type comes from this index signature. +!!! related TS6213 tests/cases/conformance/types/objectTypeLiteral/indexSignatures/stringIndexerConstrainsPropertyDeclarations2.ts:37:8: Did you mean to use `new` with this expression? b: B - ~ + ~ !!! error TS2322: Type 'typeof B' is not assignable to type 'A'. !!! error TS2322: Property 'foo' is missing in type 'typeof B'. -!!! related TS6501 tests/cases/conformance/types/objectTypeLiteral/indexSignatures/stringIndexerConstrainsPropertyDeclarations2.ts:36:10: The expected type comes from this index signature. +!!! related TS6213 tests/cases/conformance/types/objectTypeLiteral/indexSignatures/stringIndexerConstrainsPropertyDeclarations2.ts:38:8: Did you mean to use `new` with this expression? } \ No newline at end of file diff --git a/tests/baselines/reference/typeMatch1.errors.txt b/tests/baselines/reference/typeMatch1.errors.txt index 7025fd0c3b2..598d9f97483 100644 --- a/tests/baselines/reference/typeMatch1.errors.txt +++ b/tests/baselines/reference/typeMatch1.errors.txt @@ -1,6 +1,6 @@ tests/cases/compiler/typeMatch1.ts(18,1): error TS2322: Type 'D' is not assignable to type 'C'. Types have separate declarations of a private property 'x'. -tests/cases/compiler/typeMatch1.ts(19,1): error TS2322: Type 'typeof C' is not assignable to type 'C'. +tests/cases/compiler/typeMatch1.ts(19,4): error TS2322: Type 'typeof C' is not assignable to type 'C'. Property 'x' is missing in type 'typeof C'. tests/cases/compiler/typeMatch1.ts(20,1): error TS2367: This condition will always return 'false' since the types 'typeof C' and 'typeof D' have no overlap. @@ -28,9 +28,10 @@ tests/cases/compiler/typeMatch1.ts(20,1): error TS2367: This condition will alwa !!! error TS2322: Type 'D' is not assignable to type 'C'. !!! error TS2322: Types have separate declarations of a private property 'x'. x6=C; - ~~ + ~ !!! error TS2322: Type 'typeof C' is not assignable to type 'C'. !!! error TS2322: Property 'x' is missing in type 'typeof C'. +!!! related TS6213 tests/cases/compiler/typeMatch1.ts:19:4: Did you mean to use `new` with this expression? C==D; ~~~~ !!! error TS2367: This condition will always return 'false' since the types 'typeof C' and 'typeof D' have no overlap. diff --git a/tests/baselines/reference/weakType.errors.txt b/tests/baselines/reference/weakType.errors.txt index ffc1d237593..869f60cd924 100644 --- a/tests/baselines/reference/weakType.errors.txt +++ b/tests/baselines/reference/weakType.errors.txt @@ -29,12 +29,15 @@ tests/cases/compiler/weakType.ts(62,5): error TS2322: Type '{ properties: { wron doSomething(getDefaultSettings); ~~~~~~~~~~~~~~~~~~ !!! error TS2560: Value of type '() => { timeout: number; }' has no properties in common with type 'Settings'. Did you mean to call it? +!!! related TS6212 tests/cases/compiler/weakType.ts:15:13: Did you mean to call this expression? doSomething(() => ({ timeout: 1000 })); ~~~~~~~~~~~~~~~~~~~~~~~~~ !!! error TS2560: Value of type '() => { timeout: number; }' has no properties in common with type 'Settings'. Did you mean to call it? +!!! related TS6212 tests/cases/compiler/weakType.ts:16:13: Did you mean to call this expression? doSomething(null as CtorOnly); ~~~~~~~~~~~~~~~~ !!! error TS2560: Value of type 'CtorOnly' has no properties in common with type 'Settings'. Did you mean to call it? +!!! related TS6213 tests/cases/compiler/weakType.ts:17:13: Did you mean to use `new` with this expression? doSomething(12); ~~ !!! error TS2559: Type '12' has no properties in common with type 'Settings'. diff --git a/tests/cases/compiler/didYouMeanElaborationsForExpressionsWhichCouldBeCalled.ts b/tests/cases/compiler/didYouMeanElaborationsForExpressionsWhichCouldBeCalled.ts new file mode 100644 index 00000000000..392f3461d9a --- /dev/null +++ b/tests/cases/compiler/didYouMeanElaborationsForExpressionsWhichCouldBeCalled.ts @@ -0,0 +1,27 @@ +class Bar { + x!: string; +} + +declare function getNum(): number; + +declare function foo(arg: { x: Bar, y: Date }, item: number, items?: [number, number, number]): void; + +foo({ + x: Bar, + y: Date +}, getNum()); + +foo({ + x: new Bar(), + y: new Date() +}, getNum); + + +foo({ + x: new Bar(), + y: new Date() +}, getNum(), [ + 1, + 2, + getNum +]); From 5d79704931989a3a53adc4f4e31e7bd883809e05 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Tue, 11 Sep 2018 14:19:28 -0700 Subject: [PATCH 30/83] Sanitize module resolution logs for typesVersions entries --- src/compiler/utilities.ts | 9 +++++++++ src/harness/utils.ts | 15 +++++++++++++++ src/testRunner/compilerRunner.ts | 2 +- 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 5191fe1cc47..18b45d682db 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -7671,6 +7671,15 @@ namespace ts { // It may be inefficient (we could just match (/[-[\]{}()*+?.,\\^$|#\s]/g), but this is future // proof. const reservedCharacterPattern = /[^\w\s\/]/g; + + export function regExpEscape(text: string) { + return text.replace(reservedCharacterPattern, escapeRegExpCharacter); + } + + function escapeRegExpCharacter(match: string) { + return "\\" + match; + } + const wildcardCharCodes = [CharacterCodes.asterisk, CharacterCodes.question]; export function hasExtension(fileName: string): boolean { diff --git a/src/harness/utils.ts b/src/harness/utils.ts index 14820f10529..5938db7d62c 100644 --- a/src/harness/utils.ts +++ b/src/harness/utils.ts @@ -7,6 +7,21 @@ namespace utils { return text !== undefined ? text.replace(testPathPrefixRegExp, (_, scheme) => scheme || (retainTrailingDirectorySeparator ? "/" : "")) : undefined!; // TODO: GH#18217 } + function createDiagnosticMessageReplacer string[]>(diagnosticMessage: ts.DiagnosticMessage, replacer: R) { + const messageParts = diagnosticMessage.message.split(/{\d+}/g); + const regExp = new RegExp(`^(?:${messageParts.map(ts.regExpEscape).join("(.*?)")})$`); + type Args = R extends (messageArgs: string[], ...args: infer A) => string[] ? A : []; + return (text: string, ...args: Args) => text.replace(regExp, (_, ...fixedArgs) => ts.formatStringFromArgs(diagnosticMessage.message, replacer(fixedArgs, ...args))); + } + + const replaceTypesVersionsMessage = createDiagnosticMessageReplacer( + ts.Diagnostics.package_json_has_a_typesVersions_entry_0_that_matches_compiler_version_1_looking_for_a_pattern_to_match_module_name_2, + ([entry, , moduleName], compilerVersion) => [entry, compilerVersion, moduleName]); + + export function sanitizeTraceResolutionLogEntry(text: string) { + return text && removeTestPathPrefixes(replaceTypesVersionsMessage(text, "3.1.0-dev")); + } + /** * Removes leading indentation from a template literal string. */ diff --git a/src/testRunner/compilerRunner.ts b/src/testRunner/compilerRunner.ts index a0af5d88f3b..bb481eca03e 100644 --- a/src/testRunner/compilerRunner.ts +++ b/src/testRunner/compilerRunner.ts @@ -208,7 +208,7 @@ class CompilerTest { public verifyModuleResolution() { if (this.options.traceResolution) { Harness.Baseline.runBaseline(this.justName.replace(/\.tsx?$/, ".trace.json"), - utils.removeTestPathPrefixes(JSON.stringify(this.result.traces, undefined, 4))); + JSON.stringify(this.result.traces.map(utils.sanitizeTraceResolutionLogEntry), undefined, 4)); } } From c8cdb8146a8a63127db55fdc6ed0f686e64b7d0e Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 11 Sep 2018 14:27:25 -0700 Subject: [PATCH 31/83] Always create dependency graph and build order --- src/compiler/diagnosticMessages.json | 4 -- src/compiler/tsbuild.ts | 66 +++++++--------------------- src/testRunner/unittests/tsbuild.ts | 1 - 3 files changed, 15 insertions(+), 56 deletions(-) diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 7a57b89d320..56a255bead6 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3838,10 +3838,6 @@ "category": "Error", "code": 6370 }, - "Skipping clean because not all projects could be located": { - "category": "Error", - "code": 6371 - }, "The expected type comes from property '{0}' which is declared here on type '{1}'": { "category": "Message", diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts index 65dfa88256f..f61ef42c7cb 100644 --- a/src/compiler/tsbuild.ts +++ b/src/compiler/tsbuild.ts @@ -341,7 +341,7 @@ namespace ts { /*@internal*/ resolveProjectName(name: string): ResolvedConfigFileName; /*@internal*/ getUpToDateStatusOfFile(configFileName: ResolvedConfigFileName): UpToDateStatus; - /*@internal*/ getBuildGraph(configFileNames: ReadonlyArray): DependencyGraph | undefined; + /*@internal*/ getBuildGraph(configFileNames: ReadonlyArray): DependencyGraph; /*@internal*/ invalidateProject(configFileName: string, reloadLevel?: ConfigFileProgramReloadLevel): void; /*@internal*/ buildInvalidatedProject(): void; @@ -404,7 +404,7 @@ namespace ts { /** Map from config file name to up-to-date status */ const projectStatus = createFileMap(toPath); const missingRoots = createMap(); - let globalDependencyGraph: DependencyGraph | false | undefined; + let globalDependencyGraph: DependencyGraph | undefined; // Watch state // TODO(shkamat): this should be really be diagnostics but thats for later time @@ -504,12 +504,7 @@ namespace ts { } function startWatching() { - const graph = getGlobalDependencyGraph()!; - if (!graph.buildQueue) { - // Everything is broken - we don't even know what to watch. Give up. - return; - } - + const graph = getGlobalDependencyGraph(); for (const resolved of graph.buildQueue) { const cfg = parseConfigFile(resolved); if (cfg) { @@ -627,10 +622,7 @@ namespace ts { } function getGlobalDependencyGraph() { - if (globalDependencyGraph === undefined) { - globalDependencyGraph = getBuildGraph(rootNames) || false; - } - return globalDependencyGraph || undefined; + return globalDependencyGraph || (globalDependencyGraph = getBuildGraph(rootNames)); } function getUpToDateStatus(project: ParsedCommandLine | undefined): UpToDateStatus { @@ -826,10 +818,7 @@ namespace ts { if (addProjToQueue(resolved, reloadLevel)) { // TODO: instead of adding the dependent project to queue right away postpone this - const dependencyGraph = getGlobalDependencyGraph(); - if (dependencyGraph) { - queueBuildForDownstreamReferences(resolved, dependencyGraph); - } + queueBuildForDownstreamReferences(resolved, getGlobalDependencyGraph()); } } @@ -950,49 +939,36 @@ namespace ts { buildSingleProject(resolved); } - function createDependencyGraph(roots: ResolvedConfigFileName[]): DependencyGraph | undefined { - const temporaryMarks: { [path: string]: true } = {}; - const permanentMarks: { [path: string]: true } = {}; + function createDependencyGraph(roots: ResolvedConfigFileName[]): DependencyGraph { + const temporaryMarks = createFileMap(toPath); + const permanentMarks = createFileMap(toPath); const circularityReportStack: string[] = []; const buildOrder: ResolvedConfigFileName[] = []; const graph = createDependencyMapper(toPath); - - let hadError = false; - for (const root of roots) { visit(root); } - if (hadError) { - return undefined; - } - return { buildQueue: buildOrder, - dependencyMap: graph + dependencyMap: graph, }; function visit(projPath: ResolvedConfigFileName, inCircularContext = false) { // Already visited - if (permanentMarks[projPath]) return; + if (permanentMarks.hasKey(projPath)) return; // Circular - if (temporaryMarks[projPath]) { + if (temporaryMarks.hasKey(projPath)) { if (!inCircularContext) { - hadError = true; - // TODO(shkamat): Account for this error reportStatus(Diagnostics.Project_references_may_not_form_a_circular_graph_Cycle_detected_Colon_0, circularityReportStack.join("\r\n")); return; } } - temporaryMarks[projPath] = true; + temporaryMarks.setValue(projPath, true); circularityReportStack.push(projPath); const parsed = parseConfigFile(projPath); - if (parsed === undefined) { - hadError = true; - return; - } - if (parsed.projectReferences) { + if (parsed && parsed.projectReferences) { for (const ref of parsed.projectReferences) { const resolvedRefPath = resolveProjectName(ref.path); visit(resolvedRefPath, inCircularContext || ref.circular); @@ -1001,7 +977,7 @@ namespace ts { } circularityReportStack.pop(); - permanentMarks[projPath] = true; + permanentMarks.setValue(projPath, true); buildOrder.push(projPath); } } @@ -1135,11 +1111,9 @@ namespace ts { projectStatus.setValue(proj.options.configFilePath as ResolvedConfigFilePath, { type: UpToDateStatusType.UpToDate, newestDeclarationFileContentChangedTime: priorNewestUpdateTime } as UpToDateStatus); } - function getFilesToClean(): string[] | undefined { + function getFilesToClean(): string[] { // Get the same graph for cleaning we'd use for building const graph = getGlobalDependencyGraph(); - if (graph === undefined) return undefined; - const filesToDelete: string[] = []; for (const proj of graph.buildQueue) { const parsed = parseConfigFile(proj); @@ -1159,11 +1133,6 @@ namespace ts { function cleanAllProjects() { const filesToDelete = getFilesToClean(); - if (filesToDelete === undefined) { - reportStatus(Diagnostics.Skipping_clean_because_not_all_projects_could_be_located); - return ExitStatus.DiagnosticsPresent_OutputsSkipped; - } - if (options.dry) { reportStatus(Diagnostics.A_non_dry_build_would_delete_the_following_files_Colon_0, filesToDelete.map(f => `\r\n * ${f}`).join("")); return ExitStatus.Success; @@ -1187,11 +1156,6 @@ namespace ts { function buildAllProjects(): ExitStatus { if (options.watch) { reportWatchStatus(Diagnostics.Starting_compilation_in_watch_mode); } const graph = getGlobalDependencyGraph(); - if (graph === undefined) { - reportErrorSummary(); - return ExitStatus.DiagnosticsPresent_OutputsSkipped; - } - const queue = graph.buildQueue; reportBuildQueue(graph); let anyFailed = false; diff --git a/src/testRunner/unittests/tsbuild.ts b/src/testRunner/unittests/tsbuild.ts index bb620fc776b..a9993aabc40 100644 --- a/src/testRunner/unittests/tsbuild.ts +++ b/src/testRunner/unittests/tsbuild.ts @@ -377,7 +377,6 @@ namespace ts { const projFileNames = rootNames.map(getProjectFileName); const graph = builder.getBuildGraph(projFileNames); - if (graph === undefined) throw new Error("Graph shouldn't be undefined"); assert.sameMembers(graph.buildQueue, expectedBuildSet.map(getProjectFileName)); From 31374d21bf8b37c0c3745365f83d91c9888be47a Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 11 Sep 2018 14:42:17 -0700 Subject: [PATCH 32/83] Provide suggestions for common can-not-find-name errors (#27034) --- src/compiler/checker.ts | 39 +++++- src/compiler/diagnosticMessages.json | 24 ++++ .../reference/ES5For-ofTypeCheck10.errors.txt | 4 +- .../reference/ES5SymbolProperty2.errors.txt | 4 +- .../reference/ES5SymbolProperty6.errors.txt | 8 +- .../reference/anonymousModules.errors.txt | 12 +- .../argumentsObjectIterator02_ES5.errors.txt | 4 +- ...onflictingCommonJSES2015Exports.errors.txt | 4 +- ...torWithIncompleteTypeAnnotation.errors.txt | 14 +- ...tadataNoLibIsolatedModulesTypes.errors.txt | 4 +- .../didYouMeanSuggestionErrors.errors.txt | 88 ++++++++++++ .../reference/didYouMeanSuggestionErrors.js | 55 ++++++++ .../didYouMeanSuggestionErrors.symbols | 57 ++++++++ .../didYouMeanSuggestionErrors.types | 125 ++++++++++++++++++ .../reference/externModule.errors.txt | 4 +- .../reference/fixSignatureCaching.errors.txt | 12 +- .../reference/innerModExport1.errors.txt | 4 +- .../reference/innerModExport2.errors.txt | 4 +- .../reference/jsxAndTypeAssertion.errors.txt | 4 +- .../reference/metadataImportType.errors.txt | 4 +- ...mUsingES6FeaturesWithOnlyES5Lib.errors.txt | 20 +-- ...bolWithOutES6WellknownSymbolLib.errors.txt | 4 +- .../reference/moduleExports1.errors.txt | 8 +- .../moduleKeywordRepeatError.errors.txt | 4 +- .../noAssertForUnparseableTypedefs.errors.txt | 4 +- ...adingStaticFunctionsInFunctions.errors.txt | 12 +- .../reference/parser509534.errors.txt | 8 +- .../reference/parser509693.errors.txt | 8 +- .../reference/parser519458.errors.txt | 6 +- .../reference/parser521128.errors.txt | 4 +- .../parserCommaInTypeMemberList2.errors.txt | 4 +- .../parserES5SymbolProperty1.errors.txt | 4 +- .../parserES5SymbolProperty2.errors.txt | 4 +- .../parserES5SymbolProperty3.errors.txt | 4 +- .../parserES5SymbolProperty4.errors.txt | 4 +- .../parserES5SymbolProperty5.errors.txt | 4 +- .../parserES5SymbolProperty6.errors.txt | 4 +- .../parserES5SymbolProperty7.errors.txt | 4 +- .../parserES5SymbolProperty8.errors.txt | 4 +- .../parserES5SymbolProperty9.errors.txt | 4 +- .../parserMissingLambdaOpenBrace1.errors.txt | 4 +- .../reference/parserharness.errors.txt | 8 +- .../reference/reservedWords2.errors.txt | 8 +- .../reference/staticsInAFunction.errors.txt | 12 +- .../templateStringInModuleName.errors.txt | 8 +- .../templateStringInModuleNameES6.errors.txt | 8 +- .../reference/typecheckIfCondition.errors.txt | 8 +- .../compiler/didYouMeanSuggestionErrors.ts | 29 ++++ 48 files changed, 544 insertions(+), 133 deletions(-) create mode 100644 tests/baselines/reference/didYouMeanSuggestionErrors.errors.txt create mode 100644 tests/baselines/reference/didYouMeanSuggestionErrors.js create mode 100644 tests/baselines/reference/didYouMeanSuggestionErrors.symbols create mode 100644 tests/baselines/reference/didYouMeanSuggestionErrors.types create mode 100644 tests/cases/compiler/didYouMeanSuggestionErrors.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 19ca10e83be..a856df2854a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1657,7 +1657,10 @@ namespace ts { } const symbol = resolveSymbol(resolveName(errorLocation, name, SymbolFlags.Type & ~SymbolFlags.Value, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined, /*isUse*/ false)); if (symbol && !(symbol.flags & SymbolFlags.NamespaceModule)) { - error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here, unescapeLeadingUnderscores(name)); + const message = (name === "Promise" || name === "Symbol") + ? Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here_Do_you_need_to_change_your_target_library_Try_changing_the_lib_compiler_option_to_es2015_or_later + : Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here; + error(errorLocation, message, unescapeLeadingUnderscores(name)); return true; } } @@ -2081,7 +2084,7 @@ namespace ts { const namespaceMeaning = SymbolFlags.Namespace | (isInJavaScriptFile(name) ? meaning & SymbolFlags.Value : 0); let symbol: Symbol | undefined; if (name.kind === SyntaxKind.Identifier) { - const message = meaning === namespaceMeaning ? Diagnostics.Cannot_find_namespace_0 : Diagnostics.Cannot_find_name_0; + const message = meaning === namespaceMeaning ? Diagnostics.Cannot_find_namespace_0 : getCannotFindNameDiagnosticForName(getFirstIdentifier(name).escapedText); const symbolFromJSPrototype = isInJavaScriptFile(name) ? resolveEntityNameFromJSSpecialAssignment(name, meaning) : undefined; symbol = resolveName(location || name, name.escapedText, meaning, ignoreErrors || symbolFromJSPrototype ? undefined : message, name, /*isUse*/ true); if (!symbol) { @@ -13842,6 +13845,36 @@ namespace ts { // EXPRESSION TYPE CHECKING + function getCannotFindNameDiagnosticForName(name: __String): DiagnosticMessage { + switch (name) { + case "document": + case "console": + return Diagnostics.Cannot_find_name_0_Do_you_need_to_change_your_target_library_Try_changing_the_lib_compiler_option_to_include_dom; + case "$": + return Diagnostics.Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_jQuery_Try_npm_i_types_Slashjquery; + case "describe": + case "suite": + case "it": + case "test": + return Diagnostics.Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_a_test_runner_Try_npm_i_types_Slashjest_or_npm_i_types_Slashmocha; + case "process": + case "require": + case "Buffer": + case "module": + return Diagnostics.Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_node_Try_npm_i_types_Slashnode; + case "Map": + case "Set": + case "Promise": + case "Symbol": + case "WeakMap": + case "WeakSet": + case "Iterator": + case "AsyncIterator": + return Diagnostics.Cannot_find_name_0_Do_you_need_to_change_your_target_library_Try_changing_the_lib_compiler_option_to_es2015_or_later; + default: return Diagnostics.Cannot_find_name_0; + } + } + function getResolvedSymbol(node: Identifier): Symbol { const links = getNodeLinks(node); if (!links.resolvedSymbol) { @@ -13850,7 +13883,7 @@ namespace ts { node, node.escapedText, SymbolFlags.Value | SymbolFlags.ExportValue, - Diagnostics.Cannot_find_name_0, + getCannotFindNameDiagnosticForName(node.escapedText), node, !isWriteOnlyAccess(node), /*excludeGlobals*/ false, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index f3dec7287d5..18b64b74e0a 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2088,6 +2088,30 @@ "category": "Error", "code": 2577 }, + "Cannot find name '{0}'. Do you need to install type definitions for node? Try `npm i @types/node`.": { + "category": "Error", + "code": 2580 + }, + "Cannot find name '{0}'. Do you need to install type definitions for jQuery? Try `npm i @types/jquery`.": { + "category": "Error", + "code": 2581 + }, + "Cannot find name '{0}'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`.": { + "category": "Error", + "code": 2582 + }, + "Cannot find name '{0}'. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later.": { + "category": "Error", + "code": 2583 + }, + "Cannot find name '{0}'. Do you need to change your target library? Try changing the `lib` compiler option to include 'dom'.": { + "category": "Error", + "code": 2584 + }, + "'{0}' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later.": { + "category": "Error", + "code": 2585 + }, "JSX element attributes type '{0}' may not be a union type.": { "category": "Error", "code": 2600 diff --git a/tests/baselines/reference/ES5For-ofTypeCheck10.errors.txt b/tests/baselines/reference/ES5For-ofTypeCheck10.errors.txt index 232f476f66c..6622033a687 100644 --- a/tests/baselines/reference/ES5For-ofTypeCheck10.errors.txt +++ b/tests/baselines/reference/ES5For-ofTypeCheck10.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/statements/for-ofStatements/ES5For-ofTypeCheck10.ts(9,6): error TS2693: 'Symbol' only refers to a type, but is being used as a value here. +tests/cases/conformance/statements/for-ofStatements/ES5For-ofTypeCheck10.ts(9,6): error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. tests/cases/conformance/statements/for-ofStatements/ES5For-ofTypeCheck10.ts(14,15): error TS2569: Type 'StringIterator' is not an array type or a string type. Use compiler option '--downlevelIteration' to allow iterating of iterators. @@ -13,7 +13,7 @@ tests/cases/conformance/statements/for-ofStatements/ES5For-ofTypeCheck10.ts(14,1 } [Symbol.iterator]() { ~~~~~~ -!!! error TS2693: 'Symbol' only refers to a type, but is being used as a value here. +!!! error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. return this; } } diff --git a/tests/baselines/reference/ES5SymbolProperty2.errors.txt b/tests/baselines/reference/ES5SymbolProperty2.errors.txt index 0535da56f06..2115ed99979 100644 --- a/tests/baselines/reference/ES5SymbolProperty2.errors.txt +++ b/tests/baselines/reference/ES5SymbolProperty2.errors.txt @@ -1,5 +1,5 @@ tests/cases/conformance/Symbols/ES5SymbolProperty2.ts(5,10): error TS2471: A computed property name of the form 'Symbol.iterator' must be of type 'symbol'. -tests/cases/conformance/Symbols/ES5SymbolProperty2.ts(10,11): error TS2693: 'Symbol' only refers to a type, but is being used as a value here. +tests/cases/conformance/Symbols/ES5SymbolProperty2.ts(10,11): error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. ==== tests/cases/conformance/Symbols/ES5SymbolProperty2.ts (2 errors) ==== @@ -16,4 +16,4 @@ tests/cases/conformance/Symbols/ES5SymbolProperty2.ts(10,11): error TS2693: 'Sym (new M.C)[Symbol.iterator]; ~~~~~~ -!!! error TS2693: 'Symbol' only refers to a type, but is being used as a value here. \ No newline at end of file +!!! error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. \ No newline at end of file diff --git a/tests/baselines/reference/ES5SymbolProperty6.errors.txt b/tests/baselines/reference/ES5SymbolProperty6.errors.txt index e359f9b73ba..4357fe6a62f 100644 --- a/tests/baselines/reference/ES5SymbolProperty6.errors.txt +++ b/tests/baselines/reference/ES5SymbolProperty6.errors.txt @@ -1,14 +1,14 @@ -tests/cases/conformance/Symbols/ES5SymbolProperty6.ts(2,6): error TS2693: 'Symbol' only refers to a type, but is being used as a value here. -tests/cases/conformance/Symbols/ES5SymbolProperty6.ts(5,9): error TS2693: 'Symbol' only refers to a type, but is being used as a value here. +tests/cases/conformance/Symbols/ES5SymbolProperty6.ts(2,6): error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. +tests/cases/conformance/Symbols/ES5SymbolProperty6.ts(5,9): error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. ==== tests/cases/conformance/Symbols/ES5SymbolProperty6.ts (2 errors) ==== class C { [Symbol.iterator]() { } ~~~~~~ -!!! error TS2693: 'Symbol' only refers to a type, but is being used as a value here. +!!! error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. } (new C)[Symbol.iterator] ~~~~~~ -!!! error TS2693: 'Symbol' only refers to a type, but is being used as a value here. \ No newline at end of file +!!! error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. \ No newline at end of file diff --git a/tests/baselines/reference/anonymousModules.errors.txt b/tests/baselines/reference/anonymousModules.errors.txt index 4893a0c80aa..b81513cfbbd 100644 --- a/tests/baselines/reference/anonymousModules.errors.txt +++ b/tests/baselines/reference/anonymousModules.errors.txt @@ -1,22 +1,22 @@ -tests/cases/compiler/anonymousModules.ts(1,1): error TS2304: Cannot find name 'module'. +tests/cases/compiler/anonymousModules.ts(1,1): error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. tests/cases/compiler/anonymousModules.ts(1,8): error TS1005: ';' expected. -tests/cases/compiler/anonymousModules.ts(4,2): error TS2304: Cannot find name 'module'. +tests/cases/compiler/anonymousModules.ts(4,2): error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. tests/cases/compiler/anonymousModules.ts(4,9): error TS1005: ';' expected. -tests/cases/compiler/anonymousModules.ts(10,2): error TS2304: Cannot find name 'module'. +tests/cases/compiler/anonymousModules.ts(10,2): error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. tests/cases/compiler/anonymousModules.ts(10,9): error TS1005: ';' expected. ==== tests/cases/compiler/anonymousModules.ts (6 errors) ==== module { ~~~~~~ -!!! error TS2304: Cannot find name 'module'. +!!! error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. ~ !!! error TS1005: ';' expected. export var foo = 1; module { ~~~~~~ -!!! error TS2304: Cannot find name 'module'. +!!! error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. ~ !!! error TS1005: ';' expected. export var bar = 1; @@ -26,7 +26,7 @@ tests/cases/compiler/anonymousModules.ts(10,9): error TS1005: ';' expected. module { ~~~~~~ -!!! error TS2304: Cannot find name 'module'. +!!! error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. ~ !!! error TS1005: ';' expected. var x = bar; diff --git a/tests/baselines/reference/argumentsObjectIterator02_ES5.errors.txt b/tests/baselines/reference/argumentsObjectIterator02_ES5.errors.txt index 92764ddf90b..4ae19920e37 100644 --- a/tests/baselines/reference/argumentsObjectIterator02_ES5.errors.txt +++ b/tests/baselines/reference/argumentsObjectIterator02_ES5.errors.txt @@ -1,11 +1,11 @@ -tests/cases/compiler/argumentsObjectIterator02_ES5.ts(2,26): error TS2693: 'Symbol' only refers to a type, but is being used as a value here. +tests/cases/compiler/argumentsObjectIterator02_ES5.ts(2,26): error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. ==== tests/cases/compiler/argumentsObjectIterator02_ES5.ts (1 errors) ==== function doubleAndReturnAsArray(x: number, y: number, z: number): [number, number, number] { let blah = arguments[Symbol.iterator]; ~~~~~~ -!!! error TS2693: 'Symbol' only refers to a type, but is being used as a value here. +!!! error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. let result = []; for (let arg of blah()) { diff --git a/tests/baselines/reference/conflictingCommonJSES2015Exports.errors.txt b/tests/baselines/reference/conflictingCommonJSES2015Exports.errors.txt index 88b1890d6d8..2f47712c9db 100644 --- a/tests/baselines/reference/conflictingCommonJSES2015Exports.errors.txt +++ b/tests/baselines/reference/conflictingCommonJSES2015Exports.errors.txt @@ -1,11 +1,11 @@ -tests/cases/conformance/salsa/bug24934.js(2,1): error TS2304: Cannot find name 'module'. +tests/cases/conformance/salsa/bug24934.js(2,1): error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. ==== tests/cases/conformance/salsa/bug24934.js (1 errors) ==== export function abc(a, b, c) { return 5; } module.exports = { abc }; ~~~~~~ -!!! error TS2304: Cannot find name 'module'. +!!! error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. ==== tests/cases/conformance/salsa/use.js (0 errors) ==== import { abc } from './bug24934'; abc(1, 2, 3); diff --git a/tests/baselines/reference/constructorWithIncompleteTypeAnnotation.errors.txt b/tests/baselines/reference/constructorWithIncompleteTypeAnnotation.errors.txt index 46eaa413c2e..1b0034a3063 100644 --- a/tests/baselines/reference/constructorWithIncompleteTypeAnnotation.errors.txt +++ b/tests/baselines/reference/constructorWithIncompleteTypeAnnotation.errors.txt @@ -1,5 +1,5 @@ -tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(11,13): error TS2304: Cannot find name 'module'. tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(11,13): error TS2503: Cannot find namespace 'module'. +tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(11,13): error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(11,19): error TS1005: ';' expected. tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(22,35): error TS1005: ')' expected. tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(22,39): error TS2363: The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type. @@ -21,8 +21,8 @@ tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(40,41): error TS tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(40,45): error TS1002: Unterminated string literal. tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(41,21): error TS2304: Cannot find name 'retValue'. tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(46,13): error TS1005: 'try' expected. -tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(47,17): error TS2304: Cannot find name 'console'. -tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(53,13): error TS2304: Cannot find name 'console'. +tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(47,17): error TS2584: Cannot find name 'console'. Do you need to change your target library? Try changing the `lib` compiler option to include 'dom'. +tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(53,13): error TS2584: Cannot find name 'console'. Do you need to change your target library? Try changing the `lib` compiler option to include 'dom'. tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(58,5): error TS1128: Declaration or statement expected. tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(69,13): error TS1109: Expression expected. tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(72,37): error TS1127: Invalid character. @@ -103,9 +103,9 @@ tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(261,1): error TS import fs = module("fs"); ~~~~~~ -!!! error TS2304: Cannot find name 'module'. - ~~~~~~ !!! error TS2503: Cannot find namespace 'module'. + ~~~~~~ +!!! error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. ~ !!! error TS1005: ';' expected. @@ -188,7 +188,7 @@ tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(261,1): error TS !!! error TS1005: 'try' expected. console.log(e); ~~~~~~~ -!!! error TS2304: Cannot find name 'console'. +!!! error TS2584: Cannot find name 'console'. Do you need to change your target library? Try changing the `lib` compiler option to include 'dom'. } finally { @@ -196,7 +196,7 @@ tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(261,1): error TS console.log('Done'); ~~~~~~~ -!!! error TS2304: Cannot find name 'console'. +!!! error TS2584: Cannot find name 'console'. Do you need to change your target library? Try changing the `lib` compiler option to include 'dom'. return 0; diff --git a/tests/baselines/reference/decoratorMetadataNoLibIsolatedModulesTypes.errors.txt b/tests/baselines/reference/decoratorMetadataNoLibIsolatedModulesTypes.errors.txt index 1af8d3f7102..a99536c582b 100644 --- a/tests/baselines/reference/decoratorMetadataNoLibIsolatedModulesTypes.errors.txt +++ b/tests/baselines/reference/decoratorMetadataNoLibIsolatedModulesTypes.errors.txt @@ -7,7 +7,7 @@ error TS2318: Cannot find global type 'Object'. error TS2318: Cannot find global type 'RegExp'. error TS2318: Cannot find global type 'String'. tests/cases/compiler/decoratorMetadataNoLibIsolatedModulesTypes.ts(2,6): error TS2304: Cannot find name 'Decorate'. -tests/cases/compiler/decoratorMetadataNoLibIsolatedModulesTypes.ts(3,13): error TS2304: Cannot find name 'Map'. +tests/cases/compiler/decoratorMetadataNoLibIsolatedModulesTypes.ts(3,13): error TS2583: Cannot find name 'Map'. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. !!! error TS2318: Cannot find global type 'Array'. @@ -25,6 +25,6 @@ tests/cases/compiler/decoratorMetadataNoLibIsolatedModulesTypes.ts(3,13): error !!! error TS2304: Cannot find name 'Decorate'. member: Map; ~~~ -!!! error TS2304: Cannot find name 'Map'. +!!! error TS2583: Cannot find name 'Map'. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. } \ No newline at end of file diff --git a/tests/baselines/reference/didYouMeanSuggestionErrors.errors.txt b/tests/baselines/reference/didYouMeanSuggestionErrors.errors.txt new file mode 100644 index 00000000000..a41b19ecd9d --- /dev/null +++ b/tests/baselines/reference/didYouMeanSuggestionErrors.errors.txt @@ -0,0 +1,88 @@ +tests/cases/compiler/didYouMeanSuggestionErrors.ts(1,1): error TS2582: Cannot find name 'describe'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`. +tests/cases/compiler/didYouMeanSuggestionErrors.ts(2,5): error TS2582: Cannot find name 'it'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`. +tests/cases/compiler/didYouMeanSuggestionErrors.ts(3,19): error TS2581: Cannot find name '$'. Do you need to install type definitions for jQuery? Try `npm i @types/jquery`. +tests/cases/compiler/didYouMeanSuggestionErrors.ts(7,1): error TS2582: Cannot find name 'suite'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`. +tests/cases/compiler/didYouMeanSuggestionErrors.ts(8,5): error TS2582: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`. +tests/cases/compiler/didYouMeanSuggestionErrors.ts(9,9): error TS2584: Cannot find name 'console'. Do you need to change your target library? Try changing the `lib` compiler option to include 'dom'. +tests/cases/compiler/didYouMeanSuggestionErrors.ts(9,21): error TS2580: Cannot find name 'process'. Do you need to install type definitions for node? Try `npm i @types/node`. +tests/cases/compiler/didYouMeanSuggestionErrors.ts(10,9): error TS2584: Cannot find name 'document'. Do you need to change your target library? Try changing the `lib` compiler option to include 'dom'. +tests/cases/compiler/didYouMeanSuggestionErrors.ts(12,19): error TS2580: Cannot find name 'require'. Do you need to install type definitions for node? Try `npm i @types/node`. +tests/cases/compiler/didYouMeanSuggestionErrors.ts(13,19): error TS2580: Cannot find name 'Buffer'. Do you need to install type definitions for node? Try `npm i @types/node`. +tests/cases/compiler/didYouMeanSuggestionErrors.ts(14,19): error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. +tests/cases/compiler/didYouMeanSuggestionErrors.ts(16,23): error TS2583: Cannot find name 'Map'. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. +tests/cases/compiler/didYouMeanSuggestionErrors.ts(17,23): error TS2583: Cannot find name 'Set'. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. +tests/cases/compiler/didYouMeanSuggestionErrors.ts(18,23): error TS2583: Cannot find name 'WeakMap'. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. +tests/cases/compiler/didYouMeanSuggestionErrors.ts(19,23): error TS2583: Cannot find name 'WeakSet'. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. +tests/cases/compiler/didYouMeanSuggestionErrors.ts(20,19): error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. +tests/cases/compiler/didYouMeanSuggestionErrors.ts(21,19): error TS2585: 'Promise' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. +tests/cases/compiler/didYouMeanSuggestionErrors.ts(23,18): error TS2583: Cannot find name 'Iterator'. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. +tests/cases/compiler/didYouMeanSuggestionErrors.ts(24,18): error TS2583: Cannot find name 'AsyncIterator'. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. + + +==== tests/cases/compiler/didYouMeanSuggestionErrors.ts (19 errors) ==== + describe("my test suite", () => { + ~~~~~~~~ +!!! error TS2582: Cannot find name 'describe'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`. + it("should run", () => { + ~~ +!!! error TS2582: Cannot find name 'it'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`. + const a = $(".thing"); + ~ +!!! error TS2581: Cannot find name '$'. Do you need to install type definitions for jQuery? Try `npm i @types/jquery`. + }); + }); + + suite("another suite", () => { + ~~~~~ +!!! error TS2582: Cannot find name 'suite'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`. + test("everything else", () => { + ~~~~ +!!! error TS2582: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`. + console.log(process.env); + ~~~~~~~ +!!! error TS2584: Cannot find name 'console'. Do you need to change your target library? Try changing the `lib` compiler option to include 'dom'. + ~~~~~~~ +!!! error TS2580: Cannot find name 'process'. Do you need to install type definitions for node? Try `npm i @types/node`. + document.createElement("div"); + ~~~~~~~~ +!!! error TS2584: Cannot find name 'document'. Do you need to change your target library? Try changing the `lib` compiler option to include 'dom'. + + const x = require("fs"); + ~~~~~~~ +!!! error TS2580: Cannot find name 'require'. Do you need to install type definitions for node? Try `npm i @types/node`. + const y = Buffer.from([]); + ~~~~~~ +!!! error TS2580: Cannot find name 'Buffer'. Do you need to install type definitions for node? Try `npm i @types/node`. + const z = module.exports; + ~~~~~~ +!!! error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. + + const a = new Map(); + ~~~ +!!! error TS2583: Cannot find name 'Map'. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. + const b = new Set(); + ~~~ +!!! error TS2583: Cannot find name 'Set'. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. + const c = new WeakMap(); + ~~~~~~~ +!!! error TS2583: Cannot find name 'WeakMap'. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. + const d = new WeakSet(); + ~~~~~~~ +!!! error TS2583: Cannot find name 'WeakSet'. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. + const e = Symbol(); + ~~~~~~ +!!! error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. + const f = Promise.resolve(0); + ~~~~~~~ +!!! error TS2585: 'Promise' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. + + const i: Iterator = null as any; + ~~~~~~~~ +!!! error TS2583: Cannot find name 'Iterator'. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. + const j: AsyncIterator = null as any; + ~~~~~~~~~~~~~ +!!! error TS2583: Cannot find name 'AsyncIterator'. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. + const k: Symbol = null as any; + const l: Promise = null as any; + }); + }); \ No newline at end of file diff --git a/tests/baselines/reference/didYouMeanSuggestionErrors.js b/tests/baselines/reference/didYouMeanSuggestionErrors.js new file mode 100644 index 00000000000..fb13a31bb98 --- /dev/null +++ b/tests/baselines/reference/didYouMeanSuggestionErrors.js @@ -0,0 +1,55 @@ +//// [didYouMeanSuggestionErrors.ts] +describe("my test suite", () => { + it("should run", () => { + const a = $(".thing"); + }); +}); + +suite("another suite", () => { + test("everything else", () => { + console.log(process.env); + document.createElement("div"); + + const x = require("fs"); + const y = Buffer.from([]); + const z = module.exports; + + const a = new Map(); + const b = new Set(); + const c = new WeakMap(); + const d = new WeakSet(); + const e = Symbol(); + const f = Promise.resolve(0); + + const i: Iterator = null as any; + const j: AsyncIterator = null as any; + const k: Symbol = null as any; + const l: Promise = null as any; + }); +}); + +//// [didYouMeanSuggestionErrors.js] +describe("my test suite", function () { + it("should run", function () { + var a = $(".thing"); + }); +}); +suite("another suite", function () { + test("everything else", function () { + console.log(process.env); + document.createElement("div"); + var x = require("fs"); + var y = Buffer.from([]); + var z = module.exports; + var a = new Map(); + var b = new Set(); + var c = new WeakMap(); + var d = new WeakSet(); + var e = Symbol(); + var f = Promise.resolve(0); + var i = null; + var j = null; + var k = null; + var l = null; + }); +}); diff --git a/tests/baselines/reference/didYouMeanSuggestionErrors.symbols b/tests/baselines/reference/didYouMeanSuggestionErrors.symbols new file mode 100644 index 00000000000..8f63b2addd5 --- /dev/null +++ b/tests/baselines/reference/didYouMeanSuggestionErrors.symbols @@ -0,0 +1,57 @@ +=== tests/cases/compiler/didYouMeanSuggestionErrors.ts === +describe("my test suite", () => { + it("should run", () => { + const a = $(".thing"); +>a : Symbol(a, Decl(didYouMeanSuggestionErrors.ts, 2, 13)) + + }); +}); + +suite("another suite", () => { + test("everything else", () => { + console.log(process.env); + document.createElement("div"); + + const x = require("fs"); +>x : Symbol(x, Decl(didYouMeanSuggestionErrors.ts, 11, 13)) + + const y = Buffer.from([]); +>y : Symbol(y, Decl(didYouMeanSuggestionErrors.ts, 12, 13)) + + const z = module.exports; +>z : Symbol(z, Decl(didYouMeanSuggestionErrors.ts, 13, 13)) + + const a = new Map(); +>a : Symbol(a, Decl(didYouMeanSuggestionErrors.ts, 15, 13)) + + const b = new Set(); +>b : Symbol(b, Decl(didYouMeanSuggestionErrors.ts, 16, 13)) + + const c = new WeakMap(); +>c : Symbol(c, Decl(didYouMeanSuggestionErrors.ts, 17, 13)) + + const d = new WeakSet(); +>d : Symbol(d, Decl(didYouMeanSuggestionErrors.ts, 18, 13)) + + const e = Symbol(); +>e : Symbol(e, Decl(didYouMeanSuggestionErrors.ts, 19, 13)) + + const f = Promise.resolve(0); +>f : Symbol(f, Decl(didYouMeanSuggestionErrors.ts, 20, 13)) + + const i: Iterator = null as any; +>i : Symbol(i, Decl(didYouMeanSuggestionErrors.ts, 22, 13)) + + const j: AsyncIterator = null as any; +>j : Symbol(j, Decl(didYouMeanSuggestionErrors.ts, 23, 13)) + + const k: Symbol = null as any; +>k : Symbol(k, Decl(didYouMeanSuggestionErrors.ts, 24, 13)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --)) + + const l: Promise = null as any; +>l : Symbol(l, Decl(didYouMeanSuggestionErrors.ts, 25, 13)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --)) + + }); +}); diff --git a/tests/baselines/reference/didYouMeanSuggestionErrors.types b/tests/baselines/reference/didYouMeanSuggestionErrors.types new file mode 100644 index 00000000000..60259cde734 --- /dev/null +++ b/tests/baselines/reference/didYouMeanSuggestionErrors.types @@ -0,0 +1,125 @@ +=== tests/cases/compiler/didYouMeanSuggestionErrors.ts === +describe("my test suite", () => { +>describe("my test suite", () => { it("should run", () => { const a = $(".thing"); });}) : any +>describe : any +>"my test suite" : "my test suite" +>() => { it("should run", () => { const a = $(".thing"); });} : () => void + + it("should run", () => { +>it("should run", () => { const a = $(".thing"); }) : any +>it : any +>"should run" : "should run" +>() => { const a = $(".thing"); } : () => void + + const a = $(".thing"); +>a : any +>$(".thing") : any +>$ : any +>".thing" : ".thing" + + }); +}); + +suite("another suite", () => { +>suite("another suite", () => { test("everything else", () => { console.log(process.env); document.createElement("div"); const x = require("fs"); const y = Buffer.from([]); const z = module.exports; const a = new Map(); const b = new Set(); const c = new WeakMap(); const d = new WeakSet(); const e = Symbol(); const f = Promise.resolve(0); const i: Iterator = null as any; const j: AsyncIterator = null as any; const k: Symbol = null as any; const l: Promise = null as any; });}) : any +>suite : any +>"another suite" : "another suite" +>() => { test("everything else", () => { console.log(process.env); document.createElement("div"); const x = require("fs"); const y = Buffer.from([]); const z = module.exports; const a = new Map(); const b = new Set(); const c = new WeakMap(); const d = new WeakSet(); const e = Symbol(); const f = Promise.resolve(0); const i: Iterator = null as any; const j: AsyncIterator = null as any; const k: Symbol = null as any; const l: Promise = null as any; });} : () => void + + test("everything else", () => { +>test("everything else", () => { console.log(process.env); document.createElement("div"); const x = require("fs"); const y = Buffer.from([]); const z = module.exports; const a = new Map(); const b = new Set(); const c = new WeakMap(); const d = new WeakSet(); const e = Symbol(); const f = Promise.resolve(0); const i: Iterator = null as any; const j: AsyncIterator = null as any; const k: Symbol = null as any; const l: Promise = null as any; }) : any +>test : any +>"everything else" : "everything else" +>() => { console.log(process.env); document.createElement("div"); const x = require("fs"); const y = Buffer.from([]); const z = module.exports; const a = new Map(); const b = new Set(); const c = new WeakMap(); const d = new WeakSet(); const e = Symbol(); const f = Promise.resolve(0); const i: Iterator = null as any; const j: AsyncIterator = null as any; const k: Symbol = null as any; const l: Promise = null as any; } : () => void + + console.log(process.env); +>console.log(process.env) : any +>console.log : any +>console : any +>log : any +>process.env : any +>process : any +>env : any + + document.createElement("div"); +>document.createElement("div") : any +>document.createElement : any +>document : any +>createElement : any +>"div" : "div" + + const x = require("fs"); +>x : any +>require("fs") : any +>require : any +>"fs" : "fs" + + const y = Buffer.from([]); +>y : any +>Buffer.from([]) : any +>Buffer.from : any +>Buffer : any +>from : any +>[] : undefined[] + + const z = module.exports; +>z : any +>module.exports : any +>module : any +>exports : any + + const a = new Map(); +>a : any +>new Map() : any +>Map : any + + const b = new Set(); +>b : any +>new Set() : any +>Set : any + + const c = new WeakMap(); +>c : any +>new WeakMap() : any +>WeakMap : any + + const d = new WeakSet(); +>d : any +>new WeakSet() : any +>WeakSet : any + + const e = Symbol(); +>e : any +>Symbol() : any +>Symbol : any + + const f = Promise.resolve(0); +>f : any +>Promise.resolve(0) : any +>Promise.resolve : any +>Promise : any +>resolve : any +>0 : 0 + + const i: Iterator = null as any; +>i : any +>null as any : any +>null : null + + const j: AsyncIterator = null as any; +>j : any +>null as any : any +>null : null + + const k: Symbol = null as any; +>k : Symbol +>null as any : any +>null : null + + const l: Promise = null as any; +>l : Promise +>null as any : any +>null : null + + }); +}); diff --git a/tests/baselines/reference/externModule.errors.txt b/tests/baselines/reference/externModule.errors.txt index 329ef0a8862..1ca359d5d1d 100644 --- a/tests/baselines/reference/externModule.errors.txt +++ b/tests/baselines/reference/externModule.errors.txt @@ -1,6 +1,6 @@ tests/cases/compiler/externModule.ts(1,1): error TS2304: Cannot find name 'declare'. tests/cases/compiler/externModule.ts(1,9): error TS1005: ';' expected. -tests/cases/compiler/externModule.ts(1,9): error TS2304: Cannot find name 'module'. +tests/cases/compiler/externModule.ts(1,9): error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. tests/cases/compiler/externModule.ts(1,16): error TS1005: ';' expected. tests/cases/compiler/externModule.ts(3,10): error TS2391: Function implementation is missing or not immediately following the declaration. tests/cases/compiler/externModule.ts(4,10): error TS2391: Function implementation is missing or not immediately following the declaration. @@ -21,7 +21,7 @@ tests/cases/compiler/externModule.ts(37,3): error TS2552: Cannot find name 'XDat ~~~~~~ !!! error TS1005: ';' expected. ~~~~~~ -!!! error TS2304: Cannot find name 'module'. +!!! error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. ~ !!! error TS1005: ';' expected. export class XDate { diff --git a/tests/baselines/reference/fixSignatureCaching.errors.txt b/tests/baselines/reference/fixSignatureCaching.errors.txt index b1d26a73682..bf4400313b2 100644 --- a/tests/baselines/reference/fixSignatureCaching.errors.txt +++ b/tests/baselines/reference/fixSignatureCaching.errors.txt @@ -50,9 +50,9 @@ tests/cases/conformance/fixSignatureCaching.ts(915,36): error TS2339: Property ' tests/cases/conformance/fixSignatureCaching.ts(915,53): error TS2339: Property 'mobileDetectRules' does not exist on type '{}'. tests/cases/conformance/fixSignatureCaching.ts(955,42): error TS2339: Property 'mobileGrade' does not exist on type '{}'. tests/cases/conformance/fixSignatureCaching.ts(964,57): error TS2339: Property 'getDeviceSmallerSide' does not exist on type '{}'. -tests/cases/conformance/fixSignatureCaching.ts(978,16): error TS2304: Cannot find name 'module'. -tests/cases/conformance/fixSignatureCaching.ts(978,42): error TS2304: Cannot find name 'module'. -tests/cases/conformance/fixSignatureCaching.ts(979,37): error TS2304: Cannot find name 'module'. +tests/cases/conformance/fixSignatureCaching.ts(978,16): error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. +tests/cases/conformance/fixSignatureCaching.ts(978,42): error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. +tests/cases/conformance/fixSignatureCaching.ts(979,37): error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. tests/cases/conformance/fixSignatureCaching.ts(980,23): error TS2304: Cannot find name 'define'. tests/cases/conformance/fixSignatureCaching.ts(980,48): error TS2304: Cannot find name 'define'. tests/cases/conformance/fixSignatureCaching.ts(981,16): error TS2304: Cannot find name 'define'. @@ -1143,12 +1143,12 @@ tests/cases/conformance/fixSignatureCaching.ts(983,44): error TS2339: Property ' })((function (undefined) { if (typeof module !== 'undefined' && module.exports) { ~~~~~~ -!!! error TS2304: Cannot find name 'module'. +!!! error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. ~~~~~~ -!!! error TS2304: Cannot find name 'module'. +!!! error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. return function (factory) { module.exports = factory(); }; ~~~~~~ -!!! error TS2304: Cannot find name 'module'. +!!! error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. } else if (typeof define === 'function' && define.amd) { ~~~~~~ !!! error TS2304: Cannot find name 'define'. diff --git a/tests/baselines/reference/innerModExport1.errors.txt b/tests/baselines/reference/innerModExport1.errors.txt index b4f06cc998a..29ce225dfa2 100644 --- a/tests/baselines/reference/innerModExport1.errors.txt +++ b/tests/baselines/reference/innerModExport1.errors.txt @@ -1,4 +1,4 @@ -tests/cases/compiler/innerModExport1.ts(5,5): error TS2304: Cannot find name 'module'. +tests/cases/compiler/innerModExport1.ts(5,5): error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. tests/cases/compiler/innerModExport1.ts(5,12): error TS1005: ';' expected. @@ -9,7 +9,7 @@ tests/cases/compiler/innerModExport1.ts(5,12): error TS1005: ';' expected. var non_export_var: number; module { ~~~~~~ -!!! error TS2304: Cannot find name 'module'. +!!! error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. ~ !!! error TS1005: ';' expected. var non_export_var = 0; diff --git a/tests/baselines/reference/innerModExport2.errors.txt b/tests/baselines/reference/innerModExport2.errors.txt index f9568bb45a4..21cc583c5d3 100644 --- a/tests/baselines/reference/innerModExport2.errors.txt +++ b/tests/baselines/reference/innerModExport2.errors.txt @@ -1,4 +1,4 @@ -tests/cases/compiler/innerModExport2.ts(5,5): error TS2304: Cannot find name 'module'. +tests/cases/compiler/innerModExport2.ts(5,5): error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. tests/cases/compiler/innerModExport2.ts(5,12): error TS1005: ';' expected. tests/cases/compiler/innerModExport2.ts(7,20): error TS2395: Individual declarations in merged declaration 'export_var' must be all exported or all local. tests/cases/compiler/innerModExport2.ts(13,9): error TS2395: Individual declarations in merged declaration 'export_var' must be all exported or all local. @@ -12,7 +12,7 @@ tests/cases/compiler/innerModExport2.ts(20,7): error TS2339: Property 'NonExport var non_export_var: number; module { ~~~~~~ -!!! error TS2304: Cannot find name 'module'. +!!! error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. ~ !!! error TS1005: ';' expected. var non_export_var = 0; diff --git a/tests/baselines/reference/jsxAndTypeAssertion.errors.txt b/tests/baselines/reference/jsxAndTypeAssertion.errors.txt index 5aa92086c37..6d3f6874a88 100644 --- a/tests/baselines/reference/jsxAndTypeAssertion.errors.txt +++ b/tests/baselines/reference/jsxAndTypeAssertion.errors.txt @@ -1,5 +1,5 @@ tests/cases/conformance/jsx/jsxAndTypeAssertion.tsx(6,6): error TS17008: JSX element 'any' has no corresponding closing tag. -tests/cases/conformance/jsx/jsxAndTypeAssertion.tsx(6,13): error TS2304: Cannot find name 'test'. +tests/cases/conformance/jsx/jsxAndTypeAssertion.tsx(6,13): error TS2582: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`. tests/cases/conformance/jsx/jsxAndTypeAssertion.tsx(6,17): error TS1005: '}' expected. tests/cases/conformance/jsx/jsxAndTypeAssertion.tsx(8,6): error TS17008: JSX element 'any' has no corresponding closing tag. tests/cases/conformance/jsx/jsxAndTypeAssertion.tsx(10,6): error TS17008: JSX element 'foo' has no corresponding closing tag. @@ -24,7 +24,7 @@ tests/cases/conformance/jsx/jsxAndTypeAssertion.tsx(21,1): error TS1005: ' void'. tests/cases/compiler/modularizeLibrary_ErrorFromUsingES6FeaturesWithOnlyES5Lib.ts(20,6): error TS2551: Property 'sign' does not exist on type 'Math'. Did you mean 'sin'? -tests/cases/compiler/modularizeLibrary_ErrorFromUsingES6FeaturesWithOnlyES5Lib.ts(25,6): error TS2693: 'Symbol' only refers to a type, but is being used as a value here. -tests/cases/compiler/modularizeLibrary_ErrorFromUsingES6FeaturesWithOnlyES5Lib.ts(29,18): error TS2693: 'Symbol' only refers to a type, but is being used as a value here. +tests/cases/compiler/modularizeLibrary_ErrorFromUsingES6FeaturesWithOnlyES5Lib.ts(25,6): error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. +tests/cases/compiler/modularizeLibrary_ErrorFromUsingES6FeaturesWithOnlyES5Lib.ts(29,18): error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. tests/cases/compiler/modularizeLibrary_ErrorFromUsingES6FeaturesWithOnlyES5Lib.ts(33,13): error TS2304: Cannot find name 'Proxy'. tests/cases/compiler/modularizeLibrary_ErrorFromUsingES6FeaturesWithOnlyES5Lib.ts(36,1): error TS2304: Cannot find name 'Reflect'. tests/cases/compiler/modularizeLibrary_ErrorFromUsingES6FeaturesWithOnlyES5Lib.ts(40,5): error TS2339: Property 'flags' does not exist on type 'RegExp'. tests/cases/compiler/modularizeLibrary_ErrorFromUsingES6FeaturesWithOnlyES5Lib.ts(44,5): error TS2339: Property 'includes' does not exist on type 'string'. -tests/cases/compiler/modularizeLibrary_ErrorFromUsingES6FeaturesWithOnlyES5Lib.ts(47,9): error TS2693: 'Symbol' only refers to a type, but is being used as a value here. -tests/cases/compiler/modularizeLibrary_ErrorFromUsingES6FeaturesWithOnlyES5Lib.ts(51,6): error TS2693: 'Symbol' only refers to a type, but is being used as a value here. +tests/cases/compiler/modularizeLibrary_ErrorFromUsingES6FeaturesWithOnlyES5Lib.ts(47,9): error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. +tests/cases/compiler/modularizeLibrary_ErrorFromUsingES6FeaturesWithOnlyES5Lib.ts(51,6): error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. ==== tests/cases/compiler/modularizeLibrary_ErrorFromUsingES6FeaturesWithOnlyES5Lib.ts (12 errors) ==== @@ -26,7 +26,7 @@ tests/cases/compiler/modularizeLibrary_ErrorFromUsingES6FeaturesWithOnlyES5Lib.t // Using ES6 collection var m = new Map(); ~~~ -!!! error TS2304: Cannot find name 'Map'. +!!! error TS2583: Cannot find name 'Map'. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. m.clear(); // Using ES6 iterable m.keys(); @@ -48,13 +48,13 @@ tests/cases/compiler/modularizeLibrary_ErrorFromUsingES6FeaturesWithOnlyES5Lib.t a: 2, [Symbol.hasInstance](value: any) { ~~~~~~ -!!! error TS2693: 'Symbol' only refers to a type, but is being used as a value here. +!!! error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. return false; } }; o.hasOwnProperty(Symbol.hasInstance); ~~~~~~ -!!! error TS2693: 'Symbol' only refers to a type, but is being used as a value here. +!!! error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. // Using Es6 proxy var t = {} @@ -82,13 +82,13 @@ tests/cases/compiler/modularizeLibrary_ErrorFromUsingES6FeaturesWithOnlyES5Lib.t // Using ES6 symbol var s = Symbol(); ~~~~~~ -!!! error TS2693: 'Symbol' only refers to a type, but is being used as a value here. +!!! error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. // Using ES6 wellknown-symbol const o1 = { [Symbol.hasInstance](value: any) { ~~~~~~ -!!! error TS2693: 'Symbol' only refers to a type, but is being used as a value here. +!!! error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. return false; } } \ No newline at end of file diff --git a/tests/baselines/reference/modularizeLibrary_ErrorFromUsingWellknownSymbolWithOutES6WellknownSymbolLib.errors.txt b/tests/baselines/reference/modularizeLibrary_ErrorFromUsingWellknownSymbolWithOutES6WellknownSymbolLib.errors.txt index c2b9abc56f1..aab5dbc8b83 100644 --- a/tests/baselines/reference/modularizeLibrary_ErrorFromUsingWellknownSymbolWithOutES6WellknownSymbolLib.errors.txt +++ b/tests/baselines/reference/modularizeLibrary_ErrorFromUsingWellknownSymbolWithOutES6WellknownSymbolLib.errors.txt @@ -1,5 +1,5 @@ tests/cases/compiler/modularizeLibrary_ErrorFromUsingWellknownSymbolWithOutES6WellknownSymbolLib.ts(7,1): error TS2322: Type 'false' is not assignable to type 'string'. -tests/cases/compiler/modularizeLibrary_ErrorFromUsingWellknownSymbolWithOutES6WellknownSymbolLib.ts(7,3): error TS2693: 'Symbol' only refers to a type, but is being used as a value here. +tests/cases/compiler/modularizeLibrary_ErrorFromUsingWellknownSymbolWithOutES6WellknownSymbolLib.ts(7,3): error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. ==== tests/cases/compiler/modularizeLibrary_ErrorFromUsingWellknownSymbolWithOutES6WellknownSymbolLib.ts (2 errors) ==== @@ -13,4 +13,4 @@ tests/cases/compiler/modularizeLibrary_ErrorFromUsingWellknownSymbolWithOutES6We ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !!! error TS2322: Type 'false' is not assignable to type 'string'. ~~~~~~ -!!! error TS2693: 'Symbol' only refers to a type, but is being used as a value here. \ No newline at end of file +!!! error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. \ No newline at end of file diff --git a/tests/baselines/reference/moduleExports1.errors.txt b/tests/baselines/reference/moduleExports1.errors.txt index 18b65654cea..03d21d86b8a 100644 --- a/tests/baselines/reference/moduleExports1.errors.txt +++ b/tests/baselines/reference/moduleExports1.errors.txt @@ -1,5 +1,5 @@ -tests/cases/compiler/moduleExports1.ts(13,6): error TS2304: Cannot find name 'module'. -tests/cases/compiler/moduleExports1.ts(13,22): error TS2304: Cannot find name 'module'. +tests/cases/compiler/moduleExports1.ts(13,6): error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. +tests/cases/compiler/moduleExports1.ts(13,22): error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. ==== tests/cases/compiler/moduleExports1.ts (2 errors) ==== @@ -17,6 +17,6 @@ tests/cases/compiler/moduleExports1.ts(13,22): error TS2304: Cannot find name 'm if (!module.exports) module.exports = ""; ~~~~~~ -!!! error TS2304: Cannot find name 'module'. +!!! error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. ~~~~~~ -!!! error TS2304: Cannot find name 'module'. \ No newline at end of file +!!! error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. \ No newline at end of file diff --git a/tests/baselines/reference/moduleKeywordRepeatError.errors.txt b/tests/baselines/reference/moduleKeywordRepeatError.errors.txt index d77acf4f4d1..65a81c19213 100644 --- a/tests/baselines/reference/moduleKeywordRepeatError.errors.txt +++ b/tests/baselines/reference/moduleKeywordRepeatError.errors.txt @@ -1,4 +1,4 @@ -tests/cases/compiler/moduleKeywordRepeatError.ts(3,1): error TS2304: Cannot find name 'module'. +tests/cases/compiler/moduleKeywordRepeatError.ts(3,1): error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. tests/cases/compiler/moduleKeywordRepeatError.ts(3,15): error TS1005: ';' expected. @@ -7,6 +7,6 @@ tests/cases/compiler/moduleKeywordRepeatError.ts(3,15): error TS1005: ';' expect module.module { } ~~~~~~ -!!! error TS2304: Cannot find name 'module'. +!!! error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. ~ !!! error TS1005: ';' expected. \ No newline at end of file diff --git a/tests/baselines/reference/noAssertForUnparseableTypedefs.errors.txt b/tests/baselines/reference/noAssertForUnparseableTypedefs.errors.txt index 4876d5276f7..b131c8adac0 100644 --- a/tests/baselines/reference/noAssertForUnparseableTypedefs.errors.txt +++ b/tests/baselines/reference/noAssertForUnparseableTypedefs.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/jsdoc/bug26693.js(1,15): error TS2304: Cannot find name 'module'. +tests/cases/conformance/jsdoc/bug26693.js(1,15): error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. tests/cases/conformance/jsdoc/bug26693.js(1,21): error TS1005: '}' expected. tests/cases/conformance/jsdoc/bug26693.js(2,22): error TS2307: Cannot find module 'nope'. @@ -6,7 +6,7 @@ tests/cases/conformance/jsdoc/bug26693.js(2,22): error TS2307: Cannot find modul ==== tests/cases/conformance/jsdoc/bug26693.js (3 errors) ==== /** @typedef {module:locale} hi */ ~~~~~~ -!!! error TS2304: Cannot find name 'module'. +!!! error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. ~ !!! error TS1005: '}' expected. import { nope } from 'nope'; diff --git a/tests/baselines/reference/overloadingStaticFunctionsInFunctions.errors.txt b/tests/baselines/reference/overloadingStaticFunctionsInFunctions.errors.txt index cded9c44a3d..56adb4706f1 100644 --- a/tests/baselines/reference/overloadingStaticFunctionsInFunctions.errors.txt +++ b/tests/baselines/reference/overloadingStaticFunctionsInFunctions.errors.txt @@ -1,13 +1,13 @@ tests/cases/compiler/overloadingStaticFunctionsInFunctions.ts(1,14): error TS1005: '(' expected. tests/cases/compiler/overloadingStaticFunctionsInFunctions.ts(2,3): error TS1128: Declaration or statement expected. -tests/cases/compiler/overloadingStaticFunctionsInFunctions.ts(2,10): error TS2304: Cannot find name 'test'. +tests/cases/compiler/overloadingStaticFunctionsInFunctions.ts(2,10): error TS2582: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`. tests/cases/compiler/overloadingStaticFunctionsInFunctions.ts(3,3): error TS1128: Declaration or statement expected. -tests/cases/compiler/overloadingStaticFunctionsInFunctions.ts(3,10): error TS2304: Cannot find name 'test'. +tests/cases/compiler/overloadingStaticFunctionsInFunctions.ts(3,10): error TS2582: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`. tests/cases/compiler/overloadingStaticFunctionsInFunctions.ts(3,15): error TS2304: Cannot find name 'name'. tests/cases/compiler/overloadingStaticFunctionsInFunctions.ts(3,19): error TS1005: ',' expected. tests/cases/compiler/overloadingStaticFunctionsInFunctions.ts(3,20): error TS2693: 'string' only refers to a type, but is being used as a value here. tests/cases/compiler/overloadingStaticFunctionsInFunctions.ts(4,3): error TS1128: Declaration or statement expected. -tests/cases/compiler/overloadingStaticFunctionsInFunctions.ts(4,10): error TS2304: Cannot find name 'test'. +tests/cases/compiler/overloadingStaticFunctionsInFunctions.ts(4,10): error TS2582: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`. tests/cases/compiler/overloadingStaticFunctionsInFunctions.ts(4,15): error TS2304: Cannot find name 'name'. tests/cases/compiler/overloadingStaticFunctionsInFunctions.ts(4,20): error TS1109: Expression expected. tests/cases/compiler/overloadingStaticFunctionsInFunctions.ts(4,21): error TS2693: 'any' only refers to a type, but is being used as a value here. @@ -22,12 +22,12 @@ tests/cases/compiler/overloadingStaticFunctionsInFunctions.ts(4,25): error TS100 ~~~~~~ !!! error TS1128: Declaration or statement expected. ~~~~ -!!! error TS2304: Cannot find name 'test'. +!!! error TS2582: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`. static test(name:string) ~~~~~~ !!! error TS1128: Declaration or statement expected. ~~~~ -!!! error TS2304: Cannot find name 'test'. +!!! error TS2582: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`. ~~~~ !!! error TS2304: Cannot find name 'name'. ~ @@ -38,7 +38,7 @@ tests/cases/compiler/overloadingStaticFunctionsInFunctions.ts(4,25): error TS100 ~~~~~~ !!! error TS1128: Declaration or statement expected. ~~~~ -!!! error TS2304: Cannot find name 'test'. +!!! error TS2582: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`. ~~~~ !!! error TS2304: Cannot find name 'name'. ~ diff --git a/tests/baselines/reference/parser509534.errors.txt b/tests/baselines/reference/parser509534.errors.txt index 78d56d1413e..ff5eb131b5c 100644 --- a/tests/baselines/reference/parser509534.errors.txt +++ b/tests/baselines/reference/parser509534.errors.txt @@ -1,15 +1,15 @@ -tests/cases/conformance/parser/ecmascript5/RegressionTests/parser509534.ts(2,14): error TS2304: Cannot find name 'require'. -tests/cases/conformance/parser/ecmascript5/RegressionTests/parser509534.ts(3,1): error TS2304: Cannot find name 'module'. +tests/cases/conformance/parser/ecmascript5/RegressionTests/parser509534.ts(2,14): error TS2580: Cannot find name 'require'. Do you need to install type definitions for node? Try `npm i @types/node`. +tests/cases/conformance/parser/ecmascript5/RegressionTests/parser509534.ts(3,1): error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. ==== tests/cases/conformance/parser/ecmascript5/RegressionTests/parser509534.ts (2 errors) ==== "use strict"; var config = require("../config"); ~~~~~~~ -!!! error TS2304: Cannot find name 'require'. +!!! error TS2580: Cannot find name 'require'. Do you need to install type definitions for node? Try `npm i @types/node`. module.exports.route = function (server) { ~~~~~~ -!!! error TS2304: Cannot find name 'module'. +!!! error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. // General Login Page server.get(config.env.siteRoot + "/auth/login", function (req, res, next) { diff --git a/tests/baselines/reference/parser509693.errors.txt b/tests/baselines/reference/parser509693.errors.txt index b910af1c2e6..b6fbff74f33 100644 --- a/tests/baselines/reference/parser509693.errors.txt +++ b/tests/baselines/reference/parser509693.errors.txt @@ -1,10 +1,10 @@ -tests/cases/conformance/parser/ecmascript5/RegressionTests/parser509693.ts(1,6): error TS2304: Cannot find name 'module'. -tests/cases/conformance/parser/ecmascript5/RegressionTests/parser509693.ts(1,22): error TS2304: Cannot find name 'module'. +tests/cases/conformance/parser/ecmascript5/RegressionTests/parser509693.ts(1,6): error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. +tests/cases/conformance/parser/ecmascript5/RegressionTests/parser509693.ts(1,22): error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. ==== tests/cases/conformance/parser/ecmascript5/RegressionTests/parser509693.ts (2 errors) ==== if (!module.exports) module.exports = ""; ~~~~~~ -!!! error TS2304: Cannot find name 'module'. +!!! error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. ~~~~~~ -!!! error TS2304: Cannot find name 'module'. \ No newline at end of file +!!! error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. \ No newline at end of file diff --git a/tests/baselines/reference/parser519458.errors.txt b/tests/baselines/reference/parser519458.errors.txt index 66dae596b81..ee13350fcbb 100644 --- a/tests/baselines/reference/parser519458.errors.txt +++ b/tests/baselines/reference/parser519458.errors.txt @@ -1,14 +1,14 @@ -tests/cases/conformance/parser/ecmascript5/RegressionTests/parser519458.ts(1,15): error TS2304: Cannot find name 'module'. tests/cases/conformance/parser/ecmascript5/RegressionTests/parser519458.ts(1,15): error TS2503: Cannot find namespace 'module'. +tests/cases/conformance/parser/ecmascript5/RegressionTests/parser519458.ts(1,15): error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. tests/cases/conformance/parser/ecmascript5/RegressionTests/parser519458.ts(1,21): error TS1005: ';' expected. ==== tests/cases/conformance/parser/ecmascript5/RegressionTests/parser519458.ts (3 errors) ==== import rect = module("rect"); var bar = new rect.Rect(); ~~~~~~ -!!! error TS2304: Cannot find name 'module'. - ~~~~~~ !!! error TS2503: Cannot find namespace 'module'. + ~~~~~~ +!!! error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. ~ !!! error TS1005: ';' expected. \ No newline at end of file diff --git a/tests/baselines/reference/parser521128.errors.txt b/tests/baselines/reference/parser521128.errors.txt index 93491af588d..910c4217b4f 100644 --- a/tests/baselines/reference/parser521128.errors.txt +++ b/tests/baselines/reference/parser521128.errors.txt @@ -1,10 +1,10 @@ -tests/cases/conformance/parser/ecmascript5/RegressionTests/parser521128.ts(1,1): error TS2304: Cannot find name 'module'. +tests/cases/conformance/parser/ecmascript5/RegressionTests/parser521128.ts(1,1): error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. tests/cases/conformance/parser/ecmascript5/RegressionTests/parser521128.ts(1,15): error TS1005: ';' expected. ==== tests/cases/conformance/parser/ecmascript5/RegressionTests/parser521128.ts (2 errors) ==== module.module { } ~~~~~~ -!!! error TS2304: Cannot find name 'module'. +!!! error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. ~ !!! error TS1005: ';' expected. \ No newline at end of file diff --git a/tests/baselines/reference/parserCommaInTypeMemberList2.errors.txt b/tests/baselines/reference/parserCommaInTypeMemberList2.errors.txt index 931bd87293d..f2f695e0120 100644 --- a/tests/baselines/reference/parserCommaInTypeMemberList2.errors.txt +++ b/tests/baselines/reference/parserCommaInTypeMemberList2.errors.txt @@ -1,8 +1,8 @@ -tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserCommaInTypeMemberList2.ts(1,9): error TS2304: Cannot find name '$'. +tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserCommaInTypeMemberList2.ts(1,9): error TS2581: Cannot find name '$'. Do you need to install type definitions for jQuery? Try `npm i @types/jquery`. ==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserCommaInTypeMemberList2.ts (1 errors) ==== var s = $.extend< { workItem: any }, { workItem: any, width: string }>({ workItem: this._workItem }, {}); ~ -!!! error TS2304: Cannot find name '$'. +!!! error TS2581: Cannot find name '$'. Do you need to install type definitions for jQuery? Try `npm i @types/jquery`. \ No newline at end of file diff --git a/tests/baselines/reference/parserES5SymbolProperty1.errors.txt b/tests/baselines/reference/parserES5SymbolProperty1.errors.txt index 1d7d361ef3a..3082110db28 100644 --- a/tests/baselines/reference/parserES5SymbolProperty1.errors.txt +++ b/tests/baselines/reference/parserES5SymbolProperty1.errors.txt @@ -1,9 +1,9 @@ -tests/cases/conformance/parser/ecmascript5/Symbols/parserES5SymbolProperty1.ts(2,6): error TS2693: 'Symbol' only refers to a type, but is being used as a value here. +tests/cases/conformance/parser/ecmascript5/Symbols/parserES5SymbolProperty1.ts(2,6): error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. ==== tests/cases/conformance/parser/ecmascript5/Symbols/parserES5SymbolProperty1.ts (1 errors) ==== interface I { [Symbol.iterator]: string; ~~~~~~ -!!! error TS2693: 'Symbol' only refers to a type, but is being used as a value here. +!!! error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. } \ No newline at end of file diff --git a/tests/baselines/reference/parserES5SymbolProperty2.errors.txt b/tests/baselines/reference/parserES5SymbolProperty2.errors.txt index 581f65b0a49..cc0a80c7889 100644 --- a/tests/baselines/reference/parserES5SymbolProperty2.errors.txt +++ b/tests/baselines/reference/parserES5SymbolProperty2.errors.txt @@ -1,9 +1,9 @@ -tests/cases/conformance/parser/ecmascript5/Symbols/parserES5SymbolProperty2.ts(2,6): error TS2693: 'Symbol' only refers to a type, but is being used as a value here. +tests/cases/conformance/parser/ecmascript5/Symbols/parserES5SymbolProperty2.ts(2,6): error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. ==== tests/cases/conformance/parser/ecmascript5/Symbols/parserES5SymbolProperty2.ts (1 errors) ==== interface I { [Symbol.unscopables](): string; ~~~~~~ -!!! error TS2693: 'Symbol' only refers to a type, but is being used as a value here. +!!! error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. } \ No newline at end of file diff --git a/tests/baselines/reference/parserES5SymbolProperty3.errors.txt b/tests/baselines/reference/parserES5SymbolProperty3.errors.txt index 8db74c51255..894ffc0bb8f 100644 --- a/tests/baselines/reference/parserES5SymbolProperty3.errors.txt +++ b/tests/baselines/reference/parserES5SymbolProperty3.errors.txt @@ -1,9 +1,9 @@ -tests/cases/conformance/parser/ecmascript5/Symbols/parserES5SymbolProperty3.ts(2,6): error TS2693: 'Symbol' only refers to a type, but is being used as a value here. +tests/cases/conformance/parser/ecmascript5/Symbols/parserES5SymbolProperty3.ts(2,6): error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. ==== tests/cases/conformance/parser/ecmascript5/Symbols/parserES5SymbolProperty3.ts (1 errors) ==== declare class C { [Symbol.unscopables](): string; ~~~~~~ -!!! error TS2693: 'Symbol' only refers to a type, but is being used as a value here. +!!! error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. } \ No newline at end of file diff --git a/tests/baselines/reference/parserES5SymbolProperty4.errors.txt b/tests/baselines/reference/parserES5SymbolProperty4.errors.txt index 1fd929502e3..2cc89cefd71 100644 --- a/tests/baselines/reference/parserES5SymbolProperty4.errors.txt +++ b/tests/baselines/reference/parserES5SymbolProperty4.errors.txt @@ -1,9 +1,9 @@ -tests/cases/conformance/parser/ecmascript5/Symbols/parserES5SymbolProperty4.ts(2,6): error TS2693: 'Symbol' only refers to a type, but is being used as a value here. +tests/cases/conformance/parser/ecmascript5/Symbols/parserES5SymbolProperty4.ts(2,6): error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. ==== tests/cases/conformance/parser/ecmascript5/Symbols/parserES5SymbolProperty4.ts (1 errors) ==== declare class C { [Symbol.isRegExp]: string; ~~~~~~ -!!! error TS2693: 'Symbol' only refers to a type, but is being used as a value here. +!!! error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. } \ No newline at end of file diff --git a/tests/baselines/reference/parserES5SymbolProperty5.errors.txt b/tests/baselines/reference/parserES5SymbolProperty5.errors.txt index a4b25f4b64d..f37f0e0d028 100644 --- a/tests/baselines/reference/parserES5SymbolProperty5.errors.txt +++ b/tests/baselines/reference/parserES5SymbolProperty5.errors.txt @@ -1,9 +1,9 @@ -tests/cases/conformance/parser/ecmascript5/Symbols/parserES5SymbolProperty5.ts(2,6): error TS2693: 'Symbol' only refers to a type, but is being used as a value here. +tests/cases/conformance/parser/ecmascript5/Symbols/parserES5SymbolProperty5.ts(2,6): error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. ==== tests/cases/conformance/parser/ecmascript5/Symbols/parserES5SymbolProperty5.ts (1 errors) ==== class C { [Symbol.isRegExp]: string; ~~~~~~ -!!! error TS2693: 'Symbol' only refers to a type, but is being used as a value here. +!!! error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. } \ No newline at end of file diff --git a/tests/baselines/reference/parserES5SymbolProperty6.errors.txt b/tests/baselines/reference/parserES5SymbolProperty6.errors.txt index 26a4d1e8efe..08d48f2c02a 100644 --- a/tests/baselines/reference/parserES5SymbolProperty6.errors.txt +++ b/tests/baselines/reference/parserES5SymbolProperty6.errors.txt @@ -1,9 +1,9 @@ -tests/cases/conformance/parser/ecmascript5/Symbols/parserES5SymbolProperty6.ts(2,6): error TS2693: 'Symbol' only refers to a type, but is being used as a value here. +tests/cases/conformance/parser/ecmascript5/Symbols/parserES5SymbolProperty6.ts(2,6): error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. ==== tests/cases/conformance/parser/ecmascript5/Symbols/parserES5SymbolProperty6.ts (1 errors) ==== class C { [Symbol.toStringTag]: string = ""; ~~~~~~ -!!! error TS2693: 'Symbol' only refers to a type, but is being used as a value here. +!!! error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. } \ No newline at end of file diff --git a/tests/baselines/reference/parserES5SymbolProperty7.errors.txt b/tests/baselines/reference/parserES5SymbolProperty7.errors.txt index 5ecf3495fa9..3a5fd74e20a 100644 --- a/tests/baselines/reference/parserES5SymbolProperty7.errors.txt +++ b/tests/baselines/reference/parserES5SymbolProperty7.errors.txt @@ -1,9 +1,9 @@ -tests/cases/conformance/parser/ecmascript5/Symbols/parserES5SymbolProperty7.ts(2,6): error TS2693: 'Symbol' only refers to a type, but is being used as a value here. +tests/cases/conformance/parser/ecmascript5/Symbols/parserES5SymbolProperty7.ts(2,6): error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. ==== tests/cases/conformance/parser/ecmascript5/Symbols/parserES5SymbolProperty7.ts (1 errors) ==== class C { [Symbol.toStringTag](): void { } ~~~~~~ -!!! error TS2693: 'Symbol' only refers to a type, but is being used as a value here. +!!! error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. } \ No newline at end of file diff --git a/tests/baselines/reference/parserES5SymbolProperty8.errors.txt b/tests/baselines/reference/parserES5SymbolProperty8.errors.txt index 5b4c0b99b51..90e0df0211f 100644 --- a/tests/baselines/reference/parserES5SymbolProperty8.errors.txt +++ b/tests/baselines/reference/parserES5SymbolProperty8.errors.txt @@ -1,9 +1,9 @@ -tests/cases/conformance/parser/ecmascript5/Symbols/parserES5SymbolProperty8.ts(2,6): error TS2693: 'Symbol' only refers to a type, but is being used as a value here. +tests/cases/conformance/parser/ecmascript5/Symbols/parserES5SymbolProperty8.ts(2,6): error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. ==== tests/cases/conformance/parser/ecmascript5/Symbols/parserES5SymbolProperty8.ts (1 errors) ==== var x: { [Symbol.toPrimitive](): string ~~~~~~ -!!! error TS2693: 'Symbol' only refers to a type, but is being used as a value here. +!!! error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. } \ No newline at end of file diff --git a/tests/baselines/reference/parserES5SymbolProperty9.errors.txt b/tests/baselines/reference/parserES5SymbolProperty9.errors.txt index 6ff6f65f0cd..9a21a7942cb 100644 --- a/tests/baselines/reference/parserES5SymbolProperty9.errors.txt +++ b/tests/baselines/reference/parserES5SymbolProperty9.errors.txt @@ -1,9 +1,9 @@ -tests/cases/conformance/parser/ecmascript5/Symbols/parserES5SymbolProperty9.ts(2,6): error TS2693: 'Symbol' only refers to a type, but is being used as a value here. +tests/cases/conformance/parser/ecmascript5/Symbols/parserES5SymbolProperty9.ts(2,6): error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. ==== tests/cases/conformance/parser/ecmascript5/Symbols/parserES5SymbolProperty9.ts (1 errors) ==== var x: { [Symbol.toPrimitive]: string ~~~~~~ -!!! error TS2693: 'Symbol' only refers to a type, but is being used as a value here. +!!! error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. } \ No newline at end of file diff --git a/tests/baselines/reference/parserMissingLambdaOpenBrace1.errors.txt b/tests/baselines/reference/parserMissingLambdaOpenBrace1.errors.txt index 728295b76cb..c724b594159 100644 --- a/tests/baselines/reference/parserMissingLambdaOpenBrace1.errors.txt +++ b/tests/baselines/reference/parserMissingLambdaOpenBrace1.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserMissingLambdaOpenBrace1.ts(2,19): error TS2304: Cannot find name 'Iterator'. +tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserMissingLambdaOpenBrace1.ts(2,19): error TS2583: Cannot find name 'Iterator'. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserMissingLambdaOpenBrace1.ts(2,28): error TS2304: Cannot find name 'T'. tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserMissingLambdaOpenBrace1.ts(2,42): error TS2304: Cannot find name 'Query'. tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserMissingLambdaOpenBrace1.ts(2,48): error TS2304: Cannot find name 'T'. @@ -11,7 +11,7 @@ tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserMissingLambdaOpen class C { where(filter: Iterator): Query { ~~~~~~~~ -!!! error TS2304: Cannot find name 'Iterator'. +!!! error TS2583: Cannot find name 'Iterator'. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later. ~ !!! error TS2304: Cannot find name 'T'. ~~~~~ diff --git a/tests/baselines/reference/parserharness.errors.txt b/tests/baselines/reference/parserharness.errors.txt index 5ec35021fef..990fa5816c7 100644 --- a/tests/baselines/reference/parserharness.errors.txt +++ b/tests/baselines/reference/parserharness.errors.txt @@ -5,8 +5,8 @@ tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(19,21): er tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(21,29): error TS2694: Namespace 'Harness' has no exported member 'Assert'. tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(25,17): error TS2304: Cannot find name 'IIO'. tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(41,12): error TS2304: Cannot find name 'ActiveXObject'. -tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(43,19): error TS2304: Cannot find name 'require'. -tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(44,14): error TS2304: Cannot find name 'require'. +tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(43,19): error TS2580: Cannot find name 'require'. Do you need to install type definitions for node? Try `npm i @types/node`. +tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(44,14): error TS2580: Cannot find name 'require'. Do you need to install type definitions for node? Try `npm i @types/node`. tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(341,13): error TS2662: Cannot find name 'errorHandlerStack'. Did you mean the static member 'Runnable.errorHandlerStack'? tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(347,13): error TS2662: Cannot find name 'errorHandlerStack'. Did you mean the static member 'Runnable.errorHandlerStack'? tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(351,17): error TS2662: Cannot find name 'errorHandlerStack'. Did you mean the static member 'Runnable.errorHandlerStack'? @@ -169,10 +169,10 @@ tests/cases/conformance/parser/ecmascript5/RealWorld/parserharness.ts(2030,32): eval(typescriptServiceFile); } else if (typeof require === "function") { ~~~~~~~ -!!! error TS2304: Cannot find name 'require'. +!!! error TS2580: Cannot find name 'require'. Do you need to install type definitions for node? Try `npm i @types/node`. var vm = require('vm'); ~~~~~~~ -!!! error TS2304: Cannot find name 'require'. +!!! error TS2580: Cannot find name 'require'. Do you need to install type definitions for node? Try `npm i @types/node`. vm.runInThisContext(typescriptServiceFile, 'typescriptServices.js'); } else { throw new Error('Unknown context'); diff --git a/tests/baselines/reference/reservedWords2.errors.txt b/tests/baselines/reference/reservedWords2.errors.txt index 0760e1e2566..437b414a69d 100644 --- a/tests/baselines/reference/reservedWords2.errors.txt +++ b/tests/baselines/reference/reservedWords2.errors.txt @@ -1,6 +1,6 @@ tests/cases/compiler/reservedWords2.ts(1,8): error TS1109: Expression expected. tests/cases/compiler/reservedWords2.ts(1,14): error TS1005: '(' expected. -tests/cases/compiler/reservedWords2.ts(1,16): error TS2304: Cannot find name 'require'. +tests/cases/compiler/reservedWords2.ts(1,16): error TS2580: Cannot find name 'require'. Do you need to install type definitions for node? Try `npm i @types/node`. tests/cases/compiler/reservedWords2.ts(1,31): error TS1005: ')' expected. tests/cases/compiler/reservedWords2.ts(2,12): error TS2300: Duplicate identifier '(Missing)'. tests/cases/compiler/reservedWords2.ts(2,12): error TS2567: Enum declarations can only merge with namespace or other enum declarations. @@ -14,7 +14,7 @@ tests/cases/compiler/reservedWords2.ts(5,9): error TS2300: Duplicate identifier tests/cases/compiler/reservedWords2.ts(5,9): error TS2567: Enum declarations can only merge with namespace or other enum declarations. tests/cases/compiler/reservedWords2.ts(5,10): error TS1003: Identifier expected. tests/cases/compiler/reservedWords2.ts(5,18): error TS1005: '=>' expected. -tests/cases/compiler/reservedWords2.ts(6,1): error TS2304: Cannot find name 'module'. +tests/cases/compiler/reservedWords2.ts(6,1): error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. tests/cases/compiler/reservedWords2.ts(6,8): error TS1005: ';' expected. tests/cases/compiler/reservedWords2.ts(7,11): error TS2300: Duplicate identifier '(Missing)'. tests/cases/compiler/reservedWords2.ts(7,11): error TS1005: ':' expected. @@ -39,7 +39,7 @@ tests/cases/compiler/reservedWords2.ts(10,6): error TS1003: Identifier expected. ~ !!! error TS1005: '(' expected. ~~~~~~~ -!!! error TS2304: Cannot find name 'require'. +!!! error TS2580: Cannot find name 'require'. Do you need to install type definitions for node? Try `npm i @types/node`. ~ !!! error TS1005: ')' expected. import * as while from "foo" @@ -72,7 +72,7 @@ tests/cases/compiler/reservedWords2.ts(10,6): error TS1003: Identifier expected. !!! error TS1005: '=>' expected. module void {} ~~~~~~ -!!! error TS2304: Cannot find name 'module'. +!!! error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. ~~~~ !!! error TS1005: ';' expected. var {while, return} = { while: 1, return: 2 }; diff --git a/tests/baselines/reference/staticsInAFunction.errors.txt b/tests/baselines/reference/staticsInAFunction.errors.txt index 254f321913b..499ab91e93f 100644 --- a/tests/baselines/reference/staticsInAFunction.errors.txt +++ b/tests/baselines/reference/staticsInAFunction.errors.txt @@ -1,13 +1,13 @@ tests/cases/compiler/staticsInAFunction.ts(1,13): error TS1005: '(' expected. tests/cases/compiler/staticsInAFunction.ts(2,4): error TS1128: Declaration or statement expected. -tests/cases/compiler/staticsInAFunction.ts(2,11): error TS2304: Cannot find name 'test'. +tests/cases/compiler/staticsInAFunction.ts(2,11): error TS2582: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`. tests/cases/compiler/staticsInAFunction.ts(3,4): error TS1128: Declaration or statement expected. -tests/cases/compiler/staticsInAFunction.ts(3,11): error TS2304: Cannot find name 'test'. +tests/cases/compiler/staticsInAFunction.ts(3,11): error TS2582: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`. tests/cases/compiler/staticsInAFunction.ts(3,16): error TS2304: Cannot find name 'name'. tests/cases/compiler/staticsInAFunction.ts(3,20): error TS1005: ',' expected. tests/cases/compiler/staticsInAFunction.ts(3,21): error TS2693: 'string' only refers to a type, but is being used as a value here. tests/cases/compiler/staticsInAFunction.ts(4,4): error TS1128: Declaration or statement expected. -tests/cases/compiler/staticsInAFunction.ts(4,11): error TS2304: Cannot find name 'test'. +tests/cases/compiler/staticsInAFunction.ts(4,11): error TS2582: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`. tests/cases/compiler/staticsInAFunction.ts(4,16): error TS2304: Cannot find name 'name'. tests/cases/compiler/staticsInAFunction.ts(4,21): error TS1109: Expression expected. tests/cases/compiler/staticsInAFunction.ts(4,22): error TS2693: 'any' only refers to a type, but is being used as a value here. @@ -22,12 +22,12 @@ tests/cases/compiler/staticsInAFunction.ts(4,26): error TS1005: ';' expected. ~~~~~~ !!! error TS1128: Declaration or statement expected. ~~~~ -!!! error TS2304: Cannot find name 'test'. +!!! error TS2582: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`. static test(name:string) ~~~~~~ !!! error TS1128: Declaration or statement expected. ~~~~ -!!! error TS2304: Cannot find name 'test'. +!!! error TS2582: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`. ~~~~ !!! error TS2304: Cannot find name 'name'. ~ @@ -38,7 +38,7 @@ tests/cases/compiler/staticsInAFunction.ts(4,26): error TS1005: ';' expected. ~~~~~~ !!! error TS1128: Declaration or statement expected. ~~~~ -!!! error TS2304: Cannot find name 'test'. +!!! error TS2582: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`. ~~~~ !!! error TS2304: Cannot find name 'name'. ~ diff --git a/tests/baselines/reference/templateStringInModuleName.errors.txt b/tests/baselines/reference/templateStringInModuleName.errors.txt index 1664638d086..f684b305c52 100644 --- a/tests/baselines/reference/templateStringInModuleName.errors.txt +++ b/tests/baselines/reference/templateStringInModuleName.errors.txt @@ -1,10 +1,10 @@ tests/cases/conformance/es6/templates/templateStringInModuleName.ts(1,1): error TS2304: Cannot find name 'declare'. tests/cases/conformance/es6/templates/templateStringInModuleName.ts(1,9): error TS1005: ';' expected. -tests/cases/conformance/es6/templates/templateStringInModuleName.ts(1,9): error TS2304: Cannot find name 'module'. +tests/cases/conformance/es6/templates/templateStringInModuleName.ts(1,9): error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. tests/cases/conformance/es6/templates/templateStringInModuleName.ts(1,21): error TS1005: ';' expected. tests/cases/conformance/es6/templates/templateStringInModuleName.ts(4,1): error TS2304: Cannot find name 'declare'. tests/cases/conformance/es6/templates/templateStringInModuleName.ts(4,9): error TS1005: ';' expected. -tests/cases/conformance/es6/templates/templateStringInModuleName.ts(4,9): error TS2304: Cannot find name 'module'. +tests/cases/conformance/es6/templates/templateStringInModuleName.ts(4,9): error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. tests/cases/conformance/es6/templates/templateStringInModuleName.ts(4,24): error TS1005: ';' expected. @@ -15,7 +15,7 @@ tests/cases/conformance/es6/templates/templateStringInModuleName.ts(4,24): error ~~~~~~ !!! error TS1005: ';' expected. ~~~~~~ -!!! error TS2304: Cannot find name 'module'. +!!! error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. ~ !!! error TS1005: ';' expected. } @@ -26,7 +26,7 @@ tests/cases/conformance/es6/templates/templateStringInModuleName.ts(4,24): error ~~~~~~ !!! error TS1005: ';' expected. ~~~~~~ -!!! error TS2304: Cannot find name 'module'. +!!! error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. ~ !!! error TS1005: ';' expected. } \ No newline at end of file diff --git a/tests/baselines/reference/templateStringInModuleNameES6.errors.txt b/tests/baselines/reference/templateStringInModuleNameES6.errors.txt index c46b6e5fc8c..ecd072a7579 100644 --- a/tests/baselines/reference/templateStringInModuleNameES6.errors.txt +++ b/tests/baselines/reference/templateStringInModuleNameES6.errors.txt @@ -1,10 +1,10 @@ tests/cases/conformance/es6/templates/templateStringInModuleNameES6.ts(1,1): error TS2304: Cannot find name 'declare'. tests/cases/conformance/es6/templates/templateStringInModuleNameES6.ts(1,9): error TS1005: ';' expected. -tests/cases/conformance/es6/templates/templateStringInModuleNameES6.ts(1,9): error TS2304: Cannot find name 'module'. +tests/cases/conformance/es6/templates/templateStringInModuleNameES6.ts(1,9): error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. tests/cases/conformance/es6/templates/templateStringInModuleNameES6.ts(1,21): error TS1005: ';' expected. tests/cases/conformance/es6/templates/templateStringInModuleNameES6.ts(4,1): error TS2304: Cannot find name 'declare'. tests/cases/conformance/es6/templates/templateStringInModuleNameES6.ts(4,9): error TS1005: ';' expected. -tests/cases/conformance/es6/templates/templateStringInModuleNameES6.ts(4,9): error TS2304: Cannot find name 'module'. +tests/cases/conformance/es6/templates/templateStringInModuleNameES6.ts(4,9): error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. tests/cases/conformance/es6/templates/templateStringInModuleNameES6.ts(4,24): error TS1005: ';' expected. @@ -15,7 +15,7 @@ tests/cases/conformance/es6/templates/templateStringInModuleNameES6.ts(4,24): er ~~~~~~ !!! error TS1005: ';' expected. ~~~~~~ -!!! error TS2304: Cannot find name 'module'. +!!! error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. ~ !!! error TS1005: ';' expected. } @@ -26,7 +26,7 @@ tests/cases/conformance/es6/templates/templateStringInModuleNameES6.ts(4,24): er ~~~~~~ !!! error TS1005: ';' expected. ~~~~~~ -!!! error TS2304: Cannot find name 'module'. +!!! error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. ~ !!! error TS1005: ';' expected. } \ No newline at end of file diff --git a/tests/baselines/reference/typecheckIfCondition.errors.txt b/tests/baselines/reference/typecheckIfCondition.errors.txt index 3f23c71d247..e9c3707583e 100644 --- a/tests/baselines/reference/typecheckIfCondition.errors.txt +++ b/tests/baselines/reference/typecheckIfCondition.errors.txt @@ -1,5 +1,5 @@ -tests/cases/compiler/typecheckIfCondition.ts(4,10): error TS2304: Cannot find name 'module'. -tests/cases/compiler/typecheckIfCondition.ts(4,26): error TS2304: Cannot find name 'module'. +tests/cases/compiler/typecheckIfCondition.ts(4,10): error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. +tests/cases/compiler/typecheckIfCondition.ts(4,26): error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. ==== tests/cases/compiler/typecheckIfCondition.ts (2 errors) ==== @@ -8,9 +8,9 @@ tests/cases/compiler/typecheckIfCondition.ts(4,26): error TS2304: Cannot find na { if (!module.exports) module.exports = ""; ~~~~~~ -!!! error TS2304: Cannot find name 'module'. +!!! error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. ~~~~~~ -!!! error TS2304: Cannot find name 'module'. +!!! error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. var x = null; // don't want to baseline output } \ No newline at end of file diff --git a/tests/cases/compiler/didYouMeanSuggestionErrors.ts b/tests/cases/compiler/didYouMeanSuggestionErrors.ts new file mode 100644 index 00000000000..d5af5a338d3 --- /dev/null +++ b/tests/cases/compiler/didYouMeanSuggestionErrors.ts @@ -0,0 +1,29 @@ +// @lib: es5 +describe("my test suite", () => { + it("should run", () => { + const a = $(".thing"); + }); +}); + +suite("another suite", () => { + test("everything else", () => { + console.log(process.env); + document.createElement("div"); + + const x = require("fs"); + const y = Buffer.from([]); + const z = module.exports; + + const a = new Map(); + const b = new Set(); + const c = new WeakMap(); + const d = new WeakSet(); + const e = Symbol(); + const f = Promise.resolve(0); + + const i: Iterator = null as any; + const j: AsyncIterator = null as any; + const k: Symbol = null as any; + const l: Promise = null as any; + }); +}); \ No newline at end of file From 42479ca337459c24f27114676aed9beb9afbb343 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 11 Sep 2018 15:35:12 -0700 Subject: [PATCH 33/83] Maintain project references more clearly - no need to maintain map from referencing projects to references - When queueing for downstream projects, always handle build order --- src/compiler/tsbuild.ts | 82 +++++++------------- src/testRunner/unittests/tsbuildWatchMode.ts | 12 +-- 2 files changed, 33 insertions(+), 61 deletions(-) diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts index f61ef42c7cb..87c1f44430b 100644 --- a/src/compiler/tsbuild.ts +++ b/src/compiler/tsbuild.ts @@ -11,10 +11,9 @@ namespace ts { message(diag: DiagnosticMessage, ...args: string[]): void; } - type Mapper = ReturnType; interface DependencyGraph { buildQueue: ResolvedConfigFileName[]; - dependencyMap: Mapper; + referencingProjectsMap: ConfigFileMap>; } export interface BuildOptions { @@ -220,40 +219,18 @@ namespace ts { } } - function createDependencyMapper(toPath: ToResolvedConfigFilePath) { - const childToParents = createFileMap(toPath); - const parentToChildren = createFileMap(toPath); - - function addReference(childConfigFileName: ResolvedConfigFileName, parentConfigFileName: ResolvedConfigFileName): void { - addEntry(childToParents, childConfigFileName, parentConfigFileName); - addEntry(parentToChildren, parentConfigFileName, childConfigFileName); + function getOrCreateValueFromConfigFileMap(configFileMap: ConfigFileMap, resolved: ResolvedConfigFileName, createT: () => T): T { + const existingValue = configFileMap.getValue(resolved); + let newValue: T | undefined; + if (!existingValue) { + newValue = createT(); + configFileMap.setValue(resolved, newValue); } + return existingValue || newValue!; + } - function getReferencesTo(parentConfigFileName: ResolvedConfigFileName): ResolvedConfigFileName[] { - return parentToChildren.getValue(parentConfigFileName) || []; - } - - function getReferencesOf(childConfigFileName: ResolvedConfigFileName): ResolvedConfigFileName[] { - return childToParents.getValue(childConfigFileName) || []; - } - - function addEntry(mapToAddTo: typeof childToParents | typeof parentToChildren, key: ResolvedConfigFileName, element: ResolvedConfigFileName) { - key = normalizePath(key) as ResolvedConfigFileName; - element = normalizePath(element) as ResolvedConfigFileName; - let arr = mapToAddTo.getValue(key); - if (arr === undefined) { - mapToAddTo.setValue(key, arr = []); - } - if (arr.indexOf(element) < 0) { - arr.push(element); - } - } - - return { - addReference, - getReferencesTo, - getReferencesOf, - }; + function getOrCreateValueMapFromConfigFileMap(configFileMap: ConfigFileMap>, resolved: ResolvedConfigFileName): Map { + return getOrCreateValueFromConfigFileMap>(configFileMap, resolved, createMap); } function getOutputDeclarationFileName(inputFileName: string, configFile: ParsedCommandLine) { @@ -529,19 +506,9 @@ namespace ts { } } - function getOrCreateExistingWatches(resolved: ResolvedConfigFileName, allWatches: ConfigFileMap>) { - const existingWatches = allWatches.getValue(resolved); - let newWatches: Map | undefined; - if (!existingWatches) { - newWatches = createMap(); - allWatches.setValue(resolved, newWatches); - } - return existingWatches || newWatches!; - } - function watchWildCardDirectories(resolved: ResolvedConfigFileName, parsed: ParsedCommandLine) { updateWatchingWildcardDirectories( - getOrCreateExistingWatches(resolved, allWatchedWildcardDirectories), + getOrCreateValueMapFromConfigFileMap(allWatchedWildcardDirectories, resolved), createMapFromTemplate(parsed.configFileSpecs!.wildcardDirectories), (dir, flags) => { return hostWithWatch.watchDirectory(dir, fileOrDirectory => { @@ -564,7 +531,7 @@ namespace ts { function watchInputFiles(resolved: ResolvedConfigFileName, parsed: ParsedCommandLine) { mutateMap( - getOrCreateExistingWatches(resolved, allWatchedInputFiles), + getOrCreateValueMapFromConfigFileMap(allWatchedInputFiles, resolved), arrayToMap(parsed.fileNames, toPath), { createNewValue: (_key, input) => hostWithWatch.watchFile(input, () => { @@ -818,7 +785,7 @@ namespace ts { if (addProjToQueue(resolved, reloadLevel)) { // TODO: instead of adding the dependent project to queue right away postpone this - queueBuildForDownstreamReferences(resolved, getGlobalDependencyGraph()); + queueBuildForDownstreamReferences(resolved); } } @@ -857,12 +824,15 @@ namespace ts { } // Mark all downstream projects of this one needing to be built "later" - function queueBuildForDownstreamReferences(root: ResolvedConfigFileName, dependencyGraph: DependencyGraph) { - const deps = dependencyGraph.dependencyMap.getReferencesTo(root); - for (const ref of deps) { + function queueBuildForDownstreamReferences(root: ResolvedConfigFileName) { + const dependencyGraph = getGlobalDependencyGraph(); + const referencingProjects = dependencyGraph.referencingProjectsMap.getValue(root); + if (!referencingProjects) return; + // Always use build order to queue projects + for (const project of dependencyGraph.buildQueue) { // Can skip circular references - if (addProjToQueue(ref)) { - queueBuildForDownstreamReferences(ref, dependencyGraph); + if (referencingProjects.hasKey(project) && addProjToQueue(project)) { + queueBuildForDownstreamReferences(project); } } } @@ -944,14 +914,14 @@ namespace ts { const permanentMarks = createFileMap(toPath); const circularityReportStack: string[] = []; const buildOrder: ResolvedConfigFileName[] = []; - const graph = createDependencyMapper(toPath); + const referencingProjectsMap = createFileMap>(toPath); for (const root of roots) { visit(root); } return { buildQueue: buildOrder, - dependencyMap: graph, + referencingProjectsMap }; function visit(projPath: ResolvedConfigFileName, inCircularContext = false) { @@ -972,7 +942,9 @@ namespace ts { for (const ref of parsed.projectReferences) { const resolvedRefPath = resolveProjectName(ref.path); visit(resolvedRefPath, inCircularContext || ref.circular); - graph.addReference(projPath, resolvedRefPath); + // Get projects referencing resolvedRefPath and add projPath to it + const referencingProjects = getOrCreateValueFromConfigFileMap(referencingProjectsMap, resolvedRefPath, () => createFileMap(toPath)); + referencingProjects.setValue(projPath, true); } } diff --git a/src/testRunner/unittests/tsbuildWatchMode.ts b/src/testRunner/unittests/tsbuildWatchMode.ts index bc1bc4f373d..006facc0a39 100644 --- a/src/testRunner/unittests/tsbuildWatchMode.ts +++ b/src/testRunner/unittests/tsbuildWatchMode.ts @@ -137,16 +137,16 @@ namespace ts.tscWatch { ...getOutputFileNames(SubProject.core, "index"), ...(additionalFiles ? getOutputFileNames(SubProject.core, newFileWithoutExtension) : emptyArray) ]); - host.checkTimeoutQueueLengthAndRun(1); // Builds tests - const changedTests = getOutputFileStamps(host, additionalFiles); - verifyChangedFiles(changedTests, changedCore, [ - ...getOutputFileNames(SubProject.tests, "index") // Again these need not be written - ]); host.checkTimeoutQueueLengthAndRun(1); // Builds logic const changedLogic = getOutputFileStamps(host, additionalFiles); - verifyChangedFiles(changedLogic, changedTests, [ + verifyChangedFiles(changedLogic, changedCore, [ ...getOutputFileNames(SubProject.logic, "index") // Again these need not be written ]); + host.checkTimeoutQueueLengthAndRun(1); // Builds tests + const changedTests = getOutputFileStamps(host, additionalFiles); + verifyChangedFiles(changedTests, changedLogic, [ + ...getOutputFileNames(SubProject.tests, "index") // Again these need not be written + ]); host.checkTimeoutQueueLength(0); checkOutputErrorsIncremental(host, emptyArray); verifyWatches(); From 8a7550f82f887dd1e28d3f0b258a3a8f34c9dae2 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 11 Sep 2018 15:51:10 -0700 Subject: [PATCH 34/83] Deadcode removal --- src/compiler/tsbuild.ts | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts index 87c1f44430b..33790a1ab35 100644 --- a/src/compiler/tsbuild.ts +++ b/src/compiler/tsbuild.ts @@ -1128,10 +1128,9 @@ namespace ts { function buildAllProjects(): ExitStatus { if (options.watch) { reportWatchStatus(Diagnostics.Starting_compilation_in_watch_mode); } const graph = getGlobalDependencyGraph(); - const queue = graph.buildQueue; reportBuildQueue(graph); let anyFailed = false; - for (const next of queue) { + for (const next of graph.buildQueue) { const proj = parseConfigFile(next); if (proj === undefined) { anyFailed = true; @@ -1188,13 +1187,9 @@ namespace ts { * Report the build ordering inferred from the current project graph if we're in verbose mode */ function reportBuildQueue(graph: DependencyGraph) { - if (!options.verbose) return; - - const names: string[] = []; - for (const name of graph.buildQueue) { - names.push(name); + if (options.verbose) { + reportStatus(Diagnostics.Projects_in_this_build_Colon_0, graph.buildQueue.map(s => "\r\n * " + relName(s)).join("")); } - if (options.verbose) reportStatus(Diagnostics.Projects_in_this_build_Colon_0, names.map(s => "\r\n * " + relName(s)).join("")); } function relName(path: string): string { From bdf1c782b2edf0cbc82b8f37bfa5f31dc5417133 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 11 Sep 2018 15:59:24 -0700 Subject: [PATCH 35/83] Report file not found error about the project and watch config file even if not present --- src/compiler/tsbuild.ts | 50 ++++++++++--------- src/testRunner/unittests/tsbuildWatchMode.ts | 52 ++++++++++++++++++-- 2 files changed, 75 insertions(+), 27 deletions(-) diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts index 33790a1ab35..1aaa3e07f1c 100644 --- a/src/compiler/tsbuild.ts +++ b/src/compiler/tsbuild.ts @@ -483,11 +483,11 @@ namespace ts { function startWatching() { const graph = getGlobalDependencyGraph(); for (const resolved of graph.buildQueue) { + // Watch this file + watchConfigFile(resolved); + const cfg = parseConfigFile(resolved); if (cfg) { - // Watch this file - watchConfigFile(resolved); - // Update watchers for wildcard directories watchWildCardDirectories(resolved, cfg); @@ -879,7 +879,11 @@ namespace ts { // TODO:: handle this in better way later const proj = parseConfigFile(resolved); - if (!proj) return; // ? + if (!proj) { + reportParseConfigFileDiagnostic(resolved); + return; + } + if (reloadLevel === ConfigFileProgramReloadLevel.Full) { watchConfigFile(resolved); watchWildCardDirectories(resolved, proj); @@ -954,6 +958,11 @@ namespace ts { } } + function reportParseConfigFileDiagnostic(proj: ResolvedConfigFileName) { + host.reportDiagnostic(configFileCache.getValue(proj) as Diagnostic); + storeErrorSummary(proj, 1); + } + function buildSingleProject(proj: ResolvedConfigFileName): BuildResultFlags { if (options.dry) { reportStatus(Diagnostics.A_non_dry_build_would_build_project_0, proj); @@ -969,8 +978,7 @@ namespace ts { if (!configFile) { // Failed to read the config file resultFlags |= BuildResultFlags.ConfigFileErrors; - host.reportDiagnostic(configFileCache.getValue(proj) as Diagnostic); - storeErrorSummary(proj, 1); + reportParseConfigFileDiagnostic(proj); projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Config file errors" }); return resultFlags; } @@ -995,10 +1003,7 @@ namespace ts { ...program.getSyntacticDiagnostics()]; if (syntaxDiagnostics.length) { resultFlags |= BuildResultFlags.SyntaxErrors; - for (const diag of syntaxDiagnostics) { - host.reportDiagnostic(diag); - } - storeErrors(proj, syntaxDiagnostics); + reportErrors(proj, syntaxDiagnostics); projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Syntactic errors" }); return resultFlags; } @@ -1008,10 +1013,7 @@ namespace ts { const declDiagnostics = program.getDeclarationDiagnostics(); if (declDiagnostics.length) { resultFlags |= BuildResultFlags.DeclarationEmitErrors; - for (const diag of declDiagnostics) { - host.reportDiagnostic(diag); - } - storeErrors(proj, declDiagnostics); + reportErrors(proj, declDiagnostics); projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Declaration file errors" }); return resultFlags; } @@ -1021,10 +1023,7 @@ namespace ts { const semanticDiagnostics = program.getSemanticDiagnostics(); if (semanticDiagnostics.length) { resultFlags |= BuildResultFlags.TypeErrors; - for (const diag of semanticDiagnostics) { - host.reportDiagnostic(diag); - } - storeErrors(proj, semanticDiagnostics); + reportErrors(proj, semanticDiagnostics); projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Semantic errors" }); return resultFlags; } @@ -1091,6 +1090,7 @@ namespace ts { const parsed = parseConfigFile(proj); if (parsed === undefined) { // File has gone missing; fine to ignore here + reportParseConfigFileDiagnostic(proj); continue; } const outputs = getAllProjectOutputs(parsed); @@ -1133,6 +1133,7 @@ namespace ts { for (const next of graph.buildQueue) { const proj = parseConfigFile(next); if (proj === undefined) { + reportParseConfigFileDiagnostic(next); anyFailed = true; break; } @@ -1144,7 +1145,7 @@ namespace ts { const projName = proj.options.configFilePath!; if (status.type === UpToDateStatusType.UpToDate && !options.force) { - reportErrors(errors); + reportErrors(next, errors); // Up to date, skip if (defaultOptions.dry) { // In a dry build, inform the user of this fact @@ -1154,20 +1155,20 @@ namespace ts { } if (status.type === UpToDateStatusType.UpToDateWithUpstreamTypes && !options.force) { - reportErrors(errors); + reportErrors(next, errors); // Fake build updateOutputTimestamps(proj); continue; } if (status.type === UpToDateStatusType.UpstreamBlocked) { - reportErrors(errors); + reportErrors(next, errors); if (options.verbose) reportStatus(Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors, projName, status.upstreamProjectName); continue; } if (status.type === UpToDateStatusType.ContainerOnly) { - reportErrors(errors); + reportErrors(next, errors); // Do nothing continue; } @@ -1179,8 +1180,9 @@ namespace ts { return anyFailed ? ExitStatus.DiagnosticsPresent_OutputsSkipped : ExitStatus.Success; } - function reportErrors(errors: Diagnostic[]) { - errors.forEach((err) => host.reportDiagnostic(err)); + function reportErrors(proj: ResolvedConfigFileName, errors: ReadonlyArray) { + errors.forEach(err => host.reportDiagnostic(err)); + storeErrors(proj, errors); } /** diff --git a/src/testRunner/unittests/tsbuildWatchMode.ts b/src/testRunner/unittests/tsbuildWatchMode.ts index 006facc0a39..e2abd2a0d04 100644 --- a/src/testRunner/unittests/tsbuildWatchMode.ts +++ b/src/testRunner/unittests/tsbuildWatchMode.ts @@ -98,9 +98,7 @@ namespace ts.tscWatch { function createSolutionInWatchMode() { const host = createWatchedSystem(allFiles, { currentDirectory: projectsLocation }); createSolutionBuilderWithWatch(host, [`${project}/${SubProject.tests}`]); - checkWatchedFiles(host, testProjectExpectedWatchedFiles); - checkWatchedDirectories(host, emptyArray, /*recursive*/ false); - checkWatchedDirectories(host, [projectPath(SubProject.core), projectPath(SubProject.logic)], /*recursive*/ true); + verifyWatches(host); checkOutputErrorsInitial(host, emptyArray); const outputFileStamps = getOutputFileStamps(host); for (const stamp of outputFileStamps) { @@ -108,6 +106,13 @@ namespace ts.tscWatch { } return host; } + + function verifyWatches(host: WatchedSystem) { + checkWatchedFiles(host, testProjectExpectedWatchedFiles); + checkWatchedDirectories(host, emptyArray, /*recursive*/ false); + checkWatchedDirectories(host, [projectPath(SubProject.core), projectPath(SubProject.logic)], /*recursive*/ true); + } + it("creates solution in watch mode", () => { createSolutionInWatchMode(); }); @@ -197,6 +202,47 @@ export class someClass2 { }`); }); + it("watches config files that are not present", () => { + const allFiles = [libFile, ...core, logic[1], ...tests]; + const host = createWatchedSystem(allFiles, { currentDirectory: projectsLocation }); + createSolutionBuilderWithWatch(host, [`${project}/${SubProject.tests}`]); + checkWatchedFiles(host, [core[0], core[1], core[2], logic[0], ...tests].map(f => f.path)); + checkWatchedDirectories(host, emptyArray, /*recursive*/ false); + checkWatchedDirectories(host, [projectPath(SubProject.core)], /*recursive*/ true); + checkOutputErrorsInitial(host, [ + createCompilerDiagnostic(Diagnostics.File_0_not_found, logic[0].path) + ]); + for (const f of [ + ...getOutputFileNames(SubProject.core, "anotherModule"), + ...getOutputFileNames(SubProject.core, "index") + ]) { + assert.isTrue(host.fileExists(f), `${f} expected to be present`); + } + for (const f of [ + ...getOutputFileNames(SubProject.logic, "index"), + ...getOutputFileNames(SubProject.tests, "index") + ]) { + assert.isFalse(host.fileExists(f), `${f} expected to be absent`); + } + + // Create tsconfig file for logic and see that build succeeds + const initial = getOutputFileStamps(host); + host.writeFile(logic[0].path, logic[0].content); + host.checkTimeoutQueueLengthAndRun(1); // Builds logic + const changedLogic = getOutputFileStamps(host); + verifyChangedFiles(changedLogic, initial, [ + ...getOutputFileNames(SubProject.logic, "index") + ]); + host.checkTimeoutQueueLengthAndRun(1); // Builds tests + const changedTests = getOutputFileStamps(host); + verifyChangedFiles(changedTests, changedLogic, [ + ...getOutputFileNames(SubProject.tests, "index") + ]); + host.checkTimeoutQueueLength(0); + checkOutputErrorsIncremental(host, emptyArray); + verifyWatches(host); + }); + // TODO: write tests reporting errors but that will have more involved work since file }); } From 371ffffc6d497a04791f3c2b19e44b268f2e0ac5 Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Wed, 12 Sep 2018 10:17:26 -0700 Subject: [PATCH 36/83] Update user baselines (#27048) --- .../reference/user/adonis-framework.log | 2 +- tests/baselines/reference/user/assert.log | 20 +-- tests/baselines/reference/user/async.log | 2 +- .../user/chrome-devtools-frontend.log | 6 +- .../reference/user/create-react-app.log | 16 +-- tests/baselines/reference/user/debug.log | 119 ++++++++++++------ tests/baselines/reference/user/lodash.log | 16 +-- 7 files changed, 109 insertions(+), 72 deletions(-) diff --git a/tests/baselines/reference/user/adonis-framework.log b/tests/baselines/reference/user/adonis-framework.log index 6c7272790fe..7796b296dbe 100644 --- a/tests/baselines/reference/user/adonis-framework.log +++ b/tests/baselines/reference/user/adonis-framework.log @@ -35,7 +35,7 @@ node_modules/adonis-framework/src/Env/index.js(54,15): error TS2304: Cannot find node_modules/adonis-framework/src/Env/index.js(56,15): error TS2304: Cannot find name 'Mixed'. node_modules/adonis-framework/src/Env/index.js(80,15): error TS2304: Cannot find name 'Mixed'. node_modules/adonis-framework/src/Event/index.js(13,21): error TS2307: Cannot find module 'adonis-fold'. -node_modules/adonis-framework/src/Event/index.js(128,5): error TS2322: Type '() => {}[]' is not assignable to type 'any[]'. +node_modules/adonis-framework/src/Event/index.js(128,12): error TS2322: Type '() => {}[]' is not assignable to type 'any[]'. Property 'pop' is missing in type '() => {}[]'. node_modules/adonis-framework/src/Event/index.js(153,25): error TS2339: Property 'wildcard' does not exist on type 'EventEmitter2'. node_modules/adonis-framework/src/Event/index.js(188,17): error TS2304: Cannot find name 'Spread'. diff --git a/tests/baselines/reference/user/assert.log b/tests/baselines/reference/user/assert.log index 37a2c42e4d6..ab73398f14c 100644 --- a/tests/baselines/reference/user/assert.log +++ b/tests/baselines/reference/user/assert.log @@ -25,17 +25,17 @@ node_modules/assert/test.js(143,10): error TS2339: Property 'a' does not exist o node_modules/assert/test.js(149,5): error TS2552: Cannot find name 'test'. Did you mean 'tests'? node_modules/assert/test.js(157,51): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'never' has no compatible call signatures. node_modules/assert/test.js(161,5): error TS2552: Cannot find name 'test'. Did you mean 'tests'? -node_modules/assert/test.js(168,5): error TS2304: Cannot find name 'test'. -node_modules/assert/test.js(182,5): error TS2304: Cannot find name 'test'. -node_modules/assert/test.js(229,5): error TS2304: Cannot find name 'test'. -node_modules/assert/test.js(235,5): error TS2304: Cannot find name 'test'. -node_modules/assert/test.js(250,5): error TS2304: Cannot find name 'test'. -node_modules/assert/test.js(254,5): error TS2304: Cannot find name 'test'. +node_modules/assert/test.js(168,5): error TS2582: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`. +node_modules/assert/test.js(182,5): error TS2582: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`. +node_modules/assert/test.js(229,5): error TS2582: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`. +node_modules/assert/test.js(235,5): error TS2582: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`. +node_modules/assert/test.js(250,5): error TS2582: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`. +node_modules/assert/test.js(254,5): error TS2582: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`. node_modules/assert/test.js(256,55): error TS2345: Argument of type 'TypeError' is not assignable to parameter of type 'string'. -node_modules/assert/test.js(262,5): error TS2304: Cannot find name 'test'. -node_modules/assert/test.js(279,5): error TS2304: Cannot find name 'test'. -node_modules/assert/test.js(285,5): error TS2304: Cannot find name 'test'. -node_modules/assert/test.js(320,5): error TS2304: Cannot find name 'test'. +node_modules/assert/test.js(262,5): error TS2582: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`. +node_modules/assert/test.js(279,5): error TS2582: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`. +node_modules/assert/test.js(285,5): error TS2582: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`. +node_modules/assert/test.js(320,5): error TS2582: Cannot find name 'test'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`. diff --git a/tests/baselines/reference/user/async.log b/tests/baselines/reference/user/async.log index 3e7e3ab4c4b..791445bfddc 100644 --- a/tests/baselines/reference/user/async.log +++ b/tests/baselines/reference/user/async.log @@ -51,7 +51,7 @@ node_modules/async/autoInject.js(160,28): error TS2695: Left side of comma opera node_modules/async/autoInject.js(164,14): error TS2695: Left side of comma operator is unused and has no side effects. node_modules/async/autoInject.js(168,6): error TS2695: Left side of comma operator is unused and has no side effects. node_modules/async/cargo.js(62,12): error TS2304: Cannot find name 'AsyncFunction'. -node_modules/async/cargo.js(67,14): error TS2304: Cannot find name 'module'. +node_modules/async/cargo.js(67,14): error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i @types/node`. node_modules/async/cargo.js(67,20): error TS1005: '}' expected. node_modules/async/cargo.js(92,11): error TS2695: Left side of comma operator is unused and has no side effects. node_modules/async/compose.js(8,37): error TS2695: Left side of comma operator is unused and has no side effects. diff --git a/tests/baselines/reference/user/chrome-devtools-frontend.log b/tests/baselines/reference/user/chrome-devtools-frontend.log index e58d2188be4..cf555239405 100644 --- a/tests/baselines/reference/user/chrome-devtools-frontend.log +++ b/tests/baselines/reference/user/chrome-devtools-frontend.log @@ -284,7 +284,7 @@ node_modules/chrome-devtools-frontend/front_end/animation/AnimationModel.js(811, node_modules/chrome-devtools-frontend/front_end/animation/AnimationModel.js(811,44): error TS2300: Duplicate identifier 'Request'. node_modules/chrome-devtools-frontend/front_end/animation/AnimationScreenshotPopover.js(7,11): error TS2339: Property 'AnimationScreenshotPopover' does not exist on type '{ new (effect?: AnimationEffect, timeline?: AnimationTimeline): Animation; prototype: Animation; }'. node_modules/chrome-devtools-frontend/front_end/animation/AnimationScreenshotPopover.js(9,23): error TS2304: Cannot find name 'Image'. -node_modules/chrome-devtools-frontend/front_end/animation/AnimationScreenshotPopover.js(18,39): error TS2345: Argument of type 'new (width?: number, height?: number) => HTMLImageElement' is not assignable to parameter of type 'Node'. +node_modules/chrome-devtools-frontend/front_end/animation/AnimationScreenshotPopover.js(18,39): error TS2322: Type 'new (width?: number, height?: number) => HTMLImageElement' is not assignable to type 'Node'. Property 'baseURI' is missing in type 'new (width?: number, height?: number) => HTMLImageElement'. node_modules/chrome-devtools-frontend/front_end/animation/AnimationScreenshotPopover.js(19,13): error TS2339: Property 'style' does not exist on type 'new (width?: number, height?: number) => HTMLImageElement'. node_modules/chrome-devtools-frontend/front_end/animation/AnimationScreenshotPopover.js(22,21): error TS2339: Property 'style' does not exist on type 'new (width?: number, height?: number) => HTMLImageElement'. @@ -12007,7 +12007,7 @@ node_modules/chrome-devtools-frontend/front_end/timeline/TimelineFlameChartDataP node_modules/chrome-devtools-frontend/front_end/timeline/TimelineFlameChartDataProvider.js(621,36): error TS2339: Property 'preciseMillisToString' does not exist on type 'NumberConstructor'. node_modules/chrome-devtools-frontend/front_end/timeline/TimelineFlameChartDataProvider.js(654,37): error TS2339: Property 'naturalHeight' does not exist on type 'new (width?: number, height?: number) => HTMLImageElement'. node_modules/chrome-devtools-frontend/front_end/timeline/TimelineFlameChartDataProvider.js(655,39): error TS2339: Property 'naturalWidth' does not exist on type 'new (width?: number, height?: number) => HTMLImageElement'. -node_modules/chrome-devtools-frontend/front_end/timeline/TimelineFlameChartDataProvider.js(660,23): error TS2345: Argument of type 'new (width?: number, height?: number) => HTMLImageElement' is not assignable to parameter of type 'CanvasImageSource'. +node_modules/chrome-devtools-frontend/front_end/timeline/TimelineFlameChartDataProvider.js(660,23): error TS2322: Type 'new (width?: number, height?: number) => HTMLImageElement' is not assignable to type 'CanvasImageSource'. Type 'new (width?: number, height?: number) => HTMLImageElement' is not assignable to type 'ImageBitmap'. Property 'height' is missing in type 'new (width?: number, height?: number) => HTMLImageElement'. node_modules/chrome-devtools-frontend/front_end/timeline/TimelineFlameChartDataProvider.js(788,33): error TS2694: Namespace 'PerfUI.FlameChart' has no exported member 'GroupStyle'. @@ -12519,7 +12519,7 @@ node_modules/chrome-devtools-frontend/front_end/timeline/TimelineUIUtils.js(1649 node_modules/chrome-devtools-frontend/front_end/timeline/TimelineUIUtils.js(1651,33): error TS2555: Expected at least 2 arguments, but got 1. node_modules/chrome-devtools-frontend/front_end/timeline/TimelineUIUtils.js(1652,33): error TS2555: Expected at least 2 arguments, but got 1. node_modules/chrome-devtools-frontend/front_end/timeline/TimelineUIUtils.js(1652,69): error TS2339: Property 'millisToString' does not exist on type 'NumberConstructor'. -node_modules/chrome-devtools-frontend/front_end/timeline/TimelineUIUtils.js(1657,64): error TS2345: Argument of type 'new (width?: number, height?: number) => HTMLImageElement' is not assignable to parameter of type 'Node'. +node_modules/chrome-devtools-frontend/front_end/timeline/TimelineUIUtils.js(1657,64): error TS2322: Type 'new (width?: number, height?: number) => HTMLImageElement' is not assignable to type 'Node'. node_modules/chrome-devtools-frontend/front_end/timeline/TimelineUIUtils.js(1664,11): error TS2555: Expected at least 2 arguments, but got 1. node_modules/chrome-devtools-frontend/front_end/timeline/TimelineUIUtils.js(1665,67): error TS2555: Expected at least 2 arguments, but got 1. node_modules/chrome-devtools-frontend/front_end/timeline/TimelineUIUtils.js(1675,5): error TS2322: Type 'DocumentFragment' is not assignable to type 'Element'. diff --git a/tests/baselines/reference/user/create-react-app.log b/tests/baselines/reference/user/create-react-app.log index a7dc1694a90..537770fe818 100644 --- a/tests/baselines/reference/user/create-react-app.log +++ b/tests/baselines/reference/user/create-react-app.log @@ -15,9 +15,9 @@ packages/babel-preset-react-app/index.js(123,17): error TS2307: Cannot find modu packages/babel-preset-react-app/index.js(130,17): error TS2307: Cannot find module '@babel/plugin-transform-regenerator'. packages/babel-preset-react-app/index.js(137,15): error TS2307: Cannot find module '@babel/plugin-syntax-dynamic-import'. packages/babel-preset-react-app/index.js(140,17): error TS2307: Cannot find module 'babel-plugin-transform-dynamic-import'. -packages/confusing-browser-globals/test.js(14,1): error TS2304: Cannot find name 'it'. +packages/confusing-browser-globals/test.js(14,1): error TS2582: Cannot find name 'it'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`. packages/confusing-browser-globals/test.js(15,3): error TS2304: Cannot find name 'expect'. -packages/confusing-browser-globals/test.js(18,1): error TS2304: Cannot find name 'it'. +packages/confusing-browser-globals/test.js(18,1): error TS2582: Cannot find name 'it'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`. packages/confusing-browser-globals/test.js(19,3): error TS2304: Cannot find name 'expect'. packages/create-react-app/createReactApp.js(37,37): error TS2307: Cannot find module 'validate-npm-package-name'. packages/create-react-app/createReactApp.js(47,24): error TS2307: Cannot find module 'tar-pack'. @@ -35,18 +35,18 @@ packages/react-dev-utils/FileSizeReporter.js(16,24): error TS2307: Cannot find m packages/react-dev-utils/WebpackDevServerUtils.js(9,25): error TS2307: Cannot find module 'address'. packages/react-dev-utils/WebpackDevServerUtils.js(14,24): error TS2307: Cannot find module 'detect-port-alt'. packages/react-dev-utils/WebpackDevServerUtils.js(15,24): error TS2307: Cannot find module 'is-root'. -packages/react-dev-utils/__tests__/ignoredFiles.test.js(12,1): error TS2304: Cannot find name 'describe'. -packages/react-dev-utils/__tests__/ignoredFiles.test.js(13,3): error TS2304: Cannot find name 'it'. +packages/react-dev-utils/__tests__/ignoredFiles.test.js(12,1): error TS2582: Cannot find name 'describe'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`. +packages/react-dev-utils/__tests__/ignoredFiles.test.js(13,3): error TS2582: Cannot find name 'it'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`. packages/react-dev-utils/__tests__/ignoredFiles.test.js(18,5): error TS2304: Cannot find name 'expect'. packages/react-dev-utils/__tests__/ignoredFiles.test.js(19,5): error TS2304: Cannot find name 'expect'. -packages/react-dev-utils/__tests__/ignoredFiles.test.js(22,3): error TS2304: Cannot find name 'it'. +packages/react-dev-utils/__tests__/ignoredFiles.test.js(22,3): error TS2582: Cannot find name 'it'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`. packages/react-dev-utils/__tests__/ignoredFiles.test.js(26,5): error TS2304: Cannot find name 'expect'. -packages/react-dev-utils/__tests__/ignoredFiles.test.js(29,3): error TS2304: Cannot find name 'it'. +packages/react-dev-utils/__tests__/ignoredFiles.test.js(29,3): error TS2582: Cannot find name 'it'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`. packages/react-dev-utils/__tests__/ignoredFiles.test.js(36,5): error TS2304: Cannot find name 'expect'. packages/react-dev-utils/__tests__/ignoredFiles.test.js(37,5): error TS2304: Cannot find name 'expect'. -packages/react-dev-utils/__tests__/ignoredFiles.test.js(40,3): error TS2304: Cannot find name 'it'. +packages/react-dev-utils/__tests__/ignoredFiles.test.js(40,3): error TS2582: Cannot find name 'it'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`. packages/react-dev-utils/__tests__/ignoredFiles.test.js(46,5): error TS2304: Cannot find name 'expect'. -packages/react-dev-utils/__tests__/ignoredFiles.test.js(49,3): error TS2304: Cannot find name 'it'. +packages/react-dev-utils/__tests__/ignoredFiles.test.js(49,3): error TS2582: Cannot find name 'it'. Do you need to install type definitions for a test runner? Try `npm i @types/jest` or `npm i @types/mocha`. packages/react-dev-utils/__tests__/ignoredFiles.test.js(53,5): error TS2304: Cannot find name 'expect'. packages/react-dev-utils/browsersHelper.js(9,30): error TS2307: Cannot find module 'browserslist'. packages/react-dev-utils/browsersHelper.js(13,23): error TS2307: Cannot find module 'pkg-up'. diff --git a/tests/baselines/reference/user/debug.log b/tests/baselines/reference/user/debug.log index 62f54f6f17a..df15979cdb2 100644 --- a/tests/baselines/reference/user/debug.log +++ b/tests/baselines/reference/user/debug.log @@ -1,48 +1,85 @@ Exit Code: 1 Standard output: -node_modules/debug/src/browser.js(13,41): error TS2304: Cannot find name 'chrome'. -node_modules/debug/src/browser.js(14,41): error TS2304: Cannot find name 'chrome'. -node_modules/debug/src/browser.js(15,21): error TS2304: Cannot find name 'chrome'. -node_modules/debug/src/browser.js(48,47): error TS2339: Property 'process' does not exist on type 'Window'. -node_modules/debug/src/browser.js(48,65): error TS2339: Property 'process' does not exist on type 'Window'. -node_modules/debug/src/browser.js(59,139): error TS2551: Property 'WebkitAppearance' does not exist on type 'CSSStyleDeclaration'. Did you mean 'webkitAppearance'? -node_modules/debug/src/browser.js(61,73): error TS2339: Property 'firebug' does not exist on type 'Console'. -node_modules/debug/src/browser.js(187,13): error TS2304: Cannot find name 'LocalStorage'. -node_modules/debug/src/debug.js(25,1): error TS2323: Cannot redeclare exported variable 'names'. -node_modules/debug/src/debug.js(26,1): error TS2323: Cannot redeclare exported variable 'skips'. -node_modules/debug/src/debug.js(46,13): error TS2407: The right-hand side of a 'for...in' statement must be of type 'any', an object type or a type parameter, but here has type 'string'. -node_modules/debug/src/debug.js(47,57): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. -node_modules/debug/src/debug.js(51,18): error TS2339: Property 'colors' does not exist on type 'typeof createDebug'. -node_modules/debug/src/debug.js(51,50): error TS2339: Property 'colors' does not exist on type 'typeof createDebug'. -node_modules/debug/src/debug.js(75,10): error TS2339: Property 'diff' does not exist on type '{ (...args: any[]): void; namespace: string; enabled: boolean; useColors: any; color: number; destroy: () => boolean; }'. -node_modules/debug/src/debug.js(76,10): error TS2339: Property 'prev' does not exist on type '{ (...args: any[]): void; namespace: string; enabled: boolean; useColors: any; color: number; destroy: () => boolean; }'. -node_modules/debug/src/debug.js(77,10): error TS2339: Property 'curr' does not exist on type '{ (...args: any[]): void; namespace: string; enabled: boolean; useColors: any; color: number; destroy: () => boolean; }'. -node_modules/debug/src/debug.js(112,13): error TS2551: Property 'formatArgs' does not exist on type 'typeof createDebug'. Did you mean 'formatters'? -node_modules/debug/src/debug.js(114,23): error TS2339: Property 'log' does not exist on type '{ (...args: any[]): void; namespace: string; enabled: boolean; useColors: any; color: number; destroy: () => boolean; }'. -node_modules/debug/src/debug.js(114,38): error TS2339: Property 'log' does not exist on type 'typeof createDebug'. -node_modules/debug/src/debug.js(120,29): error TS2339: Property 'useColors' does not exist on type 'typeof createDebug'. -node_modules/debug/src/debug.js(125,37): error TS2339: Property 'init' does not exist on type 'typeof createDebug'. -node_modules/debug/src/debug.js(126,13): error TS2339: Property 'init' does not exist on type 'typeof createDebug'. -node_modules/debug/src/debug.js(153,11): error TS2339: Property 'save' does not exist on type 'typeof createDebug'. -node_modules/debug/src/debug.js(155,3): error TS2323: Cannot redeclare exported variable 'names'. -node_modules/debug/src/debug.js(156,3): error TS2323: Cannot redeclare exported variable 'skips'. -node_modules/debug/src/debug.js(217,12): error TS2304: Cannot find name 'Mixed'. -node_modules/debug/src/debug.js(218,13): error TS2304: Cannot find name 'Mixed'. -node_modules/debug/src/index.js(6,47): error TS2339: Property 'type' does not exist on type 'Process'. -node_modules/debug/src/node.js(26,1): error TS2323: Cannot redeclare exported variable 'colors'. -node_modules/debug/src/node.js(31,5): error TS2323: Cannot redeclare exported variable 'colors'. -node_modules/debug/src/node.js(60,39): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. +node_modules/debug/dist/debug.js(3,100): error TS2539: Cannot assign to '_typeof' because it is not a variable. +node_modules/debug/dist/debug.js(3,165): error TS2539: Cannot assign to '_typeof' because it is not a variable. +node_modules/debug/dist/debug.js(8,21): error TS2304: Cannot find name 'define'. +node_modules/debug/dist/debug.js(8,46): error TS2304: Cannot find name 'define'. +node_modules/debug/dist/debug.js(9,5): error TS2304: Cannot find name 'define'. +node_modules/debug/dist/debug.js(33,33): error TS2554: Expected 1 arguments, but got 2. +node_modules/debug/dist/debug.js(34,27): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'true | NodeRequire' has no compatible call signatures. +node_modules/debug/dist/debug.js(36,21): error TS2339: Property 'code' does not exist on type 'Error'. +node_modules/debug/dist/debug.js(89,38): error TS2339: Property 'length' does not exist on type 'string | number'. + Property 'length' does not exist on type 'number'. +node_modules/debug/dist/debug.js(90,24): error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'string'. + Type 'number' is not assignable to type 'string'. +node_modules/debug/dist/debug.js(91,47): error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'number'. + Type 'string' is not assignable to type 'number'. +node_modules/debug/dist/debug.js(92,41): error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'number'. + Type 'string' is not assignable to type 'number'. +node_modules/debug/dist/debug.js(92,57): error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'number'. + Type 'string' is not assignable to type 'number'. +node_modules/debug/dist/debug.js(110,11): error TS2322: Type 'undefined' is not assignable to type 'number'. +node_modules/debug/dist/debug.js(116,11): error TS2322: Type 'undefined' is not assignable to type 'number'. +node_modules/debug/dist/debug.js(169,13): error TS2322: Type 'undefined' is not assignable to type 'number'. +node_modules/debug/dist/debug.js(501,30): error TS2339: Property 'colors' does not exist on type '{ (namespace: string): Function; debug: any; default: any; coerce: (val: any) => any; disable: () => void; enable: (namespaces: string) => void; enabled: (name: string) => boolean; humanize: any; ... 4 more ...; selectColor: (namespace: string) => string | number; }'. +node_modules/debug/dist/debug.js(501,66): error TS2339: Property 'colors' does not exist on type '{ (namespace: string): Function; debug: any; default: any; coerce: (val: any) => any; disable: () => void; enable: (namespaces: string) => void; enabled: (name: string) => boolean; humanize: any; ... 4 more ...; selectColor: (namespace: string) => string | number; }'. +node_modules/debug/dist/debug.js(530,18): error TS2339: Property 'diff' does not exist on type '{ (...args: any[]): void; namespace: string; enabled: boolean; useColors: any; color: string | number; destroy: () => boolean; extend: (namespace: any, delimiter: any) => Function; }'. +node_modules/debug/dist/debug.js(531,18): error TS2339: Property 'prev' does not exist on type '{ (...args: any[]): void; namespace: string; enabled: boolean; useColors: any; color: string | number; destroy: () => boolean; extend: (namespace: any, delimiter: any) => Function; }'. +node_modules/debug/dist/debug.js(532,18): error TS2339: Property 'curr' does not exist on type '{ (...args: any[]): void; namespace: string; enabled: boolean; useColors: any; color: string | number; destroy: () => boolean; extend: (namespace: any, delimiter: any) => Function; }'. +node_modules/debug/dist/debug.js(563,25): error TS2551: Property 'formatArgs' does not exist on type '{ (namespace: string): Function; debug: any; default: any; coerce: (val: any) => any; disable: () => void; enable: (namespaces: string) => void; enabled: (name: string) => boolean; humanize: any; ... 4 more ...; selectColor: (namespace: string) => string | number; }'. Did you mean 'formatters'? +node_modules/debug/dist/debug.js(564,30): error TS2339: Property 'log' does not exist on type '{ (...args: any[]): void; namespace: string; enabled: boolean; useColors: any; color: string | number; destroy: () => boolean; extend: (namespace: any, delimiter: any) => Function; }'. +node_modules/debug/dist/debug.js(564,49): error TS2339: Property 'log' does not exist on type '{ (namespace: string): Function; debug: any; default: any; coerce: (val: any) => any; disable: () => void; enable: (namespaces: string) => void; enabled: (name: string) => boolean; humanize: any; ... 4 more ...; selectColor: (namespace: string) => string | number; }'. +node_modules/debug/dist/debug.js(570,41): error TS2339: Property 'useColors' does not exist on type '{ (namespace: string): Function; debug: any; default: any; coerce: (val: any) => any; disable: () => void; enable: (namespaces: string) => void; enabled: (name: string) => boolean; humanize: any; ... 4 more ...; selectColor: (namespace: string) => string | number; }'. +node_modules/debug/dist/debug.js(577,34): error TS2339: Property 'init' does not exist on type '{ (namespace: string): Function; debug: any; default: any; coerce: (val: any) => any; disable: () => void; enable: (namespaces: string) => void; enabled: (name: string) => boolean; humanize: any; ... 4 more ...; selectColor: (namespace: string) => string | number; }'. +node_modules/debug/dist/debug.js(578,25): error TS2339: Property 'init' does not exist on type '{ (namespace: string): Function; debug: any; default: any; coerce: (val: any) => any; disable: () => void; enable: (namespaces: string) => void; enabled: (name: string) => boolean; humanize: any; ... 4 more ...; selectColor: (namespace: string) => string | number; }'. +node_modules/debug/dist/debug.js(609,23): error TS2339: Property 'save' does not exist on type '{ (namespace: string): Function; debug: any; default: any; coerce: (val: any) => any; disable: () => void; enable: (namespaces: string) => void; enabled: (name: string) => boolean; humanize: any; ... 4 more ...; selectColor: (namespace: string) => string | number; }'. +node_modules/debug/dist/debug.js(680,19): error TS2304: Cannot find name 'Mixed'. +node_modules/debug/dist/debug.js(681,20): error TS2304: Cannot find name 'Mixed'. +node_modules/debug/dist/debug.js(694,40): error TS2339: Property 'load' does not exist on type '{ (namespace: string): Function; debug: any; default: any; coerce: (val: any) => any; disable: () => void; enable: (namespaces: string) => void; enabled: (name: string) => boolean; humanize: any; ... 4 more ...; selectColor: (namespace: string) => string | number; }'. +node_modules/debug/dist/debug.js(733,55): error TS2339: Property 'process' does not exist on type 'Window'. +node_modules/debug/dist/debug.js(733,74): error TS2339: Property 'process' does not exist on type 'Window'. +node_modules/debug/dist/debug.js(733,112): error TS2339: Property 'process' does not exist on type 'Window'. +node_modules/debug/dist/debug.js(744,146): error TS2551: Property 'WebkitAppearance' does not exist on type 'CSSStyleDeclaration'. Did you mean 'webkitAppearance'? +node_modules/debug/dist/debug.js(745,78): error TS2339: Property 'firebug' does not exist on type 'Console'. +node_modules/debug/dist/debug.js(851,21): error TS2304: Cannot find name 'LocalStorage'. +node_modules/debug/src/browser.js(3,100): error TS2539: Cannot assign to '_typeof' because it is not a variable. +node_modules/debug/src/browser.js(3,165): error TS2539: Cannot assign to '_typeof' because it is not a variable. +node_modules/debug/src/browser.js(34,47): error TS2339: Property 'process' does not exist on type 'Window'. +node_modules/debug/src/browser.js(34,66): error TS2339: Property 'process' does not exist on type 'Window'. +node_modules/debug/src/browser.js(34,104): error TS2339: Property 'process' does not exist on type 'Window'. +node_modules/debug/src/browser.js(45,138): error TS2551: Property 'WebkitAppearance' does not exist on type 'CSSStyleDeclaration'. Did you mean 'webkitAppearance'? +node_modules/debug/src/browser.js(46,70): error TS2339: Property 'firebug' does not exist on type 'Console'. +node_modules/debug/src/browser.js(152,13): error TS2304: Cannot find name 'LocalStorage'. +node_modules/debug/src/common.js(51,24): error TS2339: Property 'colors' does not exist on type '{ (namespace: string): Function; debug: any; default: any; coerce: (val: any) => any; disable: () => void; enable: (namespaces: string) => void; enabled: (name: string) => boolean; humanize: any; ... 4 more ...; selectColor: (namespace: string) => string | number; }'. +node_modules/debug/src/common.js(51,60): error TS2339: Property 'colors' does not exist on type '{ (namespace: string): Function; debug: any; default: any; coerce: (val: any) => any; disable: () => void; enable: (namespaces: string) => void; enabled: (name: string) => boolean; humanize: any; ... 4 more ...; selectColor: (namespace: string) => string | number; }'. +node_modules/debug/src/common.js(80,12): error TS2339: Property 'diff' does not exist on type '{ (...args: any[]): void; namespace: string; enabled: boolean; useColors: any; color: string | number; destroy: () => boolean; extend: (namespace: any, delimiter: any) => Function; }'. +node_modules/debug/src/common.js(81,12): error TS2339: Property 'prev' does not exist on type '{ (...args: any[]): void; namespace: string; enabled: boolean; useColors: any; color: string | number; destroy: () => boolean; extend: (namespace: any, delimiter: any) => Function; }'. +node_modules/debug/src/common.js(82,12): error TS2339: Property 'curr' does not exist on type '{ (...args: any[]): void; namespace: string; enabled: boolean; useColors: any; color: string | number; destroy: () => boolean; extend: (namespace: any, delimiter: any) => Function; }'. +node_modules/debug/src/common.js(113,19): error TS2551: Property 'formatArgs' does not exist on type '{ (namespace: string): Function; debug: any; default: any; coerce: (val: any) => any; disable: () => void; enable: (namespaces: string) => void; enabled: (name: string) => boolean; humanize: any; ... 4 more ...; selectColor: (namespace: string) => string | number; }'. Did you mean 'formatters'? +node_modules/debug/src/common.js(114,24): error TS2339: Property 'log' does not exist on type '{ (...args: any[]): void; namespace: string; enabled: boolean; useColors: any; color: string | number; destroy: () => boolean; extend: (namespace: any, delimiter: any) => Function; }'. +node_modules/debug/src/common.js(114,43): error TS2339: Property 'log' does not exist on type '{ (namespace: string): Function; debug: any; default: any; coerce: (val: any) => any; disable: () => void; enable: (namespaces: string) => void; enabled: (name: string) => boolean; humanize: any; ... 4 more ...; selectColor: (namespace: string) => string | number; }'. +node_modules/debug/src/common.js(120,35): error TS2339: Property 'useColors' does not exist on type '{ (namespace: string): Function; debug: any; default: any; coerce: (val: any) => any; disable: () => void; enable: (namespaces: string) => void; enabled: (name: string) => boolean; humanize: any; ... 4 more ...; selectColor: (namespace: string) => string | number; }'. +node_modules/debug/src/common.js(127,28): error TS2339: Property 'init' does not exist on type '{ (namespace: string): Function; debug: any; default: any; coerce: (val: any) => any; disable: () => void; enable: (namespaces: string) => void; enabled: (name: string) => boolean; humanize: any; ... 4 more ...; selectColor: (namespace: string) => string | number; }'. +node_modules/debug/src/common.js(128,19): error TS2339: Property 'init' does not exist on type '{ (namespace: string): Function; debug: any; default: any; coerce: (val: any) => any; disable: () => void; enable: (namespaces: string) => void; enabled: (name: string) => boolean; humanize: any; ... 4 more ...; selectColor: (namespace: string) => string | number; }'. +node_modules/debug/src/common.js(159,17): error TS2339: Property 'save' does not exist on type '{ (namespace: string): Function; debug: any; default: any; coerce: (val: any) => any; disable: () => void; enable: (namespaces: string) => void; enabled: (name: string) => boolean; humanize: any; ... 4 more ...; selectColor: (namespace: string) => string | number; }'. +node_modules/debug/src/common.js(230,13): error TS2304: Cannot find name 'Mixed'. +node_modules/debug/src/common.js(231,14): error TS2304: Cannot find name 'Mixed'. +node_modules/debug/src/common.js(244,34): error TS2339: Property 'load' does not exist on type '{ (namespace: string): Function; debug: any; default: any; coerce: (val: any) => any; disable: () => void; enable: (namespaces: string) => void; enabled: (name: string) => boolean; humanize: any; ... 4 more ...; selectColor: (namespace: string) => string | number; }'. +node_modules/debug/src/index.js(7,47): error TS2339: Property 'type' does not exist on type 'Process'. +node_modules/debug/src/index.js(7,78): error TS2339: Property 'browser' does not exist on type 'Process'. +node_modules/debug/src/index.js(7,106): error TS2339: Property '__nwjs' does not exist on type 'Process'. +node_modules/debug/src/node.js(24,1): error TS2323: Cannot redeclare exported variable 'colors'. +node_modules/debug/src/node.js(32,5): error TS2323: Cannot redeclare exported variable 'colors'. +node_modules/debug/src/node.js(53,39): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. Type 'undefined' is not assignable to type 'string'. -node_modules/debug/src/node.js(60,45): error TS2322: Type 'true' is not assignable to type 'string | undefined'. -node_modules/debug/src/node.js(61,46): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. +node_modules/debug/src/node.js(54,5): error TS2322: Type 'true' is not assignable to type 'string | undefined'. +node_modules/debug/src/node.js(55,48): error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. Type 'undefined' is not assignable to type 'string'. -node_modules/debug/src/node.js(61,52): error TS2322: Type 'false' is not assignable to type 'string | undefined'. -node_modules/debug/src/node.js(62,28): error TS2322: Type 'null' is not assignable to type 'string | undefined'. -node_modules/debug/src/node.js(63,8): error TS2322: Type 'number' is not assignable to type 'string | undefined'. -node_modules/debug/src/node.js(75,35): error TS2339: Property 'colors' does not exist on type 'never'. -node_modules/debug/src/node.js(76,33): error TS2339: Property 'fd' does not exist on type 'WriteStream'. -node_modules/debug/src/node.js(123,27): error TS2339: Property 'hideDate' does not exist on type '{}'. -node_modules/debug/src/node.js(163,3): error TS2322: Type 'string | undefined' is not assignable to type 'string'. +node_modules/debug/src/node.js(56,5): error TS2322: Type 'false' is not assignable to type 'string | undefined'. +node_modules/debug/src/node.js(58,5): error TS2322: Type 'null' is not assignable to type 'string | undefined'. +node_modules/debug/src/node.js(60,5): error TS2322: Type 'number' is not assignable to type 'string | undefined'. +node_modules/debug/src/node.js(71,108): error TS2339: Property 'fd' does not exist on type 'WriteStream'. +node_modules/debug/src/node.js(136,3): error TS2322: Type 'string | undefined' is not assignable to type 'string'. Type 'undefined' is not assignable to type 'string'. diff --git a/tests/baselines/reference/user/lodash.log b/tests/baselines/reference/user/lodash.log index 6fd61c0fb69..0551046aec1 100644 --- a/tests/baselines/reference/user/lodash.log +++ b/tests/baselines/reference/user/lodash.log @@ -36,7 +36,7 @@ node_modules/lodash/_baseDifference.js(37,5): error TS2322: Type '(array?: any[] node_modules/lodash/_baseDifference.js(43,5): error TS2322: Type 'SetCache' is not assignable to type 'any[]'. Property 'length' is missing in type 'SetCache'. node_modules/lodash/_baseDifference.js(60,15): error TS2554: Expected 2 arguments, but got 3. -node_modules/lodash/_baseFlatten.js(19,17): error TS2322: Type '(value: any) => boolean' is not assignable to type 'boolean | undefined'. +node_modules/lodash/_baseFlatten.js(19,29): error TS2322: Type '(value: any) => boolean' is not assignable to type 'boolean | undefined'. Type '(value: any) => boolean' is not assignable to type 'true'. node_modules/lodash/_baseFlatten.js(24,22): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'Boolean' has no compatible call signatures. node_modules/lodash/_baseFlatten.js(24,22): error TS2532: Object is possibly 'undefined'. @@ -180,7 +180,7 @@ node_modules/lodash/cloneWith.js(39,27): error TS2345: Argument of type 'number' node_modules/lodash/conforms.js(32,41): error TS2345: Argument of type 'number' is not assignable to parameter of type 'boolean'. node_modules/lodash/core.js(68,58): error TS2339: Property 'Object' does not exist on type 'Window'. node_modules/lodash/core.js(77,82): error TS2339: Property 'nodeType' does not exist on type 'NodeModule'. -node_modules/lodash/core.js(540,19): error TS2322: Type '(value: any) => boolean' is not assignable to type 'boolean | undefined'. +node_modules/lodash/core.js(540,31): error TS2322: Type '(value: any) => boolean' is not assignable to type 'boolean | undefined'. Type '(value: any) => boolean' is not assignable to type 'true'. node_modules/lodash/core.js(545,24): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'Boolean' has no compatible call signatures. node_modules/lodash/core.js(545,24): error TS2532: Object is possibly 'undefined'. @@ -251,12 +251,12 @@ node_modules/lodash/debounce.js(86,30): error TS2532: Object is possibly 'undefi node_modules/lodash/debounce.js(111,23): error TS2532: Object is possibly 'undefined'. node_modules/lodash/debounce.js(125,65): error TS2532: Object is possibly 'undefined'. node_modules/lodash/deburr.js(42,44): error TS2345: Argument of type 'Function' is not assignable to parameter of type '(substring: string, ...args: any[]) => string'. -node_modules/lodash/difference.js(29,52): error TS2345: Argument of type '(value: any) => boolean' is not assignable to parameter of type 'boolean | undefined'. +node_modules/lodash/difference.js(29,52): error TS2322: Type '(value: any) => boolean' is not assignable to type 'boolean | undefined'. Type '(value: any) => boolean' is not assignable to type 'true'. -node_modules/lodash/differenceBy.js(40,52): error TS2345: Argument of type '(value: any) => boolean' is not assignable to parameter of type 'boolean | undefined'. +node_modules/lodash/differenceBy.js(40,52): error TS2322: Type '(value: any) => boolean' is not assignable to type 'boolean | undefined'. Type '(value: any) => boolean' is not assignable to type 'true'. node_modules/lodash/differenceBy.js(40,78): error TS2554: Expected 0-1 arguments, but got 2. -node_modules/lodash/differenceWith.js(36,52): error TS2345: Argument of type '(value: any) => boolean' is not assignable to parameter of type 'boolean | undefined'. +node_modules/lodash/differenceWith.js(36,52): error TS2322: Type '(value: any) => boolean' is not assignable to type 'boolean | undefined'. Type '(value: any) => boolean' is not assignable to type 'true'. node_modules/lodash/drop.js(13,10): error TS1003: Identifier expected. node_modules/lodash/drop.js(13,10): error TS8024: JSDoc '@param' tag has name '', but there is no parameter with that name. @@ -425,12 +425,12 @@ node_modules/lodash/truncate.js(78,16): error TS2454: Variable 'strSymbols' is u node_modules/lodash/truncate.js(85,7): error TS2454: Variable 'strSymbols' is used before being assigned. node_modules/lodash/unary.js(19,10): error TS2554: Expected 3 arguments, but got 2. node_modules/lodash/unescape.js(30,37): error TS2345: Argument of type 'Function' is not assignable to parameter of type '(substring: string, ...args: any[]) => string'. -node_modules/lodash/union.js(23,42): error TS2345: Argument of type '(value: any) => boolean' is not assignable to parameter of type 'boolean | undefined'. +node_modules/lodash/union.js(23,42): error TS2322: Type '(value: any) => boolean' is not assignable to type 'boolean | undefined'. Type '(value: any) => boolean' is not assignable to type 'true'. -node_modules/lodash/unionBy.js(36,42): error TS2345: Argument of type '(value: any) => boolean' is not assignable to parameter of type 'boolean | undefined'. +node_modules/lodash/unionBy.js(36,42): error TS2322: Type '(value: any) => boolean' is not assignable to type 'boolean | undefined'. Type '(value: any) => boolean' is not assignable to type 'true'. node_modules/lodash/unionBy.js(36,68): error TS2554: Expected 0-1 arguments, but got 2. -node_modules/lodash/unionWith.js(31,42): error TS2345: Argument of type '(value: any) => boolean' is not assignable to parameter of type 'boolean | undefined'. +node_modules/lodash/unionWith.js(31,42): error TS2322: Type '(value: any) => boolean' is not assignable to type 'boolean | undefined'. Type '(value: any) => boolean' is not assignable to type 'true'. node_modules/lodash/uniqBy.js(28,52): error TS2554: Expected 0-1 arguments, but got 2. node_modules/lodash/words.js(15,10): error TS1003: Identifier expected. From 6bd1da20c978c6e652ec827dadecfad46d91a29f Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Wed, 12 Sep 2018 10:44:46 -0700 Subject: [PATCH 37/83] Rename JS-specific concepts (#26795) * Rename JS concepts 1. Assignment declaration -- an assignment that is treated like a declaration. Previously called [JS] special (assignment|declaration), among other things. 2. Expando -- a value that can be used as a target in assignment declarations. Currently, a class, function or empty object literal. Functions are allowed in Typescript, too. Previously called a JS container, JS initializer or expando object. 3. JavaScript -> Javascript. This is annoying to type, and looks like 'Java Script' in a camelCase world. Everything is a pure rename as far as I know. The only test change is the API baselines, which reflect the rename from SymbolFlags.JSContainer to SymbolFlags.Assignment. * Remove TODO * Rename Javascript->JS Note that this introduces a variable name collision in a couple of places, which I resolved like this: ```ts const isInJavascript = isInJSFile(node); ``` --- src/compiler/binder.ts | 52 ++-- src/compiler/checker.ts | 284 +++++++++--------- src/compiler/emitter.ts | 8 +- src/compiler/moduleNameResolver.ts | 4 +- src/compiler/moduleSpecifiers.ts | 8 +- src/compiler/program.ts | 10 +- src/compiler/transformers/declarations.ts | 12 +- src/compiler/tsbuild.ts | 4 +- src/compiler/types.ts | 12 +- src/compiler/utilities.ts | 138 ++++----- src/harness/harnessLanguageService.ts | 2 +- src/harness/vpath.ts | 6 +- src/jsTyping/jsTyping.ts | 4 +- src/server/editorServices.ts | 10 +- src/server/scriptInfo.ts | 2 +- .../codefixes/convertFunctionToEs6Class.ts | 2 +- .../codefixes/convertToAsyncFunction.ts | 6 +- .../codefixes/disableJsDiagnostics.ts | 2 +- src/services/codefixes/fixAddMissingMember.ts | 6 +- src/services/codefixes/importFixes.ts | 4 +- src/services/codefixes/inferFromUsage.ts | 2 +- src/services/completions.ts | 6 +- src/services/importTracker.ts | 6 +- src/services/jsDoc.ts | 4 +- src/services/navigationBar.ts | 16 +- src/services/refactors/extractSymbol.ts | 6 +- .../generateGetAccessorAndSetAccessor.ts | 2 +- src/services/refactors/moveToNewFile.ts | 2 +- src/services/services.ts | 2 +- src/services/signatureHelp.ts | 4 +- src/services/suggestionDiagnostics.ts | 8 +- src/services/utilities.ts | 16 +- src/testRunner/unittests/moduleResolution.ts | 6 +- src/tsserver/server.ts | 2 +- .../reference/api/tsserverlibrary.d.ts | 2 +- tests/baselines/reference/api/typescript.d.ts | 2 +- 36 files changed, 331 insertions(+), 331 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index ea8fb3eea8d..489f212967d 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -288,7 +288,7 @@ namespace ts { // module.exports = ... return InternalSymbolName.ExportEquals; case SyntaxKind.BinaryExpression: - if (getSpecialPropertyAssignmentKind(node as BinaryExpression) === SpecialPropertyAssignmentKind.ModuleExports) { + if (getAssignmentDeclarationKind(node as BinaryExpression) === AssignmentDeclarationKind.ModuleExports) { // module.exports = ... return InternalSymbolName.ExportEquals; } @@ -374,8 +374,8 @@ namespace ts { // prototype symbols like methods. symbolTable.set(name, symbol = createSymbol(SymbolFlags.None, name)); } - else if (!(includes & SymbolFlags.Variable && symbol.flags & SymbolFlags.JSContainer)) { - // JSContainers are allowed to merge with variables, no matter what other flags they have. + else if (!(includes & SymbolFlags.Variable && symbol.flags & SymbolFlags.Assignment)) { + // Assignment declarations are allowed to merge with variables, no matter what other flags they have. if (isNamedDeclaration(node)) { node.name.parent = node; } @@ -461,7 +461,7 @@ namespace ts { // during global merging in the checker. Why? The only case when ambient module is permitted inside another module is module augmentation // and this case is specially handled. Module augmentations should only be merged with original module definition // and should never be merged directly with other augmentation, and the latter case would be possible if automatic merge is allowed. - if (isJSDocTypeAlias(node)) Debug.assert(isInJavaScriptFile(node)); // We shouldn't add symbols for JSDoc nodes if not in a JS file. + if (isJSDocTypeAlias(node)) Debug.assert(isInJSFile(node)); // We shouldn't add symbols for JSDoc nodes if not in a JS file. if ((!isAmbientModule(node) && (hasExportModifier || container.flags & NodeFlags.ExportContext)) || isJSDocTypeAlias(node)) { if (hasModifier(node, ModifierFlags.Default) && !getDeclarationName(node)) { return declareSymbol(container.symbol.exports!, container.symbol, node, symbolFlags, symbolExcludes); // No local symbol for an unnamed default! @@ -2009,7 +2009,7 @@ namespace ts { function bindJSDoc(node: Node) { if (hasJSDocNodes(node)) { - if (isInJavaScriptFile(node)) { + if (isInJSFile(node)) { for (const j of node.jsDoc!) { bind(j); } @@ -2075,7 +2075,7 @@ namespace ts { if (isSpecialPropertyDeclaration(node as PropertyAccessExpression)) { bindSpecialPropertyDeclaration(node as PropertyAccessExpression); } - if (isInJavaScriptFile(node) && + if (isInJSFile(node) && file.commonJsModuleIndicator && isModuleExportsPropertyAccessExpression(node as PropertyAccessExpression) && !lookupSymbolForNameWorker(blockScopeContainer, "module" as __String)) { @@ -2084,27 +2084,27 @@ namespace ts { } break; case SyntaxKind.BinaryExpression: - const specialKind = getSpecialPropertyAssignmentKind(node as BinaryExpression); + const specialKind = getAssignmentDeclarationKind(node as BinaryExpression); switch (specialKind) { - case SpecialPropertyAssignmentKind.ExportsProperty: + case AssignmentDeclarationKind.ExportsProperty: bindExportsPropertyAssignment(node as BinaryExpression); break; - case SpecialPropertyAssignmentKind.ModuleExports: + case AssignmentDeclarationKind.ModuleExports: bindModuleExportsAssignment(node as BinaryExpression); break; - case SpecialPropertyAssignmentKind.PrototypeProperty: + case AssignmentDeclarationKind.PrototypeProperty: bindPrototypePropertyAssignment((node as BinaryExpression).left as PropertyAccessEntityNameExpression, node); break; - case SpecialPropertyAssignmentKind.Prototype: + case AssignmentDeclarationKind.Prototype: bindPrototypeAssignment(node as BinaryExpression); break; - case SpecialPropertyAssignmentKind.ThisProperty: + case AssignmentDeclarationKind.ThisProperty: bindThisPropertyAssignment(node as BinaryExpression); break; - case SpecialPropertyAssignmentKind.Property: + case AssignmentDeclarationKind.Property: bindSpecialPropertyAssignment(node as BinaryExpression); break; - case SpecialPropertyAssignmentKind.None: + case AssignmentDeclarationKind.None: // Nothing to do break; default: @@ -2184,7 +2184,7 @@ namespace ts { return bindFunctionExpression(node); case SyntaxKind.CallExpression: - if (isInJavaScriptFile(node)) { + if (isInJSFile(node)) { bindCallExpression(node); } break; @@ -2361,7 +2361,7 @@ namespace ts { const lhs = node.left as PropertyAccessEntityNameExpression; const symbol = forEachIdentifierInEntityName(lhs.expression, /*parent*/ undefined, (id, symbol) => { if (symbol) { - addDeclarationToSymbol(symbol, id, SymbolFlags.Module | SymbolFlags.JSContainer); + addDeclarationToSymbol(symbol, id, SymbolFlags.Module | SymbolFlags.Assignment); } return symbol; }); @@ -2394,7 +2394,7 @@ namespace ts { } function bindThisPropertyAssignment(node: BinaryExpression | PropertyAccessExpression) { - Debug.assert(isInJavaScriptFile(node)); + Debug.assert(isInJSFile(node)); const thisContainer = getThisContainer(node, /*includeArrowFunctions*/ false); switch (thisContainer.kind) { case SyntaxKind.FunctionDeclaration: @@ -2482,7 +2482,7 @@ namespace ts { const lhs = node.left as PropertyAccessEntityNameExpression; // Class declarations in Typescript do not allow property declarations const parentSymbol = lookupSymbolForPropertyAccess(lhs.expression); - if (!isInJavaScriptFile(node) && !isFunctionSymbol(parentSymbol)) { + if (!isInJSFile(node) && !isFunctionSymbol(parentSymbol)) { return; } // Fix up parent pointers since we're going to use these nodes before we bind into them @@ -2515,8 +2515,8 @@ namespace ts { : propertyAccess.parent.parent.kind === SyntaxKind.SourceFile; if (!isPrototypeProperty && (!namespaceSymbol || !(namespaceSymbol.flags & SymbolFlags.Namespace)) && isToplevel) { // make symbols or add declarations for intermediate containers - const flags = SymbolFlags.Module | SymbolFlags.JSContainer; - const excludeFlags = SymbolFlags.ValueModuleExcludes & ~SymbolFlags.JSContainer; + const flags = SymbolFlags.Module | SymbolFlags.Assignment; + const excludeFlags = SymbolFlags.ValueModuleExcludes & ~SymbolFlags.Assignment; namespaceSymbol = forEachIdentifierInEntityName(propertyAccess.expression, namespaceSymbol, (id, symbol, parent) => { if (symbol) { addDeclarationToSymbol(symbol, id, flags); @@ -2527,7 +2527,7 @@ namespace ts { } }); } - if (!namespaceSymbol || !isJavascriptContainer(namespaceSymbol)) { + if (!namespaceSymbol || !isExpandoSymbol(namespaceSymbol)) { return; } @@ -2536,14 +2536,14 @@ namespace ts { (namespaceSymbol.members || (namespaceSymbol.members = createSymbolTable())) : (namespaceSymbol.exports || (namespaceSymbol.exports = createSymbolTable())); - const isMethod = isFunctionLikeDeclaration(getAssignedJavascriptInitializer(propertyAccess)!); + const isMethod = isFunctionLikeDeclaration(getAssignedExpandoInitializer(propertyAccess)!); const includes = isMethod ? SymbolFlags.Method : SymbolFlags.Property; const excludes = isMethod ? SymbolFlags.MethodExcludes : SymbolFlags.PropertyExcludes; - declareSymbol(symbolTable, namespaceSymbol, propertyAccess, includes | SymbolFlags.JSContainer, excludes & ~SymbolFlags.JSContainer); + declareSymbol(symbolTable, namespaceSymbol, propertyAccess, includes | SymbolFlags.Assignment, excludes & ~SymbolFlags.Assignment); } /** - * Javascript containers are: + * Javascript expando values are: * - Functions * - classes * - namespaces @@ -2552,7 +2552,7 @@ namespace ts { * - with empty object literals * - with non-empty object literals if assigned to the prototype property */ - function isJavascriptContainer(symbol: Symbol): boolean { + function isExpandoSymbol(symbol: Symbol): boolean { if (symbol.flags & (SymbolFlags.Function | SymbolFlags.Class | SymbolFlags.NamespaceModule)) { return true; } @@ -2565,7 +2565,7 @@ namespace ts { init = init && getRightMostAssignedExpression(init); if (init) { const isPrototypeAssignment = isPrototypeAccess(isVariableDeclaration(node) ? node.name : isBinaryExpression(node) ? node.left : node); - return !!getJavascriptInitializer(isBinaryExpression(init) && init.operatorToken.kind === SyntaxKind.BarBarToken ? init.right : init, isPrototypeAssignment); + return !!getExpandoInitializer(isBinaryExpression(init) && init.operatorToken.kind === SyntaxKind.BarBarToken ? init.right : init, isPrototypeAssignment); } return false; } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a856df2854a..974c74029eb 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -824,7 +824,7 @@ namespace ts { */ function mergeSymbol(target: Symbol, source: Symbol): Symbol { if (!(target.flags & getExcludedSymbolFlags(source.flags)) || - (source.flags | target.flags) & SymbolFlags.JSContainer) { + (source.flags | target.flags) & SymbolFlags.Assignment) { Debug.assert(source !== target); if (!(target.flags & SymbolFlags.Transient)) { target = cloneSymbol(target); @@ -878,12 +878,12 @@ namespace ts { const secondInstanceList = existing.secondFileInstances.get(symbolName) || { instances: [], blockScoped: isEitherBlockScoped }; forEach(source.declarations, node => { - const errorNode = (getJavascriptInitializer(node, /*isPrototypeAssignment*/ false) ? getOuterNameOfJsInitializer(node) : getNameOfDeclaration(node)) || node; + const errorNode = (getExpandoInitializer(node, /*isPrototypeAssignment*/ false) ? getNameOfExpando(node) : getNameOfDeclaration(node)) || node; const targetList = sourceSymbolFile === firstFile ? firstInstanceList : secondInstanceList; targetList.instances.push(errorNode); }); forEach(target.declarations, node => { - const errorNode = (getJavascriptInitializer(node, /*isPrototypeAssignment*/ false) ? getOuterNameOfJsInitializer(node) : getNameOfDeclaration(node)) || node; + const errorNode = (getExpandoInitializer(node, /*isPrototypeAssignment*/ false) ? getNameOfExpando(node) : getNameOfDeclaration(node)) || node; const targetList = targetSymbolFile === firstFile ? firstInstanceList : secondInstanceList; targetList.instances.push(errorNode); }); @@ -902,7 +902,7 @@ namespace ts { function addDuplicateDeclarationErrorsForSymbols(target: Symbol, message: DiagnosticMessage, symbolName: string, source: Symbol) { forEach(target.declarations, node => { - const errorNode = (getJavascriptInitializer(node, /*isPrototypeAssignment*/ false) ? getOuterNameOfJsInitializer(node) : getNameOfDeclaration(node)) || node; + const errorNode = (getExpandoInitializer(node, /*isPrototypeAssignment*/ false) ? getNameOfExpando(node) : getNameOfDeclaration(node)) || node; addDuplicateDeclarationError(errorNode, message, symbolName, source.declarations && source.declarations[0]); }); } @@ -1446,7 +1446,7 @@ namespace ts { } } if (!result) { - if (originalLocation && isInJavaScriptFile(originalLocation) && originalLocation.parent) { + if (originalLocation && isInJSFile(originalLocation) && originalLocation.parent) { if (isRequireCall(originalLocation.parent, /*checkArgumentIsStringLiteralLike*/ false)) { return requireSymbol; } @@ -1622,7 +1622,7 @@ namespace ts { } function checkAndReportErrorForUsingTypeAsNamespace(errorLocation: Node, name: __String, meaning: SymbolFlags): boolean { - const namespaceMeaning = SymbolFlags.Namespace | (isInJavaScriptFile(errorLocation) ? SymbolFlags.Value : 0); + const namespaceMeaning = SymbolFlags.Namespace | (isInJSFile(errorLocation) ? SymbolFlags.Value : 0); if (meaning === namespaceMeaning) { const symbol = resolveSymbol(resolveName(errorLocation, name, SymbolFlags.Type & ~namespaceMeaning, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined, /*isUse*/ false)); const parent = errorLocation.parent; @@ -1788,7 +1788,7 @@ namespace ts { return true; } // TypeScript files never have a synthetic default (as they are always emitted with an __esModule marker) _unless_ they contain an export= statement - if (!isSourceFileJavaScript(file)) { + if (!isSourceFileJS(file)) { return hasExportAssignmentSymbol(moduleSymbol); } // JS files have a synthetic default if they do not contain ES2015+ module syntax (export = is not valid in js) _and_ do not have an __esModule marker @@ -1979,7 +1979,7 @@ namespace ts { */ function isNonLocalAlias(symbol: Symbol | undefined, excludes = SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace): symbol is Symbol { if (!symbol) return false; - return (symbol.flags & (SymbolFlags.Alias | excludes)) === SymbolFlags.Alias || !!(symbol.flags & SymbolFlags.Alias && symbol.flags & SymbolFlags.JSContainer); + return (symbol.flags & (SymbolFlags.Alias | excludes)) === SymbolFlags.Alias || !!(symbol.flags & SymbolFlags.Alias && symbol.flags & SymbolFlags.Assignment); } function resolveSymbol(symbol: Symbol, dontResolveAlias?: boolean): Symbol; @@ -2081,11 +2081,11 @@ namespace ts { return undefined; } - const namespaceMeaning = SymbolFlags.Namespace | (isInJavaScriptFile(name) ? meaning & SymbolFlags.Value : 0); + const namespaceMeaning = SymbolFlags.Namespace | (isInJSFile(name) ? meaning & SymbolFlags.Value : 0); let symbol: Symbol | undefined; if (name.kind === SyntaxKind.Identifier) { const message = meaning === namespaceMeaning ? Diagnostics.Cannot_find_namespace_0 : getCannotFindNameDiagnosticForName(getFirstIdentifier(name).escapedText); - const symbolFromJSPrototype = isInJavaScriptFile(name) ? resolveEntityNameFromJSSpecialAssignment(name, meaning) : undefined; + const symbolFromJSPrototype = isInJSFile(name) ? resolveEntityNameFromAssignmentDeclaration(name, meaning) : undefined; symbol = resolveName(location || name, name.escapedText, meaning, ignoreErrors || symbolFromJSPrototype ? undefined : message, name, /*isUse*/ true); if (!symbol) { return symbolFromJSPrototype; @@ -2101,7 +2101,7 @@ namespace ts { else if (namespace === unknownSymbol) { return namespace; } - if (isInJavaScriptFile(name)) { + if (isInJSFile(name)) { if (namespace.valueDeclaration && isVariableDeclaration(namespace.valueDeclaration) && namespace.valueDeclaration.initializer && @@ -2137,16 +2137,16 @@ namespace ts { * name resolution won't work either. * 2. For property assignments like `{ x: function f () { } }`, try to resolve names in the scope of `f` too. */ - function resolveEntityNameFromJSSpecialAssignment(name: Identifier, meaning: SymbolFlags) { + function resolveEntityNameFromAssignmentDeclaration(name: Identifier, meaning: SymbolFlags) { if (isJSDocTypeReference(name.parent)) { - const secondaryLocation = getJSSpecialAssignmentLocation(name.parent); + const secondaryLocation = getAssignmentDeclarationLocation(name.parent); if (secondaryLocation) { return resolveName(secondaryLocation, name.escapedText, meaning, /*nameNotFoundMessage*/ undefined, name, /*isUse*/ true); } } } - function getJSSpecialAssignmentLocation(node: TypeReferenceNode): Node | undefined { + function getAssignmentDeclarationLocation(node: TypeReferenceNode): Node | undefined { const typeAlias = findAncestor(node, node => !(isJSDocNode(node) || node.flags & NodeFlags.JSDoc) ? "quit" : isJSDocTypeAlias(node)); if (typeAlias) { return; @@ -2154,7 +2154,7 @@ namespace ts { const host = getJSDocHost(node); if (isExpressionStatement(host) && isBinaryExpression(host.expression) && - getSpecialPropertyAssignmentKind(host.expression) === SpecialPropertyAssignmentKind.PrototypeProperty) { + getAssignmentDeclarationKind(host.expression) === AssignmentDeclarationKind.PrototypeProperty) { // X.prototype.m = /** @param {K} p */ function () { } <-- look for K on X's declaration const symbol = getSymbolOfNode(host.expression.left); if (symbol) { @@ -2163,7 +2163,7 @@ namespace ts { } if ((isObjectLiteralMethod(host) || isPropertyAssignment(host)) && isBinaryExpression(host.parent.parent) && - getSpecialPropertyAssignmentKind(host.parent.parent) === SpecialPropertyAssignmentKind.Prototype) { + getAssignmentDeclarationKind(host.parent.parent) === AssignmentDeclarationKind.Prototype) { // X.prototype = { /** @param {K} p */m() { } } <-- look for K on X's declaration const symbol = getSymbolOfNode(host.parent.parent.left); if (symbol) { @@ -2179,8 +2179,8 @@ namespace ts { function getDeclarationOfJSPrototypeContainer(symbol: Symbol) { const decl = symbol.parent!.valueDeclaration; - const initializer = isAssignmentDeclaration(decl) ? getAssignedJavascriptInitializer(decl) : - hasOnlyExpressionInitializer(decl) ? getDeclaredJavascriptInitializer(decl) : + const initializer = isAssignmentDeclaration(decl) ? getAssignedExpandoInitializer(decl) : + hasOnlyExpressionInitializer(decl) ? getDeclaredExpandoInitializer(decl) : undefined; return initializer || decl; } @@ -4732,7 +4732,7 @@ namespace ts { return addOptionality(declaredType, isOptional); } - if ((noImplicitAny || isInJavaScriptFile(declaration)) && + if ((noImplicitAny || isInJSFile(declaration)) && declaration.kind === SyntaxKind.VariableDeclaration && !isBindingPattern(declaration.name) && !(getCombinedModifierFlags(declaration) & ModifierFlags.Export) && !(declaration.flags & NodeFlags.Ambient)) { // If --noImplicitAny is on or the declaration is in a Javascript file, @@ -4764,7 +4764,7 @@ namespace ts { return getReturnTypeOfSignature(getterSignature); } } - if (isInJavaScriptFile(declaration)) { + if (isInJSFile(declaration)) { const typeTag = getJSDocType(func); if (typeTag && isFunctionTypeNode(typeTag)) { return getTypeAtPosition(getSignatureFromDeclaration(typeTag), func.parameters.indexOf(declaration)); @@ -4776,10 +4776,10 @@ namespace ts { return addOptionality(type, isOptional); } } - else if (isInJavaScriptFile(declaration)) { - const expandoType = getJSExpandoObjectType(declaration, getSymbolOfNode(declaration), getDeclaredJavascriptInitializer(declaration)); - if (expandoType) { - return expandoType; + else if (isInJSFile(declaration)) { + const containerObjectType = getJSContainerObjectType(declaration, getSymbolOfNode(declaration), getDeclaredExpandoInitializer(declaration)); + if (containerObjectType) { + return containerObjectType; } } @@ -4804,16 +4804,16 @@ namespace ts { return undefined; } - function getWidenedTypeFromJSPropertyAssignments(symbol: Symbol, resolvedSymbol?: Symbol) { - // function/class/{} assignments are fresh declarations, not property assignments, so only add prototype assignments - const specialDeclaration = getAssignedJavascriptInitializer(symbol.valueDeclaration); - if (specialDeclaration) { - const tag = getJSDocTypeTag(specialDeclaration); + function getWidenedTypeFromAssignmentDeclaration(symbol: Symbol, resolvedSymbol?: Symbol) { + // function/class/{} initializers are themselves containers, so they won't merge in the same way as other initializers + const container = getAssignedExpandoInitializer(symbol.valueDeclaration); + if (container) { + const tag = getJSDocTypeTag(container); if (tag && tag.typeExpression) { return getTypeFromTypeNode(tag.typeExpression); } - const expando = getJSExpandoObjectType(symbol.valueDeclaration, symbol, specialDeclaration); - return expando || getWidenedLiteralType(checkExpressionCached(specialDeclaration)); + const containerObjectType = getJSContainerObjectType(symbol.valueDeclaration, symbol, container); + return containerObjectType || getWidenedLiteralType(checkExpressionCached(container)); } let definedInConstructor = false; let definedInMethod = false; @@ -4827,8 +4827,8 @@ namespace ts { return errorType; } - const special = isPropertyAccessExpression(expression) ? getSpecialPropertyAccessKind(expression) : getSpecialPropertyAssignmentKind(expression); - if (special === SpecialPropertyAssignmentKind.ThisProperty) { + const kind = isPropertyAccessExpression(expression) ? getAssignmentDeclarationPropertyAccessKind(expression) : getAssignmentDeclarationKind(expression); + if (kind === AssignmentDeclarationKind.ThisProperty) { if (isDeclarationInConstructor(expression)) { definedInConstructor = true; } @@ -4836,9 +4836,9 @@ namespace ts { definedInMethod = true; } } - jsdocType = getJSDocTypeFromSpecialDeclarations(jsdocType, expression, symbol, declaration); + jsdocType = getJSDocTypeFromAssignmentDeclaration(jsdocType, expression, symbol, declaration); if (!jsdocType) { - (types || (types = [])).push(isBinaryExpression(expression) ? getInitializerTypeFromSpecialDeclarations(symbol, resolvedSymbol, expression, special) : neverType); + (types || (types = [])).push(isBinaryExpression(expression) ? getInitializerTypeFromAssignmentDeclaration(symbol, resolvedSymbol, expression, kind) : neverType); } } let type = jsdocType; @@ -4846,7 +4846,7 @@ namespace ts { let constructorTypes = definedInConstructor ? getConstructorDefinedThisAssignmentTypes(types!, symbol.declarations) : undefined; // use only the constructor types unless they were only assigned null | undefined (including widening variants) if (definedInMethod) { - const propType = getTypeOfSpecialPropertyOfBaseType(symbol); + const propType = getTypeOfAssignmentDeclarationPropertyOfBaseType(symbol); if (propType) { (constructorTypes || (constructorTypes = [])).push(propType); definedInConstructor = true; @@ -4865,8 +4865,8 @@ namespace ts { return widened; } - function getJSExpandoObjectType(decl: Node, symbol: Symbol, init: Expression | undefined): Type | undefined { - if (!isInJavaScriptFile(decl) || !init || !isObjectLiteralExpression(init) || init.properties.length) { + function getJSContainerObjectType(decl: Node, symbol: Symbol, init: Expression | undefined): Type | undefined { + if (!isInJSFile(decl) || !init || !isObjectLiteralExpression(init) || init.properties.length) { return undefined; } const exports = createSymbolTable(); @@ -4886,7 +4886,7 @@ namespace ts { return type; } - function getJSDocTypeFromSpecialDeclarations(declaredType: Type | undefined, expression: Expression, _symbol: Symbol, declaration: Declaration) { + function getJSDocTypeFromAssignmentDeclaration(declaredType: Type | undefined, expression: Expression, _symbol: Symbol, declaration: Declaration) { const typeNode = getJSDocType(expression.parent); if (typeNode) { const type = getWidenedType(getTypeFromTypeNode(typeNode)); @@ -4901,10 +4901,10 @@ namespace ts { } /** If we don't have an explicit JSDoc type, get the type from the initializer. */ - function getInitializerTypeFromSpecialDeclarations(symbol: Symbol, resolvedSymbol: Symbol | undefined, expression: BinaryExpression, special: SpecialPropertyAssignmentKind) { + function getInitializerTypeFromAssignmentDeclaration(symbol: Symbol, resolvedSymbol: Symbol | undefined, expression: BinaryExpression, kind: AssignmentDeclarationKind) { const type = resolvedSymbol ? getTypeOfSymbol(resolvedSymbol) : getWidenedLiteralType(checkExpressionCached(expression.right)); if (type.flags & TypeFlags.Object && - special === SpecialPropertyAssignmentKind.ModuleExports && + kind === AssignmentDeclarationKind.ModuleExports && symbol.escapedName === InternalSymbolName.ExportEquals) { const exportedType = resolveStructuredTypeMembers(type as ObjectType); const members = createSymbolTable(); @@ -4962,8 +4962,8 @@ namespace ts { } /** check for definition in base class if any declaration is in a class */ - function getTypeOfSpecialPropertyOfBaseType(specialProperty: Symbol) { - const parentDeclaration = forEach(specialProperty.declarations, d => { + function getTypeOfAssignmentDeclarationPropertyOfBaseType(property: Symbol) { + const parentDeclaration = forEach(property.declarations, d => { const parent = getThisContainer(d, /*includeArrowFunctions*/ false).parent; return isClassLike(parent) && parent; }); @@ -4971,7 +4971,7 @@ namespace ts { const classType = getDeclaredTypeOfSymbol(getSymbolOfNode(parentDeclaration)) as InterfaceType; const baseClassType = classType && getBaseTypes(classType)[0]; if (baseClassType) { - return getTypeOfPropertyOfType(baseClassType, specialProperty.escapedName); + return getTypeOfPropertyOfType(baseClassType, property.escapedName); } } } @@ -5154,9 +5154,9 @@ namespace ts { return errorType; } let type: Type | undefined; - if (isInJavaScriptFile(declaration) && + if (isInJSFile(declaration) && (isBinaryExpression(declaration) || isPropertyAccessExpression(declaration) && isBinaryExpression(declaration.parent))) { - type = getWidenedTypeFromJSPropertyAssignments(symbol); + type = getWidenedTypeFromAssignmentDeclaration(symbol); } else if (isJSDocPropertyLikeTag(declaration) || isPropertyAccessExpression(declaration) @@ -5170,7 +5170,7 @@ namespace ts { return getTypeOfFuncClassEnumModule(symbol); } type = isBinaryExpression(declaration.parent) ? - getWidenedTypeFromJSPropertyAssignments(symbol) : + getWidenedTypeFromAssignmentDeclaration(symbol) : tryGetTypeFromEffectiveTypeNode(declaration) || anyType; } else if (isPropertyAssignment(declaration)) { @@ -5239,7 +5239,7 @@ namespace ts { const getter = getDeclarationOfKind(symbol, SyntaxKind.GetAccessor); const setter = getDeclarationOfKind(symbol, SyntaxKind.SetAccessor); - if (getter && isInJavaScriptFile(getter)) { + if (getter && isInJSFile(getter)) { const jsDocType = getTypeForDeclarationFromJSDocComment(getter); if (jsDocType) { return jsDocType; @@ -5302,7 +5302,7 @@ namespace ts { let links = getSymbolLinks(symbol); const originalLinks = links; if (!links.type) { - const jsDeclaration = getDeclarationOfJSInitializer(symbol.valueDeclaration); + const jsDeclaration = getDeclarationOfExpando(symbol.valueDeclaration); if (jsDeclaration) { const jsSymbol = getSymbolOfNode(jsDeclaration); if (jsSymbol && (hasEntries(jsSymbol.exports) || hasEntries(jsSymbol.members))) { @@ -5331,7 +5331,7 @@ namespace ts { } else if (declaration.kind === SyntaxKind.BinaryExpression || declaration.kind === SyntaxKind.PropertyAccessExpression && declaration.parent.kind === SyntaxKind.BinaryExpression) { - return getWidenedTypeFromJSPropertyAssignments(symbol); + return getWidenedTypeFromAssignmentDeclaration(symbol); } else if (symbol.flags & SymbolFlags.ValueModule && declaration && isSourceFile(declaration) && declaration.commonJsModuleIndicator) { const resolvedModule = resolveExternalModuleSymbol(symbol); @@ -5340,7 +5340,7 @@ namespace ts { return errorType; } const exportEquals = getMergedSymbol(symbol.exports!.get(InternalSymbolName.ExportEquals)!); - const type = getWidenedTypeFromJSPropertyAssignments(exportEquals, exportEquals === resolvedModule ? undefined : resolvedModule); + const type = getWidenedTypeFromAssignmentDeclaration(exportEquals, exportEquals === resolvedModule ? undefined : resolvedModule); if (!popTypeResolution()) { return reportCircularityError(symbol); } @@ -5569,7 +5569,7 @@ namespace ts { function getConstructorsForTypeArguments(type: Type, typeArgumentNodes: ReadonlyArray | undefined, location: Node): ReadonlyArray { const typeArgCount = length(typeArgumentNodes); - const isJavascript = isInJavaScriptFile(location); + const isJavascript = isInJSFile(location); if (isJavascriptConstructorType(type) && !typeArgCount) { return getSignaturesOfType(type, SignatureKind.Call); } @@ -5580,7 +5580,7 @@ namespace ts { function getInstantiatedConstructorsForTypeArguments(type: Type, typeArgumentNodes: ReadonlyArray | undefined, location: Node): ReadonlyArray { const signatures = getConstructorsForTypeArguments(type, typeArgumentNodes, location); const typeArguments = map(typeArgumentNodes, getTypeFromTypeNode); - return sameMap(signatures, sig => some(sig.typeParameters) ? getSignatureInstantiation(sig, typeArguments, isInJavaScriptFile(location)) : sig); + return sameMap(signatures, sig => some(sig.typeParameters) ? getSignatureInstantiation(sig, typeArguments, isInJSFile(location)) : sig); } /** @@ -6456,7 +6456,7 @@ namespace ts { return [createSignature(undefined, classType.localTypeParameters, undefined, emptyArray, classType, /*resolvedTypePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false)]; // TODO: GH#18217 } const baseTypeNode = getBaseTypeNodeOfClass(classType)!; - const isJavaScript = isInJavaScriptFile(baseTypeNode); + const isJavaScript = isInJSFile(baseTypeNode); const typeArguments = typeArgumentsFromTypeReferenceNode(baseTypeNode); const typeArgCount = length(typeArguments); const result: Signature[] = []; @@ -7459,7 +7459,7 @@ namespace ts { } function isJSDocOptionalParameter(node: ParameterDeclaration) { - return isInJavaScriptFile(node) && ( + return isInJSFile(node) && ( // node.type should only be a JSDocOptionalType when node is a parameter of a JSDocFunctionType node.type && node.type.kind === SyntaxKind.JSDocOptionalType || getJSDocParameterTags(node).some(({ isBracketed, typeExpression }) => @@ -7578,7 +7578,7 @@ namespace ts { const iife = getImmediatelyInvokedFunctionExpression(declaration); const isJSConstructSignature = isJSDocConstructSignature(declaration); const isUntypedSignatureInJSFile = !iife && - isInJavaScriptFile(declaration) && + isInJSFile(declaration) && isValueSignatureDeclaration(declaration) && !hasJSDocParameterTags(declaration) && !getJSDocType(declaration); @@ -7634,7 +7634,7 @@ namespace ts { getDeclaredTypeOfClassOrInterface(getMergedSymbol((declaration.parent).symbol)) : undefined; const typeParameters = classType ? classType.localTypeParameters : getTypeParametersFromDeclaration(declaration); - const hasRestLikeParameter = hasRestParameter(declaration) || isInJavaScriptFile(declaration) && maybeAddJsSyntheticRestParameter(declaration, parameters); + const hasRestLikeParameter = hasRestParameter(declaration) || isInJSFile(declaration) && maybeAddJsSyntheticRestParameter(declaration, parameters); links.resolvedSignature = createSignature(declaration, typeParameters, thisParameter, parameters, /*resolvedReturnType*/ undefined, /*resolvedTypePredicate*/ undefined, minArgumentCount, hasRestLikeParameter, hasLiteralTypes); @@ -7668,7 +7668,7 @@ namespace ts { } function getSignatureOfTypeTag(node: SignatureDeclaration | JSDocSignature) { - const typeTag = isInJavaScriptFile(node) ? getJSDocTypeTag(node) : undefined; + const typeTag = isInJSFile(node) ? getJSDocTypeTag(node) : undefined; const signature = typeTag && typeTag.typeExpression && getSingleCallSignature(getTypeFromTypeNode(typeTag.typeExpression)); return signature && getErasedSignature(signature); } @@ -7763,7 +7763,7 @@ namespace ts { else { const type = signature.declaration && getEffectiveReturnTypeNode(signature.declaration); let jsdocPredicate: TypePredicate | undefined; - if (!type && isInJavaScriptFile(signature.declaration)) { + if (!type && isInJSFile(signature.declaration)) { const jsdocSignature = getSignatureOfTypeTag(signature.declaration!); if (jsdocSignature && signature !== jsdocSignature) { jsdocPredicate = getTypePredicateOfSignature(jsdocSignature); @@ -7847,7 +7847,7 @@ namespace ts { return getTypeFromTypeNode(typeNode); } if (declaration.kind === SyntaxKind.GetAccessor && !hasNonBindableDynamicName(declaration)) { - const jsDocType = isInJavaScriptFile(declaration) && getTypeForDeclarationFromJSDocComment(declaration); + const jsDocType = isInJSFile(declaration) && getTypeForDeclarationFromJSDocComment(declaration); if (jsDocType) { return jsDocType; } @@ -7924,7 +7924,7 @@ namespace ts { return getSignatureInstantiation( signature, map(signature.typeParameters, tp => tp.target && !getConstraintOfTypeParameter(tp.target) ? tp.target : tp), - isInJavaScriptFile(signature.declaration)); + isInJSFile(signature.declaration)); } function getBaseSignature(signature: Signature) { @@ -8134,7 +8134,7 @@ namespace ts { if (typeParameters) { const numTypeArguments = length(node.typeArguments); const minTypeArgumentCount = getMinTypeArgumentCount(typeParameters); - const isJs = isInJavaScriptFile(node); + const isJs = isInJSFile(node); const isJsImplicitAny = !noImplicitAny && isJs; if (!isJsImplicitAny && (numTypeArguments < minTypeArgumentCount || numTypeArguments > typeParameters.length)) { const missingAugmentsTag = isJs && node.parent.kind !== SyntaxKind.JSDocAugmentsTag; @@ -8168,7 +8168,7 @@ namespace ts { const id = getTypeListId(typeArguments); let instantiation = links.instantiations!.get(id); if (!instantiation) { - links.instantiations!.set(id, instantiation = instantiateType(type, createTypeMapper(typeParameters, fillMissingTypeArguments(typeArguments, typeParameters, getMinTypeArgumentCount(typeParameters), isInJavaScriptFile(symbol.valueDeclaration))))); + links.instantiations!.set(id, instantiation = instantiateType(type, createTypeMapper(typeParameters, fillMissingTypeArguments(typeArguments, typeParameters, getMinTypeArgumentCount(typeParameters), isInJSFile(symbol.valueDeclaration))))); } return instantiation; } @@ -10163,7 +10163,7 @@ namespace ts { // aren't the right hand side of a generic type alias declaration we optimize by reducing the // set of type parameters to those that are possibly referenced in the literal. let declaration = symbol.declarations[0]; - if (isInJavaScriptFile(declaration)) { + if (isInJSFile(declaration)) { const paramTag = findAncestor(declaration, isJSDocParameterTag); if (paramTag) { const paramSymbol = getParameterSymbolFromJSDoc(paramTag); @@ -10484,7 +10484,7 @@ namespace ts { } function isContextSensitiveFunctionOrObjectLiteralMethod(func: Node): func is FunctionExpression | ArrowFunction | MethodDeclaration { - return (isInJavaScriptFile(func) && isFunctionDeclaration(func) || isFunctionExpressionOrArrowFunction(func) || isObjectLiteralMethod(func)) && + return (isInJSFile(func) && isFunctionDeclaration(func) || isFunctionExpressionOrArrowFunction(func) || isObjectLiteralMethod(func)) && isContextSensitiveFunctionLikeDeclaration(func); } @@ -15516,7 +15516,7 @@ namespace ts { if (assignmentKind) { if (!(localOrExportSymbol.flags & SymbolFlags.Variable) && - !(isInJavaScriptFile(node) && localOrExportSymbol.flags & SymbolFlags.ValueModule)) { + !(isInJSFile(node) && localOrExportSymbol.flags & SymbolFlags.ValueModule)) { error(node, Diagnostics.Cannot_assign_to_0_because_it_is_not_a_variable, symbolToString(symbol)); return errorType; } @@ -15817,7 +15817,7 @@ namespace ts { // Check if it's the RHS of a x.prototype.y = function [name]() { .... } if (container.kind === SyntaxKind.FunctionExpression && container.parent.kind === SyntaxKind.BinaryExpression && - getSpecialPropertyAssignmentKind(container.parent as BinaryExpression) === SpecialPropertyAssignmentKind.PrototypeProperty) { + getAssignmentDeclarationKind(container.parent as BinaryExpression) === AssignmentDeclarationKind.PrototypeProperty) { // Get the 'x' of 'x.prototype.y = f' (here, 'f' is 'container') const className = (((container.parent as BinaryExpression) // x.prototype.y = f .left as PropertyAccessExpression) // x.prototype.y @@ -15852,7 +15852,7 @@ namespace ts { return getFlowTypeOfReference(node, type); } - if (isInJavaScriptFile(node)) { + if (isInJSFile(node)) { const type = getTypeForThisExpressionFromJSDoc(container); if (type && type !== errorType) { return getFlowTypeOfReference(node, type); @@ -16109,7 +16109,7 @@ namespace ts { } } } - const inJs = isInJavaScriptFile(func); + const inJs = isInJSFile(func); if (noImplicitThis || inJs) { const containingLiteral = getContainingObjectLiteral(func); if (containingLiteral) { @@ -16332,7 +16332,7 @@ namespace ts { // expression has no contextual type, the right operand is contextually typed by the type of the left operand, // except for the special case of Javascript declarations of the form `namespace.prop = namespace.prop || {}` const type = getContextualType(binaryExpression); - return !type && node === right && !isDefaultedJavascriptInitializer(binaryExpression) ? + return !type && node === right && !isDefaultedExpandoInitializer(binaryExpression) ? getTypeOfExpression(left) : type; case SyntaxKind.AmpersandAmpersandToken: case SyntaxKind.CommaToken: @@ -16343,16 +16343,16 @@ namespace ts { } // In an assignment expression, the right operand is contextually typed by the type of the left operand. - // Don't do this for special property assignments unless there is a type tag on the assignment, to avoid circularity from checking the right operand. + // Don't do this for assignment declarations unless there is a type tag on the assignment, to avoid circularity from checking the right operand. function getIsContextSensitiveAssignmentOrContextType(binaryExpression: BinaryExpression): boolean | Type { - const kind = getSpecialPropertyAssignmentKind(binaryExpression); + const kind = getAssignmentDeclarationKind(binaryExpression); switch (kind) { - case SpecialPropertyAssignmentKind.None: + case AssignmentDeclarationKind.None: return true; - case SpecialPropertyAssignmentKind.Property: - case SpecialPropertyAssignmentKind.ExportsProperty: - case SpecialPropertyAssignmentKind.Prototype: - case SpecialPropertyAssignmentKind.PrototypeProperty: + case AssignmentDeclarationKind.Property: + case AssignmentDeclarationKind.ExportsProperty: + case AssignmentDeclarationKind.Prototype: + case AssignmentDeclarationKind.PrototypeProperty: // If `binaryExpression.left` was assigned a symbol, then this is a new declaration; otherwise it is an assignment to an existing declaration. // See `bindStaticPropertyAssignment` in `binder.ts`. if (!binaryExpression.left.symbol) { @@ -16380,10 +16380,10 @@ namespace ts { return false; } } - return !isInJavaScriptFile(decl); + return !isInJSFile(decl); } - case SpecialPropertyAssignmentKind.ModuleExports: - case SpecialPropertyAssignmentKind.ThisProperty: + case AssignmentDeclarationKind.ModuleExports: + case AssignmentDeclarationKind.ThisProperty: if (!binaryExpression.symbol) return true; if (binaryExpression.symbol.valueDeclaration) { const annotated = getEffectiveTypeAnnotationNode(binaryExpression.symbol.valueDeclaration); @@ -16394,7 +16394,7 @@ namespace ts { } } } - if (kind === SpecialPropertyAssignmentKind.ModuleExports) return false; + if (kind === AssignmentDeclarationKind.ModuleExports) return false; const thisAccess = binaryExpression.left as PropertyAccessExpression; if (!isObjectLiteralMethod(getThisContainer(thisAccess.expression, /*includeArrowFunctions*/ false))) { return false; @@ -16631,7 +16631,7 @@ namespace ts { return getContextualTypeForSubstitutionExpression(parent.parent, node); case SyntaxKind.ParenthesizedExpression: { // Like in `checkParenthesizedExpression`, an `/** @type {xyz} */` comment before a parenthesized expression acts as a type cast. - const tag = isInJavaScriptFile(parent) ? getJSDocTypeTag(parent) : undefined; + const tag = isInJSFile(parent) ? getJSDocTypeTag(parent) : undefined; return tag ? getTypeFromTypeNode(tag.typeExpression!.type) : getContextualType(parent); } case SyntaxKind.JsxExpression: @@ -16661,7 +16661,7 @@ namespace ts { return anyType; } - const isJs = isInJavaScriptFile(node); + const isJs = isInJSFile(node); return mapType(valueType, t => getJsxSignaturesParameterTypes(t, isJs, node)); } @@ -16740,11 +16740,11 @@ namespace ts { if (managedSym) { const declaredManagedType = getDeclaredTypeOfSymbol(managedSym); if (length((declaredManagedType as GenericType).typeParameters) >= 2) { - const args = fillMissingTypeArguments([checkExpressionCached(context.tagName), attributesType], (declaredManagedType as GenericType).typeParameters, 2, isInJavaScriptFile(context)); + const args = fillMissingTypeArguments([checkExpressionCached(context.tagName), attributesType], (declaredManagedType as GenericType).typeParameters, 2, isInJSFile(context)); return createTypeReference((declaredManagedType as GenericType), args); } else if (length(declaredManagedType.aliasTypeArguments) >= 2) { - const args = fillMissingTypeArguments([checkExpressionCached(context.tagName), attributesType], declaredManagedType.aliasTypeArguments!, 2, isInJavaScriptFile(context)); + const args = fillMissingTypeArguments([checkExpressionCached(context.tagName), attributesType], declaredManagedType.aliasTypeArguments!, 2, isInJSFile(context)); return getTypeAliasInstantiation(declaredManagedType.aliasSymbol!, args); } } @@ -17077,9 +17077,9 @@ namespace ts { const contextualType = getApparentTypeOfContextualType(node); const contextualTypeHasPattern = contextualType && contextualType.pattern && (contextualType.pattern.kind === SyntaxKind.ObjectBindingPattern || contextualType.pattern.kind === SyntaxKind.ObjectLiteralExpression); - const isInJSFile = isInJavaScriptFile(node) && !isInJsonFile(node); + const isInJavascript = isInJSFile(node) && !isInJsonFile(node); const enumTag = getJSDocEnumTag(node); - const isJSObjectLiteral = !contextualType && isInJSFile && !enumTag; + const isJSObjectLiteral = !contextualType && isInJavascript && !enumTag; let typeFlags: TypeFlags = 0; let patternWithComputedProperties = false; let hasComputedStringProperty = false; @@ -17098,7 +17098,7 @@ namespace ts { let type = memberDecl.kind === SyntaxKind.PropertyAssignment ? checkPropertyAssignment(memberDecl, checkMode) : memberDecl.kind === SyntaxKind.ShorthandPropertyAssignment ? checkExpressionForMutableLocation(memberDecl.name, checkMode) : checkObjectLiteralMethod(memberDecl, checkMode); - if (isInJSFile) { + if (isInJavascript) { const jsDocType = getTypeForDeclarationFromJSDocComment(memberDecl); if (jsDocType) { checkTypeAssignableTo(type, jsDocType, memberDecl); @@ -17505,7 +17505,7 @@ namespace ts { let hasTypeArgumentError: boolean = !!node.typeArguments; for (const signature of signatures) { if (signature.typeParameters) { - const isJavascript = isInJavaScriptFile(node); + const isJavascript = isInJSFile(node); const typeArgumentInstantiated = getJsxSignatureTypeArgumentInstantiation(signature, node, isJavascript, /*reportErrors*/ false); if (typeArgumentInstantiated) { hasTypeArgumentError = false; @@ -17849,7 +17849,7 @@ namespace ts { checkTypeRelatedTo(elemInstanceType, elementClassType, assignableRelation, openingLikeElement, Diagnostics.JSX_element_type_0_is_not_a_constructor_function_for_JSX_elements); } - const isJs = isInJavaScriptFile(openingLikeElement); + const isJs = isInJSFile(openingLikeElement); return getUnionType(instantiatedSignatures!.map(sig => getJsxPropsTypeFromClassType(sig, isJs, openingLikeElement, /*reportErrors*/ true))); } @@ -18107,10 +18107,10 @@ namespace ts { if (symbol.flags & SymbolFlags.Method || getCheckFlags(symbol) & CheckFlags.SyntheticMethod) { return true; } - if (isInJavaScriptFile(symbol.valueDeclaration)) { + if (isInJSFile(symbol.valueDeclaration)) { const parent = symbol.valueDeclaration.parent; return parent && isBinaryExpression(parent) && - getSpecialPropertyAssignmentKind(parent) === SpecialPropertyAssignmentKind.PrototypeProperty; + getAssignmentDeclarationKind(parent) === AssignmentDeclarationKind.PrototypeProperty; } } @@ -18593,7 +18593,7 @@ namespace ts { const prop = getPropertyOfType(type, propertyName); return prop ? checkPropertyAccessibility(node, isSuper, type, prop) // In js files properties of unions are allowed in completion - : isInJavaScriptFile(node) && (type.flags & TypeFlags.Union) !== 0 && (type).types.some(elementType => isValidPropertyAccessWithType(node, isSuper, propertyName, elementType)); + : isInJSFile(node) && (type.flags & TypeFlags.Union) !== 0 && (type).types.some(elementType => isValidPropertyAccessWithType(node, isSuper, propertyName, elementType)); } /** @@ -18908,7 +18908,7 @@ namespace ts { if (!contextualMapper) { inferTypes(context.inferences, getReturnTypeOfSignature(contextualSignature), getReturnTypeOfSignature(signature), InferencePriority.ReturnType); } - return getSignatureInstantiation(signature, getInferredTypes(context), isInJavaScriptFile(contextualSignature.declaration)); + return getSignatureInstantiation(signature, getInferredTypes(context), isInJSFile(contextualSignature.declaration)); } function inferJsxTypeArguments(signature: Signature, node: JsxOpeningLikeElement, context: InferenceContext): Type[] { @@ -19029,7 +19029,7 @@ namespace ts { } function checkTypeArguments(signature: Signature, typeArgumentNodes: ReadonlyArray, reportErrors: boolean, headMessage?: DiagnosticMessage): Type[] | undefined { - const isJavascript = isInJavaScriptFile(signature.declaration); + const isJavascript = isInJSFile(signature.declaration); const typeParameters = signature.typeParameters!; const typeArgumentTypes = fillMissingTypeArguments(map(typeArgumentNodes, getTypeFromTypeNode), typeParameters, getMinTypeArgumentCount(typeParameters), isJavascript); let mapper: TypeMapper | undefined; @@ -19488,10 +19488,10 @@ namespace ts { } } else { - inferenceContext = createInferenceContext(candidate.typeParameters, candidate, /*flags*/ isInJavaScriptFile(node) ? InferenceFlags.AnyDefault : InferenceFlags.None); + inferenceContext = createInferenceContext(candidate.typeParameters, candidate, /*flags*/ isInJSFile(node) ? InferenceFlags.AnyDefault : InferenceFlags.None); typeArgumentTypes = inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext); } - checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, isInJavaScriptFile(candidate.declaration)); + checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, isInJSFile(candidate.declaration)); // If the original signature has a generic rest type, instantiation may produce a // signature with different arity and we need to perform another arity check. if (getNonArrayRestType(candidate) && !hasCorrectArity(node, args, checkCandidate, signatureHelpTrailingComma)) { @@ -19513,7 +19513,7 @@ namespace ts { excludeArgument = undefined; if (inferenceContext) { const typeArgumentTypes = inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext); - checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, isInJavaScriptFile(candidate.declaration)); + checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, isInJSFile(candidate.declaration)); } if (!checkApplicableSignature(node, args, checkCandidate, relation, excludeArgument, /*reportErrors*/ false)) { candidateForArgumentError = checkCandidate; @@ -19623,7 +19623,7 @@ namespace ts { const typeArgumentNodes: ReadonlyArray | undefined = callLikeExpressionMayHaveTypeArguments(node) ? node.typeArguments : undefined; const instantiated = typeArgumentNodes - ? createSignatureInstantiation(candidate, getTypeArgumentsFromNodes(typeArgumentNodes, typeParameters, isInJavaScriptFile(node))) + ? createSignatureInstantiation(candidate, getTypeArgumentsFromNodes(typeArgumentNodes, typeParameters, isInJSFile(node))) : inferSignatureInstantiationForOverloadFailure(node, typeParameters, candidate, args); candidates[bestIndex] = instantiated; return instantiated; @@ -19641,7 +19641,7 @@ namespace ts { } function inferSignatureInstantiationForOverloadFailure(node: CallLikeExpression, typeParameters: ReadonlyArray, candidate: Signature, args: ReadonlyArray): Signature { - const inferenceContext = createInferenceContext(typeParameters, candidate, /*flags*/ isInJavaScriptFile(node) ? InferenceFlags.AnyDefault : InferenceFlags.None); + const inferenceContext = createInferenceContext(typeParameters, candidate, /*flags*/ isInJSFile(node) ? InferenceFlags.AnyDefault : InferenceFlags.None); const typeArgumentTypes = inferTypeArguments(node, candidate, args, getExcludeArgument(args), inferenceContext); return createSignatureInstantiation(candidate, typeArgumentTypes); } @@ -19741,7 +19741,7 @@ namespace ts { return resolveErrorCall(node); } // If the function is explicitly marked with `@class`, then it must be constructed. - if (callSignatures.some(sig => isInJavaScriptFile(sig.declaration) && !!getJSDocClassTag(sig.declaration!))) { + if (callSignatures.some(sig => isInJSFile(sig.declaration) && !!getJSDocClassTag(sig.declaration!))) { error(node, Diagnostics.Value_of_type_0_is_not_callable_Did_you_mean_to_include_new, typeToString(funcType)); return resolveErrorCall(node); } @@ -20107,7 +20107,7 @@ namespace ts { * file. */ function isJavascriptConstructor(node: Declaration | undefined): boolean { - if (node && isInJavaScriptFile(node)) { + if (node && isInJSFile(node)) { // If the node has a @class tag, treat it like a constructor. if (getJSDocClassTag(node)) return true; @@ -20232,7 +20232,7 @@ namespace ts { } // In JavaScript files, calls to any identifier 'require' are treated as external module imports - if (isInJavaScriptFile(node) && isCommonJsRequire(node)) { + if (isInJSFile(node) && isCommonJsRequire(node)) { return resolveExternalModuleTypeByLiteral(node.arguments![0] as StringLiteral); } @@ -20243,8 +20243,8 @@ namespace ts { return getESSymbolLikeTypeForNode(walkUpParenthesizedExpressions(node.parent)); } let jsAssignmentType: Type | undefined; - if (isInJavaScriptFile(node)) { - const decl = getDeclarationOfJSInitializer(node); + if (isInJSFile(node)) { + const decl = getDeclarationOfExpando(node); if (decl) { const jsSymbol = getSymbolOfNode(decl); if (jsSymbol && hasEntries(jsSymbol.exports)) { @@ -21556,7 +21556,7 @@ namespace ts { } function checkBinaryExpression(node: BinaryExpression, checkMode?: CheckMode) { - if (isInJavaScriptFile(node) && getAssignedJavascriptInitializer(node)) { + if (isInJSFile(node) && getAssignedExpandoInitializer(node)) { return checkExpression(node.right, checkMode); } return checkBinaryLikeExpression(node.left, node.operatorToken, node.right, checkMode, node); @@ -21704,9 +21704,9 @@ namespace ts { getUnionType([removeDefinitelyFalsyTypes(leftType), rightType], UnionReduction.Subtype) : leftType; case SyntaxKind.EqualsToken: - const special = isBinaryExpression(left.parent) ? getSpecialPropertyAssignmentKind(left.parent) : SpecialPropertyAssignmentKind.None; - checkSpecialAssignment(special, right); - if (isJSSpecialPropertyAssignment(special)) { + const declKind = isBinaryExpression(left.parent) ? getAssignmentDeclarationKind(left.parent) : AssignmentDeclarationKind.None; + checkAssignmentDeclaration(declKind, right); + if (isAssignmentDeclaration(declKind)) { return leftType; } else { @@ -21723,8 +21723,8 @@ namespace ts { return Debug.fail(); } - function checkSpecialAssignment(special: SpecialPropertyAssignmentKind, right: Expression) { - if (special === SpecialPropertyAssignmentKind.ModuleExports) { + function checkAssignmentDeclaration(kind: AssignmentDeclarationKind, right: Expression) { + if (kind === AssignmentDeclarationKind.ModuleExports) { const rightType = checkExpression(right, checkMode); for (const prop of getPropertiesOfObjectType(rightType)) { const propType = getTypeOfSymbol(prop); @@ -21791,17 +21791,17 @@ namespace ts { } } - function isJSSpecialPropertyAssignment(special: SpecialPropertyAssignmentKind) { - switch (special) { - case SpecialPropertyAssignmentKind.ModuleExports: + function isAssignmentDeclaration(kind: AssignmentDeclarationKind) { + switch (kind) { + case AssignmentDeclarationKind.ModuleExports: return true; - case SpecialPropertyAssignmentKind.ExportsProperty: - case SpecialPropertyAssignmentKind.Property: - case SpecialPropertyAssignmentKind.Prototype: - case SpecialPropertyAssignmentKind.PrototypeProperty: - case SpecialPropertyAssignmentKind.ThisProperty: + case AssignmentDeclarationKind.ExportsProperty: + case AssignmentDeclarationKind.Property: + case AssignmentDeclarationKind.Prototype: + case AssignmentDeclarationKind.PrototypeProperty: + case AssignmentDeclarationKind.ThisProperty: const symbol = getSymbolOfNode(left); - const init = getAssignedJavascriptInitializer(right); + const init = getAssignedExpandoInitializer(right); return init && isObjectLiteralExpression(init) && symbol && hasEntries(symbol.exports); default: @@ -21977,7 +21977,7 @@ namespace ts { const widened = getCombinedNodeFlags(declaration) & NodeFlags.Const || isDeclarationReadonly(declaration) || isTypeAssertion(initializer) ? type : getWidenedLiteralType(type); - if (isInJavaScriptFile(declaration)) { + if (isInJSFile(declaration)) { if (widened.flags & TypeFlags.Nullable) { if (noImplicitAny) { reportImplicitAnyError(declaration, anyType); @@ -22153,7 +22153,7 @@ namespace ts { } function checkParenthesizedExpression(node: ParenthesizedExpression, checkMode?: CheckMode): Type { - const tag = isInJavaScriptFile(node) ? getJSDocTypeTag(node) : undefined; + const tag = isInJSFile(node) ? getJSDocTypeTag(node) : undefined; if (tag) { return checkAssertionWorker(tag, tag.typeExpression!.type, node.expression, checkMode); } @@ -22830,7 +22830,7 @@ namespace ts { function getEffectiveTypeArguments(node: TypeReferenceNode | ExpressionWithTypeArguments, typeParameters: ReadonlyArray): Type[] { return fillMissingTypeArguments(map(node.typeArguments!, getTypeFromTypeNode), typeParameters, - getMinTypeArgumentCount(typeParameters), isInJavaScriptFile(node)); + getMinTypeArgumentCount(typeParameters), isInJSFile(node)); } function checkTypeArgumentConstraints(node: TypeReferenceNode | ExpressionWithTypeArguments, typeParameters: ReadonlyArray): boolean { @@ -22868,7 +22868,7 @@ namespace ts { function checkTypeReferenceNode(node: TypeReferenceNode | ExpressionWithTypeArguments) { checkGrammarTypeArguments(node, node.typeArguments); - if (node.kind === SyntaxKind.TypeReference && node.typeName.jsdocDotPos !== undefined && !isInJavaScriptFile(node) && !isInJSDoc(node)) { + if (node.kind === SyntaxKind.TypeReference && node.typeName.jsdocDotPos !== undefined && !isInJSFile(node) && !isInJSDoc(node)) { grammarErrorAtPos(node, node.typeName.jsdocDotPos, 1, Diagnostics.JSDoc_types_can_only_be_used_inside_documentation_comments); } const type = getTypeFromTypeReference(node); @@ -24016,7 +24016,7 @@ namespace ts { } // A js function declaration can have a @type tag instead of a return type node, but that type must have a call signature - if (isInJavaScriptFile(node)) { + if (isInJSFile(node)) { const typeTag = getJSDocTypeTag(node); if (typeTag && typeTag.typeExpression && !getContextualCallSignature(getTypeFromTypeNode(typeTag.typeExpression), node)) { error(typeTag, Diagnostics.The_type_of_a_function_declaration_must_match_the_function_s_signature); @@ -24673,7 +24673,7 @@ namespace ts { // Don't validate for-in initializer as it is already an error const initializer = getEffectiveInitializer(node); if (initializer) { - const isJSObjectLiteralInitializer = isInJavaScriptFile(node) && + const isJSObjectLiteralInitializer = isInJSFile(node) && isObjectLiteralExpression(initializer) && (initializer.properties.length === 0 || isPrototypeAccess(node.name)) && hasEntries(symbol.exports); @@ -24690,7 +24690,7 @@ namespace ts { if (type !== errorType && declarationType !== errorType && !isTypeIdenticalTo(type, declarationType) && - !(symbol.flags & SymbolFlags.JSContainer)) { + !(symbol.flags & SymbolFlags.Assignment)) { errorNextVariableOrPropertyDeclarationMustHaveSameType(type, node, declarationType); } if (node.initializer) { @@ -26771,7 +26771,7 @@ namespace ts { const exportEqualsSymbol = moduleSymbol.exports!.get("export=" as __String); if (exportEqualsSymbol && hasExportedMembers(moduleSymbol)) { const declaration = getDeclarationOfAliasSymbol(exportEqualsSymbol) || exportEqualsSymbol.valueDeclaration; - if (!isTopLevelInExternalModuleAugmentation(declaration) && !isInJavaScriptFile(declaration)) { + if (!isTopLevelInExternalModuleAugmentation(declaration) && !isInJSFile(declaration)) { error(declaration, Diagnostics.An_export_assignment_cannot_be_used_in_a_module_with_other_exported_elements); } } @@ -26821,7 +26821,7 @@ namespace ts { return; } - if (isInJavaScriptFile(node)) { + if (isInJSFile(node)) { forEach((node as JSDocContainer).jsDoc, ({ tags }) => forEach(tags, checkSourceElement)); } @@ -26988,7 +26988,7 @@ namespace ts { } function checkJSDocTypeIsInJsFile(node: Node): void { - if (!isInJavaScriptFile(node)) { + if (!isInJSFile(node)) { grammarErrorOnNode(node, Diagnostics.JSDoc_types_can_only_be_used_inside_documentation_comments); } } @@ -27410,14 +27410,14 @@ namespace ts { } function getSpecialPropertyAssignmentSymbolFromEntityName(entityName: EntityName | PropertyAccessExpression) { - const specialPropertyAssignmentKind = getSpecialPropertyAssignmentKind(entityName.parent.parent as BinaryExpression); + const specialPropertyAssignmentKind = getAssignmentDeclarationKind(entityName.parent.parent as BinaryExpression); switch (specialPropertyAssignmentKind) { - case SpecialPropertyAssignmentKind.ExportsProperty: - case SpecialPropertyAssignmentKind.PrototypeProperty: + case AssignmentDeclarationKind.ExportsProperty: + case AssignmentDeclarationKind.PrototypeProperty: return getSymbolOfNode(entityName.parent); - case SpecialPropertyAssignmentKind.ThisProperty: - case SpecialPropertyAssignmentKind.ModuleExports: - case SpecialPropertyAssignmentKind.Property: + case AssignmentDeclarationKind.ThisProperty: + case AssignmentDeclarationKind.ModuleExports: + case AssignmentDeclarationKind.Property: return getSymbolOfNode(entityName.parent.parent); } } @@ -27439,7 +27439,7 @@ namespace ts { return getSymbolOfNode(entityName.parent); } - if (isInJavaScriptFile(entityName) && + if (isInJSFile(entityName) && entityName.parent.kind === SyntaxKind.PropertyAccessExpression && entityName.parent === (entityName.parent.parent as BinaryExpression).left) { // Check if this is a special property assignment @@ -27504,7 +27504,7 @@ namespace ts { } if (entityName.parent.kind === SyntaxKind.TypeParameter && entityName.parent.parent.kind === SyntaxKind.JSDocTemplateTag) { - Debug.assert(!isInJavaScriptFile(entityName)); // Otherwise `isDeclarationName` would have been true. + Debug.assert(!isInJSFile(entityName)); // Otherwise `isDeclarationName` would have been true. const typeParameter = getTypeParameterFromJsDoc(entityName.parent as TypeParameterDeclaration & { parent: JSDocTemplateTag }); return typeParameter && typeParameter.symbol; } @@ -27631,7 +27631,7 @@ namespace ts { // 4). type A = import("./f/*gotToDefinitionHere*/oo") if ((isExternalModuleImportEqualsDeclaration(node.parent.parent) && getExternalModuleImportEqualsDeclarationExpression(node.parent.parent) === node) || ((node.parent.kind === SyntaxKind.ImportDeclaration || node.parent.kind === SyntaxKind.ExportDeclaration) && (node.parent).moduleSpecifier === node) || - ((isInJavaScriptFile(node) && isRequireCall(node.parent, /*checkArgumentIsStringLiteralLike*/ false)) || isImportCall(node.parent)) || + ((isInJSFile(node) && isRequireCall(node.parent, /*checkArgumentIsStringLiteralLike*/ false)) || isImportCall(node.parent)) || (isLiteralTypeNode(node.parent) && isLiteralImportTypeNode(node.parent.parent) && node.parent.parent.argument === node.parent) ) { return resolveExternalModuleName(node, node); @@ -28145,7 +28145,7 @@ namespace ts { hasModifier(parameter, ModifierFlags.ParameterPropertyModifier); } - function isJSContainerFunctionDeclaration(node: Declaration): boolean { + function isExpandoFunctionDeclaration(node: Declaration): boolean { const declaration = getParseTreeNode(node, isFunctionDeclaration); if (!declaration) { return false; @@ -28407,7 +28407,7 @@ namespace ts { isImplementationOfOverload, isRequiredInitializedParameter, isOptionalUninitializedParameterProperty, - isJSContainerFunctionDeclaration, + isExpandoFunctionDeclaration, getPropertiesOfContainerFunction, createTypeOfDeclaration, createReturnTypeOfSignatureDeclaration, @@ -29910,7 +29910,7 @@ namespace ts { } function checkGrammarConstructorTypeParameters(node: ConstructorDeclaration) { - const jsdocTypeParameters = isInJavaScriptFile(node) && getJSDocTypeParameterDeclarations(node); + const jsdocTypeParameters = isInJSFile(node) && getJSDocTypeParameterDeclarations(node); if (node.typeParameters || jsdocTypeParameters && jsdocTypeParameters.length) { const { pos, end } = node.typeParameters || jsdocTypeParameters && jsdocTypeParameters[0] || node; return grammarErrorAtPos(node, pos, end - pos, Diagnostics.Type_parameters_cannot_appear_on_a_constructor_declaration); diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 55e690f8ae8..2d103b8af8f 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -52,7 +52,7 @@ namespace ts { const jsFilePath = getOwnEmitOutputFilePath(sourceFile.fileName, host, getOutputExtension(sourceFile, options)); const sourceMapFilePath = isJsonSourceFile(sourceFile) ? undefined : getSourceMapFilePath(jsFilePath, options); // For legacy reasons (ie, we have baselines capturing the behavior), js files don't report a .d.ts output path - this would only matter if `declaration` and `allowJs` were both on, which is currently an error - const isJs = isSourceFileJavaScript(sourceFile); + const isJs = isSourceFileJS(sourceFile); const declarationFilePath = ((forceDtsPaths || getEmitDeclarations(options)) && !isJs) ? getDeclarationEmitOutputFilePath(sourceFile.fileName, host) : undefined; const declarationMapPath = getAreDeclarationMapsEnabled(options) ? declarationFilePath + ".map" : undefined; return { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, bundleInfoPath: undefined }; @@ -80,7 +80,7 @@ namespace ts { } if (options.jsx === JsxEmit.Preserve) { - if (isSourceFileJavaScript(sourceFile)) { + if (isSourceFileJS(sourceFile)) { if (fileExtensionIs(sourceFile.fileName, Extension.Jsx)) { return Extension.Jsx; } @@ -187,12 +187,12 @@ namespace ts { } function emitDeclarationFileOrBundle(sourceFileOrBundle: SourceFile | Bundle, declarationFilePath: string | undefined, declarationMapPath: string | undefined) { - if (!(declarationFilePath && !isInJavaScriptFile(sourceFileOrBundle))) { + if (!(declarationFilePath && !isInJSFile(sourceFileOrBundle))) { return; } const sourceFiles = isSourceFile(sourceFileOrBundle) ? [sourceFileOrBundle] : sourceFileOrBundle.sourceFiles; // Setup and perform the transformation to retrieve declarations from the input files - const nonJsFiles = filter(sourceFiles, isSourceFileNotJavaScript); + const nonJsFiles = filter(sourceFiles, isSourceFileNotJavascript); const inputListOrBundle = (compilerOptions.outFile || compilerOptions.out) ? [createBundle(nonJsFiles, !isSourceFile(sourceFileOrBundle) ? sourceFileOrBundle.prepends : undefined)] : nonJsFiles; if (emitOnlyDtsFiles && !getEmitDeclarations(compilerOptions)) { // Checker wont collect the linked aliases since thats only done when declaration is enabled. diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index bae4dbfa430..aedd1d4c3dc 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -778,7 +778,7 @@ namespace ts { * Throws an error if the module can't be resolved. */ /* @internal */ - export function resolveJavaScriptModule(moduleName: string, initialDir: string, host: ModuleResolutionHost): string { + export function resolveJavascriptModule(moduleName: string, initialDir: string, host: ModuleResolutionHost): string { const { resolvedModule, failedLookupLocations } = nodeModuleNameResolverWorker(moduleName, initialDir, { moduleResolution: ModuleResolutionKind.NodeJs, allowJs: true }, host, /*cache*/ undefined, /*jsOnly*/ true); if (!resolvedModule) { @@ -958,7 +958,7 @@ namespace ts { // If that didn't work, try stripping a ".js" or ".jsx" extension and replacing it with a TypeScript one; // e.g. "./foo.js" can be matched by "./foo.ts" or "./foo.d.ts" - if (hasJavaScriptFileExtension(candidate)) { + if (hasJavascriptFileExtension(candidate)) { const extensionless = removeFileExtension(candidate); if (state.traceEnabled) { const extension = candidate.substring(extensionless.length); diff --git a/src/compiler/moduleSpecifiers.ts b/src/compiler/moduleSpecifiers.ts index cb19dcde1e2..6033d95b2a5 100644 --- a/src/compiler/moduleSpecifiers.ts +++ b/src/compiler/moduleSpecifiers.ts @@ -30,7 +30,7 @@ namespace ts.moduleSpecifiers { function getPreferencesForUpdate(compilerOptions: CompilerOptions, oldImportSpecifier: string): Preferences { return { relativePreference: isExternalModuleNameRelative(oldImportSpecifier) ? RelativePreference.Relative : RelativePreference.NonRelative, - ending: hasJavaScriptOrJsonFileExtension(oldImportSpecifier) ? Ending.JsExtension + ending: hasJavascriptOrJsonFileExtension(oldImportSpecifier) ? Ending.JsExtension : getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.NodeJs || endsWith(oldImportSpecifier, "index") ? Ending.Index : Ending.Minimal, }; } @@ -148,7 +148,7 @@ namespace ts.moduleSpecifiers { } function usesJsExtensionOnImports({ imports }: SourceFile): boolean { - return firstDefined(imports, ({ text }) => pathIsRelative(text) ? hasJavaScriptOrJsonFileExtension(text) : undefined) || false; + return firstDefined(imports, ({ text }) => pathIsRelative(text) ? hasJavascriptOrJsonFileExtension(text) : undefined) || false; } function stringsEqual(a: string, b: string, getCanonicalFileName: GetCanonicalFileName): boolean { @@ -415,13 +415,13 @@ namespace ts.moduleSpecifiers { case Ending.Index: return noExtension; case Ending.JsExtension: - return noExtension + getJavaScriptExtensionForFile(fileName, options); + return noExtension + getJavascriptExtensionForFile(fileName, options); default: return Debug.assertNever(ending); } } - function getJavaScriptExtensionForFile(fileName: string, options: CompilerOptions): Extension { + function getJavascriptExtensionForFile(fileName: string, options: CompilerOptions): Extension { const ext = extensionFromPath(fileName); switch (ext) { case Extension.Ts: diff --git a/src/compiler/program.ts b/src/compiler/program.ts index c24f570819e..61bf38db805 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -1438,9 +1438,9 @@ namespace ts { function getSyntacticDiagnosticsForFile(sourceFile: SourceFile): ReadonlyArray { // For JavaScript files, we report semantic errors for using TypeScript-only // constructs from within a JavaScript file as syntactic errors. - if (isSourceFileJavaScript(sourceFile)) { + if (isSourceFileJS(sourceFile)) { if (!sourceFile.additionalSyntacticDiagnostics) { - sourceFile.additionalSyntacticDiagnostics = getJavaScriptSyntacticDiagnosticsForFile(sourceFile); + sourceFile.additionalSyntacticDiagnostics = getJavascriptSyntacticDiagnosticsForFile(sourceFile); } return concatenate(sourceFile.additionalSyntacticDiagnostics, sourceFile.parseDiagnostics); } @@ -1538,7 +1538,7 @@ namespace ts { return true; } - function getJavaScriptSyntacticDiagnosticsForFile(sourceFile: SourceFile): DiagnosticWithLocation[] { + function getJavascriptSyntacticDiagnosticsForFile(sourceFile: SourceFile): DiagnosticWithLocation[] { return runWithCancellationToken(() => { const diagnostics: DiagnosticWithLocation[] = []; let parent: Node = sourceFile; @@ -1801,7 +1801,7 @@ namespace ts { return; } - const isJavaScriptFile = isSourceFileJavaScript(file); + const isJavaScriptFile = isSourceFileJS(file); const isExternalModuleFile = isExternalModule(file); // file.imports may not be undefined if there exists dynamic import @@ -2295,7 +2295,7 @@ namespace ts { && i < file.imports.length && !elideImport && !(isJsFile && !options.allowJs) - && (isInJavaScriptFile(file.imports[i]) || !(file.imports[i].flags & NodeFlags.JSDoc)); + && (isInJSFile(file.imports[i]) || !(file.imports[i].flags & NodeFlags.JSDoc)); if (elideImport) { modulesWithElidedImports.set(file.path, true); diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index 49e89417ca0..14e7900b0da 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -1,11 +1,11 @@ /*@internal*/ namespace ts { export function getDeclarationDiagnostics(host: EmitHost, resolver: EmitResolver, file: SourceFile | undefined): DiagnosticWithLocation[] | undefined { - if (file && isSourceFileJavaScript(file)) { + if (file && isSourceFileJS(file)) { return []; // No declaration diagnostics for js for now } const compilerOptions = host.getCompilerOptions(); - const result = transformNodes(resolver, host, compilerOptions, file ? [file] : filter(host.getSourceFiles(), isSourceFileNotJavaScript), [transformDeclarations], /*allowDtsFiles*/ false); + const result = transformNodes(resolver, host, compilerOptions, file ? [file] : filter(host.getSourceFiles(), isSourceFileNotJavascript), [transformDeclarations], /*allowDtsFiles*/ false); return result.diagnostics; } @@ -157,7 +157,7 @@ namespace ts { function transformRoot(node: SourceFile): SourceFile; function transformRoot(node: SourceFile | Bundle): SourceFile | Bundle; function transformRoot(node: SourceFile | Bundle) { - if (node.kind === SyntaxKind.SourceFile && (node.isDeclarationFile || isSourceFileJavaScript(node))) { + if (node.kind === SyntaxKind.SourceFile && (node.isDeclarationFile || isSourceFileJS(node))) { return node; } @@ -168,7 +168,7 @@ namespace ts { let hasNoDefaultLib = false; const bundle = createBundle(map(node.sourceFiles, sourceFile => { - if (sourceFile.isDeclarationFile || isSourceFileJavaScript(sourceFile)) return undefined!; // Omit declaration files from bundle results, too // TODO: GH#18217 + if (sourceFile.isDeclarationFile || isSourceFileJS(sourceFile)) return undefined!; // Omit declaration files from bundle results, too // TODO: GH#18217 hasNoDefaultLib = hasNoDefaultLib || sourceFile.hasNoDefaultLib; currentSourceFile = sourceFile; enclosingDeclaration = sourceFile; @@ -303,7 +303,7 @@ namespace ts { } function collectReferences(sourceFile: SourceFile, ret: Map) { - if (noResolve || isSourceFileJavaScript(sourceFile)) return ret; + if (noResolve || isSourceFileJS(sourceFile)) return ret; forEach(sourceFile.referencedFiles, f => { const elem = tryResolveScriptReference(host, sourceFile, f); if (elem) { @@ -989,7 +989,7 @@ namespace ts { ensureType(input, input.type), /*body*/ undefined )); - if (clean && resolver.isJSContainerFunctionDeclaration(input)) { + if (clean && resolver.isExpandoFunctionDeclaration(input)) { const declarations = mapDefined(resolver.getPropertiesOfContainerFunction(input), p => { if (!isPropertyAccessExpression(p.valueDeclaration)) { return undefined; diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts index 418185b4c16..3692e9ca057 100644 --- a/src/compiler/tsbuild.ts +++ b/src/compiler/tsbuild.ts @@ -302,7 +302,7 @@ namespace ts { return changeExtension(outputPath, Extension.Dts); } - function getOutputJavaScriptFileName(inputFileName: string, configFile: ParsedCommandLine) { + function getOutputJavascriptFileName(inputFileName: string, configFile: ParsedCommandLine) { const relativePath = getRelativePathFromDirectory(rootDirOfOptions(configFile.options, configFile.options.configFilePath!), inputFileName, /*ignoreCase*/ true); const outputPath = resolvePath(configFile.options.outDir || getDirectoryPath(configFile.options.configFilePath!), relativePath); const newExtension = fileExtensionIs(inputFileName, Extension.Json) ? Extension.Json : @@ -317,7 +317,7 @@ namespace ts { } const outputs: string[] = []; - const js = getOutputJavaScriptFileName(inputFileName, configFile); + const js = getOutputJavascriptFileName(inputFileName, configFile); outputs.push(js); if (configFile.options.sourceMap) { outputs.push(`${js}.map`); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 279fef73d5e..a0d07e00591 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3383,7 +3383,7 @@ namespace ts { isImplementationOfOverload(node: FunctionLike): boolean | undefined; isRequiredInitializedParameter(node: ParameterDeclaration): boolean; isOptionalUninitializedParameterProperty(node: ParameterDeclaration): boolean; - isJSContainerFunctionDeclaration(node: FunctionDeclaration): boolean; + isExpandoFunctionDeclaration(node: FunctionDeclaration): boolean; getPropertiesOfContainerFunction(node: Declaration): Symbol[]; createTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration | PropertyAccessExpression, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker, addUndefined?: boolean): TypeNode | undefined; createReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker): TypeNode | undefined; @@ -3435,7 +3435,7 @@ namespace ts { ExportStar = 1 << 23, // Export * declaration Optional = 1 << 24, // Optional property Transient = 1 << 25, // Transient symbol (created during type check) - JSContainer = 1 << 26, // Contains Javascript special declarations + Assignment = 1 << 26, // Assignment treated as declaration (eg `this.prop = 1`) ModuleExports = 1 << 27, // Symbol for CommonJS `module` of `module.exports` /* @internal */ @@ -3444,8 +3444,8 @@ namespace ts { Enum = RegularEnum | ConstEnum, Variable = FunctionScopedVariable | BlockScopedVariable, - Value = Variable | Property | EnumMember | ObjectLiteral | Function | Class | Enum | ValueModule | Method | GetAccessor | SetAccessor | JSContainer, - Type = Class | Interface | Enum | EnumMember | TypeLiteral | TypeParameter | TypeAlias | JSContainer, + Value = Variable | Property | EnumMember | ObjectLiteral | Function | Class | Enum | ValueModule | Method | GetAccessor | SetAccessor | Assignment, + Type = Class | Interface | Enum | EnumMember | TypeLiteral | TypeParameter | TypeAlias | Assignment, Namespace = ValueModule | NamespaceModule | Enum, Module = ValueModule | NamespaceModule, Accessor = GetAccessor | SetAccessor, @@ -3466,7 +3466,7 @@ namespace ts { InterfaceExcludes = Type & ~(Interface | Class), RegularEnumExcludes = (Value | Type) & ~(RegularEnum | ValueModule), // regular enums merge only with regular enums and modules ConstEnumExcludes = (Value | Type) & ~ConstEnum, // const enums merge only with const enums - ValueModuleExcludes = Value & ~(Function | Class | RegularEnum | ValueModule | JSContainer), + ValueModuleExcludes = Value & ~(Function | Class | RegularEnum | ValueModule | Assignment), NamespaceModuleExcludes = 0, MethodExcludes = Value & ~Method, GetAccessorExcludes = Value & ~SetAccessor, @@ -4219,7 +4219,7 @@ namespace ts { } /* @internal */ - export const enum SpecialPropertyAssignmentKind { + export const enum AssignmentDeclarationKind { None, /// exports.name = expr ExportsProperty, diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 18b45d682db..1efbd278aed 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1678,15 +1678,15 @@ namespace ts { return node.kind === SyntaxKind.ImportEqualsDeclaration && (node).moduleReference.kind !== SyntaxKind.ExternalModuleReference; } - export function isSourceFileJavaScript(file: SourceFile): boolean { - return isInJavaScriptFile(file); + export function isSourceFileJS(file: SourceFile): boolean { + return isInJSFile(file); } - export function isSourceFileNotJavaScript(file: SourceFile): boolean { - return !isInJavaScriptFile(file); + export function isSourceFileNotJavascript(file: SourceFile): boolean { + return !isInJSFile(file); } - export function isInJavaScriptFile(node: Node | undefined): boolean { + export function isInJSFile(node: Node | undefined): boolean { return !!node && !!(node.flags & NodeFlags.JavaScriptFile); } @@ -1738,14 +1738,14 @@ namespace ts { return getSourceTextOfNodeFromSourceFile(sourceFile, str).charCodeAt(0) === CharacterCodes.doubleQuote; } - export function getDeclarationOfJSInitializer(node: Node): Node | undefined { + export function getDeclarationOfExpando(node: Node): Node | undefined { if (!node.parent) { return undefined; } let name: Expression | BindingName | undefined; let decl: Node | undefined; if (isVariableDeclaration(node.parent) && node.parent.initializer === node) { - if (!isInJavaScriptFile(node) && !isVarConst(node.parent)) { + if (!isInJSFile(node) && !isVarConst(node.parent)) { return undefined; } name = node.parent.name; @@ -1770,7 +1770,7 @@ namespace ts { } } - if (!name || !getJavascriptInitializer(node, isPrototypeAccess(name))) { + if (!name || !getExpandoInitializer(node, isPrototypeAccess(name))) { return undefined; } return decl; @@ -1782,7 +1782,7 @@ namespace ts { /** Get the initializer, taking into account defaulted Javascript initializers */ export function getEffectiveInitializer(node: HasExpressionInitializer) { - if (isInJavaScriptFile(node) && node.initializer && + if (isInJSFile(node) && node.initializer && isBinaryExpression(node.initializer) && node.initializer.operatorToken.kind === SyntaxKind.BarBarToken && node.name && isEntityNameExpression(node.name) && isSameEntityName(node.name, node.initializer.left)) { return node.initializer.right; @@ -1790,26 +1790,26 @@ namespace ts { return node.initializer; } - /** Get the declaration initializer when it is container-like (See getJavascriptInitializer). */ - export function getDeclaredJavascriptInitializer(node: HasExpressionInitializer) { + /** Get the declaration initializer when it is container-like (See getExpandoInitializer). */ + export function getDeclaredExpandoInitializer(node: HasExpressionInitializer) { const init = getEffectiveInitializer(node); - return init && getJavascriptInitializer(init, isPrototypeAccess(node.name)); + return init && getExpandoInitializer(init, isPrototypeAccess(node.name)); } /** - * Get the assignment 'initializer' -- the righthand side-- when the initializer is container-like (See getJavascriptInitializer). + * Get the assignment 'initializer' -- the righthand side-- when the initializer is container-like (See getExpandoInitializer). * We treat the right hand side of assignments with container-like initalizers as declarations. */ - export function getAssignedJavascriptInitializer(node: Node) { + export function getAssignedExpandoInitializer(node: Node) { if (node && node.parent && isBinaryExpression(node.parent) && node.parent.operatorToken.kind === SyntaxKind.EqualsToken) { const isPrototypeAssignment = isPrototypeAccess(node.parent.left); - return getJavascriptInitializer(node.parent.right, isPrototypeAssignment) || - getDefaultedJavascriptInitializer(node.parent.left as EntityNameExpression, node.parent.right, isPrototypeAssignment); + return getExpandoInitializer(node.parent.right, isPrototypeAssignment) || + getDefaultedExpandoInitializer(node.parent.left as EntityNameExpression, node.parent.right, isPrototypeAssignment); } } /** - * Recognized Javascript container-like initializers are: + * Recognized expando initializers are: * 1. (function() {})() -- IIFEs * 2. function() { } -- Function expressions * 3. class { } -- Class expressions @@ -1818,7 +1818,7 @@ namespace ts { * * This function returns the provided initializer, or undefined if it is not valid. */ - export function getJavascriptInitializer(initializer: Node, isPrototypeAssignment: boolean): Expression | undefined { + export function getExpandoInitializer(initializer: Node, isPrototypeAssignment: boolean): Expression | undefined { if (isCallExpression(initializer)) { const e = skipParentheses(initializer.expression); return e.kind === SyntaxKind.FunctionExpression || e.kind === SyntaxKind.ArrowFunction ? initializer : undefined; @@ -1834,29 +1834,29 @@ namespace ts { } /** - * A defaulted Javascript initializer matches the pattern - * `Lhs = Lhs || JavascriptInitializer` - * or `var Lhs = Lhs || JavascriptInitializer` + * A defaulted expando initializer matches the pattern + * `Lhs = Lhs || ExpandoInitializer` + * or `var Lhs = Lhs || ExpandoInitializer` * * The second Lhs is required to be the same as the first except that it may be prefixed with * 'window.', 'global.' or 'self.' The second Lhs is otherwise ignored by the binder and checker. */ - function getDefaultedJavascriptInitializer(name: EntityNameExpression, initializer: Expression, isPrototypeAssignment: boolean) { - const e = isBinaryExpression(initializer) && initializer.operatorToken.kind === SyntaxKind.BarBarToken && getJavascriptInitializer(initializer.right, isPrototypeAssignment); + function getDefaultedExpandoInitializer(name: EntityNameExpression, initializer: Expression, isPrototypeAssignment: boolean) { + const e = isBinaryExpression(initializer) && initializer.operatorToken.kind === SyntaxKind.BarBarToken && getExpandoInitializer(initializer.right, isPrototypeAssignment); if (e && isSameEntityName(name, (initializer as BinaryExpression).left as EntityNameExpression)) { return e; } } - export function isDefaultedJavascriptInitializer(node: BinaryExpression) { + export function isDefaultedExpandoInitializer(node: BinaryExpression) { const name = isVariableDeclaration(node.parent) ? node.parent.name : isBinaryExpression(node.parent) && node.parent.operatorToken.kind === SyntaxKind.EqualsToken ? node.parent.left : undefined; - return name && getJavascriptInitializer(node.right, isPrototypeAccess(name)) && isEntityNameExpression(name) && isSameEntityName(name, node.left); + return name && getExpandoInitializer(node.right, isPrototypeAccess(name)) && isEntityNameExpression(name) && isSameEntityName(name, node.left); } - /** Given a Javascript initializer, return the outer name. That is, the lhs of the assignment or the declaration name. */ - export function getOuterNameOfJsInitializer(node: Declaration): DeclarationName | undefined { + /** Given an expando initializer, return its declaration name, or the left-hand side of the assignment if it's part of an assignment declaration. */ + export function getNameOfExpando(node: Declaration): DeclarationName | undefined { if (isBinaryExpression(node.parent)) { const parent = (node.parent.operatorToken.kind === SyntaxKind.BarBarToken && isBinaryExpression(node.parent.parent)) ? node.parent.parent : node.parent; if (parent.operatorToken.kind === SyntaxKind.EqualsToken && isIdentifier(parent.left)) { @@ -1912,36 +1912,36 @@ namespace ts { /// Given a BinaryExpression, returns SpecialPropertyAssignmentKind for the various kinds of property /// assignments we treat as special in the binder - export function getSpecialPropertyAssignmentKind(expr: BinaryExpression): SpecialPropertyAssignmentKind { - const special = getSpecialPropertyAssignmentKindWorker(expr); - return special === SpecialPropertyAssignmentKind.Property || isInJavaScriptFile(expr) ? special : SpecialPropertyAssignmentKind.None; + export function getAssignmentDeclarationKind(expr: BinaryExpression): AssignmentDeclarationKind { + const special = getAssignmentDeclarationKindWorker(expr); + return special === AssignmentDeclarationKind.Property || isInJSFile(expr) ? special : AssignmentDeclarationKind.None; } - function getSpecialPropertyAssignmentKindWorker(expr: BinaryExpression): SpecialPropertyAssignmentKind { + function getAssignmentDeclarationKindWorker(expr: BinaryExpression): AssignmentDeclarationKind { if (expr.operatorToken.kind !== SyntaxKind.EqualsToken || !isPropertyAccessExpression(expr.left)) { - return SpecialPropertyAssignmentKind.None; + return AssignmentDeclarationKind.None; } const lhs = expr.left; if (isEntityNameExpression(lhs.expression) && lhs.name.escapedText === "prototype" && isObjectLiteralExpression(getInitializerOfBinaryExpression(expr))) { // F.prototype = { ... } - return SpecialPropertyAssignmentKind.Prototype; + return AssignmentDeclarationKind.Prototype; } - return getSpecialPropertyAccessKind(lhs); + return getAssignmentDeclarationPropertyAccessKind(lhs); } - export function getSpecialPropertyAccessKind(lhs: PropertyAccessExpression): SpecialPropertyAssignmentKind { + export function getAssignmentDeclarationPropertyAccessKind(lhs: PropertyAccessExpression): AssignmentDeclarationKind { if (lhs.expression.kind === SyntaxKind.ThisKeyword) { - return SpecialPropertyAssignmentKind.ThisProperty; + return AssignmentDeclarationKind.ThisProperty; } else if (isIdentifier(lhs.expression) && lhs.expression.escapedText === "module" && lhs.name.escapedText === "exports") { // module.exports = expr - return SpecialPropertyAssignmentKind.ModuleExports; + return AssignmentDeclarationKind.ModuleExports; } else if (isEntityNameExpression(lhs.expression)) { if (isPrototypeAccess(lhs.expression)) { // F.G....prototype.x = expr - return SpecialPropertyAssignmentKind.PrototypeProperty; + return AssignmentDeclarationKind.PrototypeProperty; } let nextToLast = lhs; @@ -1953,13 +1953,13 @@ namespace ts { if (id.escapedText === "exports" || id.escapedText === "module" && nextToLast.name.escapedText === "exports") { // exports.name = expr OR module.exports.name = expr - return SpecialPropertyAssignmentKind.ExportsProperty; + return AssignmentDeclarationKind.ExportsProperty; } // F.G...x = expr - return SpecialPropertyAssignmentKind.Property; + return AssignmentDeclarationKind.Property; } - return SpecialPropertyAssignmentKind.None; + return AssignmentDeclarationKind.None; } export function getInitializerOfBinaryExpression(expr: BinaryExpression) { @@ -1970,11 +1970,11 @@ namespace ts { } export function isPrototypePropertyAssignment(node: Node): boolean { - return isBinaryExpression(node) && getSpecialPropertyAssignmentKind(node) === SpecialPropertyAssignmentKind.PrototypeProperty; + return isBinaryExpression(node) && getAssignmentDeclarationKind(node) === AssignmentDeclarationKind.PrototypeProperty; } export function isSpecialPropertyDeclaration(expr: PropertyAccessExpression): boolean { - return isInJavaScriptFile(expr) && + return isInJSFile(expr) && expr.parent && expr.parent.kind === SyntaxKind.ExpressionStatement && !!getJSDocTypeTag(expr.parent); } @@ -2082,7 +2082,7 @@ namespace ts { function getSourceOfDefaultedAssignment(node: Node): Node | undefined { return isExpressionStatement(node) && isBinaryExpression(node.expression) && - getSpecialPropertyAssignmentKind(node.expression) !== SpecialPropertyAssignmentKind.None && + getAssignmentDeclarationKind(node.expression) !== AssignmentDeclarationKind.None && isBinaryExpression(node.expression.right) && node.expression.right.operatorToken.kind === SyntaxKind.BarBarToken ? node.expression.right.right @@ -2402,7 +2402,7 @@ namespace ts { else { const binExp = parent.parent; return isBinaryExpression(binExp) && - getSpecialPropertyAssignmentKind(binExp) !== SpecialPropertyAssignmentKind.None && + getAssignmentDeclarationKind(binExp) !== AssignmentDeclarationKind.None && (binExp.left.symbol || binExp.symbol) && getNameOfDeclaration(binExp) === name ? binExp @@ -2471,7 +2471,7 @@ namespace ts { node.kind === SyntaxKind.ImportSpecifier || node.kind === SyntaxKind.ExportSpecifier || node.kind === SyntaxKind.ExportAssignment && exportAssignmentIsAlias(node) || - isBinaryExpression(node) && getSpecialPropertyAssignmentKind(node) === SpecialPropertyAssignmentKind.ModuleExports; + isBinaryExpression(node) && getAssignmentDeclarationKind(node) === AssignmentDeclarationKind.ModuleExports; } export function exportAssignmentIsAlias(node: ExportAssignment | BinaryExpression): boolean { @@ -2480,7 +2480,7 @@ namespace ts { } export function getEffectiveBaseTypeNode(node: ClassLikeDeclaration | InterfaceDeclaration) { - if (isInJavaScriptFile(node)) { + if (isInJSFile(node)) { // Prefer an @augments tag because it may have type parameters. const tag = getJSDocAugmentsTag(node); if (tag) { @@ -3286,7 +3286,7 @@ namespace ts { /** Don't call this for `--outFile`, just for `--outDir` or plain emit. `--outFile` needs additional checks. */ export function sourceFileMayBeEmitted(sourceFile: SourceFile, options: CompilerOptions, isSourceFileFromExternalLibrary: (file: SourceFile) => boolean) { - return !(options.noEmitForJsFiles && isSourceFileJavaScript(sourceFile)) && !sourceFile.isDeclarationFile && !isSourceFileFromExternalLibrary(sourceFile); + return !(options.noEmitForJsFiles && isSourceFileJS(sourceFile)) && !sourceFile.isDeclarationFile && !isSourceFileFromExternalLibrary(sourceFile); } export function getSourceFilePathInNewDir(fileName: string, host: EmitHost, newDirPath: string): string { @@ -3410,7 +3410,7 @@ namespace ts { */ export function getEffectiveTypeAnnotationNode(node: Node): TypeNode | undefined { const type = (node as HasType).type; - if (type || !isInJavaScriptFile(node)) return type; + if (type || !isInJSFile(node)) return type; return isJSDocPropertyLikeTag(node) ? node.typeExpression && node.typeExpression.type : getJSDocType(node); } @@ -3425,7 +3425,7 @@ namespace ts { export function getEffectiveReturnTypeNode(node: SignatureDeclaration | JSDocSignature): TypeNode | undefined { return isJSDocSignature(node) ? node.type && node.type.typeExpression && node.type.typeExpression.type : - node.type || (isInJavaScriptFile(node) ? getJSDocReturnType(node) : undefined); + node.type || (isInJSFile(node) ? getJSDocReturnType(node) : undefined); } export function getJSDocTypeParameterDeclarations(node: DeclarationWithTypeParameters): ReadonlyArray { @@ -4986,11 +4986,11 @@ namespace ts { } case SyntaxKind.BinaryExpression: { const expr = declaration as BinaryExpression; - switch (getSpecialPropertyAssignmentKind(expr)) { - case SpecialPropertyAssignmentKind.ExportsProperty: - case SpecialPropertyAssignmentKind.ThisProperty: - case SpecialPropertyAssignmentKind.Property: - case SpecialPropertyAssignmentKind.PrototypeProperty: + switch (getAssignmentDeclarationKind(expr)) { + case AssignmentDeclarationKind.ExportsProperty: + case AssignmentDeclarationKind.ThisProperty: + case AssignmentDeclarationKind.Property: + case AssignmentDeclarationKind.PrototypeProperty: return (expr.left as PropertyAccessExpression).name; default: return undefined; @@ -5207,7 +5207,7 @@ namespace ts { if (node.typeParameters) { return node.typeParameters; } - if (isInJavaScriptFile(node)) { + if (isInJSFile(node)) { const decls = getJSDocTypeParameterDeclarations(node); if (decls.length) { return decls; @@ -6613,7 +6613,7 @@ namespace ts { /* @internal */ export function isDeclaration(node: Node): node is NamedDeclaration { if (node.kind === SyntaxKind.TypeParameter) { - return node.parent.kind !== SyntaxKind.JSDocTemplateTag || isInJavaScriptFile(node); + return node.parent.kind !== SyntaxKind.JSDocTemplateTag || isInJSFile(node); } return isDeclarationKind(node.kind); @@ -8010,42 +8010,42 @@ namespace ts { /** * List of supported extensions in order of file resolution precedence. */ - export const supportedTypeScriptExtensions: ReadonlyArray = [Extension.Ts, Extension.Tsx, Extension.Dts]; + export const supportedTypescriptExtensions: ReadonlyArray = [Extension.Ts, Extension.Tsx, Extension.Dts]; /** Must have ".d.ts" first because if ".ts" goes first, that will be detected as the extension instead of ".d.ts". */ export const supportedTypescriptExtensionsForExtractExtension: ReadonlyArray = [Extension.Dts, Extension.Ts, Extension.Tsx]; export const supportedJavascriptExtensions: ReadonlyArray = [Extension.Js, Extension.Jsx]; - export const supportedJavaScriptAndJsonExtensions: ReadonlyArray = [Extension.Js, Extension.Jsx, Extension.Json]; - const allSupportedExtensions: ReadonlyArray = [...supportedTypeScriptExtensions, ...supportedJavascriptExtensions]; + export const supportedJavascriptAndJsonExtensions: ReadonlyArray = [Extension.Js, Extension.Jsx, Extension.Json]; + const allSupportedExtensions: ReadonlyArray = [...supportedTypescriptExtensions, ...supportedJavascriptExtensions]; export function getSupportedExtensions(options?: CompilerOptions, extraFileExtensions?: ReadonlyArray): ReadonlyArray { const needJsExtensions = options && options.allowJs; if (!extraFileExtensions || extraFileExtensions.length === 0) { - return needJsExtensions ? allSupportedExtensions : supportedTypeScriptExtensions; + return needJsExtensions ? allSupportedExtensions : supportedTypescriptExtensions; } const extensions = [ - ...needJsExtensions ? allSupportedExtensions : supportedTypeScriptExtensions, - ...mapDefined(extraFileExtensions, x => x.scriptKind === ScriptKind.Deferred || needJsExtensions && isJavaScriptLike(x.scriptKind) ? x.extension : undefined) + ...needJsExtensions ? allSupportedExtensions : supportedTypescriptExtensions, + ...mapDefined(extraFileExtensions, x => x.scriptKind === ScriptKind.Deferred || needJsExtensions && isJavascriptLike(x.scriptKind) ? x.extension : undefined) ]; return deduplicate(extensions, equateStringsCaseSensitive, compareStringsCaseSensitive); } - function isJavaScriptLike(scriptKind: ScriptKind | undefined): boolean { + function isJavascriptLike(scriptKind: ScriptKind | undefined): boolean { return scriptKind === ScriptKind.JS || scriptKind === ScriptKind.JSX; } - export function hasJavaScriptFileExtension(fileName: string): boolean { + export function hasJavascriptFileExtension(fileName: string): boolean { return some(supportedJavascriptExtensions, extension => fileExtensionIs(fileName, extension)); } - export function hasJavaScriptOrJsonFileExtension(fileName: string): boolean { - return supportedJavaScriptAndJsonExtensions.some(ext => fileExtensionIs(fileName, ext)); + export function hasJavascriptOrJsonFileExtension(fileName: string): boolean { + return supportedJavascriptAndJsonExtensions.some(ext => fileExtensionIs(fileName, ext)); } - export function hasTypeScriptFileExtension(fileName: string): boolean { - return some(supportedTypeScriptExtensions, extension => fileExtensionIs(fileName, extension)); + export function hasTypescriptFileExtension(fileName: string): boolean { + return some(supportedTypescriptExtensions, extension => fileExtensionIs(fileName, extension)); } export function isSupportedSourceFileName(fileName: string, compilerOptions?: CompilerOptions, extraFileExtensions?: ReadonlyArray) { diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index fa9c88d3ffa..abb03babc8d 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -268,7 +268,7 @@ namespace Harness.LanguageService { getHost(): LanguageServiceAdapterHost { return this.host; } getLanguageService(): ts.LanguageService { return ts.createLanguageService(this.host); } getClassifier(): ts.Classifier { return ts.createClassifier(); } - getPreProcessedFileInfo(fileName: string, fileContents: string): ts.PreProcessedFileInfo { return ts.preProcessFile(fileContents, /* readImportFiles */ true, ts.hasJavaScriptFileExtension(fileName)); } + getPreProcessedFileInfo(fileName: string, fileContents: string): ts.PreProcessedFileInfo { return ts.preProcessFile(fileContents, /* readImportFiles */ true, ts.hasJavascriptFileExtension(fileName)); } } /// Shim adapter diff --git a/src/harness/vpath.ts b/src/harness/vpath.ts index 6211fc9278a..f21ee7fb6bb 100644 --- a/src/harness/vpath.ts +++ b/src/harness/vpath.ts @@ -21,8 +21,8 @@ namespace vpath { export import relative = ts.getRelativePathFromDirectory; export import beneath = ts.containsPath; export import changeExtension = ts.changeAnyExtension; - export import isTypeScript = ts.hasTypeScriptFileExtension; - export import isJavaScript = ts.hasJavaScriptFileExtension; + export import isTypeScript = ts.hasTypescriptFileExtension; + export import isJavaScript = ts.hasJavascriptFileExtension; const invalidRootComponentRegExp = /^(?!(\/|\/\/\w+\/|[a-zA-Z]:\/?|)$)/; const invalidNavigableComponentRegExp = /[:*?"<>|]/; @@ -133,4 +133,4 @@ namespace vpath { export function isTsConfigFile(path: string): boolean { return path.indexOf("tsconfig") !== -1 && path.indexOf("json") !== -1; } -} \ No newline at end of file +} diff --git a/src/jsTyping/jsTyping.ts b/src/jsTyping/jsTyping.ts index db55ce4993b..3b1868aea84 100644 --- a/src/jsTyping/jsTyping.ts +++ b/src/jsTyping/jsTyping.ts @@ -122,7 +122,7 @@ namespace ts.JsTyping { // Only infer typings for .js and .jsx files fileNames = mapDefined(fileNames, fileName => { const path = normalizePath(fileName); - if (hasJavaScriptFileExtension(path)) { + if (hasJavascriptFileExtension(path)) { return path; } }); @@ -218,7 +218,7 @@ namespace ts.JsTyping { */ function getTypingNamesFromSourceFileNames(fileNames: string[]) { const fromFileNames = mapDefined(fileNames, j => { - if (!hasJavaScriptFileExtension(j)) return undefined; + if (!hasJavascriptFileExtension(j)) return undefined; const inferredTypingName = removeFileExtension(getBaseFileName(j.toLowerCase())); const cleanedTypingName = removeMinAndVersionNumbers(inferredTypingName); diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index ddbfd8ac389..b1f88dff3b7 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -1447,14 +1447,14 @@ namespace ts.server { for (const f of fileNames) { const fileName = propertyReader.getFileName(f); - if (hasTypeScriptFileExtension(fileName)) { + if (hasTypescriptFileExtension(fileName)) { continue; } totalNonTsFileSize += this.host.getFileSize(fileName); if (totalNonTsFileSize > maxProgramSizeForNonTsFiles || totalNonTsFileSize > availableSpace) { - this.logger.info(getExceedLimitMessage({ propertyReader, hasTypeScriptFileExtension, host: this.host }, totalNonTsFileSize)); + this.logger.info(getExceedLimitMessage({ propertyReader, hasTypescriptFileExtension, host: this.host }, totalNonTsFileSize)); // Keep the size as zero since it's disabled return fileName; } @@ -1464,14 +1464,14 @@ namespace ts.server { return; - function getExceedLimitMessage(context: { propertyReader: FilePropertyReader, hasTypeScriptFileExtension: (filename: string) => boolean, host: ServerHost }, totalNonTsFileSize: number) { + function getExceedLimitMessage(context: { propertyReader: FilePropertyReader, hasTypescriptFileExtension: (filename: string) => boolean, host: ServerHost }, totalNonTsFileSize: number) { const files = getTop5LargestFiles(context); return `Non TS file size exceeded limit (${totalNonTsFileSize}). Largest files: ${files.map(file => `${file.name}:${file.size}`).join(", ")}`; } - function getTop5LargestFiles({ propertyReader, hasTypeScriptFileExtension, host }: { propertyReader: FilePropertyReader, hasTypeScriptFileExtension: (filename: string) => boolean, host: ServerHost }) { + function getTop5LargestFiles({ propertyReader, hasTypescriptFileExtension, host }: { propertyReader: FilePropertyReader, hasTypescriptFileExtension: (filename: string) => boolean, host: ServerHost }) { return fileNames.map(f => propertyReader.getFileName(f)) - .filter(name => hasTypeScriptFileExtension(name)) + .filter(name => hasTypescriptFileExtension(name)) .map(name => ({ name, size: host.getFileSize!(name) })) // TODO: GH#18217 .sort((a, b) => b.size - a.size) .slice(0, 5); diff --git a/src/server/scriptInfo.ts b/src/server/scriptInfo.ts index 085dd6d0eef..5c4eaa9a374 100644 --- a/src/server/scriptInfo.ts +++ b/src/server/scriptInfo.ts @@ -167,7 +167,7 @@ namespace ts.server { const fileName = tempFileName || this.fileName; const getText = () => text === undefined ? (text = this.host.readFile(fileName) || "") : text; // Only non typescript files have size limitation - if (!hasTypeScriptFileExtension(this.fileName)) { + if (!hasTypescriptFileExtension(this.fileName)) { const fileSize = this.host.getFileSize ? this.host.getFileSize(fileName) : getText().length; if (fileSize > maxFileSize) { Debug.assert(!!this.info.containingProjects.length); diff --git a/src/services/codefixes/convertFunctionToEs6Class.ts b/src/services/codefixes/convertFunctionToEs6Class.ts index c2041179888..78e10ce2044 100644 --- a/src/services/codefixes/convertFunctionToEs6Class.ts +++ b/src/services/codefixes/convertFunctionToEs6Class.ts @@ -138,7 +138,7 @@ namespace ts.codefix { default: { // Don't try to declare members in JavaScript files - if (isSourceFileJavaScript(sourceFile)) { + if (isSourceFileJS(sourceFile)) { return; } const prop = createProperty(/*decorators*/ undefined, modifiers, memberDeclaration.name, /*questionToken*/ undefined, diff --git a/src/services/codefixes/convertToAsyncFunction.ts b/src/services/codefixes/convertToAsyncFunction.ts index 76cdf471466..e8e24b40a0c 100644 --- a/src/services/codefixes/convertToAsyncFunction.ts +++ b/src/services/codefixes/convertToAsyncFunction.ts @@ -61,12 +61,12 @@ namespace ts.codefix { const synthNamesMap: Map = createMap(); const originalTypeMap: Map = createMap(); const allVarNames: SymbolAndIdentifier[] = []; - const isInJSFile = isInJavaScriptFile(functionToConvert); + const isInJavascript = isInJSFile(functionToConvert); const setOfExpressionsToReturn = getAllPromiseExpressionsToReturn(functionToConvert, checker); const functionToConvertRenamed: FunctionLikeDeclaration = renameCollidingVarNames(functionToConvert, checker, synthNamesMap, context, setOfExpressionsToReturn, originalTypeMap, allVarNames); const constIdentifiers = getConstIdentifiers(synthNamesMap); const returnStatements = getReturnStatementsWithPromiseHandlers(functionToConvertRenamed); - const transformer = { checker, synthNamesMap, allVarNames, setOfExpressionsToReturn, constIdentifiers, originalTypeMap, isInJSFile }; + const transformer = { checker, synthNamesMap, allVarNames, setOfExpressionsToReturn, constIdentifiers, originalTypeMap, isInJSFile: isInJavascript }; if (!returnStatements.length) { return; @@ -546,4 +546,4 @@ namespace ts.codefix { return node.original ? node.original : node; } } -} \ No newline at end of file +} diff --git a/src/services/codefixes/disableJsDiagnostics.ts b/src/services/codefixes/disableJsDiagnostics.ts index c81446152dd..4cdd7eb42d2 100644 --- a/src/services/codefixes/disableJsDiagnostics.ts +++ b/src/services/codefixes/disableJsDiagnostics.ts @@ -12,7 +12,7 @@ namespace ts.codefix { getCodeActions(context) { const { sourceFile, program, span, host, formatContext } = context; - if (!isInJavaScriptFile(sourceFile) || !isCheckJsEnabledForFile(sourceFile, program.getCompilerOptions())) { + if (!isInJSFile(sourceFile) || !isCheckJsEnabledForFile(sourceFile, program.getCompilerOptions())) { return undefined; } diff --git a/src/services/codefixes/fixAddMissingMember.ts b/src/services/codefixes/fixAddMissingMember.ts index a23cb621608..dda0903562a 100644 --- a/src/services/codefixes/fixAddMissingMember.ts +++ b/src/services/codefixes/fixAddMissingMember.ts @@ -20,7 +20,7 @@ namespace ts.codefix { const { parentDeclaration, declSourceFile, inJs, makeStatic, token, call } = info; const methodCodeAction = call && getActionForMethodDeclaration(context, declSourceFile, parentDeclaration, token, call, makeStatic, inJs, context.preferences); const addMember = inJs && !isInterfaceDeclaration(parentDeclaration) ? - singleElementArray(getActionsForAddMissingMemberInJavaScriptFile(context, declSourceFile, parentDeclaration, token.text, makeStatic)) : + singleElementArray(getActionsForAddMissingMemberInJavascriptFile(context, declSourceFile, parentDeclaration, token.text, makeStatic)) : getActionsForAddMissingMemberInTypeScriptFile(context, declSourceFile, parentDeclaration, token, makeStatic); return concatenate(singleElementArray(methodCodeAction), addMember); }, @@ -131,7 +131,7 @@ namespace ts.codefix { if (classOrInterface) { const makeStatic = ((leftExpressionType as TypeReference).target || leftExpressionType) !== checker.getDeclaredTypeOfSymbol(symbol); const declSourceFile = classOrInterface.getSourceFile(); - const inJs = isSourceFileJavaScript(declSourceFile); + const inJs = isSourceFileJS(declSourceFile); const call = tryCast(parent.parent, isCallExpression); return { kind: InfoKind.ClassOrInterface, token, parentDeclaration: classOrInterface, makeStatic, declSourceFile, inJs, call }; } @@ -142,7 +142,7 @@ namespace ts.codefix { return undefined; } - function getActionsForAddMissingMemberInJavaScriptFile(context: CodeFixContext, declSourceFile: SourceFile, classDeclaration: ClassLikeDeclaration, tokenName: string, makeStatic: boolean): CodeFixAction | undefined { + function getActionsForAddMissingMemberInJavascriptFile(context: CodeFixContext, declSourceFile: SourceFile, classDeclaration: ClassLikeDeclaration, tokenName: string, makeStatic: boolean): CodeFixAction | undefined { const changes = textChanges.ChangeTracker.with(context, t => addMissingMemberInJs(t, declSourceFile, classDeclaration, tokenName, makeStatic)); return changes.length === 0 ? undefined : createCodeFixAction(fixName, changes, [makeStatic ? Diagnostics.Initialize_static_property_0 : Diagnostics.Initialize_property_0_in_the_constructor, tokenName], fixId, Diagnostics.Add_all_missing_members); diff --git a/src/services/codefixes/importFixes.ts b/src/services/codefixes/importFixes.ts index 963d1cd64f2..578f55f5c68 100644 --- a/src/services/codefixes/importFixes.ts +++ b/src/services/codefixes/importFixes.ts @@ -267,7 +267,7 @@ namespace ts.codefix { function getExistingImportDeclarations({ moduleSymbol, importKind, exportedSymbolIsTypeOnly }: SymbolExportInfo, checker: TypeChecker, sourceFile: SourceFile): ReadonlyArray { // Can't use an es6 import for a type in JS. - return exportedSymbolIsTypeOnly && isSourceFileJavaScript(sourceFile) ? emptyArray : mapDefined(sourceFile.imports, moduleSpecifier => { + return exportedSymbolIsTypeOnly && isSourceFileJS(sourceFile) ? emptyArray : mapDefined(sourceFile.imports, moduleSpecifier => { const i = importFromModuleSpecifier(moduleSpecifier); return (i.kind === SyntaxKind.ImportDeclaration || i.kind === SyntaxKind.ImportEqualsDeclaration) && checker.getSymbolAtLocation(moduleSpecifier) === moduleSymbol ? { declaration: i, importKind } : undefined; @@ -282,7 +282,7 @@ namespace ts.codefix { host: LanguageServiceHost, preferences: UserPreferences, ): ReadonlyArray { - const isJs = isSourceFileJavaScript(sourceFile); + const isJs = isSourceFileJS(sourceFile); const choicesForEachExportingModule = flatMap(moduleSymbols, ({ moduleSymbol, importKind, exportedSymbolIsTypeOnly }) => moduleSpecifiers.getModuleSpecifiers(moduleSymbol, program.getCompilerOptions(), sourceFile, host, program.getSourceFiles(), preferences, program.redirectTargetsMap) .map((moduleSpecifier): FixAddNewImport | FixUseImportType => diff --git a/src/services/codefixes/inferFromUsage.ts b/src/services/codefixes/inferFromUsage.ts index 17b3469f0bf..f924208e321 100644 --- a/src/services/codefixes/inferFromUsage.ts +++ b/src/services/codefixes/inferFromUsage.ts @@ -26,7 +26,7 @@ namespace ts.codefix { errorCodes, getCodeActions(context) { const { sourceFile, program, span: { start }, errorCode, cancellationToken } = context; - if (isSourceFileJavaScript(sourceFile)) { + if (isSourceFileJS(sourceFile)) { return undefined; // TODO: GH#20113 } diff --git a/src/services/completions.ts b/src/services/completions.ts index 61e424c43ec..ff8c3147824 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -134,7 +134,7 @@ namespace ts.Completions { if (isUncheckedFile(sourceFile, compilerOptions)) { const uniqueNames = getCompletionEntriesFromSymbols(symbols, entries, location, sourceFile, typeChecker, compilerOptions.target!, log, completionKind, preferences, propertyAccessToConvert, isJsxInitializer, recommendedCompletion, symbolToOriginInfoMap); - getJavaScriptCompletionEntries(sourceFile, location!.pos, uniqueNames, compilerOptions.target!, entries); // TODO: GH#18217 + getJSCompletionEntries(sourceFile, location!.pos, uniqueNames, compilerOptions.target!, entries); // TODO: GH#18217 } else { if ((!symbols || symbols.length === 0) && keywordFilters === KeywordCompletionFilters.None) { @@ -161,7 +161,7 @@ namespace ts.Completions { } function isUncheckedFile(sourceFile: SourceFile, compilerOptions: CompilerOptions): boolean { - return isSourceFileJavaScript(sourceFile) && !isCheckJsEnabledForFile(sourceFile, compilerOptions); + return isSourceFileJS(sourceFile) && !isCheckJsEnabledForFile(sourceFile, compilerOptions); } function isMemberCompletionKind(kind: CompletionKind): boolean { @@ -175,7 +175,7 @@ namespace ts.Completions { } } - function getJavaScriptCompletionEntries( + function getJSCompletionEntries( sourceFile: SourceFile, position: number, uniqueNames: Map, diff --git a/src/services/importTracker.ts b/src/services/importTracker.ts index 77b3c02c80b..86bee92eaec 100644 --- a/src/services/importTracker.ts +++ b/src/services/importTracker.ts @@ -502,11 +502,11 @@ namespace ts.FindAllReferences { function getSpecialPropertyExport(node: BinaryExpression, useLhsSymbol: boolean): ExportedSymbol | undefined { let kind: ExportKind; - switch (getSpecialPropertyAssignmentKind(node)) { - case SpecialPropertyAssignmentKind.ExportsProperty: + switch (getAssignmentDeclarationKind(node)) { + case AssignmentDeclarationKind.ExportsProperty: kind = ExportKind.Named; break; - case SpecialPropertyAssignmentKind.ModuleExports: + case AssignmentDeclarationKind.ModuleExports: kind = ExportKind.ExportEquals; break; default: diff --git a/src/services/jsDoc.ts b/src/services/jsDoc.ts index d9fa8446b13..641eb643f92 100644 --- a/src/services/jsDoc.ts +++ b/src/services/jsDoc.ts @@ -312,7 +312,7 @@ namespace ts.JsDoc { const preamble = "/**" + newLine + indentationStr + " * "; const result = preamble + newLine + - parameterDocComments(parameters, hasJavaScriptFileExtension(sourceFile.fileName), indentationStr, newLine) + + parameterDocComments(parameters, hasJavascriptFileExtension(sourceFile.fileName), indentationStr, newLine) + indentationStr + " */" + (tokenStart === position ? newLine + indentationStr : ""); @@ -383,7 +383,7 @@ namespace ts.JsDoc { case SyntaxKind.BinaryExpression: { const be = commentOwner as BinaryExpression; - if (getSpecialPropertyAssignmentKind(be) === SpecialPropertyAssignmentKind.None) { + if (getAssignmentDeclarationKind(be) === AssignmentDeclarationKind.None) { return "quit"; } const parameters = isFunctionLike(be.right) ? be.right.parameters : emptyArray; diff --git a/src/services/navigationBar.ts b/src/services/navigationBar.ts index 504311a4a2d..ab7c4327bb5 100644 --- a/src/services/navigationBar.ts +++ b/src/services/navigationBar.ts @@ -270,17 +270,17 @@ namespace ts.NavigationBar { break; case SyntaxKind.BinaryExpression: { - const special = getSpecialPropertyAssignmentKind(node as BinaryExpression); + const special = getAssignmentDeclarationKind(node as BinaryExpression); switch (special) { - case SpecialPropertyAssignmentKind.ExportsProperty: - case SpecialPropertyAssignmentKind.ModuleExports: - case SpecialPropertyAssignmentKind.PrototypeProperty: - case SpecialPropertyAssignmentKind.Prototype: + case AssignmentDeclarationKind.ExportsProperty: + case AssignmentDeclarationKind.ModuleExports: + case AssignmentDeclarationKind.PrototypeProperty: + case AssignmentDeclarationKind.Prototype: addNodeWithRecursiveChild(node, (node as BinaryExpression).right); return; - case SpecialPropertyAssignmentKind.ThisProperty: - case SpecialPropertyAssignmentKind.Property: - case SpecialPropertyAssignmentKind.None: + case AssignmentDeclarationKind.ThisProperty: + case AssignmentDeclarationKind.Property: + case AssignmentDeclarationKind.None: break; default: Debug.assertNever(special); diff --git a/src/services/refactors/extractSymbol.ts b/src/services/refactors/extractSymbol.ts index 93baf2b4209..96b5ba18070 100644 --- a/src/services/refactors/extractSymbol.ts +++ b/src/services/refactors/extractSymbol.ts @@ -719,7 +719,7 @@ namespace ts.refactor.extractSymbol { // Make a unique name for the extracted function const file = scope.getSourceFile(); const functionNameText = getUniqueName(isClassLike(scope) ? "newMethod" : "newFunction", file); - const isJS = isInJavaScriptFile(scope); + const isJS = isInJSFile(scope); const functionName = createIdentifier(functionNameText); @@ -1006,7 +1006,7 @@ namespace ts.refactor.extractSymbol { // Make a unique name for the extracted variable const file = scope.getSourceFile(); const localNameText = getUniqueName(isClassLike(scope) ? "newProperty" : "newLocal", file); - const isJS = isInJavaScriptFile(scope); + const isJS = isInJSFile(scope); const variableType = isJS || !checker.isContextSensitive(node) ? undefined @@ -1424,7 +1424,7 @@ namespace ts.refactor.extractSymbol { if (expressionDiagnostic) { constantErrors.push(expressionDiagnostic); } - if (isClassLike(scope) && isInJavaScriptFile(scope)) { + if (isClassLike(scope) && isInJSFile(scope)) { constantErrors.push(createDiagnosticForNode(scope, Messages.cannotExtractToJSClass)); } if (isArrowFunction(scope) && !isBlock(scope.body)) { diff --git a/src/services/refactors/generateGetAccessorAndSetAccessor.ts b/src/services/refactors/generateGetAccessorAndSetAccessor.ts index e39eb20f8d8..57b25445f5d 100644 --- a/src/services/refactors/generateGetAccessorAndSetAccessor.ts +++ b/src/services/refactors/generateGetAccessorAndSetAccessor.ts @@ -41,7 +41,7 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor { const fieldInfo = getConvertibleFieldAtPosition(context); if (!fieldInfo) return undefined; - const isJS = isSourceFileJavaScript(file); + const isJS = isSourceFileJS(file); const changeTracker = textChanges.ChangeTracker.fromContext(context); const { isStatic, isReadonly, fieldName, accessorName, originalName, type, container, declaration, renameAccessor } = fieldInfo; diff --git a/src/services/refactors/moveToNewFile.ts b/src/services/refactors/moveToNewFile.ts index 9953293e3d1..8b6af714892 100644 --- a/src/services/refactors/moveToNewFile.ts +++ b/src/services/refactors/moveToNewFile.ts @@ -657,7 +657,7 @@ namespace ts.refactor { case SyntaxKind.ExpressionStatement: { const { expression } = statement as ExpressionStatement; - return isBinaryExpression(expression) && getSpecialPropertyAssignmentKind(expression) === SpecialPropertyAssignmentKind.ExportsProperty + return isBinaryExpression(expression) && getAssignmentDeclarationKind(expression) === AssignmentDeclarationKind.ExportsProperty ? cb(statement as TopLevelExpressionStatement) : undefined; } diff --git a/src/services/services.ts b/src/services/services.ts index dcc321b00d5..7f2ac2bcc81 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -760,7 +760,7 @@ namespace ts { break; case SyntaxKind.BinaryExpression: - if (getSpecialPropertyAssignmentKind(node as BinaryExpression) !== SpecialPropertyAssignmentKind.None) { + if (getAssignmentDeclarationKind(node as BinaryExpression) !== AssignmentDeclarationKind.None) { addDeclaration(node as BinaryExpression); } // falls through diff --git a/src/services/signatureHelp.ts b/src/services/signatureHelp.ts index b6174be75e0..29a2b728db2 100644 --- a/src/services/signatureHelp.ts +++ b/src/services/signatureHelp.ts @@ -50,7 +50,7 @@ namespace ts.SignatureHelp { if (!candidateInfo) { // We didn't have any sig help items produced by the TS compiler. If this is a JS // file, then see if we can figure out anything better. - return isSourceFileJavaScript(sourceFile) ? createJavaScriptSignatureHelpItems(argumentInfo, program, cancellationToken) : undefined; + return isSourceFileJS(sourceFile) ? createJSSignatureHelpItems(argumentInfo, program, cancellationToken) : undefined; } return typeChecker.runWithCancellationToken(cancellationToken, typeChecker => @@ -115,7 +115,7 @@ namespace ts.SignatureHelp { } } - function createJavaScriptSignatureHelpItems(argumentInfo: ArgumentListInfo, program: Program, cancellationToken: CancellationToken): SignatureHelpItems | undefined { + function createJSSignatureHelpItems(argumentInfo: ArgumentListInfo, program: Program, cancellationToken: CancellationToken): SignatureHelpItems | undefined { if (argumentInfo.invocation.kind === InvocationKind.Contextual) return undefined; // See if we can find some symbol with the call expression name that has call signatures. const expression = getExpressionFromInvocation(argumentInfo.invocation); diff --git a/src/services/suggestionDiagnostics.ts b/src/services/suggestionDiagnostics.ts index 167bcb6bbac..d4aec1b1c6f 100644 --- a/src/services/suggestionDiagnostics.ts +++ b/src/services/suggestionDiagnostics.ts @@ -11,7 +11,7 @@ namespace ts { diags.push(createDiagnosticForNode(getErrorNodeFromCommonJsIndicator(sourceFile.commonJsModuleIndicator), Diagnostics.File_is_a_CommonJS_module_it_may_be_converted_to_an_ES6_module)); } - const isJsFile = isSourceFileJavaScript(sourceFile); + const isJsFile = isSourceFileJS(sourceFile); check(sourceFile); @@ -36,7 +36,7 @@ namespace ts { if (isJsFile) { switch (node.kind) { case SyntaxKind.FunctionExpression: - const decl = getDeclarationOfJSInitializer(node); + const decl = getDeclarationOfExpando(node); if (decl) { const symbol = decl.symbol; if (symbol && (symbol.exports && symbol.exports.size || symbol.members && symbol.members.size)) { @@ -86,8 +86,8 @@ namespace ts { case SyntaxKind.ExpressionStatement: { const { expression } = statement as ExpressionStatement; if (!isBinaryExpression(expression)) return isRequireCall(expression, /*checkArgumentIsStringLiteralLike*/ true); - const kind = getSpecialPropertyAssignmentKind(expression); - return kind === SpecialPropertyAssignmentKind.ExportsProperty || kind === SpecialPropertyAssignmentKind.ModuleExports; + const kind = getAssignmentDeclarationKind(expression); + return kind === AssignmentDeclarationKind.ExportsProperty || kind === AssignmentDeclarationKind.ModuleExports; } default: return false; diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 1c10bc983fd..40a9936b605 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -355,23 +355,23 @@ namespace ts { case SyntaxKind.NamespaceImport: return ScriptElementKind.alias; case SyntaxKind.BinaryExpression: - const kind = getSpecialPropertyAssignmentKind(node as BinaryExpression); + const kind = getAssignmentDeclarationKind(node as BinaryExpression); const { right } = node as BinaryExpression; switch (kind) { - case SpecialPropertyAssignmentKind.None: + case AssignmentDeclarationKind.None: return ScriptElementKind.unknown; - case SpecialPropertyAssignmentKind.ExportsProperty: - case SpecialPropertyAssignmentKind.ModuleExports: + case AssignmentDeclarationKind.ExportsProperty: + case AssignmentDeclarationKind.ModuleExports: const rightKind = getNodeKind(right); return rightKind === ScriptElementKind.unknown ? ScriptElementKind.constElement : rightKind; - case SpecialPropertyAssignmentKind.PrototypeProperty: + case AssignmentDeclarationKind.PrototypeProperty: return isFunctionExpression(right) ? ScriptElementKind.memberFunctionElement : ScriptElementKind.memberVariableElement; - case SpecialPropertyAssignmentKind.ThisProperty: + case AssignmentDeclarationKind.ThisProperty: return ScriptElementKind.memberVariableElement; // property - case SpecialPropertyAssignmentKind.Property: + case AssignmentDeclarationKind.Property: // static method / property return isFunctionExpression(right) ? ScriptElementKind.memberFunctionElement : ScriptElementKind.memberVariableElement; - case SpecialPropertyAssignmentKind.Prototype: + case AssignmentDeclarationKind.Prototype: return ScriptElementKind.localClassElement; default: { assertType(kind); diff --git a/src/testRunner/unittests/moduleResolution.ts b/src/testRunner/unittests/moduleResolution.ts index 7a9e4278c57..e12e60e49ea 100644 --- a/src/testRunner/unittests/moduleResolution.ts +++ b/src/testRunner/unittests/moduleResolution.ts @@ -83,7 +83,7 @@ namespace ts { describe("Node module resolution - relative paths", () => { function testLoadAsFile(containingFileName: string, moduleFileNameNoExt: string, moduleName: string): void { - for (const ext of supportedTypeScriptExtensions) { + for (const ext of supportedTypescriptExtensions) { test(ext, /*hasDirectoryExists*/ false); test(ext, /*hasDirectoryExists*/ true); } @@ -96,7 +96,7 @@ namespace ts { const failedLookupLocations: string[] = []; const dir = getDirectoryPath(containingFileName); - for (const e of supportedTypeScriptExtensions) { + for (const e of supportedTypescriptExtensions) { if (e === ext) { break; } @@ -137,7 +137,7 @@ namespace ts { const resolution = nodeModuleNameResolver(moduleName, containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, packageJson, moduleFile)); checkResolvedModule(resolution.resolvedModule, createResolvedModule(moduleFile.name)); // expect three failed lookup location - attempt to load module as file with all supported extensions - assert.equal(resolution.failedLookupLocations.length, supportedTypeScriptExtensions.length); + assert.equal(resolution.failedLookupLocations.length, supportedTypescriptExtensions.length); } } diff --git a/src/tsserver/server.ts b/src/tsserver/server.ts index 95b228f6e96..9c05bf0cf16 100644 --- a/src/tsserver/server.ts +++ b/src/tsserver/server.ts @@ -891,7 +891,7 @@ namespace ts.server { sys.require = (initialDir: string, moduleName: string): RequireResult => { try { - return { module: require(resolveJavaScriptModule(moduleName, initialDir, sys)), error: undefined }; + return { module: require(resolveJavascriptModule(moduleName, initialDir, sys)), error: undefined }; } catch (error) { return { module: undefined, error }; diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 672b93e55da..9465a512a1f 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -2059,7 +2059,7 @@ declare namespace ts { ExportStar = 8388608, Optional = 16777216, Transient = 33554432, - JSContainer = 67108864, + Assignment = 67108864, ModuleExports = 134217728, Enum = 384, Variable = 3, diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 5d093382f54..66ba75bbd93 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -2059,7 +2059,7 @@ declare namespace ts { ExportStar = 8388608, Optional = 16777216, Transient = 33554432, - JSContainer = 67108864, + Assignment = 67108864, ModuleExports = 134217728, Enum = 384, Variable = 3, From 2f8a646f8e5bb0331c4b52b4596806894817994a Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Wed, 12 Sep 2018 12:21:50 -0700 Subject: [PATCH 38/83] isExpandoFunctionDeclaration only checks values (#27052) Previously it checked types too, which caused a crash because types don't have valueDeclaration set. But expando functions can't export types, only values. --- src/compiler/checker.ts | 2 +- .../reference/declarationEmitOfFuncspace.js | 23 +++++++++++++++++++ .../declarationEmitOfFuncspace.symbols | 16 +++++++++++++ .../declarationEmitOfFuncspace.types | 13 +++++++++++ .../compiler/declarationEmitOfFuncspace.ts | 9 ++++++++ 5 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/declarationEmitOfFuncspace.js create mode 100644 tests/baselines/reference/declarationEmitOfFuncspace.symbols create mode 100644 tests/baselines/reference/declarationEmitOfFuncspace.types create mode 100644 tests/cases/compiler/declarationEmitOfFuncspace.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 974c74029eb..6bd0c0409d4 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -28154,7 +28154,7 @@ namespace ts { if (!symbol || !(symbol.flags & SymbolFlags.Function)) { return false; } - return !!forEachEntry(getExportsOfSymbol(symbol), p => isPropertyAccessExpression(p.valueDeclaration)); + return !!forEachEntry(getExportsOfSymbol(symbol), p => p.flags & SymbolFlags.Value && isPropertyAccessExpression(p.valueDeclaration)); } function getPropertiesOfContainerFunction(node: Declaration): Symbol[] { diff --git a/tests/baselines/reference/declarationEmitOfFuncspace.js b/tests/baselines/reference/declarationEmitOfFuncspace.js new file mode 100644 index 00000000000..5a60a51d7e6 --- /dev/null +++ b/tests/baselines/reference/declarationEmitOfFuncspace.js @@ -0,0 +1,23 @@ +//// [expando.ts] +// #27032 +function ExpandoMerge(n: number) { + return n; +} +namespace ExpandoMerge { + export interface I { } +} + + +//// [expando.js] +// #27032 +function ExpandoMerge(n) { + return n; +} + + +//// [expando.d.ts] +declare function ExpandoMerge(n: number): number; +declare namespace ExpandoMerge { + interface I { + } +} diff --git a/tests/baselines/reference/declarationEmitOfFuncspace.symbols b/tests/baselines/reference/declarationEmitOfFuncspace.symbols new file mode 100644 index 00000000000..cd86d57ae68 --- /dev/null +++ b/tests/baselines/reference/declarationEmitOfFuncspace.symbols @@ -0,0 +1,16 @@ +=== tests/cases/compiler/expando.ts === +// #27032 +function ExpandoMerge(n: number) { +>ExpandoMerge : Symbol(ExpandoMerge, Decl(expando.ts, 0, 0), Decl(expando.ts, 3, 1)) +>n : Symbol(n, Decl(expando.ts, 1, 22)) + + return n; +>n : Symbol(n, Decl(expando.ts, 1, 22)) +} +namespace ExpandoMerge { +>ExpandoMerge : Symbol(ExpandoMerge, Decl(expando.ts, 0, 0), Decl(expando.ts, 3, 1)) + + export interface I { } +>I : Symbol(I, Decl(expando.ts, 4, 24)) +} + diff --git a/tests/baselines/reference/declarationEmitOfFuncspace.types b/tests/baselines/reference/declarationEmitOfFuncspace.types new file mode 100644 index 00000000000..030ffa34a58 --- /dev/null +++ b/tests/baselines/reference/declarationEmitOfFuncspace.types @@ -0,0 +1,13 @@ +=== tests/cases/compiler/expando.ts === +// #27032 +function ExpandoMerge(n: number) { +>ExpandoMerge : (n: number) => number +>n : number + + return n; +>n : number +} +namespace ExpandoMerge { + export interface I { } +} + diff --git a/tests/cases/compiler/declarationEmitOfFuncspace.ts b/tests/cases/compiler/declarationEmitOfFuncspace.ts new file mode 100644 index 00000000000..9648178ae81 --- /dev/null +++ b/tests/cases/compiler/declarationEmitOfFuncspace.ts @@ -0,0 +1,9 @@ +// @declaration: true +// @Filename: expando.ts +// #27032 +function ExpandoMerge(n: number) { + return n; +} +namespace ExpandoMerge { + export interface I { } +} From 5553f36c9da286befeeee8250fc8668dc8c4ed21 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Wed, 12 Sep 2018 12:30:48 -0700 Subject: [PATCH 39/83] Instead of queueing build for downstream projects right when invalidating project, do it after build for invalidated project is complete --- src/compiler/tsbuild.ts | 49 +++++++++++++---------------- src/testRunner/unittests/tsbuild.ts | 18 ++++++++++- 2 files changed, 38 insertions(+), 29 deletions(-) diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts index 1aaa3e07f1c..415e04adae9 100644 --- a/src/compiler/tsbuild.ts +++ b/src/compiler/tsbuild.ts @@ -783,10 +783,7 @@ namespace ts { diagnostics.removeKey(resolved); } - if (addProjToQueue(resolved, reloadLevel)) { - // TODO: instead of adding the dependent project to queue right away postpone this - queueBuildForDownstreamReferences(resolved); - } + addProjToQueue(resolved, reloadLevel); } /** @@ -797,10 +794,8 @@ namespace ts { if (value === undefined) { projectPendingBuild.setValue(proj, reloadLevel || ConfigFileProgramReloadLevel.None); invalidatedProjectQueue.push(proj); - return true; } - - if (value < (reloadLevel || ConfigFileProgramReloadLevel.None)) { + else if (value < (reloadLevel || ConfigFileProgramReloadLevel.None)) { projectPendingBuild.setValue(proj, reloadLevel || ConfigFileProgramReloadLevel.None); } } @@ -823,20 +818,6 @@ namespace ts { return !!projectPendingBuild.getSize(); } - // Mark all downstream projects of this one needing to be built "later" - function queueBuildForDownstreamReferences(root: ResolvedConfigFileName) { - const dependencyGraph = getGlobalDependencyGraph(); - const referencingProjects = dependencyGraph.referencingProjectsMap.getValue(root); - if (!referencingProjects) return; - // Always use build order to queue projects - for (const project of dependencyGraph.buildQueue) { - // Can skip circular references - if (referencingProjects.hasKey(project) && addProjToQueue(project)) { - queueBuildForDownstreamReferences(project); - } - } - } - function scheduleBuildInvalidatedProject() { if (!hostWithWatch.setTimeout || !hostWithWatch.clearTimeout) { return; @@ -910,7 +891,20 @@ namespace ts { return; } - buildSingleProject(resolved); + const buildResult = buildSingleProject(resolved); + // If declaration output changed then only queue in build for downstream projects + if (!(buildResult & BuildResultFlags.DeclarationOutputUnchanged)) { + const dependencyGraph = getGlobalDependencyGraph(); + const referencingProjects = dependencyGraph.referencingProjectsMap.getValue(resolved); + if (!referencingProjects) return; + // Always use build order to queue projects + for (const project of dependencyGraph.buildQueue) { + // Can skip circular references + if (referencingProjects.hasKey(project)) { + addProjToQueue(project); + } + } + } } function createDependencyGraph(roots: ResolvedConfigFileName[]): DependencyGraph { @@ -928,7 +922,7 @@ namespace ts { referencingProjectsMap }; - function visit(projPath: ResolvedConfigFileName, inCircularContext = false) { + function visit(projPath: ResolvedConfigFileName, inCircularContext?: boolean) { // Already visited if (permanentMarks.hasKey(projPath)) return; // Circular @@ -1032,14 +1026,13 @@ namespace ts { let anyDtsChanged = false; program.emit(/*targetSourceFile*/ undefined, (fileName, content, writeBom, onError) => { let priorChangeTime: Date | undefined; - - if (!anyDtsChanged && isDeclarationFile(fileName) && host.fileExists(fileName)) { - if (host.readFile(fileName) === content) { - // Check for unchanged .d.ts files - resultFlags &= ~BuildResultFlags.DeclarationOutputUnchanged; + if (!anyDtsChanged && isDeclarationFile(fileName)) { + // Check for unchanged .d.ts files + if (host.fileExists(fileName) && host.readFile(fileName) === content) { priorChangeTime = host.getModifiedTime(fileName); } else { + resultFlags &= ~BuildResultFlags.DeclarationOutputUnchanged; anyDtsChanged = true; } } diff --git a/src/testRunner/unittests/tsbuild.ts b/src/testRunner/unittests/tsbuild.ts index a9993aabc40..6ddd6d069f7 100644 --- a/src/testRunner/unittests/tsbuild.ts +++ b/src/testRunner/unittests/tsbuild.ts @@ -210,10 +210,26 @@ namespace ts { assert.equal(fs.statSync("/src/logic/index.js").mtimeMs, time(), "JS file should have been rebuilt"); assert.isBelow(fs.statSync("/src/tests/index.js").mtimeMs, time(), "Downstream JS file should *not* have been rebuilt"); + // Does not build tests or core because there is no change in declaration file + tick(); + builder.buildInvalidatedProject(); + assert.isBelow(fs.statSync("/src/tests/index.js").mtimeMs, time(), "Downstream JS file should have been rebuilt"); + assert.isBelow(fs.statSync("/src/core/index.js").mtimeMs, time(), "Upstream JS file should not have been rebuilt"); + + // Rebuild this project + tick(); + fs.writeFileSync("/src/logic/index.ts", `${fs.readFileSync("/src/logic/index.ts")} +export class cNew {}`); + builder.invalidateProject("/src/logic"); + builder.buildInvalidatedProject(); + // The file should be updated + assert.equal(fs.statSync("/src/logic/index.js").mtimeMs, time(), "JS file should have been rebuilt"); + assert.isBelow(fs.statSync("/src/tests/index.js").mtimeMs, time(), "Downstream JS file should *not* have been rebuilt"); + // Build downstream projects should update 'tests', but not 'core' tick(); builder.buildInvalidatedProject(); - assert.equal(fs.statSync("/src/tests/index.js").mtimeMs, time(), "Downstream JS file should have been rebuilt"); + assert.isBelow(fs.statSync("/src/tests/index.js").mtimeMs, time(), "Downstream JS file should have been rebuilt"); assert.isBelow(fs.statSync("/src/core/index.js").mtimeMs, time(), "Upstream JS file should not have been rebuilt"); }); }); From 906fbae37b2310dcb3b5d1bc3b36c763cd957846 Mon Sep 17 00:00:00 2001 From: Benjamin Lichtman Date: Wed, 12 Sep 2018 14:47:06 -0700 Subject: [PATCH 40/83] Handle promise handler block bodies with no return and other cleanup --- .../codefixes/convertToAsyncFunction.ts | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/services/codefixes/convertToAsyncFunction.ts b/src/services/codefixes/convertToAsyncFunction.ts index d8d6fa05d1f..235f50226eb 100644 --- a/src/services/codefixes/convertToAsyncFunction.ts +++ b/src/services/codefixes/convertToAsyncFunction.ts @@ -82,7 +82,7 @@ namespace ts.codefix { } for (const statement of returnStatements) { - forEachChild(statement, function visit(node: Node) { + forEachChild(statement, function visit(node) { if (isCallExpression(node)) { startTransformation(node, statement); } @@ -179,7 +179,7 @@ namespace ts.codefix { // Note - the choice of the last call signature is arbitrary if (lastCallSignature && lastCallSignature.parameters.length && !synthNamesMap.has(symbolIdString)) { const name = lastCallSignature.parameters[0].name; - const synthName = getNewNameIfConflict(createIdentifier(lastCallSignature.parameters[0].name), allVarNames); + const synthName = getNewNameIfConflict(createIdentifier(name), allVarNames); synthNamesMap.set(symbolIdString, synthName); allVarNames.push({ identifier: synthName.identifier, symbol, originalName: name }); } @@ -404,8 +404,13 @@ namespace ts.codefix { // Arrow functions with block bodies { } will enter this control flow if (isFunctionLikeDeclaration(func) && func.body && isBlock(func.body) && func.body.statements) { let refactoredStmts: Statement[] = []; + let seenReturnStatement = false; for (const statement of func.body.statements) { + if (isReturnStatement(statement)) { + seenReturnStatement = true; + } + if (getReturnStatementsWithPromiseHandlers(statement).length) { refactoredStmts = refactoredStmts.concat(getInnerTransformationBody(transformer, [statement], prevArgName)); } @@ -415,7 +420,7 @@ namespace ts.codefix { } return shouldReturn ? getSynthesizedDeepClones(createNodeArray(refactoredStmts)) : - removeReturns(createNodeArray(refactoredStmts), prevArgName!.identifier, transformer.constIdentifiers); + removeReturns(createNodeArray(refactoredStmts), prevArgName!.identifier, transformer.constIdentifiers, seenReturnStatement); } else { const funcBody = (func).body; @@ -443,12 +448,12 @@ namespace ts.codefix { } function getLastCallSignature(type: Type, checker: TypeChecker): Signature | undefined { - const callSignatures = type && checker.getSignaturesOfType(type, SignatureKind.Call); + const callSignatures = checker.getSignaturesOfType(type, SignatureKind.Call); return callSignatures && callSignatures[callSignatures.length - 1]; } - function removeReturns(stmts: NodeArray, prevArgName: Identifier, constIdentifiers: Identifier[]): NodeArray { + function removeReturns(stmts: NodeArray, prevArgName: Identifier, constIdentifiers: Identifier[], seenReturnStatement: boolean): NodeArray { const ret: Statement[] = []; for (const stmt of stmts) { if (isReturnStatement(stmt)) { @@ -462,6 +467,12 @@ namespace ts.codefix { } } + // if block has no return statement, need to define prevArgName as undefined to prevent undeclared variables + if (!seenReturnStatement) { + ret.push(createVariableStatement(/*modifiers*/ undefined, + (createVariableDeclarationList([createVariableDeclaration(prevArgName, /*type*/ undefined, createIdentifier("undefined"))], getFlagOfIdentifier(prevArgName, constIdentifiers))))); + } + return createNodeArray(ret); } From 95e5f7d55a5a75581093024b5c8419625db2ff9b Mon Sep 17 00:00:00 2001 From: Benjamin Lichtman Date: Wed, 12 Sep 2018 14:47:13 -0700 Subject: [PATCH 41/83] Add and update tests --- .../unittests/convertToAsyncFunction.ts | 9 +++++++++ ...vertToAsyncFunction_InnerVarNameConflict.ts | 1 + .../convertToAsyncFunction_bindingPattern.ts | 18 ++++++++++++++++++ 3 files changed, 28 insertions(+) create mode 100644 tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_bindingPattern.ts diff --git a/src/testRunner/unittests/convertToAsyncFunction.ts b/src/testRunner/unittests/convertToAsyncFunction.ts index d1655824216..f774c58de94 100644 --- a/src/testRunner/unittests/convertToAsyncFunction.ts +++ b/src/testRunner/unittests/convertToAsyncFunction.ts @@ -1198,6 +1198,15 @@ const [#|foo|] = function () { function [#|f|]() { return Promise.resolve().then(x => 1).catch(x => "a").then(x => !!x); } +`); + + _testConvertToAsyncFunction("convertToAsyncFunction_bindingPattern", ` +function [#|f|]():Promise { + return fetch('https://typescriptlang.org').then(res); +} +function res({ status, trailer }){ + console.log(status); +} `); }); diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_InnerVarNameConflict.ts b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_InnerVarNameConflict.ts index 119d9d408bb..72e4a66fb55 100644 --- a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_InnerVarNameConflict.ts +++ b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_InnerVarNameConflict.ts @@ -13,5 +13,6 @@ function /*[#|*/f/*|]*/(): Promise { async function f(): Promise { const resp = await fetch("https://typescriptlang.org"); var blob = resp.blob().then(blob_1 => blob_1.byteOffset).catch(err => 'Error'); + const blob_2 = undefined; return blob_2.toString(); } diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_bindingPattern.ts b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_bindingPattern.ts new file mode 100644 index 00000000000..f7d26faa980 --- /dev/null +++ b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_bindingPattern.ts @@ -0,0 +1,18 @@ +// ==ORIGINAL== + +function /*[#|*/f/*|]*/():Promise { + return fetch('https://typescriptlang.org').then(res); +} +function res({ status, trailer }){ + console.log(status); +} + +// ==ASYNC FUNCTION::Convert to async function== + +async function f():Promise { + const __0 = await fetch('https://typescriptlang.org'); + return res(__0); +} +function res({ status, trailer }){ + console.log(status); +} From ef2024a487e2178f8978e7a7cefc4db92becdb0d Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Wed, 12 Sep 2018 14:58:08 -0700 Subject: [PATCH 42/83] Handle circular project references --- src/compiler/tsbuild.ts | 20 ++- src/testRunner/unittests/tsbuildWatchMode.ts | 143 +++++++++++-------- 2 files changed, 99 insertions(+), 64 deletions(-) diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts index 415e04adae9..763c62deccf 100644 --- a/src/compiler/tsbuild.ts +++ b/src/compiler/tsbuild.ts @@ -61,6 +61,7 @@ namespace ts { OutOfDateWithUpstream, UpstreamOutOfDate, UpstreamBlocked, + ComputingUpstream, /** * Projects with no outputs (i.e. "solution" files) @@ -76,6 +77,7 @@ namespace ts { | Status.OutOfDateWithUpstream | Status.UpstreamOutOfDate | Status.UpstreamBlocked + | Status.ComputingUpstream | Status.ContainerOnly; export namespace Status { @@ -145,6 +147,13 @@ namespace ts { upstreamProjectName: string; } + /** + * Computing status of upstream projects referenced + */ + export interface ComputingUpstream { + type: UpToDateStatusType.ComputingUpstream; + } + /** * One or more of the project's outputs is older than the newest output of * an upstream project. @@ -689,11 +698,17 @@ namespace ts { let usesPrepend = false; let upstreamChangedProject: string | undefined; if (project.projectReferences) { + projectStatus.setValue(project.options.configFilePath as ResolvedConfigFileName, { type: UpToDateStatusType.ComputingUpstream }); for (const ref of project.projectReferences) { usesPrepend = usesPrepend || !!(ref.prepend); const resolvedRef = resolveProjectReferencePath(ref); const refStatus = getUpToDateStatus(parseConfigFile(resolvedRef)); + // Its a circular reference ignore the status of this project + if (refStatus.type === UpToDateStatusType.ComputingUpstream) { + continue; + } + // An upstream project is blocked if (refStatus.type === UpToDateStatusType.Unbuildable) { return { @@ -928,9 +943,10 @@ namespace ts { // Circular if (temporaryMarks.hasKey(projPath)) { if (!inCircularContext) { + // TODO:: Do we report this as error? reportStatus(Diagnostics.Project_references_may_not_form_a_circular_graph_Cycle_detected_Colon_0, circularityReportStack.join("\r\n")); - return; } + return; } temporaryMarks.setValue(projPath, true); @@ -1263,6 +1279,8 @@ namespace ts { status.reason); case UpToDateStatusType.ContainerOnly: // Don't report status on "solution" projects + case UpToDateStatusType.ComputingUpstream: + // Should never leak from getUptoDateStatusWorker break; default: assertType(status); diff --git a/src/testRunner/unittests/tsbuildWatchMode.ts b/src/testRunner/unittests/tsbuildWatchMode.ts index e2abd2a0d04..17e61140b2d 100644 --- a/src/testRunner/unittests/tsbuildWatchMode.ts +++ b/src/testRunner/unittests/tsbuildWatchMode.ts @@ -95,7 +95,7 @@ namespace ts.tscWatch { const allFiles: ReadonlyArray = [libFile, ...core, ...logic, ...tests, ...ui]; const testProjectExpectedWatchedFiles = [core[0], core[1], core[2], ...logic, ...tests].map(f => f.path); - function createSolutionInWatchMode() { + function createSolutionInWatchMode(allFiles: ReadonlyArray) { const host = createWatchedSystem(allFiles, { currentDirectory: projectsLocation }); createSolutionBuilderWithWatch(host, [`${project}/${SubProject.tests}`]); verifyWatches(host); @@ -114,7 +114,7 @@ namespace ts.tscWatch { } it("creates solution in watch mode", () => { - createSolutionInWatchMode(); + createSolutionInWatchMode(allFiles); }); describe("validates the changes and watched files", () => { @@ -124,82 +124,99 @@ namespace ts.tscWatch { content: `export const newFileConst = 30;` }; - function createSolutionInWatchModeToVerifyChanges(additionalFiles?: ReadonlyArray<[SubProject, string]>) { - const host = createSolutionInWatchMode(); - return { host, verifyChangeWithFile, verifyChangeAfterTimeout, verifyWatches }; + function verifyProjectChanges(allFiles: ReadonlyArray) { + function createSolutionInWatchModeToVerifyChanges(additionalFiles?: ReadonlyArray<[SubProject, string]>) { + const host = createSolutionInWatchMode(allFiles); + return { host, verifyChangeWithFile, verifyChangeAfterTimeout, verifyWatches }; - function verifyChangeWithFile(fileName: string, content: string) { - const outputFileStamps = getOutputFileStamps(host, additionalFiles); - host.writeFile(fileName, content); - verifyChangeAfterTimeout(outputFileStamps); + function verifyChangeWithFile(fileName: string, content: string) { + const outputFileStamps = getOutputFileStamps(host, additionalFiles); + host.writeFile(fileName, content); + verifyChangeAfterTimeout(outputFileStamps); + } + + function verifyChangeAfterTimeout(outputFileStamps: OutputFileStamp[]) { + host.checkTimeoutQueueLengthAndRun(1); // Builds core + const changedCore = getOutputFileStamps(host, additionalFiles); + verifyChangedFiles(changedCore, outputFileStamps, [ + ...getOutputFileNames(SubProject.core, "anotherModule"), // This should not be written really + ...getOutputFileNames(SubProject.core, "index"), + ...(additionalFiles ? getOutputFileNames(SubProject.core, newFileWithoutExtension) : emptyArray) + ]); + host.checkTimeoutQueueLengthAndRun(1); // Builds logic + const changedLogic = getOutputFileStamps(host, additionalFiles); + verifyChangedFiles(changedLogic, changedCore, [ + ...getOutputFileNames(SubProject.logic, "index") // Again these need not be written + ]); + host.checkTimeoutQueueLengthAndRun(1); // Builds tests + const changedTests = getOutputFileStamps(host, additionalFiles); + verifyChangedFiles(changedTests, changedLogic, [ + ...getOutputFileNames(SubProject.tests, "index") // Again these need not be written + ]); + host.checkTimeoutQueueLength(0); + checkOutputErrorsIncremental(host, emptyArray); + verifyWatches(); + } + + function verifyWatches() { + checkWatchedFiles(host, additionalFiles ? testProjectExpectedWatchedFiles.concat(newFile.path) : testProjectExpectedWatchedFiles); + checkWatchedDirectories(host, emptyArray, /*recursive*/ false); + checkWatchedDirectories(host, [projectPath(SubProject.core), projectPath(SubProject.logic)], /*recursive*/ true); + } } - function verifyChangeAfterTimeout(outputFileStamps: OutputFileStamp[]) { - host.checkTimeoutQueueLengthAndRun(1); // Builds core - const changedCore = getOutputFileStamps(host, additionalFiles); - verifyChangedFiles(changedCore, outputFileStamps, [ - ...getOutputFileNames(SubProject.core, "anotherModule"), // This should not be written really - ...getOutputFileNames(SubProject.core, "index"), - ...(additionalFiles ? getOutputFileNames(SubProject.core, newFileWithoutExtension) : emptyArray) - ]); - host.checkTimeoutQueueLengthAndRun(1); // Builds logic - const changedLogic = getOutputFileStamps(host, additionalFiles); - verifyChangedFiles(changedLogic, changedCore, [ - ...getOutputFileNames(SubProject.logic, "index") // Again these need not be written - ]); - host.checkTimeoutQueueLengthAndRun(1); // Builds tests - const changedTests = getOutputFileStamps(host, additionalFiles); - verifyChangedFiles(changedTests, changedLogic, [ - ...getOutputFileNames(SubProject.tests, "index") // Again these need not be written - ]); - host.checkTimeoutQueueLength(0); - checkOutputErrorsIncremental(host, emptyArray); - verifyWatches(); - } - - function verifyWatches() { - checkWatchedFiles(host, additionalFiles ? testProjectExpectedWatchedFiles.concat(newFile.path) : testProjectExpectedWatchedFiles); - checkWatchedDirectories(host, emptyArray, /*recursive*/ false); - checkWatchedDirectories(host, [projectPath(SubProject.core), projectPath(SubProject.logic)], /*recursive*/ true); - } - } - - it("change builds changes and reports found errors message", () => { - const { host, verifyChangeWithFile, verifyChangeAfterTimeout } = createSolutionInWatchModeToVerifyChanges(); - verifyChange(`${core[1].content} + it("change builds changes and reports found errors message", () => { + const { host, verifyChangeWithFile, verifyChangeAfterTimeout } = createSolutionInWatchModeToVerifyChanges(); + verifyChange(`${core[1].content} export class someClass { }`); - // Another change requeues and builds it - verifyChange(core[1].content); + // Another change requeues and builds it + verifyChange(core[1].content); - // Two changes together report only single time message: File change detected. Starting incremental compilation... - const outputFileStamps = getOutputFileStamps(host); - const change1 = `${core[1].content} + // Two changes together report only single time message: File change detected. Starting incremental compilation... + const outputFileStamps = getOutputFileStamps(host); + const change1 = `${core[1].content} export class someClass { }`; - host.writeFile(core[1].path, change1); - host.writeFile(core[1].path, `${change1} + host.writeFile(core[1].path, change1); + host.writeFile(core[1].path, `${change1} export class someClass2 { }`); - verifyChangeAfterTimeout(outputFileStamps); + verifyChangeAfterTimeout(outputFileStamps); - function verifyChange(coreContent: string) { - verifyChangeWithFile(core[1].path, coreContent); - } - }); + function verifyChange(coreContent: string) { + verifyChangeWithFile(core[1].path, coreContent); + } + }); - it("builds when new file is added, and its subsequent updates", () => { - const additinalFiles: ReadonlyArray<[SubProject, string]> = [[SubProject.core, newFileWithoutExtension]]; - const { verifyChangeWithFile } = createSolutionInWatchModeToVerifyChanges(additinalFiles); - verifyChange(newFile.content); + it("builds when new file is added, and its subsequent updates", () => { + const additinalFiles: ReadonlyArray<[SubProject, string]> = [[SubProject.core, newFileWithoutExtension]]; + const { verifyChangeWithFile } = createSolutionInWatchModeToVerifyChanges(additinalFiles); + verifyChange(newFile.content); - // Another change requeues and builds it - verifyChange(`${newFile.content} + // Another change requeues and builds it + verifyChange(`${newFile.content} export class someClass2 { }`); - function verifyChange(newFileContent: string) { - verifyChangeWithFile(newFile.path, newFileContent); - } + function verifyChange(newFileContent: string) { + verifyChangeWithFile(newFile.path, newFileContent); + } + }); + } + + describe("with simple project reference graph", () => { + verifyProjectChanges(allFiles); }); + describe("with circular project reference", () => { + const [coreTsconfig, ...otherCoreFiles] = core; + const circularCoreConfig: File = { + path: coreTsconfig.path, + content: JSON.stringify({ + compilerOptions: { composite: true, declaration: true }, + references: [{ path: "../tests", circular: true }] + }) + }; + verifyProjectChanges([libFile, circularCoreConfig, ...otherCoreFiles, ...logic, ...tests]); + }); }); it("watches config files that are not present", () => { From 0319f103f231cc69a667fc7ec20b298ffd268872 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Wed, 12 Sep 2018 15:05:20 -0700 Subject: [PATCH 43/83] Test case to verify the non local change doesnt build referencing projects --- src/testRunner/unittests/tsbuildWatchMode.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/testRunner/unittests/tsbuildWatchMode.ts b/src/testRunner/unittests/tsbuildWatchMode.ts index 17e61140b2d..12c82becef3 100644 --- a/src/testRunner/unittests/tsbuildWatchMode.ts +++ b/src/testRunner/unittests/tsbuildWatchMode.ts @@ -187,6 +187,22 @@ export class someClass2 { }`); } }); + it("non local change does not start build of referencing projects", () => { + const host = createSolutionInWatchMode(allFiles); + const outputFileStamps = getOutputFileStamps(host); + host.writeFile(core[1].path, `${core[1].content} +function foo() { }`); + host.checkTimeoutQueueLengthAndRun(1); // Builds core + const changedCore = getOutputFileStamps(host); + verifyChangedFiles(changedCore, outputFileStamps, [ + ...getOutputFileNames(SubProject.core, "anotherModule"), // This should not be written really + ...getOutputFileNames(SubProject.core, "index"), + ]); + host.checkTimeoutQueueLength(0); + checkOutputErrorsIncremental(host, emptyArray); + verifyWatches(host); + }); + it("builds when new file is added, and its subsequent updates", () => { const additinalFiles: ReadonlyArray<[SubProject, string]> = [[SubProject.core, newFileWithoutExtension]]; const { verifyChangeWithFile } = createSolutionInWatchModeToVerifyChanges(additinalFiles); From 5696384a9fd23d5fcbc93e8bd80eb791f0962ab9 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Wed, 12 Sep 2018 15:38:23 -0700 Subject: [PATCH 44/83] Handle prepend output to be emitted in downstream project even if declaration file doesnt change --- src/compiler/tsbuild.ts | 28 ++++---- src/testRunner/unittests/tsbuildWatchMode.ts | 75 ++++++++++++++++++++ 2 files changed, 89 insertions(+), 14 deletions(-) diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts index 763c62deccf..d7eb648bca2 100644 --- a/src/compiler/tsbuild.ts +++ b/src/compiler/tsbuild.ts @@ -13,7 +13,8 @@ namespace ts { interface DependencyGraph { buildQueue: ResolvedConfigFileName[]; - referencingProjectsMap: ConfigFileMap>; + /** value in config File map is true if project is referenced using prepend */ + referencingProjectsMap: ConfigFileMap>; } export interface BuildOptions { @@ -907,17 +908,16 @@ namespace ts { } const buildResult = buildSingleProject(resolved); - // If declaration output changed then only queue in build for downstream projects - if (!(buildResult & BuildResultFlags.DeclarationOutputUnchanged)) { - const dependencyGraph = getGlobalDependencyGraph(); - const referencingProjects = dependencyGraph.referencingProjectsMap.getValue(resolved); - if (!referencingProjects) return; - // Always use build order to queue projects - for (const project of dependencyGraph.buildQueue) { - // Can skip circular references - if (referencingProjects.hasKey(project)) { - addProjToQueue(project); - } + const dependencyGraph = getGlobalDependencyGraph(); + const referencingProjects = dependencyGraph.referencingProjectsMap.getValue(resolved); + if (!referencingProjects) return; + // Always use build order to queue projects + for (const project of dependencyGraph.buildQueue) { + const prepend = referencingProjects.getValue(project); + // If the project is referenced with prepend, always build downstream projectm, + // otherwise queue it only if declaration output changed + if (prepend || (prepend !== undefined && !(buildResult & BuildResultFlags.DeclarationOutputUnchanged))) { + addProjToQueue(project); } } } @@ -927,7 +927,7 @@ namespace ts { const permanentMarks = createFileMap(toPath); const circularityReportStack: string[] = []; const buildOrder: ResolvedConfigFileName[] = []; - const referencingProjectsMap = createFileMap>(toPath); + const referencingProjectsMap = createFileMap>(toPath); for (const root of roots) { visit(root); } @@ -958,7 +958,7 @@ namespace ts { visit(resolvedRefPath, inCircularContext || ref.circular); // Get projects referencing resolvedRefPath and add projPath to it const referencingProjects = getOrCreateValueFromConfigFileMap(referencingProjectsMap, resolvedRefPath, () => createFileMap(toPath)); - referencingProjects.setValue(projPath, true); + referencingProjects.setValue(projPath, !!ref.prepend); } } diff --git a/src/testRunner/unittests/tsbuildWatchMode.ts b/src/testRunner/unittests/tsbuildWatchMode.ts index 12c82becef3..697d14f72ba 100644 --- a/src/testRunner/unittests/tsbuildWatchMode.ts +++ b/src/testRunner/unittests/tsbuildWatchMode.ts @@ -276,6 +276,81 @@ export class someClass2 { }`); verifyWatches(host); }); + it("when referenced using prepend, builds referencing project even for non local change", () => { + const coreTsConfig: File = { + path: core[0].path, + content: JSON.stringify({ + compilerOptions: { composite: true, declaration: true, outFile: "index.js" } + }) + }; + const coreIndex: File = { + path: core[1].path, + content: `function foo() { return 10; }` + }; + const logicTsConfig: File = { + path: logic[0].path, + content: JSON.stringify({ + compilerOptions: { composite: true, declaration: true, outFile: "index.js" }, + references: [{ path: "../core", prepend: true }] + }) + }; + const logicIndex: File = { + path: logic[1].path, + content: `function bar() { return foo() + 1 };` + }; + + const projectFiles = [coreTsConfig, coreIndex, logicTsConfig, logicIndex]; + const host = createWatchedSystem([libFile, ...projectFiles], { currentDirectory: projectsLocation }); + createSolutionBuilderWithWatch(host, [`${project}/${SubProject.logic}`]); + verifyWatches(); + checkOutputErrorsInitial(host, emptyArray); + const outputFileStamps = getOutputFileStamps(); + for (const stamp of outputFileStamps) { + assert.isDefined(stamp[1], `${stamp[0]} expected to be present`); + } + + // Make non local change + verifyChangeInCore(`${coreIndex.content} +function myFunc() { return 10; }`); + + // Make local change to function bar + verifyChangeInCore(`${coreIndex.content} +function myFunc() { return 100; }`); + + function verifyChangeInCore(content: string) { + const outputFileStamps = getOutputFileStamps(); + host.writeFile(coreIndex.path, content); + + host.checkTimeoutQueueLengthAndRun(1); // Builds core + const changedCore = getOutputFileStamps(); + verifyChangedFiles(changedCore, outputFileStamps, [ + ...getOutputFileNames(SubProject.core, "index") + ]); + host.checkTimeoutQueueLengthAndRun(1); // Builds logic + const changedLogic = getOutputFileStamps(); + verifyChangedFiles(changedLogic, changedCore, [ + ...getOutputFileNames(SubProject.logic, "index") + ]); + host.checkTimeoutQueueLength(0); + checkOutputErrorsIncremental(host, emptyArray); + verifyWatches(); + } + + function getOutputFileStamps(): OutputFileStamp[] { + const result = [ + ...getOutputStamps(host, SubProject.core, "index"), + ...getOutputStamps(host, SubProject.logic, "index"), + ]; + return result; + } + + function verifyWatches() { + checkWatchedFiles(host, projectFiles.map(f => f.path)); + checkWatchedDirectories(host, emptyArray, /*recursive*/ false); + checkWatchedDirectories(host, [projectPath(SubProject.core), projectPath(SubProject.logic)], /*recursive*/ true); + } + }); + // TODO: write tests reporting errors but that will have more involved work since file }); } From 614423b2870f037f8046ac8d5b54b392c1fb7ee8 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Wed, 12 Sep 2018 16:21:17 -0700 Subject: [PATCH 45/83] Fix this-type in prototype-assigned object literals (#26925) * Fix this-type in prototype-assigned object literals Some cases were missing from tryGetThisTypeAt. Fixes #26831 * Lookup this in JS only for @constructor+prototype assignments --- src/compiler/checker.ts | 51 ++++-- .../reference/jsdocTemplateTag5.errors.txt | 77 --------- .../reference/jsdocTemplateTag5.symbols | 9 +- .../reference/jsdocTemplateTag5.types | 24 +-- .../typeFromPrototypeAssignment.errors.txt | 45 ++++++ .../typeFromPrototypeAssignment.symbols | 122 ++++++++++++++ .../typeFromPrototypeAssignment.types | 149 ++++++++++++++++++ .../salsa/typeFromPrototypeAssignment.ts | 44 ++++++ 8 files changed, 416 insertions(+), 105 deletions(-) delete mode 100644 tests/baselines/reference/jsdocTemplateTag5.errors.txt create mode 100644 tests/baselines/reference/typeFromPrototypeAssignment.errors.txt create mode 100644 tests/baselines/reference/typeFromPrototypeAssignment.symbols create mode 100644 tests/baselines/reference/typeFromPrototypeAssignment.types create mode 100644 tests/cases/conformance/salsa/typeFromPrototypeAssignment.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6bd0c0409d4..e6a794e866a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15809,30 +15809,27 @@ namespace ts { } function tryGetThisTypeAt(node: Node, container = getThisContainer(node, /*includeArrowFunctions*/ false)): Type | undefined { + const isInJS = isInJSFile(node); if (isFunctionLike(container) && (!isInParameterInitializerBeforeContainingFunction(node) || getThisParameter(container))) { // Note: a parameter initializer should refer to class-this unless function-this is explicitly annotated. - // If this is a function in a JS file, it might be a class method. - // Check if it's the RHS of a x.prototype.y = function [name]() { .... } - if (container.kind === SyntaxKind.FunctionExpression && - container.parent.kind === SyntaxKind.BinaryExpression && - getAssignmentDeclarationKind(container.parent as BinaryExpression) === AssignmentDeclarationKind.PrototypeProperty) { - // Get the 'x' of 'x.prototype.y = f' (here, 'f' is 'container') - const className = (((container.parent as BinaryExpression) // x.prototype.y = f - .left as PropertyAccessExpression) // x.prototype.y - .expression as PropertyAccessExpression) // x.prototype - .expression; // x + const className = getClassNameFromPrototypeMethod(container); + if (isInJS && className) { const classSymbol = checkExpression(className).symbol; if (classSymbol && classSymbol.members && (classSymbol.flags & SymbolFlags.Function)) { - return getFlowTypeOfReference(node, getInferredClassType(classSymbol)); + const classType = getJavascriptClassType(classSymbol); + if (classType) { + return getFlowTypeOfReference(node, classType); + } } } // Check if it's a constructor definition, can be either a variable decl or function decl // i.e. // * /** @constructor */ function [name]() { ... } // * /** @constructor */ var x = function() { ... } - else if ((container.kind === SyntaxKind.FunctionExpression || container.kind === SyntaxKind.FunctionDeclaration) && + else if (isInJS && + (container.kind === SyntaxKind.FunctionExpression || container.kind === SyntaxKind.FunctionDeclaration) && getJSDocClassTag(container)) { const classType = getJavascriptClassType(container.symbol); if (classType) { @@ -15852,7 +15849,7 @@ namespace ts { return getFlowTypeOfReference(node, type); } - if (isInJSFile(node)) { + if (isInJS) { const type = getTypeForThisExpressionFromJSDoc(container); if (type && type !== errorType) { return getFlowTypeOfReference(node, type); @@ -15860,6 +15857,34 @@ namespace ts { } } + function getClassNameFromPrototypeMethod(container: Node) { + // Check if it's the RHS of a x.prototype.y = function [name]() { .... } + if (container.kind === SyntaxKind.FunctionExpression && + isBinaryExpression(container.parent) && + getAssignmentDeclarationKind(container.parent) === AssignmentDeclarationKind.PrototypeProperty) { + // Get the 'x' of 'x.prototype.y = container' + return ((container.parent // x.prototype.y = container + .left as PropertyAccessExpression) // x.prototype.y + .expression as PropertyAccessExpression) // x.prototype + .expression; // x + } + // x.prototype = { method() { } } + else if (container.kind === SyntaxKind.MethodDeclaration && + container.parent.kind === SyntaxKind.ObjectLiteralExpression && + isBinaryExpression(container.parent.parent) && + getAssignmentDeclarationKind(container.parent.parent) === AssignmentDeclarationKind.Prototype) { + return (container.parent.parent.left as PropertyAccessExpression).expression; + } + // x.prototype = { method: function() { } } + else if (container.kind === SyntaxKind.FunctionExpression && + container.parent.kind === SyntaxKind.PropertyAssignment && + container.parent.parent.kind === SyntaxKind.ObjectLiteralExpression && + isBinaryExpression(container.parent.parent.parent) && + getAssignmentDeclarationKind(container.parent.parent.parent) === AssignmentDeclarationKind.Prototype) { + return (container.parent.parent.parent.left as PropertyAccessExpression).expression; + } + } + function getTypeForThisExpressionFromJSDoc(node: Node) { const jsdocType = getJSDocType(node); if (jsdocType && jsdocType.kind === SyntaxKind.JSDocFunctionType) { diff --git a/tests/baselines/reference/jsdocTemplateTag5.errors.txt b/tests/baselines/reference/jsdocTemplateTag5.errors.txt deleted file mode 100644 index e24cd0926b6..00000000000 --- a/tests/baselines/reference/jsdocTemplateTag5.errors.txt +++ /dev/null @@ -1,77 +0,0 @@ -tests/cases/conformance/jsdoc/a.js(18,21): error TS2339: Property '_map' does not exist on type '{ get(key: K): V; }'. -tests/cases/conformance/jsdoc/a.js(39,21): error TS2339: Property '_map' does not exist on type '{ get: (key: K) => V; }'. -tests/cases/conformance/jsdoc/a.js(61,21): error TS2339: Property '_map' does not exist on type '{ get(key: K): V; }'. - - -==== tests/cases/conformance/jsdoc/a.js (3 errors) ==== - /** - * Should work for function declarations - * @constructor - * @template {string} K - * @template V - */ - function Multimap() { - /** @type {Object} TODO: Remove the prototype from the fresh object */ - this._map = {}; - }; - - Multimap.prototype = { - /** - * @param {K} key the key ok - * @returns {V} the value ok - */ - get(key) { - return this._map[key + '']; - ~~~~ -!!! error TS2339: Property '_map' does not exist on type '{ get(key: K): V; }'. - } - } - - /** - * Should work for initialisers too - * @constructor - * @template {string} K - * @template V - */ - var Multimap2 = function() { - /** @type {Object} TODO: Remove the prototype from the fresh object */ - this._map = {}; - }; - - Multimap2.prototype = { - /** - * @param {K} key the key ok - * @returns {V} the value ok - */ - get: function(key) { - return this._map[key + '']; - ~~~~ -!!! error TS2339: Property '_map' does not exist on type '{ get: (key: K) => V; }'. - } - } - - var Ns = {}; - /** - * Should work for expando-namespaced initialisers too - * @constructor - * @template {string} K - * @template V - */ - Ns.Multimap3 = function() { - /** @type {Object} TODO: Remove the prototype from the fresh object */ - this._map = {}; - }; - - Ns.Multimap3.prototype = { - /** - * @param {K} key the key ok - * @returns {V} the value ok - */ - get(key) { - return this._map[key + '']; - ~~~~ -!!! error TS2339: Property '_map' does not exist on type '{ get(key: K): V; }'. - } - } - - \ No newline at end of file diff --git a/tests/baselines/reference/jsdocTemplateTag5.symbols b/tests/baselines/reference/jsdocTemplateTag5.symbols index 249e92ab257..aa1b023f339 100644 --- a/tests/baselines/reference/jsdocTemplateTag5.symbols +++ b/tests/baselines/reference/jsdocTemplateTag5.symbols @@ -29,7 +29,8 @@ Multimap.prototype = { >key : Symbol(key, Decl(a.js, 16, 8)) return this._map[key + '']; ->this : Symbol(__object, Decl(a.js, 11, 20)) +>this._map : Symbol(Multimap._map, Decl(a.js, 6, 21)) +>_map : Symbol(Multimap._map, Decl(a.js, 6, 21)) >key : Symbol(key, Decl(a.js, 16, 8)) } } @@ -64,7 +65,8 @@ Multimap2.prototype = { >key : Symbol(key, Decl(a.js, 37, 18)) return this._map[key + '']; ->this : Symbol(__object, Decl(a.js, 32, 21)) +>this._map : Symbol(Multimap2._map, Decl(a.js, 27, 28)) +>_map : Symbol(Multimap2._map, Decl(a.js, 27, 28)) >key : Symbol(key, Decl(a.js, 37, 18)) } } @@ -106,7 +108,8 @@ Ns.Multimap3.prototype = { >key : Symbol(key, Decl(a.js, 59, 8)) return this._map[key + '']; ->this : Symbol(__object, Decl(a.js, 54, 24)) +>this._map : Symbol(Multimap3._map, Decl(a.js, 49, 27)) +>_map : Symbol(Multimap3._map, Decl(a.js, 49, 27)) >key : Symbol(key, Decl(a.js, 59, 8)) } } diff --git a/tests/baselines/reference/jsdocTemplateTag5.types b/tests/baselines/reference/jsdocTemplateTag5.types index c5b8752d2b6..1195b372e18 100644 --- a/tests/baselines/reference/jsdocTemplateTag5.types +++ b/tests/baselines/reference/jsdocTemplateTag5.types @@ -34,10 +34,10 @@ Multimap.prototype = { >key : K return this._map[key + '']; ->this._map[key + ''] : any ->this._map : any ->this : { get(key: K): V; } ->_map : any +>this._map[key + ''] : V +>this._map : { [x: string]: V; } +>this : Multimap & { get(key: K): V; } +>_map : { [x: string]: V; } >key + '' : string >key : K >'' : "" @@ -81,10 +81,10 @@ Multimap2.prototype = { >key : K return this._map[key + '']; ->this._map[key + ''] : any ->this._map : any ->this : { get: (key: K) => V; } ->_map : any +>this._map[key + ''] : V +>this._map : { [x: string]: V; } +>this : Multimap2 & { get: (key: K) => V; } +>_map : { [x: string]: V; } >key + '' : string >key : K >'' : "" @@ -136,10 +136,10 @@ Ns.Multimap3.prototype = { >key : K return this._map[key + '']; ->this._map[key + ''] : any ->this._map : any ->this : { get(key: K): V; } ->_map : any +>this._map[key + ''] : V +>this._map : { [x: string]: V; } +>this : Multimap3 & { get(key: K): V; } +>_map : { [x: string]: V; } >key + '' : string >key : K >'' : "" diff --git a/tests/baselines/reference/typeFromPrototypeAssignment.errors.txt b/tests/baselines/reference/typeFromPrototypeAssignment.errors.txt new file mode 100644 index 00000000000..edd3435c445 --- /dev/null +++ b/tests/baselines/reference/typeFromPrototypeAssignment.errors.txt @@ -0,0 +1,45 @@ +tests/cases/conformance/salsa/a.js(27,20): error TS2339: Property 'addon' does not exist on type '{ set: () => void; get(): void; }'. + + +==== tests/cases/conformance/salsa/a.js (1 errors) ==== + // all references to _map, set, get, addon should be ok + + /** @constructor */ + var Multimap = function() { + this._map = {}; + this._map + this.set + this.get + this.addon + }; + + Multimap.prototype = { + set: function() { + this._map + this.set + this.get + this.addon + }, + get() { + this._map + this.set + this.get + this.addon + } + } + + Multimap.prototype.addon = function () { + ~~~~~ +!!! error TS2339: Property 'addon' does not exist on type '{ set: () => void; get(): void; }'. + this._map + this.set + this.get + this.addon + } + + var mm = new Multimap(); + mm._map + mm.set + mm.get + mm.addon + \ No newline at end of file diff --git a/tests/baselines/reference/typeFromPrototypeAssignment.symbols b/tests/baselines/reference/typeFromPrototypeAssignment.symbols new file mode 100644 index 00000000000..d51382a639f --- /dev/null +++ b/tests/baselines/reference/typeFromPrototypeAssignment.symbols @@ -0,0 +1,122 @@ +=== tests/cases/conformance/salsa/a.js === +// all references to _map, set, get, addon should be ok + +/** @constructor */ +var Multimap = function() { +>Multimap : Symbol(Multimap, Decl(a.js, 3, 3), Decl(a.js, 9, 2)) + + this._map = {}; +>this._map : Symbol(Multimap._map, Decl(a.js, 3, 27)) +>_map : Symbol(Multimap._map, Decl(a.js, 3, 27)) + + this._map +>this._map : Symbol(Multimap._map, Decl(a.js, 3, 27)) +>_map : Symbol(Multimap._map, Decl(a.js, 3, 27)) + + this.set +>this.set : Symbol(set, Decl(a.js, 11, 22)) +>set : Symbol(set, Decl(a.js, 11, 22)) + + this.get +>this.get : Symbol(get, Decl(a.js, 17, 6)) +>get : Symbol(get, Decl(a.js, 17, 6)) + + this.addon +>this.addon : Symbol(Multimap.addon, Decl(a.js, 24, 1)) +>addon : Symbol(Multimap.addon, Decl(a.js, 24, 1)) + +}; + +Multimap.prototype = { +>Multimap.prototype : Symbol(Multimap.prototype, Decl(a.js, 9, 2)) +>Multimap : Symbol(Multimap, Decl(a.js, 3, 3), Decl(a.js, 9, 2)) +>prototype : Symbol(Multimap.prototype, Decl(a.js, 9, 2)) + + set: function() { +>set : Symbol(set, Decl(a.js, 11, 22)) + + this._map +>this._map : Symbol(Multimap._map, Decl(a.js, 3, 27)) +>_map : Symbol(Multimap._map, Decl(a.js, 3, 27)) + + this.set +>this.set : Symbol(set, Decl(a.js, 11, 22)) +>set : Symbol(set, Decl(a.js, 11, 22)) + + this.get +>this.get : Symbol(get, Decl(a.js, 17, 6)) +>get : Symbol(get, Decl(a.js, 17, 6)) + + this.addon +>this.addon : Symbol(Multimap.addon, Decl(a.js, 24, 1)) +>addon : Symbol(Multimap.addon, Decl(a.js, 24, 1)) + + }, + get() { +>get : Symbol(get, Decl(a.js, 17, 6)) + + this._map +>this._map : Symbol(Multimap._map, Decl(a.js, 3, 27)) +>_map : Symbol(Multimap._map, Decl(a.js, 3, 27)) + + this.set +>this.set : Symbol(set, Decl(a.js, 11, 22)) +>set : Symbol(set, Decl(a.js, 11, 22)) + + this.get +>this.get : Symbol(get, Decl(a.js, 17, 6)) +>get : Symbol(get, Decl(a.js, 17, 6)) + + this.addon +>this.addon : Symbol(Multimap.addon, Decl(a.js, 24, 1)) +>addon : Symbol(Multimap.addon, Decl(a.js, 24, 1)) + } +} + +Multimap.prototype.addon = function () { +>Multimap.prototype : Symbol(Multimap.addon, Decl(a.js, 24, 1)) +>Multimap : Symbol(Multimap, Decl(a.js, 3, 3), Decl(a.js, 9, 2)) +>prototype : Symbol(Multimap.prototype, Decl(a.js, 9, 2)) +>addon : Symbol(Multimap.addon, Decl(a.js, 24, 1)) + + this._map +>this._map : Symbol(Multimap._map, Decl(a.js, 3, 27)) +>_map : Symbol(Multimap._map, Decl(a.js, 3, 27)) + + this.set +>this.set : Symbol(set, Decl(a.js, 11, 22)) +>set : Symbol(set, Decl(a.js, 11, 22)) + + this.get +>this.get : Symbol(get, Decl(a.js, 17, 6)) +>get : Symbol(get, Decl(a.js, 17, 6)) + + this.addon +>this.addon : Symbol(Multimap.addon, Decl(a.js, 24, 1)) +>addon : Symbol(Multimap.addon, Decl(a.js, 24, 1)) +} + +var mm = new Multimap(); +>mm : Symbol(mm, Decl(a.js, 33, 3)) +>Multimap : Symbol(Multimap, Decl(a.js, 3, 3), Decl(a.js, 9, 2)) + +mm._map +>mm._map : Symbol(Multimap._map, Decl(a.js, 3, 27)) +>mm : Symbol(mm, Decl(a.js, 33, 3)) +>_map : Symbol(Multimap._map, Decl(a.js, 3, 27)) + +mm.set +>mm.set : Symbol(set, Decl(a.js, 11, 22)) +>mm : Symbol(mm, Decl(a.js, 33, 3)) +>set : Symbol(set, Decl(a.js, 11, 22)) + +mm.get +>mm.get : Symbol(get, Decl(a.js, 17, 6)) +>mm : Symbol(mm, Decl(a.js, 33, 3)) +>get : Symbol(get, Decl(a.js, 17, 6)) + +mm.addon +>mm.addon : Symbol(Multimap.addon, Decl(a.js, 24, 1)) +>mm : Symbol(mm, Decl(a.js, 33, 3)) +>addon : Symbol(Multimap.addon, Decl(a.js, 24, 1)) + diff --git a/tests/baselines/reference/typeFromPrototypeAssignment.types b/tests/baselines/reference/typeFromPrototypeAssignment.types new file mode 100644 index 00000000000..87e4be5e0b9 --- /dev/null +++ b/tests/baselines/reference/typeFromPrototypeAssignment.types @@ -0,0 +1,149 @@ +=== tests/cases/conformance/salsa/a.js === +// all references to _map, set, get, addon should be ok + +/** @constructor */ +var Multimap = function() { +>Multimap : typeof Multimap +>function() { this._map = {}; this._map this.set this.get this.addon} : typeof Multimap + + this._map = {}; +>this._map = {} : {} +>this._map : {} +>this : Multimap & { set: () => void; get(): void; } +>_map : {} +>{} : {} + + this._map +>this._map : {} +>this : Multimap & { set: () => void; get(): void; } +>_map : {} + + this.set +>this.set : () => void +>this : Multimap & { set: () => void; get(): void; } +>set : () => void + + this.get +>this.get : () => void +>this : Multimap & { set: () => void; get(): void; } +>get : () => void + + this.addon +>this.addon : () => void +>this : Multimap & { set: () => void; get(): void; } +>addon : () => void + +}; + +Multimap.prototype = { +>Multimap.prototype = { set: function() { this._map this.set this.get this.addon }, get() { this._map this.set this.get this.addon }} : { set: () => void; get(): void; } +>Multimap.prototype : { set: () => void; get(): void; } +>Multimap : typeof Multimap +>prototype : { set: () => void; get(): void; } +>{ set: function() { this._map this.set this.get this.addon }, get() { this._map this.set this.get this.addon }} : { set: () => void; get(): void; } + + set: function() { +>set : () => void +>function() { this._map this.set this.get this.addon } : () => void + + this._map +>this._map : {} +>this : Multimap & { set: () => void; get(): void; } +>_map : {} + + this.set +>this.set : () => void +>this : Multimap & { set: () => void; get(): void; } +>set : () => void + + this.get +>this.get : () => void +>this : Multimap & { set: () => void; get(): void; } +>get : () => void + + this.addon +>this.addon : () => void +>this : Multimap & { set: () => void; get(): void; } +>addon : () => void + + }, + get() { +>get : () => void + + this._map +>this._map : {} +>this : Multimap & { set: () => void; get(): void; } +>_map : {} + + this.set +>this.set : () => void +>this : Multimap & { set: () => void; get(): void; } +>set : () => void + + this.get +>this.get : () => void +>this : Multimap & { set: () => void; get(): void; } +>get : () => void + + this.addon +>this.addon : () => void +>this : Multimap & { set: () => void; get(): void; } +>addon : () => void + } +} + +Multimap.prototype.addon = function () { +>Multimap.prototype.addon = function () { this._map this.set this.get this.addon} : () => void +>Multimap.prototype.addon : any +>Multimap.prototype : { set: () => void; get(): void; } +>Multimap : typeof Multimap +>prototype : { set: () => void; get(): void; } +>addon : any +>function () { this._map this.set this.get this.addon} : () => void + + this._map +>this._map : {} +>this : Multimap & { set: () => void; get(): void; } +>_map : {} + + this.set +>this.set : () => void +>this : Multimap & { set: () => void; get(): void; } +>set : () => void + + this.get +>this.get : () => void +>this : Multimap & { set: () => void; get(): void; } +>get : () => void + + this.addon +>this.addon : () => void +>this : Multimap & { set: () => void; get(): void; } +>addon : () => void +} + +var mm = new Multimap(); +>mm : Multimap & { set: () => void; get(): void; } +>new Multimap() : Multimap & { set: () => void; get(): void; } +>Multimap : typeof Multimap + +mm._map +>mm._map : {} +>mm : Multimap & { set: () => void; get(): void; } +>_map : {} + +mm.set +>mm.set : () => void +>mm : Multimap & { set: () => void; get(): void; } +>set : () => void + +mm.get +>mm.get : () => void +>mm : Multimap & { set: () => void; get(): void; } +>get : () => void + +mm.addon +>mm.addon : () => void +>mm : Multimap & { set: () => void; get(): void; } +>addon : () => void + diff --git a/tests/cases/conformance/salsa/typeFromPrototypeAssignment.ts b/tests/cases/conformance/salsa/typeFromPrototypeAssignment.ts new file mode 100644 index 00000000000..373ccab0394 --- /dev/null +++ b/tests/cases/conformance/salsa/typeFromPrototypeAssignment.ts @@ -0,0 +1,44 @@ +// @noEmit: true +// @allowJs: true +// @checkJs: true +// @Filename: a.js +// @strict: true + +// all references to _map, set, get, addon should be ok + +/** @constructor */ +var Multimap = function() { + this._map = {}; + this._map + this.set + this.get + this.addon +}; + +Multimap.prototype = { + set: function() { + this._map + this.set + this.get + this.addon + }, + get() { + this._map + this.set + this.get + this.addon + } +} + +Multimap.prototype.addon = function () { + this._map + this.set + this.get + this.addon +} + +var mm = new Multimap(); +mm._map +mm.set +mm.get +mm.addon From b8f33f6a35e6659912f39055c4844e786d581c86 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Wed, 12 Sep 2018 16:09:22 -0700 Subject: [PATCH 46/83] Report all project errors on incremental compile --- src/compiler/tsbuild.ts | 65 ++++++++++---------- src/testRunner/unittests/tsbuildWatchMode.ts | 27 ++++++++ src/testRunner/unittests/tscWatchMode.ts | 18 +++--- 3 files changed, 72 insertions(+), 38 deletions(-) diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts index d7eb648bca2..2c064bea137 100644 --- a/src/compiler/tsbuild.ts +++ b/src/compiler/tsbuild.ts @@ -394,9 +394,9 @@ namespace ts { let globalDependencyGraph: DependencyGraph | undefined; // Watch state - // TODO(shkamat): this should be really be diagnostics but thats for later time - const diagnostics = createFileMap(toPath); + const diagnostics = createFileMap>(toPath); const projectPendingBuild = createFileMap(toPath); + const projectErrorsReported = createFileMap(toPath); const invalidatedProjectQueue = [] as ResolvedConfigFileName[]; let nextProjectToBuild = 0; let timerToBuildInvalidatedProject: any; @@ -438,6 +438,7 @@ namespace ts { diagnostics.clear(); projectPendingBuild.clear(); + projectErrorsReported.clear(); invalidatedProjectQueue.length = 0; nextProjectToBuild = 0; if (timerToBuildInvalidatedProject) { @@ -472,18 +473,6 @@ namespace ts { host.reportSolutionBuilderStatus(createCompilerDiagnostic(message, ...args)); } - function storeErrors(proj: ResolvedConfigFileName, diagnostics: ReadonlyArray) { - if (options.watch) { - storeErrorSummary(proj, diagnostics.filter(diagnostic => diagnostic.category === DiagnosticCategory.Error).length); - } - } - - function storeErrorSummary(proj: ResolvedConfigFileName, errorCount: number) { - if (options.watch) { - diagnostics.setValue(proj, errorCount); - } - } - function reportWatchStatus(message: DiagnosticMessage, ...args: (string | number | undefined)[]) { if (hostWithWatch.onWatchStatusChange) { hostWithWatch.onWatchStatusChange(createCompilerDiagnostic(message, ...args), host.getNewLine(), { preserveWatchOutput: options.preserveWatchOutput }); @@ -509,7 +498,7 @@ namespace ts { } function watchConfigFile(resolved: ResolvedConfigFileName) { - if (!allWatchedConfigFiles.hasKey(resolved)) { + if (options.watch && !allWatchedConfigFiles.hasKey(resolved)) { allWatchedConfigFiles.setValue(resolved, hostWithWatch.watchFile(resolved, () => { invalidateProjectAndScheduleBuilds(resolved, ConfigFileProgramReloadLevel.Full); })); @@ -517,6 +506,7 @@ namespace ts { } function watchWildCardDirectories(resolved: ResolvedConfigFileName, parsed: ParsedCommandLine) { + if (!options.watch) return; updateWatchingWildcardDirectories( getOrCreateValueMapFromConfigFileMap(allWatchedWildcardDirectories, resolved), createMapFromTemplate(parsed.configFileSpecs!.wildcardDirectories), @@ -540,6 +530,7 @@ namespace ts { } function watchInputFiles(resolved: ResolvedConfigFileName, parsed: ParsedCommandLine) { + if (!options.watch) return; mutateMap( getOrCreateValueMapFromConfigFileMap(allWatchedInputFiles, resolved), arrayToMap(parsed.fileNames, toPath), @@ -848,6 +839,7 @@ namespace ts { timerToBuildInvalidatedProject = undefined; if (reportFileChangeDetected) { reportFileChangeDetected = false; + projectErrorsReported.clear(); reportWatchStatus(Diagnostics.File_change_detected_Starting_incremental_compilation); } const buildProject = getNextInvalidatedProject(); @@ -866,15 +858,19 @@ namespace ts { function reportErrorSummary() { if (options.watch) { + // Report errors from the other projects + getGlobalDependencyGraph().buildQueue.forEach(project => { + if (!projectErrorsReported.hasKey(project)) { + reportErrors(diagnostics.getValue(project) || emptyArray); + } + }); let totalErrors = 0; - diagnostics.forEach(singleProjectErrors => totalErrors += singleProjectErrors); + diagnostics.forEach(singleProjectErrors => totalErrors += singleProjectErrors.filter(diagnostic => diagnostic.category === DiagnosticCategory.Error).length); reportWatchStatus(totalErrors === 1 ? Diagnostics.Found_1_error_Watching_for_file_changes : Diagnostics.Found_0_errors_Watching_for_file_changes, totalErrors); } } function buildSingleInvalidatedProject(resolved: ResolvedConfigFileName, reloadLevel: ConfigFileProgramReloadLevel) { - // TODO:: handle this in better way later - const proj = parseConfigFile(resolved); if (!proj) { reportParseConfigFileDiagnostic(resolved); @@ -968,10 +964,6 @@ namespace ts { } } - function reportParseConfigFileDiagnostic(proj: ResolvedConfigFileName) { - host.reportDiagnostic(configFileCache.getValue(proj) as Diagnostic); - storeErrorSummary(proj, 1); - } function buildSingleProject(proj: ResolvedConfigFileName): BuildResultFlags { if (options.dry) { @@ -1013,7 +1005,7 @@ namespace ts { ...program.getSyntacticDiagnostics()]; if (syntaxDiagnostics.length) { resultFlags |= BuildResultFlags.SyntaxErrors; - reportErrors(proj, syntaxDiagnostics); + reportAndStoreErrors(proj, syntaxDiagnostics); projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Syntactic errors" }); return resultFlags; } @@ -1023,7 +1015,7 @@ namespace ts { const declDiagnostics = program.getDeclarationDiagnostics(); if (declDiagnostics.length) { resultFlags |= BuildResultFlags.DeclarationEmitErrors; - reportErrors(proj, declDiagnostics); + reportAndStoreErrors(proj, declDiagnostics); projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Declaration file errors" }); return resultFlags; } @@ -1033,7 +1025,7 @@ namespace ts { const semanticDiagnostics = program.getSemanticDiagnostics(); if (semanticDiagnostics.length) { resultFlags |= BuildResultFlags.TypeErrors; - reportErrors(proj, semanticDiagnostics); + reportAndStoreErrors(proj, semanticDiagnostics); projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Semantic errors" }); return resultFlags; } @@ -1154,7 +1146,7 @@ namespace ts { const projName = proj.options.configFilePath!; if (status.type === UpToDateStatusType.UpToDate && !options.force) { - reportErrors(next, errors); + reportAndStoreErrors(next, errors); // Up to date, skip if (defaultOptions.dry) { // In a dry build, inform the user of this fact @@ -1164,20 +1156,20 @@ namespace ts { } if (status.type === UpToDateStatusType.UpToDateWithUpstreamTypes && !options.force) { - reportErrors(next, errors); + reportAndStoreErrors(next, errors); // Fake build updateOutputTimestamps(proj); continue; } if (status.type === UpToDateStatusType.UpstreamBlocked) { - reportErrors(next, errors); + reportAndStoreErrors(next, errors); if (options.verbose) reportStatus(Diagnostics.Skipping_build_of_project_0_because_its_dependency_1_has_errors, projName, status.upstreamProjectName); continue; } if (status.type === UpToDateStatusType.ContainerOnly) { - reportErrors(next, errors); + reportAndStoreErrors(next, errors); // Do nothing continue; } @@ -1189,9 +1181,20 @@ namespace ts { return anyFailed ? ExitStatus.DiagnosticsPresent_OutputsSkipped : ExitStatus.Success; } - function reportErrors(proj: ResolvedConfigFileName, errors: ReadonlyArray) { + function reportParseConfigFileDiagnostic(proj: ResolvedConfigFileName) { + reportAndStoreErrors(proj, [configFileCache.getValue(proj) as Diagnostic]); + } + + function reportAndStoreErrors(proj: ResolvedConfigFileName, errors: ReadonlyArray) { + reportErrors(errors); + if (options.watch) { + projectErrorsReported.setValue(proj, true); + diagnostics.setValue(proj, errors); + } + } + + function reportErrors(errors: ReadonlyArray) { errors.forEach(err => host.reportDiagnostic(err)); - storeErrors(proj, errors); } /** diff --git a/src/testRunner/unittests/tsbuildWatchMode.ts b/src/testRunner/unittests/tsbuildWatchMode.ts index 697d14f72ba..d9dcda94bff 100644 --- a/src/testRunner/unittests/tsbuildWatchMode.ts +++ b/src/testRunner/unittests/tsbuildWatchMode.ts @@ -351,6 +351,33 @@ function myFunc() { return 100; }`); } }); + it("reports errors in all projects on incremental compile", () => { + const host = createSolutionInWatchMode(allFiles); + const outputFileStamps = getOutputFileStamps(host); + + host.writeFile(logic[1].path, `${logic[1].content} +let y: string = 10;`); + + host.checkTimeoutQueueLengthAndRun(1); // Builds logic + const changedLogic = getOutputFileStamps(host); + verifyChangedFiles(changedLogic, outputFileStamps, emptyArray); + host.checkTimeoutQueueLength(0); + checkOutputErrorsIncremental(host, [ + `sample1/logic/index.ts(8,5): error TS2322: Type '10' is not assignable to type 'string'.\n` + ]); + + host.writeFile(core[1].path, `${core[1].content} +let x: string = 10;`); + + host.checkTimeoutQueueLengthAndRun(1); // Builds core + const changedCore = getOutputFileStamps(host); + verifyChangedFiles(changedCore, changedLogic, emptyArray); + host.checkTimeoutQueueLength(0); + checkOutputErrorsIncremental(host, [ + `sample1/core/index.ts(5,5): error TS2322: Type '10' is not assignable to type 'string'.\n`, + `sample1/logic/index.ts(8,5): error TS2322: Type '10' is not assignable to type 'string'.\n` + ]); + }); // TODO: write tests reporting errors but that will have more involved work since file }); } diff --git a/src/testRunner/unittests/tscWatchMode.ts b/src/testRunner/unittests/tscWatchMode.ts index da1c4fd0d70..b750e4c556c 100644 --- a/src/testRunner/unittests/tscWatchMode.ts +++ b/src/testRunner/unittests/tscWatchMode.ts @@ -77,7 +77,7 @@ namespace ts.tscWatch { logsBeforeWatchDiagnostic: string[] | undefined, preErrorsWatchDiagnostic: Diagnostic, logsBeforeErrors: string[] | undefined, - errors: ReadonlyArray, + errors: ReadonlyArray | ReadonlyArray, disableConsoleClears?: boolean | undefined, ...postErrorsWatchDiagnostics: Diagnostic[] ) { @@ -96,8 +96,12 @@ namespace ts.tscWatch { assert.equal(host.screenClears.length, screenClears, "Expected number of screen clears"); host.clearOutput(); - function assertDiagnostic(diagnostic: Diagnostic) { - const expected = formatDiagnostic(diagnostic, host); + function isDiagnostic(diagnostic: Diagnostic | string): diagnostic is Diagnostic { + return !!(diagnostic as Diagnostic).messageText; + } + + function assertDiagnostic(diagnostic: Diagnostic | string) { + const expected = isDiagnostic(diagnostic) ? formatDiagnostic(diagnostic, host) : diagnostic; assert.equal(outputs[index], expected, getOutputAtFailedMessage("Diagnostic", expected)); index++; } @@ -130,13 +134,13 @@ namespace ts.tscWatch { } } - function createErrorsFoundCompilerDiagnostic(errors: ReadonlyArray) { + function createErrorsFoundCompilerDiagnostic(errors: ReadonlyArray | ReadonlyArray) { return errors.length === 1 ? createCompilerDiagnostic(Diagnostics.Found_1_error_Watching_for_file_changes) : createCompilerDiagnostic(Diagnostics.Found_0_errors_Watching_for_file_changes, errors.length); } - export function checkOutputErrorsInitial(host: WatchedSystem, errors: ReadonlyArray, disableConsoleClears?: boolean, logsBeforeErrors?: string[]) { + export function checkOutputErrorsInitial(host: WatchedSystem, errors: ReadonlyArray | ReadonlyArray, disableConsoleClears?: boolean, logsBeforeErrors?: string[]) { checkOutputErrors( host, /*logsBeforeWatchDiagnostic*/ undefined, @@ -147,7 +151,7 @@ namespace ts.tscWatch { createErrorsFoundCompilerDiagnostic(errors)); } - export function checkOutputErrorsIncremental(host: WatchedSystem, errors: ReadonlyArray, disableConsoleClears?: boolean, logsBeforeWatchDiagnostic?: string[], logsBeforeErrors?: string[]) { + export function checkOutputErrorsIncremental(host: WatchedSystem, errors: ReadonlyArray | ReadonlyArray, disableConsoleClears?: boolean, logsBeforeWatchDiagnostic?: string[], logsBeforeErrors?: string[]) { checkOutputErrors( host, logsBeforeWatchDiagnostic, @@ -158,7 +162,7 @@ namespace ts.tscWatch { createErrorsFoundCompilerDiagnostic(errors)); } - function checkOutputErrorsIncrementalWithExit(host: WatchedSystem, errors: ReadonlyArray, expectedExitCode: ExitStatus, disableConsoleClears?: boolean, logsBeforeWatchDiagnostic?: string[], logsBeforeErrors?: string[]) { + function checkOutputErrorsIncrementalWithExit(host: WatchedSystem, errors: ReadonlyArray | ReadonlyArray, expectedExitCode: ExitStatus, disableConsoleClears?: boolean, logsBeforeWatchDiagnostic?: string[], logsBeforeErrors?: string[]) { checkOutputErrors( host, logsBeforeWatchDiagnostic, From d3463ce3560641ce8b164f50401e00e7d99e36d8 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 12 Sep 2018 17:16:34 -0700 Subject: [PATCH 47/83] Avoid circularly resolving names when looking up type members using resolveName (#26924) * Avoid circularly resolving names when looking up type members using resolveName * Add comment --- src/compiler/checker.ts | 5 ++++- ...ationTypecheckNoUseBeforeReferenceCheck.symbols | 14 ++++++++++++++ ...arationTypecheckNoUseBeforeReferenceCheck.types | 14 ++++++++++++++ ...eclarationTypecheckNoUseBeforeReferenceCheck.ts | 5 +++++ 4 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/declarationTypecheckNoUseBeforeReferenceCheck.symbols create mode 100644 tests/baselines/reference/declarationTypecheckNoUseBeforeReferenceCheck.types create mode 100644 tests/cases/compiler/declarationTypecheckNoUseBeforeReferenceCheck.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e6a794e866a..6f541461b09 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1312,7 +1312,10 @@ namespace ts { case SyntaxKind.ClassDeclaration: case SyntaxKind.ClassExpression: case SyntaxKind.InterfaceDeclaration: - if (result = lookup(getMembersOfSymbol(getSymbolOfNode(location as ClassLikeDeclaration | InterfaceDeclaration)), name, meaning & SymbolFlags.Type)) { + // The below is used to lookup type parameters within a class or interface, as they are added to the class/interface locals + // These can never be latebound, so the symbol's raw members are sufficient. `getMembersOfNode` cannot be used, as it would + // trigger resolving late-bound names, which we may already be in the process of doing while we're here! + if (result = lookup(getSymbolOfNode(location as ClassLikeDeclaration | InterfaceDeclaration).members || emptySymbols, name, meaning & SymbolFlags.Type)) { if (!isTypeParameterSymbolDeclaredInContainer(result, location)) { // ignore type parameters not declared in this container result = undefined; diff --git a/tests/baselines/reference/declarationTypecheckNoUseBeforeReferenceCheck.symbols b/tests/baselines/reference/declarationTypecheckNoUseBeforeReferenceCheck.symbols new file mode 100644 index 00000000000..95b3bd297c9 --- /dev/null +++ b/tests/baselines/reference/declarationTypecheckNoUseBeforeReferenceCheck.symbols @@ -0,0 +1,14 @@ +=== tests/cases/compiler/index.d.ts === +export class C extends Object { +>C : Symbol(C, Decl(index.d.ts, 0, 0)) +>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) + + static readonly p: unique symbol; +>p : Symbol(C.p, Decl(index.d.ts, 0, 31)) + + [C.p](): void; +>[C.p] : Symbol(C[C.p], Decl(index.d.ts, 1, 37)) +>C.p : Symbol(C.p, Decl(index.d.ts, 0, 31)) +>C : Symbol(C, Decl(index.d.ts, 0, 0)) +>p : Symbol(C.p, Decl(index.d.ts, 0, 31)) +} diff --git a/tests/baselines/reference/declarationTypecheckNoUseBeforeReferenceCheck.types b/tests/baselines/reference/declarationTypecheckNoUseBeforeReferenceCheck.types new file mode 100644 index 00000000000..86f294591dc --- /dev/null +++ b/tests/baselines/reference/declarationTypecheckNoUseBeforeReferenceCheck.types @@ -0,0 +1,14 @@ +=== tests/cases/compiler/index.d.ts === +export class C extends Object { +>C : C +>Object : Object + + static readonly p: unique symbol; +>p : unique symbol + + [C.p](): void; +>[C.p] : () => void +>C.p : unique symbol +>C : typeof C +>p : unique symbol +} diff --git a/tests/cases/compiler/declarationTypecheckNoUseBeforeReferenceCheck.ts b/tests/cases/compiler/declarationTypecheckNoUseBeforeReferenceCheck.ts new file mode 100644 index 00000000000..21c1db5f59c --- /dev/null +++ b/tests/cases/compiler/declarationTypecheckNoUseBeforeReferenceCheck.ts @@ -0,0 +1,5 @@ +// @filename: index.d.ts +export class C extends Object { + static readonly p: unique symbol; + [C.p](): void; +} \ No newline at end of file From 2b888c30f9a86c33d95cc9796baec1b3a3e29091 Mon Sep 17 00:00:00 2001 From: Andy Date: Wed, 12 Sep 2018 17:44:06 -0700 Subject: [PATCH 48/83] Consistently pass indent to 'parseTagComments' (#27055) * Consistently pass indent to 'parseTagComments' * Update baselines --- src/compiler/parser.ts | 29 +++++++++---------- ...ts.parsesCorrectly.Nested @param tags.json | 2 +- ...sCorrectly.typedefTagWithChildrenTags.json | 4 +-- tests/cases/fourslash/quickInfoPropertyTag.ts | 3 +- 4 files changed, 17 insertions(+), 21 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 1d65e31b490..415a62e5627 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -6724,7 +6724,7 @@ namespace ts { } } - function parseParameterOrPropertyTag(atToken: AtToken, tagName: Identifier, target: PropertyLikeParse, indent: number | undefined): JSDocParameterTag | JSDocPropertyTag { + function parseParameterOrPropertyTag(atToken: AtToken, tagName: Identifier, target: PropertyLikeParse, indent: number): JSDocParameterTag | JSDocPropertyTag { let typeExpression = tryParseTypeExpression(); let isNameFirst = !typeExpression; skipWhitespaceOrAsterisk(); @@ -6739,9 +6739,8 @@ namespace ts { const result = target === PropertyLikeParse.Property ? createNode(SyntaxKind.JSDocPropertyTag, atToken.pos) : createNode(SyntaxKind.JSDocParameterTag, atToken.pos); - let comment: string | undefined; - if (indent !== undefined) comment = parseTagComments(indent + scanner.getStartPos() - atToken.pos); - const nestedTypeLiteral = target !== PropertyLikeParse.CallbackParameter && parseNestedTypeLiteral(typeExpression, name, target); + const comment = parseTagComments(indent + scanner.getStartPos() - atToken.pos); + const nestedTypeLiteral = target !== PropertyLikeParse.CallbackParameter && parseNestedTypeLiteral(typeExpression, name, target, indent); if (nestedTypeLiteral) { typeExpression = nestedTypeLiteral; isNameFirst = true; @@ -6756,14 +6755,14 @@ namespace ts { return finishNode(result); } - function parseNestedTypeLiteral(typeExpression: JSDocTypeExpression | undefined, name: EntityName, target: PropertyLikeParse) { + function parseNestedTypeLiteral(typeExpression: JSDocTypeExpression | undefined, name: EntityName, target: PropertyLikeParse, indent: number) { if (typeExpression && isObjectOrObjectArrayTypeReference(typeExpression.type)) { const typeLiteralExpression = createNode(SyntaxKind.JSDocTypeExpression, scanner.getTokenPos()); let child: JSDocPropertyLikeTag | JSDocTypeTag | false; let jsdocTypeLiteral: JSDocTypeLiteral; const start = scanner.getStartPos(); let children: JSDocPropertyLikeTag[] | undefined; - while (child = tryParse(() => parseChildParameterOrPropertyTag(target, name))) { + while (child = tryParse(() => parseChildParameterOrPropertyTag(target, indent, name))) { if (child.kind === SyntaxKind.JSDocParameterTag || child.kind === SyntaxKind.JSDocPropertyTag) { children = append(children, child); } @@ -6879,7 +6878,7 @@ namespace ts { let jsdocTypeLiteral: JSDocTypeLiteral | undefined; let childTypeTag: JSDocTypeTag | undefined; const start = atToken.pos; - while (child = tryParse(() => parseChildPropertyTag())) { + while (child = tryParse(() => parseChildPropertyTag(indent))) { if (!jsdocTypeLiteral) { jsdocTypeLiteral = createNode(SyntaxKind.JSDocTypeLiteral, start); } @@ -6945,7 +6944,7 @@ namespace ts { const start = scanner.getStartPos(); const jsdocSignature = createNode(SyntaxKind.JSDocSignature, start) as JSDocSignature; jsdocSignature.parameters = []; - while (child = tryParse(() => parseChildParameterOrPropertyTag(PropertyLikeParse.CallbackParameter) as JSDocParameterTag)) { + while (child = tryParse(() => parseChildParameterOrPropertyTag(PropertyLikeParse.CallbackParameter, indent) as JSDocParameterTag)) { jsdocSignature.parameters = append(jsdocSignature.parameters as MutableNodeArray, child); } const returnTag = tryParse(() => { @@ -6988,18 +6987,18 @@ namespace ts { return a.escapedText === b.escapedText; } - function parseChildPropertyTag() { - return parseChildParameterOrPropertyTag(PropertyLikeParse.Property) as JSDocTypeTag | JSDocPropertyTag | false; + function parseChildPropertyTag(indent: number) { + return parseChildParameterOrPropertyTag(PropertyLikeParse.Property, indent) as JSDocTypeTag | JSDocPropertyTag | false; } - function parseChildParameterOrPropertyTag(target: PropertyLikeParse, name?: EntityName): JSDocTypeTag | JSDocPropertyTag | JSDocParameterTag | false { + function parseChildParameterOrPropertyTag(target: PropertyLikeParse, indent: number, name?: EntityName): JSDocTypeTag | JSDocPropertyTag | JSDocParameterTag | false { let canParseTag = true; let seenAsterisk = false; while (true) { switch (nextJSDocToken()) { case SyntaxKind.AtToken: if (canParseTag) { - const child = tryParseChildTag(target); + const child = tryParseChildTag(target, indent); if (child && (child.kind === SyntaxKind.JSDocParameterTag || child.kind === SyntaxKind.JSDocPropertyTag) && target !== PropertyLikeParse.CallbackParameter && name && (ts.isIdentifier(child.name) || !escapedTextsEqual(name, child.name.left))) { @@ -7028,7 +7027,7 @@ namespace ts { } } - function tryParseChildTag(target: PropertyLikeParse): JSDocTypeTag | JSDocPropertyTag | JSDocParameterTag | false { + function tryParseChildTag(target: PropertyLikeParse, indent: number): JSDocTypeTag | JSDocPropertyTag | JSDocParameterTag | false { Debug.assert(token() === SyntaxKind.AtToken); const atToken = createNode(SyntaxKind.AtToken); atToken.end = scanner.getTextPos(); @@ -7055,9 +7054,7 @@ namespace ts { if (!(target & t)) { return false; } - const tag = parseParameterOrPropertyTag(atToken, tagName, target, /*indent*/ undefined); - tag.comment = parseTagComments(tag.end - tag.pos); - return tag; + return parseParameterOrPropertyTag(atToken, tagName, target, indent); } function parseTemplateTag(atToken: AtToken, tagName: Identifier): JSDocTemplateTag { diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.Nested @param tags.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.Nested @param tags.json index 73d3f598059..f75d1e5fc6b 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.Nested @param tags.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.Nested @param tags.json @@ -30,7 +30,7 @@ { "kind": "JSDocParameterTag", "pos": 34, - "end": 54, + "end": 64, "atToken": { "kind": "AtToken", "pos": 34, diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.typedefTagWithChildrenTags.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.typedefTagWithChildrenTags.json index 6d2fb4ada2f..7b3050cffa2 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.typedefTagWithChildrenTags.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.typedefTagWithChildrenTags.json @@ -38,7 +38,7 @@ { "kind": "JSDocPropertyTag", "pos": 47, - "end": 72, + "end": 74, "atToken": { "kind": "AtToken", "pos": 47, @@ -72,7 +72,7 @@ { "kind": "JSDocPropertyTag", "pos": 74, - "end": 97, + "end": 100, "atToken": { "kind": "AtToken", "pos": 74, diff --git a/tests/cases/fourslash/quickInfoPropertyTag.ts b/tests/cases/fourslash/quickInfoPropertyTag.ts index b413a7610e1..e702436ed42 100644 --- a/tests/cases/fourslash/quickInfoPropertyTag.ts +++ b/tests/cases/fourslash/quickInfoPropertyTag.ts @@ -12,5 +12,4 @@ /////** @type {I} */ ////const obj = { /**/x: 10 }; -// TODO: GH#21123 There shouldn't be a " " before "More doc" -verify.quickInfoAt("", "(property) x: number", "Doc\n More doc"); +verify.quickInfoAt("", "(property) x: number", "Doc\nMore doc"); From ea7ff15307757400a57ca524caa28b1a95cd309f Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 12 Sep 2018 17:51:57 -0700 Subject: [PATCH 49/83] makeFileLevelOptmiisticUniqueName -> makeFileLevelOptimisticUniqueName --- src/compiler/emitter.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 2d103b8af8f..bce36bca73c 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1015,7 +1015,7 @@ namespace ts { writeLines(helper.text); } else { - writeLines(helper.text(makeFileLevelOptmiisticUniqueName)); + writeLines(helper.text(makeFileLevelOptimisticUniqueName)); } helpersEmitted = true; } @@ -3588,7 +3588,7 @@ namespace ts { } } - function makeFileLevelOptmiisticUniqueName(name: string) { + function makeFileLevelOptimisticUniqueName(name: string) { return makeUniqueName(name, isFileLevelUniqueName, /*optimistic*/ true); } From cc7bfc03496716374b9d28d0ff73c9ad5d942dd0 Mon Sep 17 00:00:00 2001 From: Andy Date: Thu, 13 Sep 2018 08:47:50 -0700 Subject: [PATCH 50/83] Support testing jsdoc tags of completions (#26962) --- src/harness/fourslash.ts | 27 ++- src/services/jsDoc.ts | 4 +- src/services/symbolDisplay.ts | 2 +- .../unittests/tsserverProjectSystem.ts | 6 +- tests/baselines/reference/jsDocTypedef1.js | 3 +- ...splayPartsArrowFunctionExpression.baseline | 24 +-- .../quickInfoDisplayPartsClass.baseline | 15 +- ...ickInfoDisplayPartsClassAccessors.baseline | 96 +++------ ...kInfoDisplayPartsClassConstructor.baseline | 78 +++---- .../quickInfoDisplayPartsClassMethod.baseline | 48 ++--- ...uickInfoDisplayPartsClassProperty.baseline | 48 ++--- .../quickInfoDisplayPartsConst.baseline | 48 ++--- .../quickInfoDisplayPartsEnum1.baseline | 90 +++----- .../quickInfoDisplayPartsEnum2.baseline | 90 +++----- .../quickInfoDisplayPartsEnum3.baseline | 90 +++----- ...layPartsExternalModuleAlias_file0.baseline | 18 +- ...ckInfoDisplayPartsExternalModules.baseline | 51 ++--- .../quickInfoDisplayPartsFunction.baseline | 42 ++-- ...nfoDisplayPartsFunctionExpression.baseline | 18 +- .../quickInfoDisplayPartsInterface.baseline | 9 +- ...kInfoDisplayPartsInterfaceMembers.baseline | 27 +-- ...foDisplayPartsInternalModuleAlias.baseline | 24 +-- .../quickInfoDisplayPartsLet.baseline | 48 ++--- ...nfoDisplayPartsLiteralLikeNames01.baseline | 30 +-- ...uickInfoDisplayPartsLocalFunction.baseline | 48 ++--- .../quickInfoDisplayPartsModules.baseline | 51 ++--- .../quickInfoDisplayPartsParameters.baseline | 27 +-- .../quickInfoDisplayPartsTypeAlias.baseline | 18 +- ...oDisplayPartsTypeParameterInClass.baseline | 123 ++++------- ...splayPartsTypeParameterInFunction.baseline | 36 ++-- ...arameterInFunctionLikeInTypeAlias.baseline | 9 +- ...playPartsTypeParameterInInterface.baseline | 195 ++++++------------ ...playPartsTypeParameterInTypeAlias.baseline | 18 +- .../quickInfoDisplayPartsVar.baseline | 42 ++-- ...quickInfoDisplayPartsVar.shims-pp.baseline | 42 ++-- .../quickInfoDisplayPartsVar.shims.baseline | 42 ++-- ...oDisplayPartsVarWithStringTypes01.baseline | 9 +- .../cases/fourslash/commentsCommentParsing.ts | 14 +- tests/cases/fourslash/fourslash.ts | 9 +- .../fourslash/jsDocFunctionSignatures9.ts | 2 +- .../completionEntryDetailAcrossFiles02.ts | 4 +- 41 files changed, 562 insertions(+), 1063 deletions(-) diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 1abb7d4c1cc..a1f3517b6e6 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -908,8 +908,8 @@ namespace FourSlash { } private verifyCompletionEntry(actual: ts.CompletionEntry, expected: FourSlashInterface.ExpectedCompletionEntry) { - const { insertText, replacementSpan, hasAction, isRecommended, kind, text, documentation, source, sourceDisplay } = typeof expected === "string" - ? { insertText: undefined, replacementSpan: undefined, hasAction: undefined, isRecommended: undefined, kind: undefined, text: undefined, documentation: undefined, source: undefined, sourceDisplay: undefined } + const { insertText, replacementSpan, hasAction, isRecommended, kind, text, documentation, tags, source, sourceDisplay } = typeof expected === "string" + ? { insertText: undefined, replacementSpan: undefined, hasAction: undefined, isRecommended: undefined, kind: undefined, text: undefined, documentation: undefined, tags: undefined, source: undefined, sourceDisplay: undefined } : expected; if (actual.insertText !== insertText) { @@ -929,7 +929,7 @@ namespace FourSlash { assert.equal(actual.isRecommended, isRecommended); assert.equal(actual.source, source); - if (text) { + if (text !== undefined) { const actualDetails = this.getCompletionEntryDetails(actual.name, actual.source)!; assert.equal(ts.displayPartsToString(actualDetails.displayParts), text); assert.equal(ts.displayPartsToString(actualDetails.documentation), documentation || ""); @@ -937,9 +937,10 @@ namespace FourSlash { // assert.equal(actualDetails.kind, actual.kind); assert.equal(actualDetails.kindModifiers, actual.kindModifiers); assert.equal(actualDetails.source && ts.displayPartsToString(actualDetails.source), sourceDisplay); + assert.deepEqual(actualDetails.tags, tags); } else { - assert(documentation === undefined && sourceDisplay === undefined, "If specifying completion details, should specify 'text'"); + assert(documentation === undefined && tags === undefined && sourceDisplay === undefined, "If specifying completion details, should specify 'text'"); } } @@ -1363,7 +1364,7 @@ Actual: ${stringify(fullActual)}`); public verifyQuickInfoDisplayParts(kind: string, kindModifiers: string, textSpan: TextSpan, displayParts: ts.SymbolDisplayPart[], documentation: ts.SymbolDisplayPart[], - tags: ts.JSDocTagInfo[] + tags: ts.JSDocTagInfo[] | undefined ) { const actualQuickInfo = this.languageService.getQuickInfoAtPosition(this.activeFile.fileName, this.currentCaretPosition)!; @@ -1372,11 +1373,16 @@ Actual: ${stringify(fullActual)}`); assert.equal(JSON.stringify(actualQuickInfo.textSpan), JSON.stringify(textSpan), this.messageAtLastKnownMarker("QuickInfo textSpan")); assert.equal(TestState.getDisplayPartsJson(actualQuickInfo.displayParts), TestState.getDisplayPartsJson(displayParts), this.messageAtLastKnownMarker("QuickInfo displayParts")); assert.equal(TestState.getDisplayPartsJson(actualQuickInfo.documentation), TestState.getDisplayPartsJson(documentation), this.messageAtLastKnownMarker("QuickInfo documentation")); - assert.equal(actualQuickInfo.tags!.length, tags.length, this.messageAtLastKnownMarker("QuickInfo tags")); - ts.zipWith(tags, actualQuickInfo.tags!, (expectedTag, actualTag) => { - assert.equal(expectedTag.name, actualTag.name); - assert.equal(expectedTag.text, actualTag.text, this.messageAtLastKnownMarker("QuickInfo tag " + actualTag.name)); - }); + if (!actualQuickInfo.tags || !tags) { + assert.equal(actualQuickInfo.tags, tags, this.messageAtLastKnownMarker("QuickInfo tags")); + } + else { + assert.equal(actualQuickInfo.tags.length, tags.length, this.messageAtLastKnownMarker("QuickInfo tags")); + ts.zipWith(tags, actualQuickInfo.tags, (expectedTag, actualTag) => { + assert.equal(expectedTag.name, actualTag.name); + assert.equal(expectedTag.text, actualTag.text, this.messageAtLastKnownMarker("QuickInfo tag " + actualTag.name)); + }); + } } public verifyRangesAreRenameLocations(options?: Range[] | { findInStrings?: boolean, findInComments?: boolean, ranges?: Range[] }) { @@ -4802,6 +4808,7 @@ namespace FourSlashInterface { readonly text: string; readonly documentation: string; readonly sourceDisplay?: string; + readonly tags?: ReadonlyArray; }; export interface CompletionsAtOptions extends Partial { triggerCharacter?: ts.CompletionsTriggerCharacter; diff --git a/src/services/jsDoc.ts b/src/services/jsDoc.ts index 641eb643f92..442df61e073 100644 --- a/src/services/jsDoc.ts +++ b/src/services/jsDoc.ts @@ -208,7 +208,7 @@ namespace ts.JsDoc { kindModifiers: "", displayParts: [textPart(name)], documentation: emptyArray, - tags: emptyArray, + tags: undefined, codeActions: undefined, }; } @@ -242,7 +242,7 @@ namespace ts.JsDoc { kindModifiers: "", displayParts: [textPart(name)], documentation: emptyArray, - tags: emptyArray, + tags: undefined, codeActions: undefined, }; } diff --git a/src/services/symbolDisplay.ts b/src/services/symbolDisplay.ts index cc59aa3c0ce..e0728f98a29 100644 --- a/src/services/symbolDisplay.ts +++ b/src/services/symbolDisplay.ts @@ -534,7 +534,7 @@ namespace ts.SymbolDisplay { tags = tagsFromAlias; } - return { displayParts, documentation, symbolKind, tags: tags! }; + return { displayParts, documentation, symbolKind, tags: tags!.length === 0 ? undefined : tags }; function getPrinter() { if (!printer) { diff --git a/src/testRunner/unittests/tsserverProjectSystem.ts b/src/testRunner/unittests/tsserverProjectSystem.ts index 7114759b097..988ccbc3bfe 100644 --- a/src/testRunner/unittests/tsserverProjectSystem.ts +++ b/src/testRunner/unittests/tsserverProjectSystem.ts @@ -3204,7 +3204,7 @@ namespace ts.projectSystem { { text: "number", kind: "keyword" } ], documentation: [], - tags: [] + tags: undefined, }); }); @@ -9501,7 +9501,7 @@ export function Test2() { kindModifiers: ScriptElementKindModifier.exportedModifier, name: "foo", source: [{ text: "./a", kind: "text" }], - tags: emptyArray, + tags: undefined, }; assert.deepEqual | undefined>(detailsResponse, [ { @@ -9583,7 +9583,7 @@ declare class TestLib { constructor() { var l = new TestLib(); - + } public test2() { diff --git a/tests/baselines/reference/jsDocTypedef1.js b/tests/baselines/reference/jsDocTypedef1.js index bc00dcafb5d..4745ca9d226 100644 --- a/tests/baselines/reference/jsDocTypedef1.js +++ b/tests/baselines/reference/jsDocTypedef1.js @@ -100,8 +100,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } } ] \ No newline at end of file diff --git a/tests/baselines/reference/quickInfoDisplayPartsArrowFunctionExpression.baseline b/tests/baselines/reference/quickInfoDisplayPartsArrowFunctionExpression.baseline index f4484663b97..7ee4e5b25cd 100644 --- a/tests/baselines/reference/quickInfoDisplayPartsArrowFunctionExpression.baseline +++ b/tests/baselines/reference/quickInfoDisplayPartsArrowFunctionExpression.baseline @@ -73,8 +73,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -123,8 +122,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -225,8 +223,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -275,8 +272,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -325,8 +321,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -403,8 +398,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -453,8 +447,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -515,8 +508,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } } ] \ No newline at end of file diff --git a/tests/baselines/reference/quickInfoDisplayPartsClass.baseline b/tests/baselines/reference/quickInfoDisplayPartsClass.baseline index 68e3b16c7a6..0b048b737a6 100644 --- a/tests/baselines/reference/quickInfoDisplayPartsClass.baseline +++ b/tests/baselines/reference/quickInfoDisplayPartsClass.baseline @@ -25,8 +25,7 @@ "kind": "className" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -67,8 +66,7 @@ "kind": "className" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -117,8 +115,7 @@ "kind": "className" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -167,8 +164,7 @@ "kind": "className" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -197,8 +193,7 @@ "kind": "className" } ], - "documentation": [], - "tags": [] + "documentation": [] } } ] \ No newline at end of file diff --git a/tests/baselines/reference/quickInfoDisplayPartsClassAccessors.baseline b/tests/baselines/reference/quickInfoDisplayPartsClassAccessors.baseline index 97f167fdd80..b0c27fd9d28 100644 --- a/tests/baselines/reference/quickInfoDisplayPartsClassAccessors.baseline +++ b/tests/baselines/reference/quickInfoDisplayPartsClassAccessors.baseline @@ -53,8 +53,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -111,8 +110,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -169,8 +167,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -227,8 +224,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -285,8 +281,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -343,8 +338,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -401,8 +395,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -459,8 +452,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -517,8 +509,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -575,8 +566,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -633,8 +623,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -691,8 +680,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -749,8 +737,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -807,8 +794,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -865,8 +851,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -923,8 +908,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -981,8 +965,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1039,8 +1022,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1097,8 +1079,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1155,8 +1136,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1213,8 +1193,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1271,8 +1250,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1329,8 +1307,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1387,8 +1364,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1429,8 +1405,7 @@ "kind": "className" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1487,8 +1462,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1517,8 +1491,7 @@ "kind": "className" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1575,8 +1548,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1617,8 +1589,7 @@ "kind": "className" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1675,8 +1646,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1705,8 +1675,7 @@ "kind": "className" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1763,8 +1732,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } } ] \ No newline at end of file diff --git a/tests/baselines/reference/quickInfoDisplayPartsClassConstructor.baseline b/tests/baselines/reference/quickInfoDisplayPartsClassConstructor.baseline index f6217460180..76ca00a4048 100644 --- a/tests/baselines/reference/quickInfoDisplayPartsClassConstructor.baseline +++ b/tests/baselines/reference/quickInfoDisplayPartsClassConstructor.baseline @@ -45,8 +45,7 @@ "kind": "className" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -87,8 +86,7 @@ "kind": "className" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -137,8 +135,7 @@ "kind": "className" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -187,8 +184,7 @@ "kind": "className" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -217,8 +213,7 @@ "kind": "className" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -311,8 +306,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -405,8 +399,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -499,8 +492,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -541,8 +533,7 @@ "kind": "className" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -635,8 +626,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -677,8 +667,7 @@ "kind": "className" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -771,8 +760,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -821,8 +809,7 @@ "kind": "className" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -851,8 +838,7 @@ "kind": "className" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -945,8 +931,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1039,8 +1024,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1133,8 +1117,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1227,8 +1210,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1269,8 +1251,7 @@ "kind": "className" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1363,8 +1344,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1405,8 +1385,7 @@ "kind": "className" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1499,8 +1478,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1541,8 +1519,7 @@ "kind": "className" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1635,8 +1612,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1685,8 +1661,7 @@ "kind": "className" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1715,8 +1690,7 @@ "kind": "className" } ], - "documentation": [], - "tags": [] + "documentation": [] } } ] \ No newline at end of file diff --git a/tests/baselines/reference/quickInfoDisplayPartsClassMethod.baseline b/tests/baselines/reference/quickInfoDisplayPartsClassMethod.baseline index e17708f1bc6..d6f3f187d02 100644 --- a/tests/baselines/reference/quickInfoDisplayPartsClassMethod.baseline +++ b/tests/baselines/reference/quickInfoDisplayPartsClassMethod.baseline @@ -61,8 +61,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -127,8 +126,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -193,8 +191,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -259,8 +256,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -325,8 +321,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -391,8 +386,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -457,8 +451,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -523,8 +516,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -589,8 +581,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -655,8 +646,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -721,8 +711,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -787,8 +776,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -829,8 +817,7 @@ "kind": "className" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -895,8 +882,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -925,8 +911,7 @@ "kind": "className" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -991,8 +976,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } } ] \ No newline at end of file diff --git a/tests/baselines/reference/quickInfoDisplayPartsClassProperty.baseline b/tests/baselines/reference/quickInfoDisplayPartsClassProperty.baseline index 57a41e6beb4..b49fb80c38a 100644 --- a/tests/baselines/reference/quickInfoDisplayPartsClassProperty.baseline +++ b/tests/baselines/reference/quickInfoDisplayPartsClassProperty.baseline @@ -53,8 +53,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -111,8 +110,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -169,8 +167,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -227,8 +224,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -285,8 +281,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -343,8 +338,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -401,8 +395,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -459,8 +452,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -517,8 +509,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -575,8 +566,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -633,8 +623,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -691,8 +680,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -733,8 +721,7 @@ "kind": "className" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -791,8 +778,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -821,8 +807,7 @@ "kind": "className" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -879,8 +864,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } } ] \ No newline at end of file diff --git a/tests/baselines/reference/quickInfoDisplayPartsConst.baseline b/tests/baselines/reference/quickInfoDisplayPartsConst.baseline index f73ef50dc0c..7493d001bd3 100644 --- a/tests/baselines/reference/quickInfoDisplayPartsConst.baseline +++ b/tests/baselines/reference/quickInfoDisplayPartsConst.baseline @@ -37,8 +37,7 @@ "kind": "stringLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -79,8 +78,7 @@ "kind": "stringLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -121,8 +119,7 @@ "kind": "stringLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -163,8 +160,7 @@ "kind": "stringLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -205,8 +201,7 @@ "kind": "stringLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -255,8 +250,7 @@ "kind": "stringLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -297,8 +291,7 @@ "kind": "stringLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -359,8 +352,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -421,8 +413,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -483,8 +474,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -545,8 +535,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -691,8 +680,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -837,8 +825,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -983,8 +970,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1089,8 +1075,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1195,8 +1180,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } } ] \ No newline at end of file diff --git a/tests/baselines/reference/quickInfoDisplayPartsEnum1.baseline b/tests/baselines/reference/quickInfoDisplayPartsEnum1.baseline index cf3ddc3025c..6dc27a4a5b3 100644 --- a/tests/baselines/reference/quickInfoDisplayPartsEnum1.baseline +++ b/tests/baselines/reference/quickInfoDisplayPartsEnum1.baseline @@ -25,8 +25,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -87,8 +86,7 @@ "kind": "numericLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -149,8 +147,7 @@ "kind": "numericLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -211,8 +208,7 @@ "kind": "numericLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -253,8 +249,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -283,8 +278,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -325,8 +319,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -355,8 +348,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -417,8 +409,7 @@ "kind": "numericLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -459,8 +450,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -489,8 +479,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -551,8 +540,7 @@ "kind": "numericLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -593,8 +581,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -623,8 +610,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -685,8 +671,7 @@ "kind": "numericLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -723,8 +708,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -785,8 +769,7 @@ "kind": "numericLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -847,8 +830,7 @@ "kind": "numericLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -909,8 +891,7 @@ "kind": "numericLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -951,8 +932,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -989,8 +969,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1031,8 +1010,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1069,8 +1047,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1131,8 +1108,7 @@ "kind": "numericLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1173,8 +1149,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1211,8 +1186,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1273,8 +1247,7 @@ "kind": "numericLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1315,8 +1288,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1353,8 +1325,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1415,8 +1386,7 @@ "kind": "numericLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } } ] \ No newline at end of file diff --git a/tests/baselines/reference/quickInfoDisplayPartsEnum2.baseline b/tests/baselines/reference/quickInfoDisplayPartsEnum2.baseline index 0bb72e51078..43d0683faef 100644 --- a/tests/baselines/reference/quickInfoDisplayPartsEnum2.baseline +++ b/tests/baselines/reference/quickInfoDisplayPartsEnum2.baseline @@ -25,8 +25,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -91,8 +90,7 @@ "kind": "numericLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -157,8 +155,7 @@ "kind": "numericLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -223,8 +220,7 @@ "kind": "numericLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -265,8 +261,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -295,8 +290,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -337,8 +331,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -367,8 +360,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -433,8 +425,7 @@ "kind": "numericLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -475,8 +466,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -505,8 +495,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -571,8 +560,7 @@ "kind": "numericLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -613,8 +601,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -643,8 +630,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -709,8 +695,7 @@ "kind": "numericLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -747,8 +732,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -813,8 +797,7 @@ "kind": "numericLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -879,8 +862,7 @@ "kind": "numericLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -945,8 +927,7 @@ "kind": "numericLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -987,8 +968,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1025,8 +1005,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1067,8 +1046,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1105,8 +1083,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1171,8 +1148,7 @@ "kind": "numericLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1213,8 +1189,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1251,8 +1226,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1317,8 +1291,7 @@ "kind": "numericLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1359,8 +1332,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1397,8 +1369,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1463,8 +1434,7 @@ "kind": "numericLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } } ] \ No newline at end of file diff --git a/tests/baselines/reference/quickInfoDisplayPartsEnum3.baseline b/tests/baselines/reference/quickInfoDisplayPartsEnum3.baseline index 1366a49ec7b..b9f6483f63a 100644 --- a/tests/baselines/reference/quickInfoDisplayPartsEnum3.baseline +++ b/tests/baselines/reference/quickInfoDisplayPartsEnum3.baseline @@ -25,8 +25,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -91,8 +90,7 @@ "kind": "numericLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -157,8 +155,7 @@ "kind": "numericLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -223,8 +220,7 @@ "kind": "numericLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -265,8 +261,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -295,8 +290,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -337,8 +331,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -367,8 +360,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -433,8 +425,7 @@ "kind": "numericLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -475,8 +466,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -505,8 +495,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -571,8 +560,7 @@ "kind": "numericLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -613,8 +601,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -643,8 +630,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -709,8 +695,7 @@ "kind": "numericLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -747,8 +732,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -813,8 +797,7 @@ "kind": "numericLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -879,8 +862,7 @@ "kind": "numericLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -945,8 +927,7 @@ "kind": "numericLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -987,8 +968,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1025,8 +1005,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1067,8 +1046,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1105,8 +1083,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1171,8 +1148,7 @@ "kind": "numericLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1213,8 +1189,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1251,8 +1226,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1317,8 +1291,7 @@ "kind": "numericLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1359,8 +1332,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1397,8 +1369,7 @@ "kind": "enumName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1463,8 +1434,7 @@ "kind": "numericLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } } ] \ No newline at end of file diff --git a/tests/baselines/reference/quickInfoDisplayPartsExternalModuleAlias_file0.baseline b/tests/baselines/reference/quickInfoDisplayPartsExternalModuleAlias_file0.baseline index 182ae0a4040..78667e7c6e6 100644 --- a/tests/baselines/reference/quickInfoDisplayPartsExternalModuleAlias_file0.baseline +++ b/tests/baselines/reference/quickInfoDisplayPartsExternalModuleAlias_file0.baseline @@ -53,8 +53,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -83,8 +82,7 @@ "kind": "aliasName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -141,8 +139,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -199,8 +196,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -229,8 +225,7 @@ "kind": "aliasName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -287,8 +282,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } } ] \ No newline at end of file diff --git a/tests/baselines/reference/quickInfoDisplayPartsExternalModules.baseline b/tests/baselines/reference/quickInfoDisplayPartsExternalModules.baseline index dc422bbac33..fa548470a76 100644 --- a/tests/baselines/reference/quickInfoDisplayPartsExternalModules.baseline +++ b/tests/baselines/reference/quickInfoDisplayPartsExternalModules.baseline @@ -25,8 +25,7 @@ "kind": "moduleName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -67,8 +66,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -117,8 +115,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -167,8 +164,7 @@ "kind": "moduleName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -197,8 +193,7 @@ "kind": "moduleName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -247,8 +242,7 @@ "kind": "moduleName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -277,8 +271,7 @@ "kind": "moduleName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -307,8 +300,7 @@ "kind": "moduleName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -345,8 +337,7 @@ "kind": "moduleName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -387,8 +378,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -445,8 +435,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -503,8 +492,7 @@ "kind": "moduleName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -533,8 +521,7 @@ "kind": "moduleName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -571,8 +558,7 @@ "kind": "moduleName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -629,8 +615,7 @@ "kind": "moduleName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -659,8 +644,7 @@ "kind": "moduleName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -697,8 +681,7 @@ "kind": "moduleName" } ], - "documentation": [], - "tags": [] + "documentation": [] } } ] \ No newline at end of file diff --git a/tests/baselines/reference/quickInfoDisplayPartsFunction.baseline b/tests/baselines/reference/quickInfoDisplayPartsFunction.baseline index 2e3cacb9801..6ac80589629 100644 --- a/tests/baselines/reference/quickInfoDisplayPartsFunction.baseline +++ b/tests/baselines/reference/quickInfoDisplayPartsFunction.baseline @@ -153,8 +153,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -247,8 +246,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -341,8 +339,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -435,8 +432,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -529,8 +525,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -623,8 +618,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -717,8 +711,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -811,8 +804,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -969,8 +961,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1063,8 +1054,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1157,8 +1147,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1251,8 +1240,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1345,8 +1333,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1439,8 +1426,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } } ] \ No newline at end of file diff --git a/tests/baselines/reference/quickInfoDisplayPartsFunctionExpression.baseline b/tests/baselines/reference/quickInfoDisplayPartsFunctionExpression.baseline index 2e67ba6c4aa..ec943e3ac7c 100644 --- a/tests/baselines/reference/quickInfoDisplayPartsFunctionExpression.baseline +++ b/tests/baselines/reference/quickInfoDisplayPartsFunctionExpression.baseline @@ -57,8 +57,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -115,8 +114,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -173,8 +171,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -235,8 +232,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -293,8 +289,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -351,8 +346,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } } ] \ No newline at end of file diff --git a/tests/baselines/reference/quickInfoDisplayPartsInterface.baseline b/tests/baselines/reference/quickInfoDisplayPartsInterface.baseline index 51383489237..43b9faa9540 100644 --- a/tests/baselines/reference/quickInfoDisplayPartsInterface.baseline +++ b/tests/baselines/reference/quickInfoDisplayPartsInterface.baseline @@ -25,8 +25,7 @@ "kind": "interfaceName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -67,8 +66,7 @@ "kind": "interfaceName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -97,8 +95,7 @@ "kind": "interfaceName" } ], - "documentation": [], - "tags": [] + "documentation": [] } } ] \ No newline at end of file diff --git a/tests/baselines/reference/quickInfoDisplayPartsInterfaceMembers.baseline b/tests/baselines/reference/quickInfoDisplayPartsInterfaceMembers.baseline index fa1e5977dd5..4a82bd41d30 100644 --- a/tests/baselines/reference/quickInfoDisplayPartsInterfaceMembers.baseline +++ b/tests/baselines/reference/quickInfoDisplayPartsInterfaceMembers.baseline @@ -53,8 +53,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -119,8 +118,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -161,8 +159,7 @@ "kind": "interfaceName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -219,8 +216,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -261,8 +257,7 @@ "kind": "interfaceName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -327,8 +322,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -397,8 +391,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -439,8 +432,7 @@ "kind": "interfaceName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -517,8 +509,7 @@ "kind": "interfaceName" } ], - "documentation": [], - "tags": [] + "documentation": [] } } ] \ No newline at end of file diff --git a/tests/baselines/reference/quickInfoDisplayPartsInternalModuleAlias.baseline b/tests/baselines/reference/quickInfoDisplayPartsInternalModuleAlias.baseline index c476abad356..0d4660e51d5 100644 --- a/tests/baselines/reference/quickInfoDisplayPartsInternalModuleAlias.baseline +++ b/tests/baselines/reference/quickInfoDisplayPartsInternalModuleAlias.baseline @@ -73,8 +73,7 @@ "kind": "moduleName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -151,8 +150,7 @@ "kind": "moduleName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -237,8 +235,7 @@ "kind": "moduleName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -323,8 +320,7 @@ "kind": "moduleName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -417,8 +413,7 @@ "kind": "moduleName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -511,8 +506,7 @@ "kind": "moduleName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -613,8 +607,7 @@ "kind": "moduleName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -715,8 +708,7 @@ "kind": "moduleName" } ], - "documentation": [], - "tags": [] + "documentation": [] } } ] \ No newline at end of file diff --git a/tests/baselines/reference/quickInfoDisplayPartsLet.baseline b/tests/baselines/reference/quickInfoDisplayPartsLet.baseline index d8f339f8451..2153c0b132b 100644 --- a/tests/baselines/reference/quickInfoDisplayPartsLet.baseline +++ b/tests/baselines/reference/quickInfoDisplayPartsLet.baseline @@ -37,8 +37,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -79,8 +78,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -121,8 +119,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -163,8 +160,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -205,8 +201,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -255,8 +250,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -297,8 +291,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -359,8 +352,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -421,8 +413,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -483,8 +474,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -545,8 +535,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -691,8 +680,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -837,8 +825,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -983,8 +970,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1089,8 +1075,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1195,8 +1180,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } } ] \ No newline at end of file diff --git a/tests/baselines/reference/quickInfoDisplayPartsLiteralLikeNames01.baseline b/tests/baselines/reference/quickInfoDisplayPartsLiteralLikeNames01.baseline index 1d2d8216808..47e5239c605 100644 --- a/tests/baselines/reference/quickInfoDisplayPartsLiteralLikeNames01.baseline +++ b/tests/baselines/reference/quickInfoDisplayPartsLiteralLikeNames01.baseline @@ -65,8 +65,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -131,8 +130,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -197,8 +195,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -267,8 +264,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -337,8 +333,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -407,8 +402,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -473,8 +467,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -539,8 +532,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -605,8 +597,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -675,8 +666,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } } ] \ No newline at end of file diff --git a/tests/baselines/reference/quickInfoDisplayPartsLocalFunction.baseline b/tests/baselines/reference/quickInfoDisplayPartsLocalFunction.baseline index 1b7d050c3b3..65c3dc88390 100644 --- a/tests/baselines/reference/quickInfoDisplayPartsLocalFunction.baseline +++ b/tests/baselines/reference/quickInfoDisplayPartsLocalFunction.baseline @@ -45,8 +45,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -211,8 +210,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -313,8 +311,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -415,8 +412,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -517,8 +513,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -619,8 +614,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -721,8 +715,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -823,8 +816,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -925,8 +917,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1091,8 +1082,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1193,8 +1183,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1295,8 +1284,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1397,8 +1385,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1499,8 +1486,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1601,8 +1587,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1651,8 +1636,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } } ] \ No newline at end of file diff --git a/tests/baselines/reference/quickInfoDisplayPartsModules.baseline b/tests/baselines/reference/quickInfoDisplayPartsModules.baseline index 66c04216af6..e2f04ea75e8 100644 --- a/tests/baselines/reference/quickInfoDisplayPartsModules.baseline +++ b/tests/baselines/reference/quickInfoDisplayPartsModules.baseline @@ -25,8 +25,7 @@ "kind": "moduleName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -67,8 +66,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -117,8 +115,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -167,8 +164,7 @@ "kind": "moduleName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -197,8 +193,7 @@ "kind": "moduleName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -247,8 +242,7 @@ "kind": "moduleName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -277,8 +271,7 @@ "kind": "moduleName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -307,8 +300,7 @@ "kind": "moduleName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -345,8 +337,7 @@ "kind": "moduleName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -387,8 +378,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -445,8 +435,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -503,8 +492,7 @@ "kind": "moduleName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -533,8 +521,7 @@ "kind": "moduleName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -571,8 +558,7 @@ "kind": "moduleName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -629,8 +615,7 @@ "kind": "moduleName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -659,8 +644,7 @@ "kind": "moduleName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -697,8 +681,7 @@ "kind": "moduleName" } ], - "documentation": [], - "tags": [] + "documentation": [] } } ] \ No newline at end of file diff --git a/tests/baselines/reference/quickInfoDisplayPartsParameters.baseline b/tests/baselines/reference/quickInfoDisplayPartsParameters.baseline index c0451e35dbb..45f6128c2b1 100644 --- a/tests/baselines/reference/quickInfoDisplayPartsParameters.baseline +++ b/tests/baselines/reference/quickInfoDisplayPartsParameters.baseline @@ -153,8 +153,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -203,8 +202,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -253,8 +251,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -303,8 +300,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -361,8 +357,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -411,8 +406,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -461,8 +455,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -511,8 +504,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -569,8 +561,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } } ] \ No newline at end of file diff --git a/tests/baselines/reference/quickInfoDisplayPartsTypeAlias.baseline b/tests/baselines/reference/quickInfoDisplayPartsTypeAlias.baseline index 367acd4dbc4..49a97ac6773 100644 --- a/tests/baselines/reference/quickInfoDisplayPartsTypeAlias.baseline +++ b/tests/baselines/reference/quickInfoDisplayPartsTypeAlias.baseline @@ -25,8 +25,7 @@ "kind": "className" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -71,8 +70,7 @@ "kind": "className" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -101,8 +99,7 @@ "kind": "className" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -143,8 +140,7 @@ "kind": "className" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -189,8 +185,7 @@ "kind": "className" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -239,8 +234,7 @@ "kind": "className" } ], - "documentation": [], - "tags": [] + "documentation": [] } } ] \ No newline at end of file diff --git a/tests/baselines/reference/quickInfoDisplayPartsTypeParameterInClass.baseline b/tests/baselines/reference/quickInfoDisplayPartsTypeParameterInClass.baseline index db995905483..48bd280a1b5 100644 --- a/tests/baselines/reference/quickInfoDisplayPartsTypeParameterInClass.baseline +++ b/tests/baselines/reference/quickInfoDisplayPartsTypeParameterInClass.baseline @@ -37,8 +37,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -103,8 +102,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -193,8 +191,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -243,8 +240,7 @@ "kind": "typeParameterName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -309,8 +305,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -439,8 +434,7 @@ "kind": "typeParameterName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -585,8 +579,7 @@ "kind": "typeParameterName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -635,8 +628,7 @@ "kind": "typeParameterName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -781,8 +773,7 @@ "kind": "typeParameterName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -831,8 +822,7 @@ "kind": "typeParameterName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -897,8 +887,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -947,8 +936,7 @@ "kind": "typeParameterName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1001,8 +989,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1091,8 +1078,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1141,8 +1127,7 @@ "kind": "className" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1183,8 +1168,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1237,8 +1221,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1367,8 +1350,7 @@ "kind": "stringLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1437,8 +1419,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1531,8 +1512,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1573,8 +1553,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1691,8 +1670,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1769,8 +1747,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1863,8 +1840,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -2049,8 +2025,7 @@ "kind": "typeParameterName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -2251,8 +2226,7 @@ "kind": "typeParameterName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -2293,8 +2267,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -2371,8 +2344,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -2573,8 +2545,7 @@ "kind": "typeParameterName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -2651,8 +2622,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -2745,8 +2715,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -2823,8 +2792,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -2889,8 +2857,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -3015,8 +2982,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -3069,8 +3035,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -3119,8 +3084,7 @@ "kind": "className" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -3189,8 +3153,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -3255,8 +3218,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -3445,8 +3407,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -3499,8 +3460,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -3553,8 +3513,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } } ] \ No newline at end of file diff --git a/tests/baselines/reference/quickInfoDisplayPartsTypeParameterInFunction.baseline b/tests/baselines/reference/quickInfoDisplayPartsTypeParameterInFunction.baseline index efe6ccd7130..278e9396fb6 100644 --- a/tests/baselines/reference/quickInfoDisplayPartsTypeParameterInFunction.baseline +++ b/tests/baselines/reference/quickInfoDisplayPartsTypeParameterInFunction.baseline @@ -73,8 +73,7 @@ "kind": "typeParameterName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -175,8 +174,7 @@ "kind": "typeParameterName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -225,8 +223,7 @@ "kind": "typeParameterName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -327,8 +324,7 @@ "kind": "typeParameterName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -377,8 +373,7 @@ "kind": "typeParameterName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -455,8 +450,7 @@ "kind": "stringLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -549,8 +543,7 @@ "kind": "typeParameterName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -667,8 +660,7 @@ "kind": "typeParameterName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -733,8 +725,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -851,8 +842,7 @@ "kind": "typeParameterName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -917,8 +907,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -995,8 +984,7 @@ "kind": "stringLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } } ] \ No newline at end of file diff --git a/tests/baselines/reference/quickInfoDisplayPartsTypeParameterInFunctionLikeInTypeAlias.baseline b/tests/baselines/reference/quickInfoDisplayPartsTypeParameterInFunctionLikeInTypeAlias.baseline index 92763ef5b10..50f0ac16a1c 100644 --- a/tests/baselines/reference/quickInfoDisplayPartsTypeParameterInFunctionLikeInTypeAlias.baseline +++ b/tests/baselines/reference/quickInfoDisplayPartsTypeParameterInFunctionLikeInTypeAlias.baseline @@ -69,8 +69,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -143,8 +142,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -217,8 +215,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } } ] \ No newline at end of file diff --git a/tests/baselines/reference/quickInfoDisplayPartsTypeParameterInInterface.baseline b/tests/baselines/reference/quickInfoDisplayPartsTypeParameterInInterface.baseline index 80da1f19ef9..715811f9918 100644 --- a/tests/baselines/reference/quickInfoDisplayPartsTypeParameterInInterface.baseline +++ b/tests/baselines/reference/quickInfoDisplayPartsTypeParameterInInterface.baseline @@ -37,8 +37,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -103,8 +102,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -233,8 +231,7 @@ "kind": "typeParameterName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -283,8 +280,7 @@ "kind": "typeParameterName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -413,8 +409,7 @@ "kind": "typeParameterName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -463,8 +458,7 @@ "kind": "typeParameterName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -529,8 +523,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -659,8 +652,7 @@ "kind": "typeParameterName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -781,8 +773,7 @@ "kind": "typeParameterName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -831,8 +822,7 @@ "kind": "typeParameterName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -953,8 +943,7 @@ "kind": "typeParameterName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1003,8 +992,7 @@ "kind": "typeParameterName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1069,8 +1057,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1191,8 +1178,7 @@ "kind": "typeParameterName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1321,8 +1307,7 @@ "kind": "typeParameterName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1467,8 +1452,7 @@ "kind": "typeParameterName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1517,8 +1501,7 @@ "kind": "typeParameterName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1663,8 +1646,7 @@ "kind": "typeParameterName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1713,8 +1695,7 @@ "kind": "typeParameterName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1779,8 +1760,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1925,8 +1905,7 @@ "kind": "typeParameterName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1979,8 +1958,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -2021,8 +1999,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -2151,8 +2128,7 @@ "kind": "stringLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -2273,8 +2249,7 @@ "kind": "stringLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -2327,8 +2302,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -2457,8 +2431,7 @@ "kind": "stringLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -2527,8 +2500,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -2621,8 +2593,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -2663,8 +2634,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -2821,8 +2791,7 @@ "kind": "typeParameterName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -2863,8 +2832,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -2941,8 +2909,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -3099,8 +3066,7 @@ "kind": "typeParameterName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -3177,8 +3143,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -3271,8 +3236,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -3429,8 +3393,7 @@ "kind": "typeParameterName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -3579,8 +3542,7 @@ "kind": "typeParameterName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -3621,8 +3583,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -3699,8 +3660,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -3849,8 +3809,7 @@ "kind": "typeParameterName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -3927,8 +3886,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -4021,8 +3979,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -4171,8 +4128,7 @@ "kind": "typeParameterName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -4357,8 +4313,7 @@ "kind": "typeParameterName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -4559,8 +4514,7 @@ "kind": "typeParameterName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -4601,8 +4555,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -4679,8 +4632,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -4881,8 +4833,7 @@ "kind": "typeParameterName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -4959,8 +4910,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -5053,8 +5003,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -5255,8 +5204,7 @@ "kind": "typeParameterName" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -5321,8 +5269,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -5391,8 +5338,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -5433,8 +5379,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -5611,8 +5556,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -5665,8 +5609,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -5719,8 +5662,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -5889,8 +5831,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -5943,8 +5884,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -5997,8 +5937,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -6063,8 +6002,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -6253,8 +6191,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -6307,8 +6244,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -6361,8 +6297,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } } ] \ No newline at end of file diff --git a/tests/baselines/reference/quickInfoDisplayPartsTypeParameterInTypeAlias.baseline b/tests/baselines/reference/quickInfoDisplayPartsTypeParameterInTypeAlias.baseline index 0f24ff6c767..e6f1d451288 100644 --- a/tests/baselines/reference/quickInfoDisplayPartsTypeParameterInTypeAlias.baseline +++ b/tests/baselines/reference/quickInfoDisplayPartsTypeParameterInTypeAlias.baseline @@ -61,8 +61,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -135,8 +134,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -209,8 +207,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -291,8 +288,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -381,8 +377,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -471,8 +466,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } } ] \ No newline at end of file diff --git a/tests/baselines/reference/quickInfoDisplayPartsVar.baseline b/tests/baselines/reference/quickInfoDisplayPartsVar.baseline index 250f10ff533..b56e1b31542 100644 --- a/tests/baselines/reference/quickInfoDisplayPartsVar.baseline +++ b/tests/baselines/reference/quickInfoDisplayPartsVar.baseline @@ -37,8 +37,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -87,8 +86,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -129,8 +127,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -171,8 +168,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -221,8 +217,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -283,8 +278,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -345,8 +339,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -407,8 +400,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -469,8 +461,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -615,8 +606,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -761,8 +751,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -907,8 +896,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1013,8 +1001,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1119,8 +1106,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } } ] \ No newline at end of file diff --git a/tests/baselines/reference/quickInfoDisplayPartsVar.shims-pp.baseline b/tests/baselines/reference/quickInfoDisplayPartsVar.shims-pp.baseline index 5d072155c95..dfe65565790 100644 --- a/tests/baselines/reference/quickInfoDisplayPartsVar.shims-pp.baseline +++ b/tests/baselines/reference/quickInfoDisplayPartsVar.shims-pp.baseline @@ -37,8 +37,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -87,8 +86,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -129,8 +127,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -171,8 +168,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -221,8 +217,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -283,8 +278,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -345,8 +339,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -407,8 +400,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -469,8 +461,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -615,8 +606,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -761,8 +751,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -907,8 +896,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1013,8 +1001,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1119,8 +1106,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } } ] \ No newline at end of file diff --git a/tests/baselines/reference/quickInfoDisplayPartsVar.shims.baseline b/tests/baselines/reference/quickInfoDisplayPartsVar.shims.baseline index 448595e3f64..249772f416e 100644 --- a/tests/baselines/reference/quickInfoDisplayPartsVar.shims.baseline +++ b/tests/baselines/reference/quickInfoDisplayPartsVar.shims.baseline @@ -37,8 +37,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -87,8 +86,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -129,8 +127,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -171,8 +168,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -221,8 +217,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -283,8 +278,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -345,8 +339,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -407,8 +400,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -469,8 +461,7 @@ "kind": "keyword" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -615,8 +606,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -761,8 +751,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -907,8 +896,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1013,8 +1001,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -1119,8 +1106,7 @@ "kind": "punctuation" } ], - "documentation": [], - "tags": [] + "documentation": [] } } ] \ No newline at end of file diff --git a/tests/baselines/reference/quickInfoDisplayPartsVarWithStringTypes01.baseline b/tests/baselines/reference/quickInfoDisplayPartsVarWithStringTypes01.baseline index 92a09a4d7fa..3c46a6ba6bd 100644 --- a/tests/baselines/reference/quickInfoDisplayPartsVarWithStringTypes01.baseline +++ b/tests/baselines/reference/quickInfoDisplayPartsVarWithStringTypes01.baseline @@ -37,8 +37,7 @@ "kind": "stringLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -79,8 +78,7 @@ "kind": "stringLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } }, { @@ -137,8 +135,7 @@ "kind": "stringLiteral" } ], - "documentation": [], - "tags": [] + "documentation": [] } } ] \ No newline at end of file diff --git a/tests/cases/fourslash/commentsCommentParsing.ts b/tests/cases/fourslash/commentsCommentParsing.ts index df3adca4c87..8f7d35ce0f9 100644 --- a/tests/cases/fourslash/commentsCommentParsing.ts +++ b/tests/cases/fourslash/commentsCommentParsing.ts @@ -244,8 +244,18 @@ verify.quickInfoAt("13q", "function noHelpComment2(): void"); verify.signatureHelp({ marker: "14", docComment: "" }); verify.quickInfoAt("14q", "function noHelpComment3(): void"); -goTo.marker('15'); -verify.completionListContains("sum", "function sum(a: number, b: number): number", "Adds two integers and returns the result"); +verify.completions({ + marker: "15", + includes: { + name: "sum", + text: "function sum(a: number, b: number): number", + documentation: "Adds two integers and returns the result", + tags: [ + { name: "param", text: "a first number" }, + { name: "param", text: "b second number" }, + ], + }, +}); const addTags: ReadonlyArray = [ { name: "param", text: "a first number" }, diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index 2fb29e245da..cf4752a65ab 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -299,7 +299,7 @@ declare namespace FourSlashInterface { rangesAreDocumentHighlights(ranges?: Range[], options?: VerifyDocumentHighlightsOptions): void; rangesWithSameTextAreDocumentHighlights(): void; documentHighlightsOf(startRange: Range, ranges: Range[], options?: VerifyDocumentHighlightsOptions): void; - completionEntryDetailIs(entryName: string, text: string, documentation?: string, kind?: string, tags?: ts.JSDocTagInfo[]): void; + completionEntryDetailIs(entryName: string, text: string, documentation?: string, kind?: string, tags?: JSDocTagInfo[]): void; /** * This method *requires* a contiguous, complete, and ordered stream of classifications for a file. */ @@ -331,7 +331,7 @@ declare namespace FourSlashInterface { verifyQuickInfoDisplayParts(kind: string, kindModifiers: string, textSpan: { start: number; length: number; - }, displayParts: ts.SymbolDisplayPart[], documentation: ts.SymbolDisplayPart[], tags: { name: string, text?: string }[]): void; + }, displayParts: ts.SymbolDisplayPart[], documentation: ts.SymbolDisplayPart[], tags: { name: string, text?: string }[] | undefined): void; getSyntacticDiagnostics(expected: ReadonlyArray): void; getSemanticDiagnostics(expected: ReadonlyArray): void; getSuggestionDiagnostics(expected: ReadonlyArray): void; @@ -550,6 +550,7 @@ declare namespace FourSlashInterface { // details readonly text?: string, readonly documentation?: string, + readonly tags?: ReadonlyArray; readonly sourceDisplay?: string, }; @@ -632,8 +633,8 @@ declare namespace FourSlashInterface { } interface JSDocTagInfo { - name: string; - text: string | undefined; + readonly name: string; + readonly text: string | undefined; } type ArrayOrSingle = T | ReadonlyArray; diff --git a/tests/cases/fourslash/jsDocFunctionSignatures9.ts b/tests/cases/fourslash/jsDocFunctionSignatures9.ts index 6c3342c0a3f..68c906b93ef 100644 --- a/tests/cases/fourslash/jsDocFunctionSignatures9.ts +++ b/tests/cases/fourslash/jsDocFunctionSignatures9.ts @@ -20,4 +20,4 @@ verify.verifyQuickInfoDisplayParts('function', {"text": "void", "kind": "keyword"} ], [{"text": "first line of the comment\n\nthird line", "kind": "text"}], - []); + undefined); diff --git a/tests/cases/fourslash/server/completionEntryDetailAcrossFiles02.ts b/tests/cases/fourslash/server/completionEntryDetailAcrossFiles02.ts index 1c499efc7e2..d915c55e320 100644 --- a/tests/cases/fourslash/server/completionEntryDetailAcrossFiles02.ts +++ b/tests/cases/fourslash/server/completionEntryDetailAcrossFiles02.ts @@ -15,6 +15,6 @@ //// a.fo/*2*/ verify.completions( - { marker: "1", includes: { name: "foo", text: "var foo: (p1: string) => void", documentation: "Modify the parameter" } }, - { marker: "2", exact: { name: "foo", text: "(property) a.foo: (p1: string) => void", documentation: "Modify the parameter" } }, + { marker: "1", includes: { name: "foo", text: "var foo: (p1: string) => void", documentation: "Modify the parameter", tags: [{ name: "param", text: "p1" }] } }, + { marker: "2", exact: { name: "foo", text: "(property) a.foo: (p1: string) => void", documentation: "Modify the parameter", tags: [{ name: "param", text: "p1" }] } }, ); From 905578cf371ad287bf3b975ecdb8c4a43c20270b Mon Sep 17 00:00:00 2001 From: Benjamin Lichtman Date: Thu, 13 Sep 2018 09:02:02 -0700 Subject: [PATCH 51/83] Use existing identifier when possible for renaming functions --- src/services/codefixes/convertToAsyncFunction.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/services/codefixes/convertToAsyncFunction.ts b/src/services/codefixes/convertToAsyncFunction.ts index 235f50226eb..51511c2207c 100644 --- a/src/services/codefixes/convertToAsyncFunction.ts +++ b/src/services/codefixes/convertToAsyncFunction.ts @@ -178,10 +178,11 @@ namespace ts.codefix { // if the identifier refers to a function we want to add the new synthesized variable for the declaration (ex. blob in let blob = res(arg)) // Note - the choice of the last call signature is arbitrary if (lastCallSignature && lastCallSignature.parameters.length && !synthNamesMap.has(symbolIdString)) { - const name = lastCallSignature.parameters[0].name; - const synthName = getNewNameIfConflict(createIdentifier(name), allVarNames); + const firstParameter = lastCallSignature.parameters[0]; + const ident = isParameter(firstParameter.valueDeclaration) && tryCast(firstParameter.valueDeclaration.name, isIdentifier) || createOptimisticUniqueName("result"); + const synthName = getNewNameIfConflict(ident, allVarNames); synthNamesMap.set(symbolIdString, synthName); - allVarNames.push({ identifier: synthName.identifier, symbol, originalName: name }); + allVarNames.push({ identifier: synthName.identifier, symbol, originalName: ident.text }); } // we only care about identifiers that are parameters and declarations (don't care about other uses) else if (node.parent && (isParameter(node.parent) || isVariableDeclaration(node.parent))) { @@ -449,7 +450,7 @@ namespace ts.codefix { function getLastCallSignature(type: Type, checker: TypeChecker): Signature | undefined { const callSignatures = checker.getSignaturesOfType(type, SignatureKind.Call); - return callSignatures && callSignatures[callSignatures.length - 1]; + return lastOrUndefined(callSignatures); } From 504b5f298542236b902892d6af66b4eab2cc966c Mon Sep 17 00:00:00 2001 From: Benjamin Lichtman Date: Thu, 13 Sep 2018 09:04:52 -0700 Subject: [PATCH 52/83] Add and update tests --- .../unittests/convertToAsyncFunction.ts | 10 ++++++++++ .../convertToAsyncFunction_bindingPattern.ts | 4 ++-- ...yncFunction_bindingPatternNameCollision.ts | 20 +++++++++++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_bindingPatternNameCollision.ts diff --git a/src/testRunner/unittests/convertToAsyncFunction.ts b/src/testRunner/unittests/convertToAsyncFunction.ts index f774c58de94..05df4f297e8 100644 --- a/src/testRunner/unittests/convertToAsyncFunction.ts +++ b/src/testRunner/unittests/convertToAsyncFunction.ts @@ -1207,6 +1207,16 @@ function [#|f|]():Promise { function res({ status, trailer }){ console.log(status); } +`); + + _testConvertToAsyncFunction("convertToAsyncFunction_bindingPatternNameCollision", ` +function [#|f|]():Promise { + const result = 'https://typescriptlang.org'; + return fetch(result).then(res); +} +function res({ status, trailer }){ + console.log(status); +} `); }); diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_bindingPattern.ts b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_bindingPattern.ts index f7d26faa980..97c68d57260 100644 --- a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_bindingPattern.ts +++ b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_bindingPattern.ts @@ -10,8 +10,8 @@ function res({ status, trailer }){ // ==ASYNC FUNCTION::Convert to async function== async function f():Promise { - const __0 = await fetch('https://typescriptlang.org'); - return res(__0); + const result = await fetch('https://typescriptlang.org'); + return res(result); } function res({ status, trailer }){ console.log(status); diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_bindingPatternNameCollision.ts b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_bindingPatternNameCollision.ts new file mode 100644 index 00000000000..db0c63535c7 --- /dev/null +++ b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_bindingPatternNameCollision.ts @@ -0,0 +1,20 @@ +// ==ORIGINAL== + +function /*[#|*/f/*|]*/():Promise { + const result = 'https://typescriptlang.org'; + return fetch(result).then(res); +} +function res({ status, trailer }){ + console.log(status); +} + +// ==ASYNC FUNCTION::Convert to async function== + +async function f():Promise { + const result = 'https://typescriptlang.org'; + const result_1 = await fetch(result); + return res(result_1); +} +function res({ status, trailer }){ + console.log(status); +} From d12110d3e5fe2682fa9f89718c033d975924d306 Mon Sep 17 00:00:00 2001 From: Benjamin Lichtman Date: Thu, 13 Sep 2018 09:32:38 -0700 Subject: [PATCH 53/83] Respond to CR --- .../codefixes/convertToAsyncFunction.ts | 5 +++-- src/services/utilities.ts | 11 +++++----- .../unittests/convertToAsyncFunction.ts | 6 +++--- ...convertToAsyncFunction_MultipleReturns2.ts | 4 ++-- .../convertToAsyncFunction_bindingPattern.js | 18 +++++++++++++++++ .../convertToAsyncFunction_bindingPattern.ts | 4 ++-- ...yncFunction_bindingPatternNameCollision.js | 20 +++++++++++++++++++ ...yncFunction_bindingPatternNameCollision.ts | 4 ++-- 8 files changed, 55 insertions(+), 17 deletions(-) create mode 100644 tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_bindingPattern.js create mode 100644 tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_bindingPatternNameCollision.js diff --git a/src/services/codefixes/convertToAsyncFunction.ts b/src/services/codefixes/convertToAsyncFunction.ts index 51511c2207c..e698218baf9 100644 --- a/src/services/codefixes/convertToAsyncFunction.ts +++ b/src/services/codefixes/convertToAsyncFunction.ts @@ -186,20 +186,21 @@ namespace ts.codefix { } // we only care about identifiers that are parameters and declarations (don't care about other uses) else if (node.parent && (isParameter(node.parent) || isVariableDeclaration(node.parent))) { + const originalName = node.text; // if the identifier name conflicts with a different identifier that we've already seen if (allVarNames.some(ident => ident.originalName === node.text && ident.symbol !== symbol)) { const newName = getNewNameIfConflict(node, allVarNames); identsToRenameMap.set(symbolIdString, newName.identifier); synthNamesMap.set(symbolIdString, newName); - allVarNames.push({ identifier: newName.identifier, symbol, originalName: node.text }); + allVarNames.push({ identifier: newName.identifier, symbol, originalName }); } else { const identifier = getSynthesizedDeepClone(node); identsToRenameMap.set(symbolIdString, identifier); synthNamesMap.set(symbolIdString, { identifier, types: [], numberOfAssignmentsOriginal: allVarNames.filter(elem => elem.identifier.text === node.text).length/*, numberOfAssignmentsSynthesized: 0*/ }); if ((isParameter(node.parent) && isExpressionOrCallOnTypePromise(node.parent.parent)) || isVariableDeclaration(node.parent)) { - allVarNames.push({ identifier, symbol, originalName: node.text }); + allVarNames.push({ identifier, symbol, originalName }); } } } diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 4559a88881e..01613a23b0d 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1654,11 +1654,10 @@ namespace ts { return clone; } - export function getSynthesizedDeepCloneWithRenames(node: T, includeTrivia = true, renameMap?: Map, checker?: TypeChecker, callback?: (originalNode: Node, clone: Node) => any): T { - + export function getSynthesizedDeepCloneWithRenames(node: T, includeTrivia = true, renameMap?: Map, checker?: TypeChecker, callback?: (originalNode: Node, clone: Node) => any): T { let clone; - if (node && isIdentifier(node!) && renameMap && checker) { - const symbol = checker.getSymbolAtLocation(node!); + if (isIdentifier(node) && renameMap && checker) { + const symbol = checker.getSymbolAtLocation(node); const renameInfo = symbol && renameMap.get(String(getSymbolId(symbol))); if (renameInfo) { @@ -1667,11 +1666,11 @@ namespace ts { } if (!clone) { - clone = node && getSynthesizedDeepCloneWorker(node as NonNullable, renameMap, checker, callback); + clone = getSynthesizedDeepCloneWorker(node as NonNullable, renameMap, checker, callback); } if (clone && !includeTrivia) suppressLeadingAndTrailingTrivia(clone); - if (callback && node && clone) callback(node!, clone); + if (callback && clone) callback(node, clone); return clone as T; } diff --git a/src/testRunner/unittests/convertToAsyncFunction.ts b/src/testRunner/unittests/convertToAsyncFunction.ts index 05df4f297e8..047df5ffadc 100644 --- a/src/testRunner/unittests/convertToAsyncFunction.ts +++ b/src/testRunner/unittests/convertToAsyncFunction.ts @@ -823,7 +823,7 @@ function [#|f|](): Promise { } return x.then(resp => { var blob = resp.blob().then(blob => blob.byteOffset).catch(err => 'Error'); - return fetch("https://micorosft.com").then(res => console.log("Another one!")); + return fetch("https://microsoft.com").then(res => console.log("Another one!")); }); } ` @@ -1201,7 +1201,7 @@ function [#|f|]() { `); _testConvertToAsyncFunction("convertToAsyncFunction_bindingPattern", ` -function [#|f|]():Promise { +function [#|f|]() { return fetch('https://typescriptlang.org').then(res); } function res({ status, trailer }){ @@ -1210,7 +1210,7 @@ function res({ status, trailer }){ `); _testConvertToAsyncFunction("convertToAsyncFunction_bindingPatternNameCollision", ` -function [#|f|]():Promise { +function [#|f|]() { const result = 'https://typescriptlang.org'; return fetch(result).then(res); } diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_MultipleReturns2.ts b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_MultipleReturns2.ts index 389faf61891..59a02875d84 100644 --- a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_MultipleReturns2.ts +++ b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_MultipleReturns2.ts @@ -7,7 +7,7 @@ function /*[#|*/f/*|]*/(): Promise { } return x.then(resp => { var blob = resp.blob().then(blob => blob.byteOffset).catch(err => 'Error'); - return fetch("https://micorosft.com").then(res => console.log("Another one!")); + return fetch("https://microsoft.com").then(res => console.log("Another one!")); }); } @@ -21,6 +21,6 @@ async function f(): Promise { } const resp = await x; var blob = resp.blob().then(blob_1 => blob_1.byteOffset).catch(err => 'Error'); - const res_2 = await fetch("https://micorosft.com"); + const res_2 = await fetch("https://microsoft.com"); return console.log("Another one!"); } diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_bindingPattern.js b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_bindingPattern.js new file mode 100644 index 00000000000..f06ce44e78b --- /dev/null +++ b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_bindingPattern.js @@ -0,0 +1,18 @@ +// ==ORIGINAL== + +function /*[#|*/f/*|]*/() { + return fetch('https://typescriptlang.org').then(res); +} +function res({ status, trailer }){ + console.log(status); +} + +// ==ASYNC FUNCTION::Convert to async function== + +async function f() { + const result = await fetch('https://typescriptlang.org'); + return res(result); +} +function res({ status, trailer }){ + console.log(status); +} diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_bindingPattern.ts b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_bindingPattern.ts index 97c68d57260..f06ce44e78b 100644 --- a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_bindingPattern.ts +++ b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_bindingPattern.ts @@ -1,6 +1,6 @@ // ==ORIGINAL== -function /*[#|*/f/*|]*/():Promise { +function /*[#|*/f/*|]*/() { return fetch('https://typescriptlang.org').then(res); } function res({ status, trailer }){ @@ -9,7 +9,7 @@ function res({ status, trailer }){ // ==ASYNC FUNCTION::Convert to async function== -async function f():Promise { +async function f() { const result = await fetch('https://typescriptlang.org'); return res(result); } diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_bindingPatternNameCollision.js b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_bindingPatternNameCollision.js new file mode 100644 index 00000000000..6813472966a --- /dev/null +++ b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_bindingPatternNameCollision.js @@ -0,0 +1,20 @@ +// ==ORIGINAL== + +function /*[#|*/f/*|]*/() { + const result = 'https://typescriptlang.org'; + return fetch(result).then(res); +} +function res({ status, trailer }){ + console.log(status); +} + +// ==ASYNC FUNCTION::Convert to async function== + +async function f() { + const result = 'https://typescriptlang.org'; + const result_1 = await fetch(result); + return res(result_1); +} +function res({ status, trailer }){ + console.log(status); +} diff --git a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_bindingPatternNameCollision.ts b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_bindingPatternNameCollision.ts index db0c63535c7..6813472966a 100644 --- a/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_bindingPatternNameCollision.ts +++ b/tests/baselines/reference/convertToAsyncFunction/convertToAsyncFunction_bindingPatternNameCollision.ts @@ -1,6 +1,6 @@ // ==ORIGINAL== -function /*[#|*/f/*|]*/():Promise { +function /*[#|*/f/*|]*/() { const result = 'https://typescriptlang.org'; return fetch(result).then(res); } @@ -10,7 +10,7 @@ function res({ status, trailer }){ // ==ASYNC FUNCTION::Convert to async function== -async function f():Promise { +async function f() { const result = 'https://typescriptlang.org'; const result_1 = await fetch(result); return res(result_1); From e700022cef4dbee7b10d44f91d0320d2a89d8922 Mon Sep 17 00:00:00 2001 From: Benjamin Lichtman Date: Thu, 13 Sep 2018 09:46:40 -0700 Subject: [PATCH 54/83] Remove unnecessary case --- src/services/codefixes/convertToAsyncFunction.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/services/codefixes/convertToAsyncFunction.ts b/src/services/codefixes/convertToAsyncFunction.ts index e698218baf9..bceee6811bb 100644 --- a/src/services/codefixes/convertToAsyncFunction.ts +++ b/src/services/codefixes/convertToAsyncFunction.ts @@ -520,10 +520,6 @@ namespace ts.codefix { name = getMapEntryIfExists(param); } } - // currently not relevant, since we don't produce a valid transformation if the argument to a promise operation is a CallExpression - else if (isCallExpression(funcNode) && funcNode.arguments.length > 0 && isIdentifier(funcNode.arguments[0])) { - name = { identifier: funcNode.arguments[0] as Identifier, types, numberOfAssignmentsOriginal }; - } else if (isIdentifier(funcNode)) { name = getMapEntryIfExists(funcNode); } From 37c3c5d8bb165dd5c08e0789c1b08184cc99cc9d Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Thu, 13 Sep 2018 09:24:54 -0700 Subject: [PATCH 55/83] Refactoring --- src/tsc/tsc.ts | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/src/tsc/tsc.ts b/src/tsc/tsc.ts index 523fcefd88c..29cac24fdd0 100644 --- a/src/tsc/tsc.ts +++ b/src/tsc/tsc.ts @@ -53,14 +53,10 @@ namespace ts { } export function executeCommandLine(args: string[]): void { - if (args.length > 0 && ((args[0].toLowerCase() === "--build") || (args[0].toLowerCase() === "-b"))) { - const result = performBuild(args.slice(1)); - // undefined = in watch mode, do not exit - if (result !== undefined) { - return sys.exit(result); - } - else { - return; + if (args.length > 0 && args[0].charCodeAt(0) === CharacterCodes.minus) { + const firstOption = args[0].slice(args[0].charCodeAt(1) === CharacterCodes.minus ? 2 : 1).toLowerCase(); + if (firstOption === "build" || firstOption === "b") { + return performBuild(args.slice(1)); } } @@ -164,17 +160,17 @@ namespace ts { } } - function performBuild(args: string[]): number | undefined { + function performBuild(args: string[]) { const { buildOptions, projects, errors } = parseBuildCommand(args); if (errors.length > 0) { errors.forEach(reportDiagnostic); - return ExitStatus.DiagnosticsPresent_OutputsSkipped; + return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); } if (buildOptions.help) { printVersion(); printHelp(buildOpts, "--build "); - return ExitStatus.Success; + return sys.exit(ExitStatus.Success); } // Update to pretty if host supports it @@ -182,12 +178,12 @@ namespace ts { if (projects.length === 0) { printVersion(); printHelp(buildOpts, "--build "); - return ExitStatus.Success; + return sys.exit(ExitStatus.Success); } if (!sys.getModifiedTime || !sys.setModifiedTime || (buildOptions.clean && !sys.deleteFile)) { reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--build")); - return ExitStatus.DiagnosticsPresent_OutputsSkipped; + return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); } if (buildOptions.watch) { reportWatchModeWithoutSysSupport(); @@ -196,16 +192,15 @@ namespace ts { // TODO: change this to host if watch => watchHost otherwiue without wathc const builder = createSolutionBuilder(createSolutionBuilderWithWatchHost(sys, reportDiagnostic, createBuilderStatusReporter(sys, shouldBePretty()), createWatchStatusReporter()), projects, buildOptions); if (buildOptions.clean) { - return builder.cleanAllProjects(); + return sys.exit(builder.cleanAllProjects()); } if (buildOptions.watch) { builder.buildAllProjects(); - builder.startWatching(); - return undefined; + return builder.startWatching(); } - return builder.buildAllProjects(); + return sys.exit(builder.buildAllProjects()); } function performCompilation(rootNames: string[], projectReferences: ReadonlyArray | undefined, options: CompilerOptions, configFileParsingDiagnostics?: ReadonlyArray) { From 0d60348e45035ffacb775f8e1b4621ea7d1eb562 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Thu, 13 Sep 2018 09:54:35 -0700 Subject: [PATCH 56/83] Unify the commandline parsing worker --- src/compiler/commandLineParser.ts | 70 ++++++++++++++-------------- src/compiler/diagnosticMessages.json | 15 +++--- src/compiler/tsbuild.ts | 16 +++++-- 3 files changed, 58 insertions(+), 43 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 055bccbb2ad..0d7b6f6085c 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -62,7 +62,8 @@ namespace ts { /* @internal */ export const libMap = createMapFromEntries(libEntries); - const commonOptionsWithBuild: CommandLineOption[] = [ + /* @internal */ + export const commonOptionsWithBuild: CommandLineOption[] = [ { name: "help", shortName: "h", @@ -903,17 +904,27 @@ namespace ts { } } - export function parseCommandLine(commandLine: ReadonlyArray, readFile?: (path: string) => string | undefined): ParsedCommandLine { - const options: CompilerOptions = {}; + /* @internal */ + export interface OptionsBase { + [option: string]: CompilerOptionsValue | undefined; + } + + /** Tuple with error messages for 'unknown compiler option', 'option requires type' */ + type ParseCommandLineWorkerDiagnostics = [DiagnosticMessage, DiagnosticMessage]; + + function parseCommandLineWorker( + getOptionNameMap: () => OptionNameMap, + [unknownOptionDiagnostic, optionTypeMismatchDiagnostic]: ParseCommandLineWorkerDiagnostics, + commandLine: ReadonlyArray, + readFile?: (path: string) => string | undefined) { + const options = {} as T; const fileNames: string[] = []; - const projectReferences: ProjectReference[] | undefined = undefined; const errors: Diagnostic[] = []; parseStrings(commandLine); return { options, fileNames, - projectReferences, errors }; @@ -926,7 +937,7 @@ namespace ts { parseResponseFile(s.slice(1)); } else if (s.charCodeAt(0) === CharacterCodes.minus) { - const opt = getOptionFromName(s.slice(s.charCodeAt(1) === CharacterCodes.minus ? 2 : 1), /*allowShort*/ true); + const opt = getOptionDeclarationFromName(getOptionNameMap, s.slice(s.charCodeAt(1) === CharacterCodes.minus ? 2 : 1), /*allowShort*/ true); if (opt) { if (opt.isTSConfigOnly) { errors.push(createCompilerDiagnostic(Diagnostics.Option_0_can_only_be_specified_in_tsconfig_json_file, opt.name)); @@ -934,7 +945,7 @@ namespace ts { else { // Check to see if no argument was provided (e.g. "--locale" is the last command-line argument). if (!args[i] && opt.type !== "boolean") { - errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_expects_an_argument, opt.name)); + errors.push(createCompilerDiagnostic(optionTypeMismatchDiagnostic, opt.name)); } switch (opt.type) { @@ -971,7 +982,7 @@ namespace ts { } } else { - errors.push(createCompilerDiagnostic(Diagnostics.Unknown_compiler_option_0, s)); + errors.push(createCompilerDiagnostic(unknownOptionDiagnostic, s)); } } else { @@ -1014,13 +1025,19 @@ namespace ts { } } + export function parseCommandLine(commandLine: ReadonlyArray, readFile?: (path: string) => string | undefined): ParsedCommandLine { + return parseCommandLineWorker(getOptionNameMap, [ + Diagnostics.Unknown_compiler_option_0, + Diagnostics.Compiler_option_0_expects_an_argument + ], commandLine, readFile); + } + /** @internal */ export function getOptionFromName(optionName: string, allowShort?: boolean): CommandLineOption | undefined { return getOptionDeclarationFromName(getOptionNameMap, optionName, allowShort); } - /*@internal*/ - export function getOptionDeclarationFromName(getOptionNameMap: () => OptionNameMap, optionName: string, allowShort = false): CommandLineOption | undefined { + function getOptionDeclarationFromName(getOptionNameMap: () => OptionNameMap, optionName: string, allowShort = false): CommandLineOption | undefined { optionName = optionName.toLowerCase(); const { optionNameMap, shortOptionNames } = getOptionNameMap(); // Try to translate short option names to their full equivalents. @@ -1044,25 +1061,10 @@ namespace ts { export function parseBuildCommand(args: string[]): ParsedBuildCommand { let buildOptionNameMap: OptionNameMap | undefined; const returnBuildOptionNameMap = () => (buildOptionNameMap || (buildOptionNameMap = createOptionNameMap(buildOpts))); - - const buildOptions: BuildOptions = {}; - const projects: string[] = []; - let errors: Diagnostic[] | undefined; - for (const arg of args) { - if (arg.charCodeAt(0) === CharacterCodes.minus) { - const opt = getOptionDeclarationFromName(returnBuildOptionNameMap, arg.slice(arg.charCodeAt(1) === CharacterCodes.minus ? 2 : 1), /*allowShort*/ true); - if (opt) { - buildOptions[opt.name as keyof BuildOptions] = true; - } - else { - (errors || (errors = [])).push(createCompilerDiagnostic(Diagnostics.Unknown_build_option_0, arg)); - } - } - else { - // Not a flag, parse as filename - projects.push(arg); - } - } + const { options: buildOptions, fileNames: projects, errors } = parseCommandLineWorker(returnBuildOptionNameMap, [ + Diagnostics.Unknown_build_option_0, + Diagnostics.Build_option_0_requires_a_value_of_type_1 + ], args); if (projects.length === 0) { // tsc -b invoked with no extra arguments; act as if invoked with "tsc -b ." @@ -1071,19 +1073,19 @@ namespace ts { // Nonsensical combinations if (buildOptions.clean && buildOptions.force) { - (errors || (errors = [])).push(createCompilerDiagnostic(Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "force")); + errors.push(createCompilerDiagnostic(Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "force")); } if (buildOptions.clean && buildOptions.verbose) { - (errors || (errors = [])).push(createCompilerDiagnostic(Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "verbose")); + errors.push(createCompilerDiagnostic(Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "verbose")); } if (buildOptions.clean && buildOptions.watch) { - (errors || (errors = [])).push(createCompilerDiagnostic(Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "watch")); + errors.push(createCompilerDiagnostic(Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "watch")); } if (buildOptions.watch && buildOptions.dry) { - (errors || (errors = [])).push(createCompilerDiagnostic(Diagnostics.Options_0_and_1_cannot_be_combined, "watch", "dry")); + errors.push(createCompilerDiagnostic(Diagnostics.Options_0_and_1_cannot_be_combined, "watch", "dry")); } - return { buildOptions, projects, errors: errors || emptyArray }; + return { buildOptions, projects, errors }; } function getDiagnosticText(_message: DiagnosticMessage, ..._args: any[]): string { diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 56a255bead6..941250c467d 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2920,7 +2920,10 @@ "category": "Error", "code": 5072 }, - + "Build option '{0}' requires a value of type {1}.": { + "category": "Error", + "code": 5073 + }, "Generates a sourcemap for each corresponding '.d.ts' file.": { "category": "Message", @@ -4604,7 +4607,7 @@ "category": "Message", "code": 95062 }, - + "Add missing enum member '{0}'": { "category": "Message", "code": 95063 @@ -4613,12 +4616,12 @@ "category": "Message", "code": 95064 }, - "Convert to async function":{ + "Convert to async function": { "category": "Message", - "code": 95065 + "code": 95065 }, "Convert all to async functions": { - "category": "Message", - "code": 95066 + "category": "Message", + "code": 95066 } } diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts index 2c064bea137..8947310c1af 100644 --- a/src/compiler/tsbuild.ts +++ b/src/compiler/tsbuild.ts @@ -17,7 +17,7 @@ namespace ts { referencingProjectsMap: ConfigFileMap>; } - export interface BuildOptions { + export interface BuildOptions extends OptionsBase { dry?: boolean; force?: boolean; verbose?: boolean; @@ -370,6 +370,14 @@ namespace ts { return host; } + function getCompilerOptionsOfBuildOptions(buildOptions: BuildOptions): CompilerOptions { + const result = {} as CompilerOptions; + commonOptionsWithBuild.forEach(option => { + result[option.name] = buildOptions[option.name]; + }); + return result; + } + /** * A SolutionBuilder has an immutable set of rootNames that are the "entry point" projects, but * can dynamically add/remove other projects based on changes on the rootNames' references @@ -384,6 +392,7 @@ namespace ts { // State of the solution let options = defaultOptions; + let baseCompilerOptions = getCompilerOptionsOfBuildOptions(options); type ConfigFileCacheEntry = ParsedCommandLine | Diagnostic; const configFileCache = createFileMap(toPath); /** Map from output file name to its pre-build timestamp */ @@ -430,6 +439,7 @@ namespace ts { function resetBuildContext(opts = defaultOptions) { options = opts; + baseCompilerOptions = getCompilerOptionsOfBuildOptions(options); configFileCache.clear(); unchangedOutputs.clear(); projectStatus.clear(); @@ -463,7 +473,7 @@ namespace ts { let diagnostic: Diagnostic | undefined; parseConfigFileHost.onUnRecoverableConfigFileDiagnostic = d => diagnostic = d; - const parsed = getParsedCommandLineOfConfigFile(configFilePath, {}, parseConfigFileHost); + const parsed = getParsedCommandLineOfConfigFile(configFilePath, baseCompilerOptions, parseConfigFileHost); parseConfigFileHost.onUnRecoverableConfigFileDiagnostic = noop; configFileCache.setValue(configFilePath, parsed || diagnostic!); return parsed; @@ -475,7 +485,7 @@ namespace ts { function reportWatchStatus(message: DiagnosticMessage, ...args: (string | number | undefined)[]) { if (hostWithWatch.onWatchStatusChange) { - hostWithWatch.onWatchStatusChange(createCompilerDiagnostic(message, ...args), host.getNewLine(), { preserveWatchOutput: options.preserveWatchOutput }); + hostWithWatch.onWatchStatusChange(createCompilerDiagnostic(message, ...args), host.getNewLine(), baseCompilerOptions); } } From 4cf746cdc40f822efcb664e97ea46263bc3cb025 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Thu, 13 Sep 2018 11:17:03 -0700 Subject: [PATCH 57/83] Enable listFiles and listEmittedFiles as build option --- src/compiler/commandLineParser.ts | 24 ++++++------ src/compiler/tsbuild.ts | 38 ++++++++++++------- src/compiler/watch.ts | 6 +-- src/testRunner/unittests/tsbuild.ts | 57 +++++++++++++++++++++++++++++ 4 files changed, 96 insertions(+), 29 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 0d7b6f6085c..9391fac72ed 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -84,6 +84,18 @@ namespace ts { category: Diagnostics.Command_line_Options, description: Diagnostics.Whether_to_keep_outdated_console_output_in_watch_mode_instead_of_clearing_the_screen, }, + { + name: "listFiles", + type: "boolean", + category: Diagnostics.Advanced_Options, + description: Diagnostics.Print_names_of_files_part_of_the_compilation + }, + { + name: "listEmittedFiles", + type: "boolean", + category: Diagnostics.Advanced_Options, + description: Diagnostics.Print_names_of_generated_files_part_of_the_compilation + }, { name: "watch", shortName: "w", @@ -562,18 +574,6 @@ namespace ts { category: Diagnostics.Advanced_Options, description: Diagnostics.Include_modules_imported_with_json_extension }, - { - name: "listFiles", - type: "boolean", - category: Diagnostics.Advanced_Options, - description: Diagnostics.Print_names_of_files_part_of_the_compilation - }, - { - name: "listEmittedFiles", - type: "boolean", - category: Diagnostics.Advanced_Options, - description: Diagnostics.Print_names_of_generated_files_part_of_the_compilation - }, { name: "out", diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts index 8947310c1af..58b470b8b9d 100644 --- a/src/compiler/tsbuild.ts +++ b/src/compiler/tsbuild.ts @@ -21,10 +21,14 @@ namespace ts { dry?: boolean; force?: boolean; verbose?: boolean; + /*@internal*/ clean?: boolean; /*@internal*/ watch?: boolean; /*@internal*/ help?: boolean; + preserveWatchOutput?: boolean; + listEmittedFiles?: boolean; + listFiles?: boolean; } enum BuildResultFlags { @@ -44,8 +48,9 @@ namespace ts { SyntaxErrors = 1 << 3, TypeErrors = 1 << 4, DeclarationEmitErrors = 1 << 5, + EmitErrors = 1 << 6, - AnyErrors = ConfigFileErrors | SyntaxErrors | TypeErrors | DeclarationEmitErrors + AnyErrors = ConfigFileErrors | SyntaxErrors | TypeErrors | DeclarationEmitErrors | EmitErrors } export enum UpToDateStatusType { @@ -401,6 +406,7 @@ namespace ts { const projectStatus = createFileMap(toPath); const missingRoots = createMap(); let globalDependencyGraph: DependencyGraph | undefined; + const writeFileName = (s: string) => host.trace && host.trace(s); // Watch state const diagnostics = createFileMap>(toPath); @@ -1014,35 +1020,28 @@ namespace ts { ...program.getConfigFileParsingDiagnostics(), ...program.getSyntacticDiagnostics()]; if (syntaxDiagnostics.length) { - resultFlags |= BuildResultFlags.SyntaxErrors; - reportAndStoreErrors(proj, syntaxDiagnostics); - projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Syntactic errors" }); - return resultFlags; + return buildErrors(syntaxDiagnostics, BuildResultFlags.SyntaxErrors, "Syntactic"); } // Don't emit .d.ts if there are decl file errors if (getEmitDeclarations(program.getCompilerOptions())) { const declDiagnostics = program.getDeclarationDiagnostics(); if (declDiagnostics.length) { - resultFlags |= BuildResultFlags.DeclarationEmitErrors; - reportAndStoreErrors(proj, declDiagnostics); - projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Declaration file errors" }); - return resultFlags; + return buildErrors(declDiagnostics, BuildResultFlags.DeclarationEmitErrors, "Declaration file"); } } // Same as above but now for semantic diagnostics const semanticDiagnostics = program.getSemanticDiagnostics(); if (semanticDiagnostics.length) { - resultFlags |= BuildResultFlags.TypeErrors; - reportAndStoreErrors(proj, semanticDiagnostics); - projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: "Semantic errors" }); - return resultFlags; + return buildErrors(semanticDiagnostics, BuildResultFlags.TypeErrors, "Semantic"); } let newestDeclarationFileContentChangedTime = minimumDate; let anyDtsChanged = false; - program.emit(/*targetSourceFile*/ undefined, (fileName, content, writeBom, onError) => { + let emitDiagnostics: Diagnostic[] | undefined; + const reportEmitDiagnostic = (d: Diagnostic) => (emitDiagnostics || (emitDiagnostics = [])).push(d); + emitFilesAndReportErrors(program, reportEmitDiagnostic, writeFileName, /*reportSummary*/ undefined, (fileName, content, writeBom, onError) => { let priorChangeTime: Date | undefined; if (!anyDtsChanged && isDeclarationFile(fileName)) { // Check for unchanged .d.ts files @@ -1062,12 +1061,23 @@ namespace ts { } }); + if (emitDiagnostics) { + return buildErrors(emitDiagnostics, BuildResultFlags.EmitErrors, "Emit"); + } + const status: UpToDateStatus = { type: UpToDateStatusType.UpToDate, newestDeclarationFileContentChangedTime: anyDtsChanged ? maximumDate : newestDeclarationFileContentChangedTime }; projectStatus.setValue(proj, status); return resultFlags; + + function buildErrors(diagnostics: ReadonlyArray, errorFlags: BuildResultFlags, errorType: string) { + resultFlags |= errorFlags; + reportAndStoreErrors(proj, diagnostics); + projectStatus.setValue(proj, { type: UpToDateStatusType.Unbuildable, reason: `${errorType} errors` }); + return resultFlags; + } } function updateOutputTimestamps(proj: ParsedCommandLine) { diff --git a/src/compiler/watch.ts b/src/compiler/watch.ts index c091ad5c30c..f442a1a88e8 100644 --- a/src/compiler/watch.ts +++ b/src/compiler/watch.ts @@ -101,7 +101,7 @@ namespace ts { getGlobalDiagnostics(): ReadonlyArray; getSemanticDiagnostics(): ReadonlyArray; getConfigFileParsingDiagnostics(): ReadonlyArray; - emit(): EmitResult; + emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback): EmitResult; } export type ReportEmitErrorSummary = (errorCount: number) => void; @@ -109,7 +109,7 @@ namespace ts { /** * Helper that emit files, report diagnostics and lists emitted and/or source files depending on compiler options */ - export function emitFilesAndReportErrors(program: ProgramToEmitFilesAndReportErrors, reportDiagnostic: DiagnosticReporter, writeFileName?: (s: string) => void, reportSummary?: ReportEmitErrorSummary) { + export function emitFilesAndReportErrors(program: ProgramToEmitFilesAndReportErrors, reportDiagnostic: DiagnosticReporter, writeFileName?: (s: string) => void, reportSummary?: ReportEmitErrorSummary, writeFile?: WriteFileCallback) { // First get and report any syntactic errors. const diagnostics = program.getConfigFileParsingDiagnostics().slice(); const configFileParsingDiagnosticsLength = diagnostics.length; @@ -128,7 +128,7 @@ namespace ts { } // Emit and report any errors we ran into. - const { emittedFiles, emitSkipped, diagnostics: emitDiagnostics } = program.emit(); + const { emittedFiles, emitSkipped, diagnostics: emitDiagnostics } = program.emit(/*targetSourceFile*/ undefined, writeFile); addRange(diagnostics, emitDiagnostics); if (reportSemanticDiagnostics) { diff --git a/src/testRunner/unittests/tsbuild.ts b/src/testRunner/unittests/tsbuild.ts index 6ddd6d069f7..f54e3c93215 100644 --- a/src/testRunner/unittests/tsbuild.ts +++ b/src/testRunner/unittests/tsbuild.ts @@ -264,6 +264,63 @@ export class cNew {}`); verifyProjectWithResolveJsonModule("/src/tests/tsconfig_withIncludeAndFiles.json"); }); }); + + describe("tsbuild - lists files", () => { + it("listFiles", () => { + const fs = projFs.shadow(); + const host = new fakes.SolutionBuilderHost(fs); + const builder = createSolutionBuilder(host, ["/src/tests"], { listFiles: true }); + builder.buildAllProjects(); + assert.deepEqual(host.traces, [ + ...getLibs(), + "/src/core/anotherModule.ts", + "/src/core/index.ts", + "/src/core/some_decl.d.ts", + ...getLibs(), + ...getCoreOutputs(), + "/src/logic/index.ts", + ...getLibs(), + ...getCoreOutputs(), + "/src/logic/index.d.ts", + "/src/tests/index.ts" + ]); + + function getLibs() { + return [ + "/lib/lib.d.ts", + "/lib/lib.es5.d.ts", + "/lib/lib.dom.d.ts", + "/lib/lib.webworker.importscripts.d.ts", + "/lib/lib.scripthost.d.ts" + ]; + } + + function getCoreOutputs() { + return [ + "/src/core/index.d.ts", + "/src/core/anotherModule.d.ts" + ]; + } + }); + + it("listEmittedFiles", () => { + const fs = projFs.shadow(); + const host = new fakes.SolutionBuilderHost(fs); + const builder = createSolutionBuilder(host, ["/src/tests"], { listEmittedFiles: true }); + builder.buildAllProjects(); + assert.deepEqual(host.traces, [ + "TSFILE: /src/core/anotherModule.js", + "TSFILE: /src/core/anotherModule.d.ts", + "TSFILE: /src/core/index.js", + "TSFILE: /src/core/index.d.ts", + "TSFILE: /src/logic/index.js", + "TSFILE: /src/logic/index.js.map", + "TSFILE: /src/logic/index.d.ts", + "TSFILE: /src/tests/index.js", + "TSFILE: /src/tests/index.d.ts", + ]); + }); + }); } export namespace OutFile { From 1a69f78fba3340013a353ecb72c9d8fe6dc4f310 Mon Sep 17 00:00:00 2001 From: Andy Date: Thu, 13 Sep 2018 12:53:46 -0700 Subject: [PATCH 58/83] Fix bug: Ensure `export =` symbol always has a valueDeclaration (#26973) --- src/compiler/binder.ts | 27 ++++++++++++------- ...ForConflictingExportEqualsValue.errors.txt | 9 ++++--- .../errorForConflictingExportEqualsValue.js | 10 ++++--- ...rorForConflictingExportEqualsValue.symbols | 10 ++++--- ...errorForConflictingExportEqualsValue.types | 10 ++++--- .../errorForConflictingExportEqualsValue.ts | 5 +++- 6 files changed, 47 insertions(+), 24 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 489f212967d..3205b2c5a55 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -234,13 +234,17 @@ namespace ts { } if (symbolFlags & SymbolFlags.Value) { - const { valueDeclaration } = symbol; - if (!valueDeclaration || - (isAssignmentDeclaration(valueDeclaration) && !isAssignmentDeclaration(node)) || - (valueDeclaration.kind !== node.kind && isEffectiveModuleDeclaration(valueDeclaration))) { - // other kinds of value declarations take precedence over modules and assignment declarations - symbol.valueDeclaration = node; - } + setValueDeclaration(symbol, node); + } + } + + function setValueDeclaration(symbol: Symbol, node: Declaration): void { + const { valueDeclaration } = symbol; + if (!valueDeclaration || + (isAssignmentDeclaration(valueDeclaration) && !isAssignmentDeclaration(node)) || + (valueDeclaration.kind !== node.kind && isEffectiveModuleDeclaration(valueDeclaration))) { + // other kinds of value declarations take precedence over modules and assignment declarations + symbol.valueDeclaration = node; } } @@ -2286,14 +2290,19 @@ namespace ts { bindAnonymousDeclaration(node, SymbolFlags.Alias, getDeclarationName(node)!); } else { - const flags = node.kind === SyntaxKind.ExportAssignment && exportAssignmentIsAlias(node) + const flags = exportAssignmentIsAlias(node) // An export default clause with an EntityNameExpression or a class expression exports all meanings of that identifier or expression; ? SymbolFlags.Alias // An export default clause with any other expression exports a value : SymbolFlags.Property; // If there is an `export default x;` alias declaration, can't `export default` anything else. // (In contrast, you can still have `export default function f() {}` and `export default interface I {}`.) - declareSymbol(container.symbol.exports, container.symbol, node, flags, SymbolFlags.All); + const symbol = declareSymbol(container.symbol.exports, container.symbol, node, flags, SymbolFlags.All); + + if (node.isExportEquals) { + // Will be an error later, since the module already has other exports. Just make sure this has a valueDeclaration set. + setValueDeclaration(symbol, node); + } } } diff --git a/tests/baselines/reference/errorForConflictingExportEqualsValue.errors.txt b/tests/baselines/reference/errorForConflictingExportEqualsValue.errors.txt index 9a5858f46ab..19ebd6ebb20 100644 --- a/tests/baselines/reference/errorForConflictingExportEqualsValue.errors.txt +++ b/tests/baselines/reference/errorForConflictingExportEqualsValue.errors.txt @@ -1,9 +1,10 @@ -tests/cases/compiler/errorForConflictingExportEqualsValue.ts(2,1): error TS2309: An export assignment cannot be used in a module with other exported elements. +/a.ts(2,1): error TS2309: An export assignment cannot be used in a module with other exported elements. -==== tests/cases/compiler/errorForConflictingExportEqualsValue.ts (1 errors) ==== +==== /a.ts (1 errors) ==== export var x; - export = {}; - ~~~~~~~~~~~~ + export = x; + ~~~~~~~~~~~ !!! error TS2309: An export assignment cannot be used in a module with other exported elements. + import("./a"); \ No newline at end of file diff --git a/tests/baselines/reference/errorForConflictingExportEqualsValue.js b/tests/baselines/reference/errorForConflictingExportEqualsValue.js index 88762e7e846..65adec35902 100644 --- a/tests/baselines/reference/errorForConflictingExportEqualsValue.js +++ b/tests/baselines/reference/errorForConflictingExportEqualsValue.js @@ -1,8 +1,10 @@ -//// [errorForConflictingExportEqualsValue.ts] +//// [a.ts] export var x; -export = {}; +export = x; +import("./a"); -//// [errorForConflictingExportEqualsValue.js] +//// [a.js] "use strict"; -module.exports = {}; +Promise.resolve().then(function () { return require("./a"); }); +module.exports = exports.x; diff --git a/tests/baselines/reference/errorForConflictingExportEqualsValue.symbols b/tests/baselines/reference/errorForConflictingExportEqualsValue.symbols index a66ef69c1cb..138f37f4a5e 100644 --- a/tests/baselines/reference/errorForConflictingExportEqualsValue.symbols +++ b/tests/baselines/reference/errorForConflictingExportEqualsValue.symbols @@ -1,6 +1,10 @@ -=== tests/cases/compiler/errorForConflictingExportEqualsValue.ts === +=== /a.ts === export var x; ->x : Symbol(x, Decl(errorForConflictingExportEqualsValue.ts, 0, 10)) +>x : Symbol(x, Decl(a.ts, 0, 10)) -export = {}; +export = x; +>x : Symbol(x, Decl(a.ts, 0, 10)) + +import("./a"); +>"./a" : Symbol("/a", Decl(a.ts, 0, 0)) diff --git a/tests/baselines/reference/errorForConflictingExportEqualsValue.types b/tests/baselines/reference/errorForConflictingExportEqualsValue.types index f2484e83d0d..b9915169120 100644 --- a/tests/baselines/reference/errorForConflictingExportEqualsValue.types +++ b/tests/baselines/reference/errorForConflictingExportEqualsValue.types @@ -1,7 +1,11 @@ -=== tests/cases/compiler/errorForConflictingExportEqualsValue.ts === +=== /a.ts === export var x; >x : any -export = {}; ->{} : {} +export = x; +>x : any + +import("./a"); +>import("./a") : Promise +>"./a" : "./a" diff --git a/tests/cases/compiler/errorForConflictingExportEqualsValue.ts b/tests/cases/compiler/errorForConflictingExportEqualsValue.ts index 59af1f46690..a91ecc390b5 100644 --- a/tests/cases/compiler/errorForConflictingExportEqualsValue.ts +++ b/tests/cases/compiler/errorForConflictingExportEqualsValue.ts @@ -1,2 +1,5 @@ +// @lib: es6 +// @Filename: /a.ts export var x; -export = {}; +export = x; +import("./a"); From 4ed63e52ef130ee82e2191769985fa162c2154f6 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Thu, 13 Sep 2018 13:00:06 -0700 Subject: [PATCH 59/83] Add test for preserveWatchOutput on command line #26873 --- src/testRunner/unittests/tsbuildWatchMode.ts | 58 ++++++++++++-------- 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/src/testRunner/unittests/tsbuildWatchMode.ts b/src/testRunner/unittests/tsbuildWatchMode.ts index d9dcda94bff..563200b1cf5 100644 --- a/src/testRunner/unittests/tsbuildWatchMode.ts +++ b/src/testRunner/unittests/tsbuildWatchMode.ts @@ -2,7 +2,7 @@ namespace ts.tscWatch { export import libFile = TestFSWithWatch.libFile; function createSolutionBuilder(system: WatchedSystem, rootNames: ReadonlyArray, defaultOptions?: BuildOptions) { const host = createSolutionBuilderWithWatchHost(system); - return ts.createSolutionBuilder(host, rootNames, defaultOptions || { dry: false, force: false, verbose: false, watch: true }); + return ts.createSolutionBuilder(host, rootNames, defaultOptions || { watch: true }); } function createSolutionBuilderWithWatch(host: WatchedSystem, rootNames: ReadonlyArray, defaultOptions?: BuildOptions) { @@ -95,11 +95,11 @@ namespace ts.tscWatch { const allFiles: ReadonlyArray = [libFile, ...core, ...logic, ...tests, ...ui]; const testProjectExpectedWatchedFiles = [core[0], core[1], core[2], ...logic, ...tests].map(f => f.path); - function createSolutionInWatchMode(allFiles: ReadonlyArray) { + function createSolutionInWatchMode(allFiles: ReadonlyArray, defaultOptions?: BuildOptions, disableConsoleClears?: boolean) { const host = createWatchedSystem(allFiles, { currentDirectory: projectsLocation }); - createSolutionBuilderWithWatch(host, [`${project}/${SubProject.tests}`]); + createSolutionBuilderWithWatch(host, [`${project}/${SubProject.tests}`], defaultOptions); verifyWatches(host); - checkOutputErrorsInitial(host, emptyArray); + checkOutputErrorsInitial(host, emptyArray, disableConsoleClears); const outputFileStamps = getOutputFileStamps(host); for (const stamp of outputFileStamps) { assert.isDefined(stamp[1], `${stamp[0]} expected to be present`); @@ -351,32 +351,42 @@ function myFunc() { return 100; }`); } }); - it("reports errors in all projects on incremental compile", () => { - const host = createSolutionInWatchMode(allFiles); - const outputFileStamps = getOutputFileStamps(host); + describe("reports errors in all projects on incremental compile", () => { + function verifyIncrementalErrors(defaultBuildOptions?: BuildOptions, disabledConsoleClear?: boolean) { + const host = createSolutionInWatchMode(allFiles, defaultBuildOptions, disabledConsoleClear); + const outputFileStamps = getOutputFileStamps(host); - host.writeFile(logic[1].path, `${logic[1].content} + host.writeFile(logic[1].path, `${logic[1].content} let y: string = 10;`); - host.checkTimeoutQueueLengthAndRun(1); // Builds logic - const changedLogic = getOutputFileStamps(host); - verifyChangedFiles(changedLogic, outputFileStamps, emptyArray); - host.checkTimeoutQueueLength(0); - checkOutputErrorsIncremental(host, [ - `sample1/logic/index.ts(8,5): error TS2322: Type '10' is not assignable to type 'string'.\n` - ]); + host.checkTimeoutQueueLengthAndRun(1); // Builds logic + const changedLogic = getOutputFileStamps(host); + verifyChangedFiles(changedLogic, outputFileStamps, emptyArray); + host.checkTimeoutQueueLength(0); + checkOutputErrorsIncremental(host, [ + `sample1/logic/index.ts(8,5): error TS2322: Type '10' is not assignable to type 'string'.\n` + ], disabledConsoleClear); - host.writeFile(core[1].path, `${core[1].content} + host.writeFile(core[1].path, `${core[1].content} let x: string = 10;`); - host.checkTimeoutQueueLengthAndRun(1); // Builds core - const changedCore = getOutputFileStamps(host); - verifyChangedFiles(changedCore, changedLogic, emptyArray); - host.checkTimeoutQueueLength(0); - checkOutputErrorsIncremental(host, [ - `sample1/core/index.ts(5,5): error TS2322: Type '10' is not assignable to type 'string'.\n`, - `sample1/logic/index.ts(8,5): error TS2322: Type '10' is not assignable to type 'string'.\n` - ]); + host.checkTimeoutQueueLengthAndRun(1); // Builds core + const changedCore = getOutputFileStamps(host); + verifyChangedFiles(changedCore, changedLogic, emptyArray); + host.checkTimeoutQueueLength(0); + checkOutputErrorsIncremental(host, [ + `sample1/core/index.ts(5,5): error TS2322: Type '10' is not assignable to type 'string'.\n`, + `sample1/logic/index.ts(8,5): error TS2322: Type '10' is not assignable to type 'string'.\n` + ], disabledConsoleClear); + } + + it("when preserveWatchOutput is not used", () => { + verifyIncrementalErrors(); + }); + + it("when preserveWatchOutput is passed on command line", () => { + verifyIncrementalErrors({ preserveWatchOutput: true, watch: true }, /*disabledConsoleClear*/ true); + }); }); // TODO: write tests reporting errors but that will have more involved work since file }); From e2edb696385c2992b8174dc27312569d4375105f Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Wed, 1 Aug 2018 15:30:14 -0700 Subject: [PATCH 60/83] Instead of watching individual script infos, watch the node modules folder for script infos in node modules --- src/compiler/sys.ts | 16 ++- src/server/editorServices.ts | 109 ++++++++++++++++-- src/server/scriptInfo.ts | 3 + .../unittests/tsserverProjectSystem.ts | 23 +++- .../reference/api/tsserverlibrary.d.ts | 5 + 5 files changed, 134 insertions(+), 22 deletions(-) diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index eaa910a0b5c..713085f1922 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -317,18 +317,22 @@ namespace ts { const newTime = modifiedTime.getTime(); if (oldTime !== newTime) { watchedFile.mtime = modifiedTime; - const eventKind = oldTime === 0 - ? FileWatcherEventKind.Created - : newTime === 0 - ? FileWatcherEventKind.Deleted - : FileWatcherEventKind.Changed; - watchedFile.callback(watchedFile.fileName, eventKind); + watchedFile.callback(watchedFile.fileName, getFileWatcherEventKind(oldTime, newTime)); return true; } return false; } + /*@internal*/ + export function getFileWatcherEventKind(oldTime: number, newTime: number) { + return oldTime === 0 + ? FileWatcherEventKind.Created + : newTime === 0 + ? FileWatcherEventKind.Deleted + : FileWatcherEventKind.Changed; + } + /*@internal*/ export interface RecursiveDirectoryWatcherHost { watchDirectory: HostWatchDirectory; diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index b1f88dff3b7..f4d8265bc19 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -291,7 +291,8 @@ namespace ts.server { ClosedScriptInfo = "Closed Script info", ConfigFileForInferredRoot = "Config file for the inferred project root", FailedLookupLocation = "Directory of Failed lookup locations in module resolution", - TypeRoots = "Type root directory" + TypeRoots = "Type root directory", + NodeModulesForClosedScriptInfo = "node_modules for closed script infos in them", } const enum ConfigFileWatcherStatus { @@ -353,10 +354,18 @@ namespace ts.server { return !!(infoOrFileName as ScriptInfo).containingProjects; } + interface ScriptInfoInNodeModulesWatcher extends FileWatcher { + refCount: number; + } + function getDetailWatchInfo(watchType: WatchType, project: Project | undefined) { return `Project: ${project ? project.getProjectName() : ""} WatchType: ${watchType}`; } + function isScriptInfoWatchedFromNodeModules(info: ScriptInfo) { + return !info.isScriptOpen() && info.mTime !== undefined; + } + /*@internal*/ export function updateProjectIfDirty(project: Project) { return project.dirty && project.updateGraph(); @@ -380,6 +389,7 @@ namespace ts.server { * Container of all known scripts */ private readonly filenameToScriptInfo = createMap(); + private readonly scriptInfoInNodeModulesWatchers = createMap (); /** * Contains all the deleted script info's version information so that * it does not reset when creating script info again @@ -1923,18 +1933,97 @@ namespace ts.server { if (!info.isDynamicOrHasMixedContent() && (!this.globalCacheLocationDirectoryPath || !startsWith(info.path, this.globalCacheLocationDirectoryPath))) { - const { fileName } = info; - info.fileWatcher = this.watchFactory.watchFilePath( - this.host, - fileName, - (fileName, eventKind, path) => this.onSourceFileChanged(fileName, eventKind, path), - PollingInterval.Medium, - info.path, - WatchType.ClosedScriptInfo - ); + const indexOfNodeModules = info.path.indexOf("/node_modules/"); + if (!this.host.getModifiedTime || indexOfNodeModules === -1) { + info.fileWatcher = this.watchFactory.watchFilePath( + this.host, + info.fileName, + (fileName, eventKind, path) => this.onSourceFileChanged(fileName, eventKind, path), + PollingInterval.Medium, + info.path, + WatchType.ClosedScriptInfo + ); + } + else { + info.mTime = this.getModifiedTime(info); + info.fileWatcher = this.watchClosedScriptInfoInNodeModules(info.path.substr(0, indexOfNodeModules) as Path); + } } } + private watchClosedScriptInfoInNodeModules(dir: Path): ScriptInfoInNodeModulesWatcher { + // Watch only directory + const existing = this.scriptInfoInNodeModulesWatchers.get(dir); + if (existing) { + existing.refCount++; + return existing; + } + + const watchDir = dir + "/node_modules" as Path; + const watcher = this.watchFactory.watchDirectory( + this.host, + watchDir, + (fileOrDirectory) => { + const fileOrDirectoryPath = this.toPath(fileOrDirectory); + // Has extension + Debug.assert(result.refCount > 0); + if (watchDir === fileOrDirectoryPath) { + this.refreshScriptInfosInDirectory(watchDir); + } + else { + const info = this.getScriptInfoForPath(fileOrDirectoryPath); + if (info) { + if (isScriptInfoWatchedFromNodeModules(info)) { + this.refreshScriptInfo(info); + } + } + // Folder + else if (!hasExtension(fileOrDirectoryPath)) { + this.refreshScriptInfosInDirectory(fileOrDirectoryPath); + } + } + }, + WatchDirectoryFlags.Recursive, + WatchType.NodeModulesForClosedScriptInfo + ); + const result: ScriptInfoInNodeModulesWatcher = { + close: () => { + if (result.refCount === 1) { + watcher.close(); + this.scriptInfoInNodeModulesWatchers.delete(dir); + } + else { + result.refCount--; + } + }, + refCount: 1 + }; + this.scriptInfoInNodeModulesWatchers.set(dir, result); + return result; + } + + private getModifiedTime(info: ScriptInfo) { + return (this.host.getModifiedTime!(info.path) || missingFileModifiedTime).getTime(); + } + + private refreshScriptInfo(info: ScriptInfo) { + const mTime = this.getModifiedTime(info); + if (mTime !== info.mTime) { + const eventKind = getFileWatcherEventKind(info.mTime!, mTime); + info.mTime = mTime; + this.onSourceFileChanged(info.fileName, eventKind, info.path); + } + } + + private refreshScriptInfosInDirectory(dir: Path) { + dir = dir + directorySeparator as Path; + this.filenameToScriptInfo.forEach(info => { + if (isScriptInfoWatchedFromNodeModules(info) && startsWith(info.path, dir)) { + this.refreshScriptInfo(info); + } + }); + } + private stopWatchingScriptInfo(info: ScriptInfo) { if (info.fileWatcher) { info.fileWatcher.close(); diff --git a/src/server/scriptInfo.ts b/src/server/scriptInfo.ts index 5c4eaa9a374..e52c597ffa1 100644 --- a/src/server/scriptInfo.ts +++ b/src/server/scriptInfo.ts @@ -250,6 +250,9 @@ namespace ts.server { /*@internal*/ cacheSourceFile: DocumentRegistrySourceFileCache; + /*@internal*/ + mTime?: number; + constructor( private readonly host: ServerHost, readonly fileName: NormalizedPath, diff --git a/src/testRunner/unittests/tsserverProjectSystem.ts b/src/testRunner/unittests/tsserverProjectSystem.ts index 988ccbc3bfe..ed130f6772b 100644 --- a/src/testRunner/unittests/tsserverProjectSystem.ts +++ b/src/testRunner/unittests/tsserverProjectSystem.ts @@ -3136,7 +3136,7 @@ namespace ts.projectSystem { const project = projectService.configuredProjects.get(configFile.path)!; assert.isDefined(project); checkProjectActualFiles(project, [file1.path, libFile.path, module1.path, module2.path, configFile.path]); - checkWatchedFiles(host, [libFile.path, module1.path, module2.path, configFile.path]); + checkWatchedFiles(host, [libFile.path, configFile.path]); checkWatchedDirectories(host, [], /*recursive*/ false); const watchedRecursiveDirectories = getTypeRootsFromLocation(root + "/a/b/src"); watchedRecursiveDirectories.push(`${root}/a/b/src/node_modules`, `${root}/a/b/node_modules`); @@ -7435,7 +7435,7 @@ namespace ts.projectSystem { const projectFilePaths = map(projectFiles, f => f.path); checkProjectActualFiles(project, projectFilePaths); - const filesWatched = filter(projectFilePaths, p => p !== app.path); + const filesWatched = filter(projectFilePaths, p => p !== app.path && p.indexOf("/a/b/node_modules") === -1); checkWatchedFiles(host, filesWatched); checkWatchedDirectories(host, typeRootDirectories.concat(recursiveWatchedDirectories), /*recursive*/ true); checkWatchedDirectories(host, [], /*recursive*/ false); @@ -8658,10 +8658,21 @@ new C();` } function verifyWatchesWithConfigFile(host: TestServerHost, files: File[], openFile: File, extraExpectedDirectories?: ReadonlyArray) { - checkWatchedFiles(host, mapDefined(files, f => f === openFile ? undefined : f.path)); + const expectedRecursiveDirectories = arrayToSet([projectLocation, `${projectLocation}/${nodeModulesAtTypes}`, ...(extraExpectedDirectories || emptyArray)]); + checkWatchedFiles(host, mapDefined(files, f => { + if (f === openFile) { + return undefined; + } + const indexOfNodeModules = f.path.indexOf("/node_modules/"); + if (indexOfNodeModules === -1) { + return f.path; + } + expectedRecursiveDirectories.set(f.path.substr(0, indexOfNodeModules + "/node_modules".length), true); + return undefined; + })); checkWatchedDirectories(host, [], /*recursive*/ false); - checkWatchedDirectories(host, [projectLocation, `${projectLocation}/${nodeModulesAtTypes}`, ...(extraExpectedDirectories || emptyArray)], /*recursive*/ true); - } + checkWatchedDirectories(host, arrayFrom(expectedRecursiveDirectories.keys()), /*recursive*/ true); + } describe("from files in same folder", () => { function getFiles(fileContent: string) { @@ -8862,7 +8873,7 @@ new C();` verifyTrace(resolutionTrace, expectedTrace); const currentDirectory = getDirectoryPath(file1.path); - const watchedFiles = mapDefined(files, f => f === file1 ? undefined : f.path); + const watchedFiles = mapDefined(files, f => f === file1 || f.path.indexOf("/node_modules/") !== -1 ? undefined : f.path); forEachAncestorDirectory(currentDirectory, d => { watchedFiles.push(combinePaths(d, "tsconfig.json"), combinePaths(d, "jsconfig.json")); }); diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 9465a512a1f..4ca8445f4af 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -8382,6 +8382,7 @@ declare namespace ts.server { * Container of all known scripts */ private readonly filenameToScriptInfo; + private readonly scriptInfoInNodeModulesWatchers; /** * Contains all the deleted script info's version information so that * it does not reset when creating script info again @@ -8552,6 +8553,10 @@ declare namespace ts.server { private createInferredProject; getScriptInfo(uncheckedFileName: string): ScriptInfo | undefined; private watchClosedScriptInfo; + private watchClosedScriptInfoInNodeModules; + private getModifiedTime; + private refreshScriptInfo; + private refreshScriptInfosInDirectory; private stopWatchingScriptInfo; private getOrCreateScriptInfoNotOpenedByClientForNormalizedPath; private getOrCreateScriptInfoOpenedByClientForNormalizedPath; From 2b0e9e686b83ba18aaf9de9aa19d73f4d4182da0 Mon Sep 17 00:00:00 2001 From: Dan Rollo Date: Thu, 13 Sep 2018 17:23:56 -0400 Subject: [PATCH 61/83] typo: missing word: "to" (#27079) Change: ...a resolve callback used resolve the promise... to: ...a resolve callback used to resolve the promise... This PR suggested from: https://github.com/Microsoft/TypeScript/pull/27075 --- src/lib/es2015.promise.d.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/es2015.promise.d.ts b/src/lib/es2015.promise.d.ts index 14602c0b5ed..2a98f215193 100644 --- a/src/lib/es2015.promise.d.ts +++ b/src/lib/es2015.promise.d.ts @@ -7,7 +7,7 @@ interface PromiseConstructor { /** * Creates a new Promise. * @param executor A callback used to initialize the promise. This callback is passed two arguments: - * a resolve callback used resolve the promise with a value or the result of another promise, + * a resolve callback used to resolve the promise with a value or the result of another promise, * and a reject callback used to reject the promise with a provided reason or error. */ new (executor: (resolve: (value?: T | PromiseLike) => void, reject: (reason?: any) => void) => void): Promise; @@ -193,4 +193,4 @@ interface PromiseConstructor { resolve(): Promise; } -declare var Promise: PromiseConstructor; \ No newline at end of file +declare var Promise: PromiseConstructor; From 64d0e0d448453ab8a84d6e551359d934aa244a5e Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Thu, 13 Sep 2018 15:05:57 -0700 Subject: [PATCH 62/83] Shorten more internal names to JS or TS (#27080) --- src/compiler/checker.ts | 58 ++++++++++---------- src/compiler/emitter.ts | 2 +- src/compiler/moduleNameResolver.ts | 8 +-- src/compiler/moduleSpecifiers.ts | 8 +-- src/compiler/program.ts | 8 +-- src/compiler/resolutionCache.ts | 2 +- src/compiler/transformers/declarations.ts | 2 +- src/compiler/tsbuild.ts | 4 +- src/compiler/utilities.ts | 42 +++++++------- src/harness/fourslash.ts | 2 +- src/harness/harnessLanguageService.ts | 2 +- src/harness/vpath.ts | 4 +- src/jsTyping/jsTyping.ts | 4 +- src/server/editorServices.ts | 10 ++-- src/server/scriptInfo.ts | 2 +- src/services/jsDoc.ts | 2 +- src/testRunner/unittests/moduleResolution.ts | 6 +- src/tsserver/server.ts | 2 +- 18 files changed, 84 insertions(+), 84 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6f541461b09..f4314726942 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2219,7 +2219,7 @@ namespace ts { const sourceFile = resolvedModule && !resolutionDiagnostic && host.getSourceFile(resolvedModule.resolvedFileName); if (sourceFile) { if (sourceFile.symbol) { - if (resolvedModule.isExternalLibraryImport && !extensionIsTypeScript(resolvedModule.extension)) { + if (resolvedModule.isExternalLibraryImport && !extensionIsTS(resolvedModule.extension)) { errorOnImplicitAnyModule(/*isError*/ false, errorNode, resolvedModule, moduleReference); } // merged symbol is module declaration symbol combined with all augmentations @@ -2240,7 +2240,7 @@ namespace ts { } // May be an untyped module. If so, ignore resolutionDiagnostic. - if (resolvedModule && !resolutionExtensionIsTypeScriptOrJson(resolvedModule.extension) && resolutionDiagnostic === undefined || resolutionDiagnostic === Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type) { + if (resolvedModule && !resolutionExtensionIsTSOrJson(resolvedModule.extension) && resolutionDiagnostic === undefined || resolutionDiagnostic === Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type) { if (isForAugmentation) { const diag = Diagnostics.Invalid_module_name_in_augmentation_Module_0_resolves_to_an_untyped_module_at_1_which_cannot_be_augmented; error(errorNode, diag, moduleReference, resolvedModule.resolvedFileName); @@ -2273,7 +2273,7 @@ namespace ts { error(errorNode, resolutionDiagnostic, moduleReference, resolvedModule.resolvedFileName); } else { - const tsExtension = tryExtractTypeScriptExtension(moduleReference); + const tsExtension = tryExtractTSExtension(moduleReference); if (tsExtension) { const diag = Diagnostics.An_import_path_cannot_end_with_a_0_extension_Consider_importing_1_instead; error(errorNode, diag, tsExtension, removeExtension(moduleReference, tsExtension)); @@ -3351,7 +3351,7 @@ namespace ts { if (symbol) { const isConstructorObject = getObjectFlags(type) & ObjectFlags.Anonymous && type.symbol && type.symbol.flags & SymbolFlags.Class; id = (isConstructorObject ? "+" : "") + getSymbolId(symbol); - if (isJavascriptConstructor(symbol.valueDeclaration)) { + if (isJSConstructor(symbol.valueDeclaration)) { // Instance and static types share the same symbol; only add 'typeof' for the static side. const isInstanceType = type === getInferredClassType(symbol) ? SymbolFlags.Type : SymbolFlags.Value; return symbolToTypeNode(symbol, context, isInstanceType); @@ -5563,7 +5563,7 @@ namespace ts { const constraint = getBaseConstraintOfType(type); return !!constraint && isValidBaseType(constraint) && isMixinConstructorType(constraint); } - return isJavascriptConstructorType(type); + return isJSConstructorType(type); } function getBaseTypeNodeOfClass(type: InterfaceType): ExpressionWithTypeArguments | undefined { @@ -5573,7 +5573,7 @@ namespace ts { function getConstructorsForTypeArguments(type: Type, typeArgumentNodes: ReadonlyArray | undefined, location: Node): ReadonlyArray { const typeArgCount = length(typeArgumentNodes); const isJavascript = isInJSFile(location); - if (isJavascriptConstructorType(type) && !typeArgCount) { + if (isJSConstructorType(type) && !typeArgCount) { return getSignaturesOfType(type, SignatureKind.Call); } return filter(getSignaturesOfType(type, SignatureKind.Construct), @@ -5668,8 +5668,8 @@ namespace ts { else if (baseConstructorType.flags & TypeFlags.Any) { baseType = baseConstructorType; } - else if (isJavascriptConstructorType(baseConstructorType) && !baseTypeNode.typeArguments) { - baseType = getJavascriptClassType(baseConstructorType.symbol) || anyType; + else if (isJSConstructorType(baseConstructorType) && !baseTypeNode.typeArguments) { + baseType = getJSClassType(baseConstructorType.symbol) || anyType; } else { // The class derives from a "class-like" constructor function, check that we have at least one construct signature @@ -10176,7 +10176,7 @@ namespace ts { } } let outerTypeParameters = getOuterTypeParameters(declaration, /*includeThisTypes*/ true); - if (isJavascriptConstructor(declaration)) { + if (isJSConstructor(declaration)) { const templateTagParameters = getTypeParametersFromDeclaration(declaration as DeclarationWithTypeParameters); outerTypeParameters = addRange(outerTypeParameters, templateTagParameters); } @@ -10862,13 +10862,13 @@ namespace ts { } if (!ignoreReturnTypes) { - const targetReturnType = (target.declaration && isJavascriptConstructor(target.declaration)) ? - getJavascriptClassType(target.declaration.symbol)! : getReturnTypeOfSignature(target); + const targetReturnType = (target.declaration && isJSConstructor(target.declaration)) ? + getJSClassType(target.declaration.symbol)! : getReturnTypeOfSignature(target); if (targetReturnType === voidType) { return result; } - const sourceReturnType = (source.declaration && isJavascriptConstructor(source.declaration)) ? - getJavascriptClassType(source.declaration.symbol)! : getReturnTypeOfSignature(source); + const sourceReturnType = (source.declaration && isJSConstructor(source.declaration)) ? + getJSClassType(source.declaration.symbol)! : getReturnTypeOfSignature(source); // The following block preserves behavior forbidding boolean returning functions from being assignable to type guard returning functions const targetTypePredicate = getTypePredicateOfSignature(target); @@ -12132,8 +12132,8 @@ namespace ts { return Ternary.True; } - const sourceIsJSConstructor = source.symbol && isJavascriptConstructor(source.symbol.valueDeclaration); - const targetIsJSConstructor = target.symbol && isJavascriptConstructor(target.symbol.valueDeclaration); + const sourceIsJSConstructor = source.symbol && isJSConstructor(source.symbol.valueDeclaration); + const targetIsJSConstructor = target.symbol && isJSConstructor(target.symbol.valueDeclaration); const sourceSignatures = getSignaturesOfType(source, (sourceIsJSConstructor && kind === SignatureKind.Construct) ? SignatureKind.Call : kind); @@ -15821,7 +15821,7 @@ namespace ts { if (isInJS && className) { const classSymbol = checkExpression(className).symbol; if (classSymbol && classSymbol.members && (classSymbol.flags & SymbolFlags.Function)) { - const classType = getJavascriptClassType(classSymbol); + const classType = getJSClassType(classSymbol); if (classType) { return getFlowTypeOfReference(node, classType); } @@ -15834,7 +15834,7 @@ namespace ts { else if (isInJS && (container.kind === SyntaxKind.FunctionExpression || container.kind === SyntaxKind.FunctionDeclaration) && getJSDocClassTag(container)) { - const classType = getJavascriptClassType(container.symbol); + const classType = getJSClassType(container.symbol); if (classType) { return getFlowTypeOfReference(node, classType); } @@ -19851,7 +19851,7 @@ namespace ts { if (callSignatures.length) { const signature = resolveCall(node, callSignatures, candidatesOutArray, isForSignatureHelp); if (!noImplicitAny) { - if (signature.declaration && !isJavascriptConstructor(signature.declaration) && getReturnTypeOfSignature(signature) !== voidType) { + if (signature.declaration && !isJSConstructor(signature.declaration) && getReturnTypeOfSignature(signature) !== voidType) { error(node, Diagnostics.Only_a_void_function_can_be_called_with_the_new_keyword); } if (getThisTypeOfSignature(signature) === voidType) { @@ -20134,7 +20134,7 @@ namespace ts { * Indicates whether a declaration can be treated as a constructor in a JavaScript * file. */ - function isJavascriptConstructor(node: Declaration | undefined): boolean { + function isJSConstructor(node: Declaration | undefined): boolean { if (node && isInJSFile(node)) { // If the node has a @class tag, treat it like a constructor. if (getJSDocClassTag(node)) return true; @@ -20150,22 +20150,22 @@ namespace ts { return false; } - function isJavascriptConstructorType(type: Type) { + function isJSConstructorType(type: Type) { if (type.flags & TypeFlags.Object) { const resolved = resolveStructuredTypeMembers(type); - return resolved.callSignatures.length === 1 && isJavascriptConstructor(resolved.callSignatures[0].declaration); + return resolved.callSignatures.length === 1 && isJSConstructor(resolved.callSignatures[0].declaration); } return false; } - function getJavascriptClassType(symbol: Symbol): Type | undefined { + function getJSClassType(symbol: Symbol): Type | undefined { let inferred: Type | undefined; - if (isJavascriptConstructor(symbol.valueDeclaration)) { + if (isJSConstructor(symbol.valueDeclaration)) { inferred = getInferredClassType(symbol); } const assigned = getAssignedClassType(symbol); const valueType = getTypeOfSymbol(symbol); - if (valueType.symbol && !isInferredClassType(valueType) && isJavascriptConstructor(valueType.symbol.valueDeclaration)) { + if (valueType.symbol && !isInferredClassType(valueType) && isJSConstructor(valueType.symbol.valueDeclaration)) { inferred = getInferredClassType(valueType.symbol); } return assigned && inferred ? @@ -20180,14 +20180,14 @@ namespace ts { isBinaryExpression(decl.parent) && getSymbolOfNode(decl.parent.left) || isVariableDeclaration(decl.parent) && getSymbolOfNode(decl.parent)); if (assignmentSymbol) { - const prototype = forEach(assignmentSymbol.declarations, getAssignedJavascriptPrototype); + const prototype = forEach(assignmentSymbol.declarations, getAssignedJSPrototype); if (prototype) { return checkExpression(prototype); } } } - function getAssignedJavascriptPrototype(node: Node) { + function getAssignedJSPrototype(node: Node) { if (!node.parent) { return false; } @@ -20248,7 +20248,7 @@ namespace ts { if (!funcSymbol && node.expression.kind === SyntaxKind.Identifier) { funcSymbol = getResolvedSymbol(node.expression as Identifier); } - const type = funcSymbol && getJavascriptClassType(funcSymbol); + const type = funcSymbol && getJSClassType(funcSymbol); if (type) { return signature.target ? instantiateType(type, signature.mapper) : type; } @@ -20897,7 +20897,7 @@ namespace ts { return undefined; } if (strictNullChecks && aggregatedTypes.length && hasReturnWithNoExpression && - !(isJavascriptConstructor(func) && aggregatedTypes.some(t => t.symbol === func.symbol))) { + !(isJSConstructor(func) && aggregatedTypes.some(t => t.symbol === func.symbol))) { // Javascript "callable constructors", containing eg `if (!(this instanceof A)) return new A()` should not add undefined pushIfUnique(aggregatedTypes, undefinedType); } @@ -25811,7 +25811,7 @@ namespace ts { // that the base type is a class or interface type (and not, for example, an anonymous object type). // (Javascript constructor functions have this property trivially true since their return type is ignored.) const constructors = getInstantiatedConstructorsForTypeArguments(staticBaseType, baseTypeNode.typeArguments, baseTypeNode); - if (forEach(constructors, sig => !isJavascriptConstructor(sig.declaration) && getReturnTypeOfSignature(sig) !== baseType)) { + if (forEach(constructors, sig => !isJSConstructor(sig.declaration) && getReturnTypeOfSignature(sig) !== baseType)) { error(baseTypeNode.expression, Diagnostics.Base_constructors_must_all_have_the_same_return_type); } } diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index bce36bca73c..62dfb46f7c5 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -192,7 +192,7 @@ namespace ts { } const sourceFiles = isSourceFile(sourceFileOrBundle) ? [sourceFileOrBundle] : sourceFileOrBundle.sourceFiles; // Setup and perform the transformation to retrieve declarations from the input files - const nonJsFiles = filter(sourceFiles, isSourceFileNotJavascript); + const nonJsFiles = filter(sourceFiles, isSourceFileNotJS); const inputListOrBundle = (compilerOptions.outFile || compilerOptions.out) ? [createBundle(nonJsFiles, !isSourceFile(sourceFileOrBundle) ? sourceFileOrBundle.prepends : undefined)] : nonJsFiles; if (emitOnlyDtsFiles && !getEmitDeclarations(compilerOptions)) { // Checker wont collect the linked aliases since thats only done when declaration is enabled. diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index aedd1d4c3dc..335e47286b7 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -74,7 +74,7 @@ namespace ts { if (!resolved) { return undefined; } - Debug.assert(extensionIsTypeScript(resolved.extension)); + Debug.assert(extensionIsTS(resolved.extension)); return { fileName: resolved.path, packageId: resolved.packageId }; } @@ -778,7 +778,7 @@ namespace ts { * Throws an error if the module can't be resolved. */ /* @internal */ - export function resolveJavascriptModule(moduleName: string, initialDir: string, host: ModuleResolutionHost): string { + export function resolveJSModule(moduleName: string, initialDir: string, host: ModuleResolutionHost): string { const { resolvedModule, failedLookupLocations } = nodeModuleNameResolverWorker(moduleName, initialDir, { moduleResolution: ModuleResolutionKind.NodeJs, allowJs: true }, host, /*cache*/ undefined, /*jsOnly*/ true); if (!resolvedModule) { @@ -958,7 +958,7 @@ namespace ts { // If that didn't work, try stripping a ".js" or ".jsx" extension and replacing it with a TypeScript one; // e.g. "./foo.js" can be matched by "./foo.ts" or "./foo.d.ts" - if (hasJavascriptFileExtension(candidate)) { + if (hasJSFileExtension(candidate)) { const extensionless = removeFileExtension(candidate); if (state.traceEnabled) { const extension = candidate.substring(extensionless.length); @@ -1052,7 +1052,7 @@ namespace ts { const jsPath = readPackageJsonMainField(packageJsonContent, packageDirectory, state); if (typeof jsPath === "string" && jsPath.length > packageDirectory.length) { const potentialSubModule = jsPath.substring(packageDirectory.length + 1); - subModuleName = (forEach(supportedJavascriptExtensions, extension => + subModuleName = (forEach(supportedJSExtensions, extension => tryRemoveExtension(potentialSubModule, extension)) || potentialSubModule) + Extension.Dts; } else { diff --git a/src/compiler/moduleSpecifiers.ts b/src/compiler/moduleSpecifiers.ts index 6033d95b2a5..e50aaf99453 100644 --- a/src/compiler/moduleSpecifiers.ts +++ b/src/compiler/moduleSpecifiers.ts @@ -30,7 +30,7 @@ namespace ts.moduleSpecifiers { function getPreferencesForUpdate(compilerOptions: CompilerOptions, oldImportSpecifier: string): Preferences { return { relativePreference: isExternalModuleNameRelative(oldImportSpecifier) ? RelativePreference.Relative : RelativePreference.NonRelative, - ending: hasJavascriptOrJsonFileExtension(oldImportSpecifier) ? Ending.JsExtension + ending: hasJSOrJsonFileExtension(oldImportSpecifier) ? Ending.JsExtension : getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.NodeJs || endsWith(oldImportSpecifier, "index") ? Ending.Index : Ending.Minimal, }; } @@ -148,7 +148,7 @@ namespace ts.moduleSpecifiers { } function usesJsExtensionOnImports({ imports }: SourceFile): boolean { - return firstDefined(imports, ({ text }) => pathIsRelative(text) ? hasJavascriptOrJsonFileExtension(text) : undefined) || false; + return firstDefined(imports, ({ text }) => pathIsRelative(text) ? hasJSOrJsonFileExtension(text) : undefined) || false; } function stringsEqual(a: string, b: string, getCanonicalFileName: GetCanonicalFileName): boolean { @@ -415,13 +415,13 @@ namespace ts.moduleSpecifiers { case Ending.Index: return noExtension; case Ending.JsExtension: - return noExtension + getJavascriptExtensionForFile(fileName, options); + return noExtension + getJSExtensionForFile(fileName, options); default: return Debug.assertNever(ending); } } - function getJavascriptExtensionForFile(fileName: string, options: CompilerOptions): Extension { + function getJSExtensionForFile(fileName: string, options: CompilerOptions): Extension { const ext = extensionFromPath(fileName); switch (ext) { case Extension.Ts: diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 61bf38db805..b2726696e3e 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -1440,7 +1440,7 @@ namespace ts { // constructs from within a JavaScript file as syntactic errors. if (isSourceFileJS(sourceFile)) { if (!sourceFile.additionalSyntacticDiagnostics) { - sourceFile.additionalSyntacticDiagnostics = getJavascriptSyntacticDiagnosticsForFile(sourceFile); + sourceFile.additionalSyntacticDiagnostics = getJSSyntacticDiagnosticsForFile(sourceFile); } return concatenate(sourceFile.additionalSyntacticDiagnostics, sourceFile.parseDiagnostics); } @@ -1538,7 +1538,7 @@ namespace ts { return true; } - function getJavascriptSyntacticDiagnosticsForFile(sourceFile: SourceFile): DiagnosticWithLocation[] { + function getJSSyntacticDiagnosticsForFile(sourceFile: SourceFile): DiagnosticWithLocation[] { return runWithCancellationToken(() => { const diagnostics: DiagnosticWithLocation[] = []; let parent: Node = sourceFile; @@ -2273,7 +2273,7 @@ namespace ts { } const isFromNodeModulesSearch = resolution.isExternalLibraryImport; - const isJsFile = !resolutionExtensionIsTypeScriptOrJson(resolution.extension); + const isJsFile = !resolutionExtensionIsTSOrJson(resolution.extension); const isJsFileFromNodeModules = isFromNodeModulesSearch && isJsFile; const resolvedFileName = resolution.resolvedFileName; @@ -2794,7 +2794,7 @@ namespace ts { return containsPath(options.outDir, filePath, currentDirectory, !host.useCaseSensitiveFileNames()); } - if (fileExtensionIsOneOf(filePath, supportedJavascriptExtensions) || fileExtensionIs(filePath, Extension.Dts)) { + if (fileExtensionIsOneOf(filePath, supportedJSExtensions) || fileExtensionIs(filePath, Extension.Dts)) { // Otherwise just check if sourceFile with the name exists const filePathWithoutExtension = removeFileExtension(filePath); return !!getSourceFileByPath((filePathWithoutExtension + Extension.Ts) as Path) || diff --git a/src/compiler/resolutionCache.ts b/src/compiler/resolutionCache.ts index 2d7bcb34c2d..33e6dcd1221 100644 --- a/src/compiler/resolutionCache.ts +++ b/src/compiler/resolutionCache.ts @@ -226,7 +226,7 @@ namespace ts { // otherwise try to load typings from @types const globalCache = resolutionHost.getGlobalCache(); - if (globalCache !== undefined && !isExternalModuleNameRelative(moduleName) && !(primaryResult.resolvedModule && extensionIsTypeScript(primaryResult.resolvedModule.extension))) { + if (globalCache !== undefined && !isExternalModuleNameRelative(moduleName) && !(primaryResult.resolvedModule && extensionIsTS(primaryResult.resolvedModule.extension))) { // create different collection of failed lookup locations for second pass // if it will fail and we've already found something during the first pass - we don't want to pollute its results const { resolvedModule, failedLookupLocations } = loadModuleFromGlobalCache(moduleName, resolutionHost.projectName, compilerOptions, host, globalCache); diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index 14e7900b0da..5312efb5aac 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -5,7 +5,7 @@ namespace ts { return []; // No declaration diagnostics for js for now } const compilerOptions = host.getCompilerOptions(); - const result = transformNodes(resolver, host, compilerOptions, file ? [file] : filter(host.getSourceFiles(), isSourceFileNotJavascript), [transformDeclarations], /*allowDtsFiles*/ false); + const result = transformNodes(resolver, host, compilerOptions, file ? [file] : filter(host.getSourceFiles(), isSourceFileNotJS), [transformDeclarations], /*allowDtsFiles*/ false); return result.diagnostics; } diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts index 3692e9ca057..3a4b2b2429d 100644 --- a/src/compiler/tsbuild.ts +++ b/src/compiler/tsbuild.ts @@ -302,7 +302,7 @@ namespace ts { return changeExtension(outputPath, Extension.Dts); } - function getOutputJavascriptFileName(inputFileName: string, configFile: ParsedCommandLine) { + function getOutputJSFileName(inputFileName: string, configFile: ParsedCommandLine) { const relativePath = getRelativePathFromDirectory(rootDirOfOptions(configFile.options, configFile.options.configFilePath!), inputFileName, /*ignoreCase*/ true); const outputPath = resolvePath(configFile.options.outDir || getDirectoryPath(configFile.options.configFilePath!), relativePath); const newExtension = fileExtensionIs(inputFileName, Extension.Json) ? Extension.Json : @@ -317,7 +317,7 @@ namespace ts { } const outputs: string[] = []; - const js = getOutputJavascriptFileName(inputFileName, configFile); + const js = getOutputJSFileName(inputFileName, configFile); outputs.push(js); if (configFile.options.sourceMap) { outputs.push(`${js}.map`); diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 1efbd278aed..82d1e57ad41 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1682,7 +1682,7 @@ namespace ts { return isInJSFile(file); } - export function isSourceFileNotJavascript(file: SourceFile): boolean { + export function isSourceFileNotJS(file: SourceFile): boolean { return !isInJSFile(file); } @@ -3818,8 +3818,8 @@ namespace ts { } /** Return ".ts", ".d.ts", or ".tsx", if that is the extension. */ - export function tryExtractTypeScriptExtension(fileName: string): string | undefined { - return find(supportedTypescriptExtensionsForExtractExtension, extension => fileExtensionIs(fileName, extension)); + export function tryExtractTSExtension(fileName: string): string | undefined { + return find(supportedTSExtensionsForExtractExtension, extension => fileExtensionIs(fileName, extension)); } /** * Replace each instance of non-ascii characters by one, two, three, or four escape sequences @@ -8010,42 +8010,42 @@ namespace ts { /** * List of supported extensions in order of file resolution precedence. */ - export const supportedTypescriptExtensions: ReadonlyArray = [Extension.Ts, Extension.Tsx, Extension.Dts]; + export const supportedTSExtensions: ReadonlyArray = [Extension.Ts, Extension.Tsx, Extension.Dts]; /** Must have ".d.ts" first because if ".ts" goes first, that will be detected as the extension instead of ".d.ts". */ - export const supportedTypescriptExtensionsForExtractExtension: ReadonlyArray = [Extension.Dts, Extension.Ts, Extension.Tsx]; - export const supportedJavascriptExtensions: ReadonlyArray = [Extension.Js, Extension.Jsx]; - export const supportedJavascriptAndJsonExtensions: ReadonlyArray = [Extension.Js, Extension.Jsx, Extension.Json]; - const allSupportedExtensions: ReadonlyArray = [...supportedTypescriptExtensions, ...supportedJavascriptExtensions]; + export const supportedTSExtensionsForExtractExtension: ReadonlyArray = [Extension.Dts, Extension.Ts, Extension.Tsx]; + export const supportedJSExtensions: ReadonlyArray = [Extension.Js, Extension.Jsx]; + export const supportedJSAndJsonExtensions: ReadonlyArray = [Extension.Js, Extension.Jsx, Extension.Json]; + const allSupportedExtensions: ReadonlyArray = [...supportedTSExtensions, ...supportedJSExtensions]; export function getSupportedExtensions(options?: CompilerOptions, extraFileExtensions?: ReadonlyArray): ReadonlyArray { const needJsExtensions = options && options.allowJs; if (!extraFileExtensions || extraFileExtensions.length === 0) { - return needJsExtensions ? allSupportedExtensions : supportedTypescriptExtensions; + return needJsExtensions ? allSupportedExtensions : supportedTSExtensions; } const extensions = [ - ...needJsExtensions ? allSupportedExtensions : supportedTypescriptExtensions, - ...mapDefined(extraFileExtensions, x => x.scriptKind === ScriptKind.Deferred || needJsExtensions && isJavascriptLike(x.scriptKind) ? x.extension : undefined) + ...needJsExtensions ? allSupportedExtensions : supportedTSExtensions, + ...mapDefined(extraFileExtensions, x => x.scriptKind === ScriptKind.Deferred || needJsExtensions && isJSLike(x.scriptKind) ? x.extension : undefined) ]; return deduplicate(extensions, equateStringsCaseSensitive, compareStringsCaseSensitive); } - function isJavascriptLike(scriptKind: ScriptKind | undefined): boolean { + function isJSLike(scriptKind: ScriptKind | undefined): boolean { return scriptKind === ScriptKind.JS || scriptKind === ScriptKind.JSX; } - export function hasJavascriptFileExtension(fileName: string): boolean { - return some(supportedJavascriptExtensions, extension => fileExtensionIs(fileName, extension)); + export function hasJSFileExtension(fileName: string): boolean { + return some(supportedJSExtensions, extension => fileExtensionIs(fileName, extension)); } - export function hasJavascriptOrJsonFileExtension(fileName: string): boolean { - return supportedJavascriptAndJsonExtensions.some(ext => fileExtensionIs(fileName, ext)); + export function hasJSOrJsonFileExtension(fileName: string): boolean { + return supportedJSAndJsonExtensions.some(ext => fileExtensionIs(fileName, ext)); } - export function hasTypescriptFileExtension(fileName: string): boolean { - return some(supportedTypescriptExtensions, extension => fileExtensionIs(fileName, extension)); + export function hasTSFileExtension(fileName: string): boolean { + return some(supportedTSExtensions, extension => fileExtensionIs(fileName, extension)); } export function isSupportedSourceFileName(fileName: string, compilerOptions?: CompilerOptions, extraFileExtensions?: ReadonlyArray) { @@ -8181,12 +8181,12 @@ namespace ts { } /** True if an extension is one of the supported TypeScript extensions. */ - export function extensionIsTypeScript(ext: Extension): boolean { + export function extensionIsTS(ext: Extension): boolean { return ext === Extension.Ts || ext === Extension.Tsx || ext === Extension.Dts; } - export function resolutionExtensionIsTypeScriptOrJson(ext: Extension) { - return extensionIsTypeScript(ext) || ext === Extension.Json; + export function resolutionExtensionIsTSOrJson(ext: Extension) { + return extensionIsTS(ext) || ext === Extension.Json; } /** diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index a1f3517b6e6..fb1ed9fcb1b 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -593,7 +593,7 @@ namespace FourSlash { public verifyNoErrors() { ts.forEachKey(this.inputFiles, fileName => { if (!ts.isAnySupportedFileExtension(fileName) - || !this.getProgram().getCompilerOptions().allowJs && !ts.extensionIsTypeScript(ts.extensionFromPath(fileName))) return; + || !this.getProgram().getCompilerOptions().allowJs && !ts.extensionIsTS(ts.extensionFromPath(fileName))) return; const errors = this.getDiagnostics(fileName).filter(e => e.category !== ts.DiagnosticCategory.Suggestion); if (errors.length) { this.printErrorLog(/*expectErrors*/ false, errors); diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index abb03babc8d..e90f29446c3 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -268,7 +268,7 @@ namespace Harness.LanguageService { getHost(): LanguageServiceAdapterHost { return this.host; } getLanguageService(): ts.LanguageService { return ts.createLanguageService(this.host); } getClassifier(): ts.Classifier { return ts.createClassifier(); } - getPreProcessedFileInfo(fileName: string, fileContents: string): ts.PreProcessedFileInfo { return ts.preProcessFile(fileContents, /* readImportFiles */ true, ts.hasJavascriptFileExtension(fileName)); } + getPreProcessedFileInfo(fileName: string, fileContents: string): ts.PreProcessedFileInfo { return ts.preProcessFile(fileContents, /* readImportFiles */ true, ts.hasJSFileExtension(fileName)); } } /// Shim adapter diff --git a/src/harness/vpath.ts b/src/harness/vpath.ts index f21ee7fb6bb..68ba0465e50 100644 --- a/src/harness/vpath.ts +++ b/src/harness/vpath.ts @@ -21,8 +21,8 @@ namespace vpath { export import relative = ts.getRelativePathFromDirectory; export import beneath = ts.containsPath; export import changeExtension = ts.changeAnyExtension; - export import isTypeScript = ts.hasTypescriptFileExtension; - export import isJavaScript = ts.hasJavascriptFileExtension; + export import isTypeScript = ts.hasTSFileExtension; + export import isJavaScript = ts.hasJSFileExtension; const invalidRootComponentRegExp = /^(?!(\/|\/\/\w+\/|[a-zA-Z]:\/?|)$)/; const invalidNavigableComponentRegExp = /[:*?"<>|]/; diff --git a/src/jsTyping/jsTyping.ts b/src/jsTyping/jsTyping.ts index 3b1868aea84..ad21068d578 100644 --- a/src/jsTyping/jsTyping.ts +++ b/src/jsTyping/jsTyping.ts @@ -122,7 +122,7 @@ namespace ts.JsTyping { // Only infer typings for .js and .jsx files fileNames = mapDefined(fileNames, fileName => { const path = normalizePath(fileName); - if (hasJavascriptFileExtension(path)) { + if (hasJSFileExtension(path)) { return path; } }); @@ -218,7 +218,7 @@ namespace ts.JsTyping { */ function getTypingNamesFromSourceFileNames(fileNames: string[]) { const fromFileNames = mapDefined(fileNames, j => { - if (!hasJavascriptFileExtension(j)) return undefined; + if (!hasJSFileExtension(j)) return undefined; const inferredTypingName = removeFileExtension(getBaseFileName(j.toLowerCase())); const cleanedTypingName = removeMinAndVersionNumbers(inferredTypingName); diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index b1f88dff3b7..b5ea4e52c3f 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -1447,14 +1447,14 @@ namespace ts.server { for (const f of fileNames) { const fileName = propertyReader.getFileName(f); - if (hasTypescriptFileExtension(fileName)) { + if (hasTSFileExtension(fileName)) { continue; } totalNonTsFileSize += this.host.getFileSize(fileName); if (totalNonTsFileSize > maxProgramSizeForNonTsFiles || totalNonTsFileSize > availableSpace) { - this.logger.info(getExceedLimitMessage({ propertyReader, hasTypescriptFileExtension, host: this.host }, totalNonTsFileSize)); + this.logger.info(getExceedLimitMessage({ propertyReader, hasTSFileExtension, host: this.host }, totalNonTsFileSize)); // Keep the size as zero since it's disabled return fileName; } @@ -1464,14 +1464,14 @@ namespace ts.server { return; - function getExceedLimitMessage(context: { propertyReader: FilePropertyReader, hasTypescriptFileExtension: (filename: string) => boolean, host: ServerHost }, totalNonTsFileSize: number) { + function getExceedLimitMessage(context: { propertyReader: FilePropertyReader, hasTSFileExtension: (filename: string) => boolean, host: ServerHost }, totalNonTsFileSize: number) { const files = getTop5LargestFiles(context); return `Non TS file size exceeded limit (${totalNonTsFileSize}). Largest files: ${files.map(file => `${file.name}:${file.size}`).join(", ")}`; } - function getTop5LargestFiles({ propertyReader, hasTypescriptFileExtension, host }: { propertyReader: FilePropertyReader, hasTypescriptFileExtension: (filename: string) => boolean, host: ServerHost }) { + function getTop5LargestFiles({ propertyReader, hasTSFileExtension, host }: { propertyReader: FilePropertyReader, hasTSFileExtension: (filename: string) => boolean, host: ServerHost }) { return fileNames.map(f => propertyReader.getFileName(f)) - .filter(name => hasTypescriptFileExtension(name)) + .filter(name => hasTSFileExtension(name)) .map(name => ({ name, size: host.getFileSize!(name) })) // TODO: GH#18217 .sort((a, b) => b.size - a.size) .slice(0, 5); diff --git a/src/server/scriptInfo.ts b/src/server/scriptInfo.ts index 5c4eaa9a374..48c54a6fba8 100644 --- a/src/server/scriptInfo.ts +++ b/src/server/scriptInfo.ts @@ -167,7 +167,7 @@ namespace ts.server { const fileName = tempFileName || this.fileName; const getText = () => text === undefined ? (text = this.host.readFile(fileName) || "") : text; // Only non typescript files have size limitation - if (!hasTypescriptFileExtension(this.fileName)) { + if (!hasTSFileExtension(this.fileName)) { const fileSize = this.host.getFileSize ? this.host.getFileSize(fileName) : getText().length; if (fileSize > maxFileSize) { Debug.assert(!!this.info.containingProjects.length); diff --git a/src/services/jsDoc.ts b/src/services/jsDoc.ts index 442df61e073..8016b0e9ff6 100644 --- a/src/services/jsDoc.ts +++ b/src/services/jsDoc.ts @@ -312,7 +312,7 @@ namespace ts.JsDoc { const preamble = "/**" + newLine + indentationStr + " * "; const result = preamble + newLine + - parameterDocComments(parameters, hasJavascriptFileExtension(sourceFile.fileName), indentationStr, newLine) + + parameterDocComments(parameters, hasJSFileExtension(sourceFile.fileName), indentationStr, newLine) + indentationStr + " */" + (tokenStart === position ? newLine + indentationStr : ""); diff --git a/src/testRunner/unittests/moduleResolution.ts b/src/testRunner/unittests/moduleResolution.ts index e12e60e49ea..a3ebf4f84a7 100644 --- a/src/testRunner/unittests/moduleResolution.ts +++ b/src/testRunner/unittests/moduleResolution.ts @@ -83,7 +83,7 @@ namespace ts { describe("Node module resolution - relative paths", () => { function testLoadAsFile(containingFileName: string, moduleFileNameNoExt: string, moduleName: string): void { - for (const ext of supportedTypescriptExtensions) { + for (const ext of supportedTSExtensions) { test(ext, /*hasDirectoryExists*/ false); test(ext, /*hasDirectoryExists*/ true); } @@ -96,7 +96,7 @@ namespace ts { const failedLookupLocations: string[] = []; const dir = getDirectoryPath(containingFileName); - for (const e of supportedTypescriptExtensions) { + for (const e of supportedTSExtensions) { if (e === ext) { break; } @@ -137,7 +137,7 @@ namespace ts { const resolution = nodeModuleNameResolver(moduleName, containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, packageJson, moduleFile)); checkResolvedModule(resolution.resolvedModule, createResolvedModule(moduleFile.name)); // expect three failed lookup location - attempt to load module as file with all supported extensions - assert.equal(resolution.failedLookupLocations.length, supportedTypescriptExtensions.length); + assert.equal(resolution.failedLookupLocations.length, supportedTSExtensions.length); } } diff --git a/src/tsserver/server.ts b/src/tsserver/server.ts index 9c05bf0cf16..951b158c152 100644 --- a/src/tsserver/server.ts +++ b/src/tsserver/server.ts @@ -891,7 +891,7 @@ namespace ts.server { sys.require = (initialDir: string, moduleName: string): RequireResult => { try { - return { module: require(resolveJavascriptModule(moduleName, initialDir, sys)), error: undefined }; + return { module: require(resolveJSModule(moduleName, initialDir, sys)), error: undefined }; } catch (error) { return { module: undefined, error }; From ebfcc1b52db6eacd814e20efd33c2984b3b43538 Mon Sep 17 00:00:00 2001 From: Andy Date: Thu, 13 Sep 2018 15:24:49 -0700 Subject: [PATCH 63/83] Fix bug: Ignore @enum tag in TS (#27076) --- src/compiler/binder.ts | 2 +- tests/baselines/reference/jsdocInTypeScript.errors.txt | 4 ++++ tests/baselines/reference/jsdocInTypeScript.js | 7 +++++++ tests/baselines/reference/jsdocInTypeScript.symbols | 7 +++++++ tests/baselines/reference/jsdocInTypeScript.types | 10 ++++++++++ tests/cases/compiler/jsdocInTypeScript.ts | 4 ++++ 6 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 3205b2c5a55..81d4857ad07 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -2666,7 +2666,7 @@ namespace ts { } if (!isBindingPattern(node.name)) { - const isEnum = !!getJSDocEnumTag(node); + const isEnum = isInJSFile(node) && !!getJSDocEnumTag(node); const enumFlags = (isEnum ? SymbolFlags.RegularEnum : SymbolFlags.None); const enumExcludes = (isEnum ? SymbolFlags.RegularEnumExcludes : SymbolFlags.None); if (isBlockOrCatchScoped(node)) { diff --git a/tests/baselines/reference/jsdocInTypeScript.errors.txt b/tests/baselines/reference/jsdocInTypeScript.errors.txt index 7903ef8057f..c8972bb0f0a 100644 --- a/tests/baselines/reference/jsdocInTypeScript.errors.txt +++ b/tests/baselines/reference/jsdocInTypeScript.errors.txt @@ -67,4 +67,8 @@ tests/cases/compiler/jsdocInTypeScript.ts(42,12): error TS2503: Cannot find name * @type {{foo: (function(string, string): string)}} */ const obj = { foo: (a, b) => a + b }; + + /** @enum {string} */ + var E = {}; + E[""]; \ No newline at end of file diff --git a/tests/baselines/reference/jsdocInTypeScript.js b/tests/baselines/reference/jsdocInTypeScript.js index e79f400d039..ebff5629c37 100644 --- a/tests/baselines/reference/jsdocInTypeScript.js +++ b/tests/baselines/reference/jsdocInTypeScript.js @@ -47,6 +47,10 @@ import M = N; // Error: @typedef does not create namespaces in TypeScript code. * @type {{foo: (function(string, string): string)}} */ const obj = { foo: (a, b) => a + b }; + +/** @enum {string} */ +var E = {}; +E[""]; //// [jsdocInTypeScript.js] @@ -79,3 +83,6 @@ var M = N; // Error: @typedef does not create namespaces in TypeScript code. * @type {{foo: (function(string, string): string)}} */ var obj = { foo: function (a, b) { return a + b; } }; +/** @enum {string} */ +var E = {}; +E[""]; diff --git a/tests/baselines/reference/jsdocInTypeScript.symbols b/tests/baselines/reference/jsdocInTypeScript.symbols index 52caadb2064..c65d1215abe 100644 --- a/tests/baselines/reference/jsdocInTypeScript.symbols +++ b/tests/baselines/reference/jsdocInTypeScript.symbols @@ -83,3 +83,10 @@ const obj = { foo: (a, b) => a + b }; >a : Symbol(a, Decl(jsdocInTypeScript.ts, 47, 20)) >b : Symbol(b, Decl(jsdocInTypeScript.ts, 47, 22)) +/** @enum {string} */ +var E = {}; +>E : Symbol(E, Decl(jsdocInTypeScript.ts, 50, 3)) + +E[""]; +>E : Symbol(E, Decl(jsdocInTypeScript.ts, 50, 3)) + diff --git a/tests/baselines/reference/jsdocInTypeScript.types b/tests/baselines/reference/jsdocInTypeScript.types index 8916e006242..010efb68b7a 100644 --- a/tests/baselines/reference/jsdocInTypeScript.types +++ b/tests/baselines/reference/jsdocInTypeScript.types @@ -93,3 +93,13 @@ const obj = { foo: (a, b) => a + b }; >a : any >b : any +/** @enum {string} */ +var E = {}; +>E : {} +>{} : {} + +E[""]; +>E[""] : any +>E : {} +>"" : "" + diff --git a/tests/cases/compiler/jsdocInTypeScript.ts b/tests/cases/compiler/jsdocInTypeScript.ts index bceac17aa2c..4d1f0fbbe42 100644 --- a/tests/cases/compiler/jsdocInTypeScript.ts +++ b/tests/cases/compiler/jsdocInTypeScript.ts @@ -46,3 +46,7 @@ import M = N; // Error: @typedef does not create namespaces in TypeScript code. * @type {{foo: (function(string, string): string)}} */ const obj = { foo: (a, b) => a + b }; + +/** @enum {string} */ +var E = {}; +E[""]; From ea67e3ac563f51568c3a71cfd7c68f1d0a08dda8 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Thu, 13 Sep 2018 15:18:53 -0700 Subject: [PATCH 64/83] Fix watch of project with project references --- src/compiler/builder.ts | 29 ++++++++----- src/compiler/program.ts | 41 +++++++++++++------ src/compiler/types.ts | 3 +- src/compiler/utilities.ts | 6 +++ src/compiler/watch.ts | 23 +++++++---- src/server/project.ts | 4 +- src/services/services.ts | 5 ++- .../unittests/reuseProgramStructure.ts | 3 +- src/testRunner/unittests/tsbuildWatchMode.ts | 8 ++++ src/testRunner/unittests/tscWatchMode.ts | 2 +- .../reference/api/tsserverlibrary.d.ts | 15 ++++--- tests/baselines/reference/api/typescript.d.ts | 15 ++++--- 12 files changed, 102 insertions(+), 52 deletions(-) diff --git a/src/compiler/builder.ts b/src/compiler/builder.ts index f4a61267144..fbc2dc3f7d2 100644 --- a/src/compiler/builder.ts +++ b/src/compiler/builder.ts @@ -294,7 +294,7 @@ namespace ts { configFileParsingDiagnostics: ReadonlyArray; } - export function getBuilderCreationParameters(newProgramOrRootNames: Program | ReadonlyArray | undefined, hostOrOptions: BuilderProgramHost | CompilerOptions | undefined, oldProgramOrHost?: BuilderProgram | CompilerHost, configFileParsingDiagnosticsOrOldProgram?: ReadonlyArray | BuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): BuilderCreationParameters { + export function getBuilderCreationParameters(newProgramOrRootNames: Program | ReadonlyArray | undefined, hostOrOptions: BuilderProgramHost | CompilerOptions | undefined, oldProgramOrHost?: BuilderProgram | CompilerHost, configFileParsingDiagnosticsOrOldProgram?: ReadonlyArray | BuilderProgram, configFileParsingDiagnostics?: ReadonlyArray, projectReferences?: ReadonlyArray): BuilderCreationParameters { let host: BuilderProgramHost; let newProgram: Program; let oldProgram: BuilderProgram; @@ -307,7 +307,14 @@ namespace ts { } else if (isArray(newProgramOrRootNames)) { oldProgram = configFileParsingDiagnosticsOrOldProgram as BuilderProgram; - newProgram = createProgram(newProgramOrRootNames, hostOrOptions as CompilerOptions, oldProgramOrHost as CompilerHost, oldProgram && oldProgram.getProgram(), configFileParsingDiagnostics); + newProgram = createProgram({ + rootNames: newProgramOrRootNames, + options: hostOrOptions as CompilerOptions, + host: oldProgramOrHost as CompilerHost, + oldProgram: oldProgram && oldProgram.getProgram(), + configFileParsingDiagnostics, + projectReferences + }); host = oldProgramOrHost as CompilerHost; } else { @@ -623,9 +630,9 @@ namespace ts { * Create the builder to manage semantic diagnostics and cache them */ export function createSemanticDiagnosticsBuilderProgram(newProgram: Program, host: BuilderProgramHost, oldProgram?: SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): SemanticDiagnosticsBuilderProgram; - export function createSemanticDiagnosticsBuilderProgram(rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): SemanticDiagnosticsBuilderProgram; - export function createSemanticDiagnosticsBuilderProgram(newProgramOrRootNames: Program | ReadonlyArray | undefined, hostOrOptions: BuilderProgramHost | CompilerOptions | undefined, oldProgramOrHost?: CompilerHost | SemanticDiagnosticsBuilderProgram, configFileParsingDiagnosticsOrOldProgram?: ReadonlyArray | SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray) { - return createBuilderProgram(BuilderProgramKind.SemanticDiagnosticsBuilderProgram, getBuilderCreationParameters(newProgramOrRootNames, hostOrOptions, oldProgramOrHost, configFileParsingDiagnosticsOrOldProgram, configFileParsingDiagnostics)); + export function createSemanticDiagnosticsBuilderProgram(rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray, projectReferences?: ReadonlyArray): SemanticDiagnosticsBuilderProgram; + export function createSemanticDiagnosticsBuilderProgram(newProgramOrRootNames: Program | ReadonlyArray | undefined, hostOrOptions: BuilderProgramHost | CompilerOptions | undefined, oldProgramOrHost?: CompilerHost | SemanticDiagnosticsBuilderProgram, configFileParsingDiagnosticsOrOldProgram?: ReadonlyArray | SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray, projectReferences?: ReadonlyArray) { + return createBuilderProgram(BuilderProgramKind.SemanticDiagnosticsBuilderProgram, getBuilderCreationParameters(newProgramOrRootNames, hostOrOptions, oldProgramOrHost, configFileParsingDiagnosticsOrOldProgram, configFileParsingDiagnostics, projectReferences)); } /** @@ -633,18 +640,18 @@ namespace ts { * to emit the those files and manage semantic diagnostics cache as well */ export function createEmitAndSemanticDiagnosticsBuilderProgram(newProgram: Program, host: BuilderProgramHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): EmitAndSemanticDiagnosticsBuilderProgram; - export function createEmitAndSemanticDiagnosticsBuilderProgram(rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): EmitAndSemanticDiagnosticsBuilderProgram; - export function createEmitAndSemanticDiagnosticsBuilderProgram(newProgramOrRootNames: Program | ReadonlyArray | undefined, hostOrOptions: BuilderProgramHost | CompilerOptions | undefined, oldProgramOrHost?: CompilerHost | EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnosticsOrOldProgram?: ReadonlyArray | EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray) { - return createBuilderProgram(BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram, getBuilderCreationParameters(newProgramOrRootNames, hostOrOptions, oldProgramOrHost, configFileParsingDiagnosticsOrOldProgram, configFileParsingDiagnostics)); + export function createEmitAndSemanticDiagnosticsBuilderProgram(rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray, projectReferences?: ReadonlyArray): EmitAndSemanticDiagnosticsBuilderProgram; + export function createEmitAndSemanticDiagnosticsBuilderProgram(newProgramOrRootNames: Program | ReadonlyArray | undefined, hostOrOptions: BuilderProgramHost | CompilerOptions | undefined, oldProgramOrHost?: CompilerHost | EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnosticsOrOldProgram?: ReadonlyArray | EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray, projectReferences?: ReadonlyArray) { + return createBuilderProgram(BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram, getBuilderCreationParameters(newProgramOrRootNames, hostOrOptions, oldProgramOrHost, configFileParsingDiagnosticsOrOldProgram, configFileParsingDiagnostics, projectReferences)); } /** * Creates a builder thats just abstraction over program and can be used with watch */ export function createAbstractBuilder(newProgram: Program, host: BuilderProgramHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): BuilderProgram; - export function createAbstractBuilder(rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): BuilderProgram; - export function createAbstractBuilder(newProgramOrRootNames: Program | ReadonlyArray | undefined, hostOrOptions: BuilderProgramHost | CompilerOptions | undefined, oldProgramOrHost?: CompilerHost | BuilderProgram, configFileParsingDiagnosticsOrOldProgram?: ReadonlyArray | BuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): BuilderProgram { - const { newProgram: program } = getBuilderCreationParameters(newProgramOrRootNames, hostOrOptions, oldProgramOrHost, configFileParsingDiagnosticsOrOldProgram, configFileParsingDiagnostics); + export function createAbstractBuilder(rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: ReadonlyArray, projectReferences?: ReadonlyArray): BuilderProgram; + export function createAbstractBuilder(newProgramOrRootNames: Program | ReadonlyArray | undefined, hostOrOptions: BuilderProgramHost | CompilerOptions | undefined, oldProgramOrHost?: CompilerHost | BuilderProgram, configFileParsingDiagnosticsOrOldProgram?: ReadonlyArray | BuilderProgram, configFileParsingDiagnostics?: ReadonlyArray, projectReferences?: ReadonlyArray): BuilderProgram { + const { newProgram: program } = getBuilderCreationParameters(newProgramOrRootNames, hostOrOptions, oldProgramOrHost, configFileParsingDiagnosticsOrOldProgram, configFileParsingDiagnostics, projectReferences); return { // Only return program, all other methods are not implemented getProgram: () => program, diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 61bf38db805..ab19041611d 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -442,6 +442,7 @@ namespace ts { fileExists: (fileName: string) => boolean, hasInvalidatedResolution: HasInvalidatedResolution, hasChangedAutomaticTypeDirectiveNames: boolean, + projectReferences: ReadonlyArray | undefined ): boolean { // If we haven't created a program yet or have changed automatic type directives, then it is not up-to-date if (!program || hasChangedAutomaticTypeDirectiveNames) { @@ -453,6 +454,11 @@ namespace ts { return false; } + // If project references dont match + if (!arrayIsEqualTo(program.getProjectReferences(), projectReferences)) { + return false; + } + // If any file is not up-to-date, then the whole program is not up-to-date if (program.getSourceFiles().some(sourceFileNotUptoDate)) { return false; @@ -759,7 +765,8 @@ namespace ts { isEmittedFile, getConfigFileParsingDiagnostics, getResolvedModuleWithFailedLookupLocationsFromCache, - getProjectReferences + getProjectReferences, + getResolvedProjectReferences }; verifyCompilerOptions(); @@ -1007,15 +1014,21 @@ namespace ts { } // Check if any referenced project tsconfig files are different - const oldRefs = oldProgram.getProjectReferences(); + + // If array of references is changed, we cant resue old program + const oldProjectReferences = oldProgram.getProjectReferences(); + if (!arrayIsEqualTo(oldProjectReferences!, projectReferences, projectReferencesIsEqualTo)) { + return oldProgram.structureIsReused = StructureIsReused.Not; + } + + // Check the json files for the project references + const oldRefs = oldProgram.getResolvedProjectReferences(); if (projectReferences) { - if (!oldRefs) { - return oldProgram.structureIsReused = StructureIsReused.Not; - } + Debug.assert(!!oldRefs); for (let i = 0; i < projectReferences.length; i++) { - const oldRef = oldRefs[i]; + const oldRef = oldRefs![i]; + const newRef = parseProjectReferenceConfigFile(projectReferences[i]); if (oldRef) { - const newRef = parseProjectReferenceConfigFile(projectReferences[i]); if (!newRef || newRef.sourceFile !== oldRef.sourceFile) { // Resolved project reference has gone missing or changed return oldProgram.structureIsReused = StructureIsReused.Not; @@ -1023,16 +1036,14 @@ namespace ts { } else { // A previously-unresolved reference may be resolved now - if (parseProjectReferenceConfigFile(projectReferences[i]) !== undefined) { + if (newRef !== undefined) { return oldProgram.structureIsReused = StructureIsReused.Not; } } } } else { - if (oldRefs) { - return oldProgram.structureIsReused = StructureIsReused.Not; - } + Debug.assert(!oldRefs); } // check if program source files has changed in the way that can affect structure of the program @@ -1219,7 +1230,7 @@ namespace ts { fileProcessingDiagnostics.reattachFileDiagnostics(modifiedFile.newFile); } resolvedTypeReferenceDirectives = oldProgram.getResolvedTypeReferenceDirectives(); - resolvedProjectReferences = oldProgram.getProjectReferences(); + resolvedProjectReferences = oldProgram.getResolvedProjectReferences(); sourceFileToPackageName = oldProgram.sourceFileToPackageName; redirectTargetsMap = oldProgram.redirectTargetsMap; @@ -1257,10 +1268,14 @@ namespace ts { }; } - function getProjectReferences() { + function getResolvedProjectReferences() { return resolvedProjectReferences; } + function getProjectReferences() { + return projectReferences; + } + function getPrependNodes(): InputFiles[] { if (!projectReferences) { return emptyArray; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index a0d07e00591..85b52e0637f 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2815,7 +2815,8 @@ namespace ts { /* @internal */ getResolvedModuleWithFailedLookupLocationsFromCache(moduleName: string, containingFile: string): ResolvedModuleWithFailedLookupLocations | undefined; - getProjectReferences(): (ResolvedProjectReference | undefined)[] | undefined; + getProjectReferences(): ReadonlyArray | undefined; + getResolvedProjectReferences(): (ResolvedProjectReference | undefined)[] | undefined; } /* @internal */ diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 1efbd278aed..c84a9b34980 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -249,6 +249,12 @@ namespace ts { sourceFile.resolvedTypeReferenceDirectiveNames.set(typeReferenceDirectiveName, resolvedTypeReferenceDirective); } + export function projectReferencesIsEqualTo(oldRef: ProjectReference, newRef: ProjectReference) { + return oldRef.path === newRef.path && + !oldRef.prepend === !newRef.prepend && + !oldRef.circular === !newRef.circular; + } + export function moduleResolutionIsEqualTo(oldResolution: ResolvedModuleFull, newResolution: ResolvedModuleFull): boolean { return oldResolution.isExternalLibraryImport === newResolution.isExternalLibraryImport && oldResolution.extension === newResolution.extension && diff --git a/src/compiler/watch.ts b/src/compiler/watch.ts index c091ad5c30c..a3b0cc23c23 100644 --- a/src/compiler/watch.ts +++ b/src/compiler/watch.ts @@ -263,10 +263,11 @@ namespace ts { /** * Creates the watch compiler host from system for compiling root files and options in watch mode */ - export function createWatchCompilerHostOfFilesAndCompilerOptions(rootFiles: string[], options: CompilerOptions, system: System, createProgram?: CreateProgram, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter): WatchCompilerHostOfFilesAndCompilerOptions { + export function createWatchCompilerHostOfFilesAndCompilerOptions(rootFiles: string[], options: CompilerOptions, system: System, createProgram?: CreateProgram, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter, projectReferences?: ReadonlyArray): WatchCompilerHostOfFilesAndCompilerOptions { const host = createWatchCompilerHost(system, createProgram, reportDiagnostic || createDiagnosticReporter(system), reportWatchStatus) as WatchCompilerHostOfFilesAndCompilerOptions; host.rootFiles = rootFiles; host.options = options; + host.projectReferences = projectReferences; return host; } } @@ -274,7 +275,7 @@ namespace ts { namespace ts { export type WatchStatusReporter = (diagnostic: Diagnostic, newLine: string, options: CompilerOptions) => void; /** Create the program with rootNames and options, if they are undefined, oldProgram and new configFile diagnostics create new program */ - export type CreateProgram = (rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: T, configFileParsingDiagnostics?: ReadonlyArray) => T; + export type CreateProgram = (rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: T, configFileParsingDiagnostics?: ReadonlyArray, projectReferences?: ReadonlyArray | undefined) => T; /** Host that has watch functionality used in --watch mode */ export interface WatchHost { /** If provided, called with Diagnostic message that informs about change in watch status */ @@ -360,6 +361,9 @@ namespace ts { /** Compiler options */ options: CompilerOptions; + + /** Project References */ + projectReferences?: ReadonlyArray; } /** @@ -413,11 +417,11 @@ namespace ts { /** * Create the watch compiler host for either configFile or fileNames and its options */ - export function createWatchCompilerHost(rootFiles: string[], options: CompilerOptions, system: System, createProgram?: CreateProgram, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter): WatchCompilerHostOfFilesAndCompilerOptions; export function createWatchCompilerHost(configFileName: string, optionsToExtend: CompilerOptions | undefined, system: System, createProgram?: CreateProgram, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter): WatchCompilerHostOfConfigFile; - export function createWatchCompilerHost(rootFilesOrConfigFileName: string | string[], options: CompilerOptions | undefined, system: System, createProgram?: CreateProgram, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter): WatchCompilerHostOfFilesAndCompilerOptions | WatchCompilerHostOfConfigFile { + export function createWatchCompilerHost(rootFiles: string[], options: CompilerOptions, system: System, createProgram?: CreateProgram, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter, projectReferences?: ReadonlyArray): WatchCompilerHostOfFilesAndCompilerOptions; + export function createWatchCompilerHost(rootFilesOrConfigFileName: string | string[], options: CompilerOptions | undefined, system: System, createProgram?: CreateProgram, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter, projectReferences?: ReadonlyArray): WatchCompilerHostOfFilesAndCompilerOptions | WatchCompilerHostOfConfigFile { if (isArray(rootFilesOrConfigFileName)) { - return createWatchCompilerHostOfFilesAndCompilerOptions(rootFilesOrConfigFileName, options!, system, createProgram, reportDiagnostic, reportWatchStatus); // TODO: GH#18217 + return createWatchCompilerHostOfFilesAndCompilerOptions(rootFilesOrConfigFileName, options!, system, createProgram, reportDiagnostic, reportWatchStatus, projectReferences); // TODO: GH#18217 } else { return createWatchCompilerHostOfConfigFile(rootFilesOrConfigFileName, options, system, createProgram, reportDiagnostic, reportWatchStatus); @@ -463,7 +467,7 @@ namespace ts { const getCurrentDirectory = () => currentDirectory; const readFile: (path: string, encoding?: string) => string | undefined = (path, encoding) => host.readFile(path, encoding); const { configFileName, optionsToExtend: optionsToExtendForConfigFile = {}, createProgram } = host; - let { rootFiles: rootFileNames, options: compilerOptions } = host; + let { rootFiles: rootFileNames, options: compilerOptions, projectReferences } = host; let configFileSpecs: ConfigFileSpecs; let configFileParsingDiagnostics: ReadonlyArray | undefined; let hasChangedConfigFileParsingErrors = false; @@ -589,9 +593,9 @@ namespace ts { // All resolutions are invalid if user provided resolutions const hasInvalidatedResolution = resolutionCache.createHasInvalidatedResolution(userProvidedResolution); - if (isProgramUptoDate(getCurrentProgram(), rootFileNames, compilerOptions, getSourceVersion, fileExists, hasInvalidatedResolution, hasChangedAutomaticTypeDirectiveNames)) { + if (isProgramUptoDate(getCurrentProgram(), rootFileNames, compilerOptions, getSourceVersion, fileExists, hasInvalidatedResolution, hasChangedAutomaticTypeDirectiveNames, projectReferences)) { if (hasChangedConfigFileParsingErrors) { - builderProgram = createProgram(/*rootNames*/ undefined, /*options*/ undefined, compilerHost, builderProgram, configFileParsingDiagnostics); + builderProgram = createProgram(/*rootNames*/ undefined, /*options*/ undefined, compilerHost, builderProgram, configFileParsingDiagnostics, projectReferences); hasChangedConfigFileParsingErrors = false; } } @@ -620,7 +624,7 @@ namespace ts { resolutionCache.startCachingPerDirectoryResolution(); compilerHost.hasInvalidatedResolution = hasInvalidatedResolution; compilerHost.hasChangedAutomaticTypeDirectiveNames = hasChangedAutomaticTypeDirectiveNames; - builderProgram = createProgram(rootFileNames, compilerOptions, compilerHost, builderProgram, configFileParsingDiagnostics); + builderProgram = createProgram(rootFileNames, compilerOptions, compilerHost, builderProgram, configFileParsingDiagnostics, projectReferences); resolutionCache.finishCachingPerDirectoryResolution(); // Update watches @@ -861,6 +865,7 @@ namespace ts { rootFileNames = configFileParseResult.fileNames; compilerOptions = configFileParseResult.options; configFileSpecs = configFileParseResult.configFileSpecs!; // TODO: GH#18217 + projectReferences = configFileParseResult.projectReferences; configFileParsingDiagnostics = getConfigFileParsingDiagnostics(configFileParseResult); hasChangedConfigFileParsingErrors = true; } diff --git a/src/server/project.ts b/src/server/project.ts index f20530c88a9..3cabc8793db 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -574,7 +574,7 @@ namespace ts.server { for (const f of this.program.getSourceFiles()) { this.detachScriptInfoIfNotRoot(f.fileName); } - const projectReferences = this.program.getProjectReferences(); + const projectReferences = this.program.getResolvedProjectReferences(); if (projectReferences) { for (const ref of projectReferences) { if (ref) { @@ -1390,7 +1390,7 @@ namespace ts.server { /*@internal*/ getResolvedProjectReferences() { const program = this.getCurrentProgram(); - return program && program.getProjectReferences(); + return program && program.getResolvedProjectReferences(); } enablePlugins() { diff --git a/src/services/services.ts b/src/services/services.ts index 7f2ac2bcc81..0cbd4107028 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1175,9 +1175,10 @@ namespace ts { const rootFileNames = hostCache.getRootFileNames(); const hasInvalidatedResolution: HasInvalidatedResolution = host.hasInvalidatedResolution || returnFalse; + const projectReferences = hostCache.getProjectReferences(); // If the program is already up-to-date, we can reuse it - if (isProgramUptoDate(program, rootFileNames, hostCache.compilationSettings(), path => hostCache!.getVersion(path), fileExists, hasInvalidatedResolution, !!host.hasChangedAutomaticTypeDirectiveNames)) { + if (isProgramUptoDate(program, rootFileNames, hostCache.compilationSettings(), path => hostCache!.getVersion(path), fileExists, hasInvalidatedResolution, !!host.hasChangedAutomaticTypeDirectiveNames, projectReferences)) { return; } @@ -1240,7 +1241,7 @@ namespace ts { options: newSettings, host: compilerHost, oldProgram: program, - projectReferences: hostCache.getProjectReferences() + projectReferences }; program = createProgram(options); diff --git a/src/testRunner/unittests/reuseProgramStructure.ts b/src/testRunner/unittests/reuseProgramStructure.ts index f0f9cc6493b..3fec096d4fa 100644 --- a/src/testRunner/unittests/reuseProgramStructure.ts +++ b/src/testRunner/unittests/reuseProgramStructure.ts @@ -914,7 +914,8 @@ namespace ts { program, newRootFileNames, newOptions, path => program.getSourceFileByPath(path)!.version, /*fileExists*/ returnFalse, /*hasInvalidatedResolution*/ returnFalse, - /*hasChangedAutomaticTypeDirectiveNames*/ false + /*hasChangedAutomaticTypeDirectiveNames*/ false, + /*projectReferences*/ undefined ); assert.isTrue(actual); } diff --git a/src/testRunner/unittests/tsbuildWatchMode.ts b/src/testRunner/unittests/tsbuildWatchMode.ts index daa1276e023..7de3437c1fa 100644 --- a/src/testRunner/unittests/tsbuildWatchMode.ts +++ b/src/testRunner/unittests/tsbuildWatchMode.ts @@ -149,6 +149,14 @@ export class someClass2 { }`); } }); + it("tsc-watch works with project references", () => { + // Build the composite project + const host = createSolutionInWatchMode(); + + createWatchOfConfigFile(tests[0].path, host); + checkOutputErrorsInitial(host, emptyArray); + }); + // TODO: write tests reporting errors but that will have more involved work since file }); } diff --git a/src/testRunner/unittests/tscWatchMode.ts b/src/testRunner/unittests/tscWatchMode.ts index da1c4fd0d70..8e7bb175136 100644 --- a/src/testRunner/unittests/tscWatchMode.ts +++ b/src/testRunner/unittests/tscWatchMode.ts @@ -20,7 +20,7 @@ namespace ts.tscWatch { checkArray(`Program rootFileNames`, program.getRootFileNames(), expectedFiles); } - function createWatchOfConfigFile(configFileName: string, host: WatchedSystem, maxNumberOfFilesToIterateForInvalidation?: number) { + export function createWatchOfConfigFile(configFileName: string, host: WatchedSystem, maxNumberOfFilesToIterateForInvalidation?: number) { const compilerHost = createWatchCompilerHostOfConfigFile(configFileName, {}, host); compilerHost.maxNumberOfFilesToIterateForInvalidation = maxNumberOfFilesToIterateForInvalidation; const watch = createWatchProgram(compilerHost); diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 9465a512a1f..73b29d8ad4d 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -1811,7 +1811,8 @@ declare namespace ts { getTypeChecker(): TypeChecker; isSourceFileFromExternalLibrary(file: SourceFile): boolean; isSourceFileDefaultLibrary(file: SourceFile): boolean; - getProjectReferences(): (ResolvedProjectReference | undefined)[] | undefined; + getProjectReferences(): ReadonlyArray | undefined; + getResolvedProjectReferences(): (ResolvedProjectReference | undefined)[] | undefined; } interface ResolvedProjectReference { commandLine: ParsedCommandLine; @@ -4315,23 +4316,23 @@ declare namespace ts { * Create the builder to manage semantic diagnostics and cache them */ function createSemanticDiagnosticsBuilderProgram(newProgram: Program, host: BuilderProgramHost, oldProgram?: SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): SemanticDiagnosticsBuilderProgram; - function createSemanticDiagnosticsBuilderProgram(rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): SemanticDiagnosticsBuilderProgram; + function createSemanticDiagnosticsBuilderProgram(rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray, projectReferences?: ReadonlyArray): SemanticDiagnosticsBuilderProgram; /** * Create the builder that can handle the changes in program and iterate through changed files * to emit the those files and manage semantic diagnostics cache as well */ function createEmitAndSemanticDiagnosticsBuilderProgram(newProgram: Program, host: BuilderProgramHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): EmitAndSemanticDiagnosticsBuilderProgram; - function createEmitAndSemanticDiagnosticsBuilderProgram(rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): EmitAndSemanticDiagnosticsBuilderProgram; + function createEmitAndSemanticDiagnosticsBuilderProgram(rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray, projectReferences?: ReadonlyArray): EmitAndSemanticDiagnosticsBuilderProgram; /** * Creates a builder thats just abstraction over program and can be used with watch */ function createAbstractBuilder(newProgram: Program, host: BuilderProgramHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): BuilderProgram; - function createAbstractBuilder(rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): BuilderProgram; + function createAbstractBuilder(rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: ReadonlyArray, projectReferences?: ReadonlyArray): BuilderProgram; } declare namespace ts { type WatchStatusReporter = (diagnostic: Diagnostic, newLine: string, options: CompilerOptions) => void; /** Create the program with rootNames and options, if they are undefined, oldProgram and new configFile diagnostics create new program */ - type CreateProgram = (rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: T, configFileParsingDiagnostics?: ReadonlyArray) => T; + type CreateProgram = (rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: T, configFileParsingDiagnostics?: ReadonlyArray, projectReferences?: ReadonlyArray | undefined) => T; /** Host that has watch functionality used in --watch mode */ interface WatchHost { /** If provided, called with Diagnostic message that informs about change in watch status */ @@ -4393,6 +4394,8 @@ declare namespace ts { rootFiles: string[]; /** Compiler options */ options: CompilerOptions; + /** Project References */ + projectReferences?: ReadonlyArray; } /** * Host to create watch with config file @@ -4427,8 +4430,8 @@ declare namespace ts { /** * Create the watch compiler host for either configFile or fileNames and its options */ - function createWatchCompilerHost(rootFiles: string[], options: CompilerOptions, system: System, createProgram?: CreateProgram, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter): WatchCompilerHostOfFilesAndCompilerOptions; function createWatchCompilerHost(configFileName: string, optionsToExtend: CompilerOptions | undefined, system: System, createProgram?: CreateProgram, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter): WatchCompilerHostOfConfigFile; + function createWatchCompilerHost(rootFiles: string[], options: CompilerOptions, system: System, createProgram?: CreateProgram, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter, projectReferences?: ReadonlyArray): WatchCompilerHostOfFilesAndCompilerOptions; /** * Creates the watch from the host for root files and compiler options */ diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 66ba75bbd93..2093992e223 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -1811,7 +1811,8 @@ declare namespace ts { getTypeChecker(): TypeChecker; isSourceFileFromExternalLibrary(file: SourceFile): boolean; isSourceFileDefaultLibrary(file: SourceFile): boolean; - getProjectReferences(): (ResolvedProjectReference | undefined)[] | undefined; + getProjectReferences(): ReadonlyArray | undefined; + getResolvedProjectReferences(): (ResolvedProjectReference | undefined)[] | undefined; } interface ResolvedProjectReference { commandLine: ParsedCommandLine; @@ -4315,23 +4316,23 @@ declare namespace ts { * Create the builder to manage semantic diagnostics and cache them */ function createSemanticDiagnosticsBuilderProgram(newProgram: Program, host: BuilderProgramHost, oldProgram?: SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): SemanticDiagnosticsBuilderProgram; - function createSemanticDiagnosticsBuilderProgram(rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): SemanticDiagnosticsBuilderProgram; + function createSemanticDiagnosticsBuilderProgram(rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray, projectReferences?: ReadonlyArray): SemanticDiagnosticsBuilderProgram; /** * Create the builder that can handle the changes in program and iterate through changed files * to emit the those files and manage semantic diagnostics cache as well */ function createEmitAndSemanticDiagnosticsBuilderProgram(newProgram: Program, host: BuilderProgramHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): EmitAndSemanticDiagnosticsBuilderProgram; - function createEmitAndSemanticDiagnosticsBuilderProgram(rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): EmitAndSemanticDiagnosticsBuilderProgram; + function createEmitAndSemanticDiagnosticsBuilderProgram(rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray, projectReferences?: ReadonlyArray): EmitAndSemanticDiagnosticsBuilderProgram; /** * Creates a builder thats just abstraction over program and can be used with watch */ function createAbstractBuilder(newProgram: Program, host: BuilderProgramHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): BuilderProgram; - function createAbstractBuilder(rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): BuilderProgram; + function createAbstractBuilder(rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: ReadonlyArray, projectReferences?: ReadonlyArray): BuilderProgram; } declare namespace ts { type WatchStatusReporter = (diagnostic: Diagnostic, newLine: string, options: CompilerOptions) => void; /** Create the program with rootNames and options, if they are undefined, oldProgram and new configFile diagnostics create new program */ - type CreateProgram = (rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: T, configFileParsingDiagnostics?: ReadonlyArray) => T; + type CreateProgram = (rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: T, configFileParsingDiagnostics?: ReadonlyArray, projectReferences?: ReadonlyArray | undefined) => T; /** Host that has watch functionality used in --watch mode */ interface WatchHost { /** If provided, called with Diagnostic message that informs about change in watch status */ @@ -4393,6 +4394,8 @@ declare namespace ts { rootFiles: string[]; /** Compiler options */ options: CompilerOptions; + /** Project References */ + projectReferences?: ReadonlyArray; } /** * Host to create watch with config file @@ -4427,8 +4430,8 @@ declare namespace ts { /** * Create the watch compiler host for either configFile or fileNames and its options */ - function createWatchCompilerHost(rootFiles: string[], options: CompilerOptions, system: System, createProgram?: CreateProgram, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter): WatchCompilerHostOfFilesAndCompilerOptions; function createWatchCompilerHost(configFileName: string, optionsToExtend: CompilerOptions | undefined, system: System, createProgram?: CreateProgram, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter): WatchCompilerHostOfConfigFile; + function createWatchCompilerHost(rootFiles: string[], options: CompilerOptions, system: System, createProgram?: CreateProgram, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter, projectReferences?: ReadonlyArray): WatchCompilerHostOfFilesAndCompilerOptions; /** * Creates the watch from the host for root files and compiler options */ From f71d6005a259c3c29c2e2a19bd4d0ee42392328c Mon Sep 17 00:00:00 2001 From: Andy Date: Thu, 13 Sep 2018 15:49:06 -0700 Subject: [PATCH 65/83] Use nextToken() after parsing a tag name so we can parse type keywords (#26915) * Use nextToken() after parsing a tag name so we can parse type keywords * Make callback to skipWhitespaceOrAsterisk non-optional --- src/compiler/checker.ts | 9 +++++---- src/compiler/parser.ts | 19 ++++++++++--------- ...ocComments.parsesCorrectly.@link tags.json | 4 ++-- ...cComments.parsesCorrectly.templateTag.json | 4 ++-- ...Comments.parsesCorrectly.templateTag2.json | 4 ++-- ...Comments.parsesCorrectly.templateTag3.json | 4 ++-- ...Comments.parsesCorrectly.templateTag4.json | 4 ++-- ...Comments.parsesCorrectly.templateTag5.json | 4 ++-- ...Comments.parsesCorrectly.templateTag6.json | 4 ++-- tests/baselines/reference/enumTag.errors.txt | 2 +- tests/baselines/reference/enumTag.symbols | 2 +- tests/baselines/reference/enumTag.types | 2 +- .../reference/paramTagWrapping.errors.txt | 8 ++++---- tests/cases/conformance/jsdoc/enumTag.ts | 2 +- 14 files changed, 37 insertions(+), 35 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f4314726942..3e9a3300726 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -29938,10 +29938,11 @@ namespace ts { } function checkGrammarConstructorTypeParameters(node: ConstructorDeclaration) { - const jsdocTypeParameters = isInJSFile(node) && getJSDocTypeParameterDeclarations(node); - if (node.typeParameters || jsdocTypeParameters && jsdocTypeParameters.length) { - const { pos, end } = node.typeParameters || jsdocTypeParameters && jsdocTypeParameters[0] || node; - return grammarErrorAtPos(node, pos, end - pos, Diagnostics.Type_parameters_cannot_appear_on_a_constructor_declaration); + const jsdocTypeParameters = isInJSFile(node) ? getJSDocTypeParameterDeclarations(node) : undefined; + const range = node.typeParameters || jsdocTypeParameters && firstOrUndefined(jsdocTypeParameters); + if (range) { + const pos = range.pos === range.end ? range.pos : skipTrivia(getSourceFileOfNode(node).text, range.pos); + return grammarErrorAtPos(node, pos, range.end - pos, Diagnostics.Type_parameters_cannot_appear_on_a_constructor_declaration); } } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 415a62e5627..33829fccb7a 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -6517,7 +6517,7 @@ namespace ts { } } - function skipWhitespaceOrAsterisk(): void { + function skipWhitespaceOrAsterisk(next: () => void): void { if (token() === SyntaxKind.WhitespaceTrivia || token() === SyntaxKind.NewLineTrivia) { if (lookAhead(isNextNonwhitespaceTokenEndOfFile)) { return; // Don't skip whitespace prior to EoF (or end of comment) - that shouldn't be included in any node's range @@ -6532,7 +6532,7 @@ namespace ts { else if (token() === SyntaxKind.AsteriskToken) { precedingLineBreak = false; } - nextJSDocToken(); + next(); } } @@ -6542,8 +6542,9 @@ namespace ts { atToken.end = scanner.getTextPos(); nextJSDocToken(); - const tagName = parseJSDocIdentifierName(); - skipWhitespaceOrAsterisk(); + // Use 'nextToken' instead of 'nextJsDocToken' so we can parse a type like 'number' in `@enum number` + const tagName = parseJSDocIdentifierName(/*message*/ undefined, nextToken); + skipWhitespaceOrAsterisk(nextToken); let tag: JSDocTag | undefined; switch (tagName.escapedText) { @@ -6687,7 +6688,7 @@ namespace ts { } function tryParseTypeExpression(): JSDocTypeExpression | undefined { - skipWhitespaceOrAsterisk(); + skipWhitespaceOrAsterisk(nextJSDocToken); return token() === SyntaxKind.OpenBraceToken ? parseJSDocTypeExpression() : undefined; } @@ -6727,7 +6728,7 @@ namespace ts { function parseParameterOrPropertyTag(atToken: AtToken, tagName: Identifier, target: PropertyLikeParse, indent: number): JSDocParameterTag | JSDocPropertyTag { let typeExpression = tryParseTypeExpression(); let isNameFirst = !typeExpression; - skipWhitespaceOrAsterisk(); + skipWhitespaceOrAsterisk(nextJSDocToken); const { name, isBracketed } = parseBracketNameInPropertyAndParamTag(); skipWhitespace(); @@ -6861,7 +6862,7 @@ namespace ts { function parseTypedefTag(atToken: AtToken, tagName: Identifier, indent: number): JSDocTypedefTag { const typeExpression = tryParseTypeExpression(); - skipWhitespaceOrAsterisk(); + skipWhitespaceOrAsterisk(nextJSDocToken); const typedefTag = createNode(SyntaxKind.JSDocTypedefTag, atToken.pos); typedefTag.atToken = atToken; @@ -7114,7 +7115,7 @@ namespace ts { return entity; } - function parseJSDocIdentifierName(message?: DiagnosticMessage): Identifier { + function parseJSDocIdentifierName(message?: DiagnosticMessage, next: () => void = nextJSDocToken): Identifier { if (!tokenIsIdentifierOrKeyword(token())) { return createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ !message, message || Diagnostics.Identifier_expected); } @@ -7125,7 +7126,7 @@ namespace ts { result.escapedText = escapeLeadingUnderscores(scanner.getTokenText()); finishNode(result, end); - nextJSDocToken(); + next(); return result; } } diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.@link tags.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.@link tags.json index c694d240371..2ea60ed3e42 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.@link tags.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.@link tags.json @@ -6,7 +6,7 @@ "0": { "kind": "JSDocTag", "pos": 63, - "end": 68, + "end": 67, "atToken": { "kind": "AtToken", "pos": 63, @@ -22,7 +22,7 @@ }, "length": 1, "pos": 63, - "end": 68 + "end": 67 }, "comment": "{@link first link}\nInside {@link link text} thing" } \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag.json index 4d16157d91d..cd453fce8c5 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag.json @@ -21,7 +21,7 @@ "typeParameters": { "0": { "kind": "TypeParameter", - "pos": 18, + "pos": 17, "end": 19, "name": { "kind": "Identifier", @@ -31,7 +31,7 @@ } }, "length": 1, - "pos": 18, + "pos": 17, "end": 19 } }, diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag2.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag2.json index 3f5f2a54ec7..bfc59a6a3bb 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag2.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag2.json @@ -21,7 +21,7 @@ "typeParameters": { "0": { "kind": "TypeParameter", - "pos": 18, + "pos": 17, "end": 19, "name": { "kind": "Identifier", @@ -42,7 +42,7 @@ } }, "length": 2, - "pos": 18, + "pos": 17, "end": 21 } }, diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag3.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag3.json index 193c5c0eb01..e6ad0c0d0f3 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag3.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag3.json @@ -21,7 +21,7 @@ "typeParameters": { "0": { "kind": "TypeParameter", - "pos": 18, + "pos": 17, "end": 19, "name": { "kind": "Identifier", @@ -42,7 +42,7 @@ } }, "length": 2, - "pos": 18, + "pos": 17, "end": 22 } }, diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag4.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag4.json index 193c5c0eb01..e6ad0c0d0f3 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag4.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag4.json @@ -21,7 +21,7 @@ "typeParameters": { "0": { "kind": "TypeParameter", - "pos": 18, + "pos": 17, "end": 19, "name": { "kind": "Identifier", @@ -42,7 +42,7 @@ } }, "length": 2, - "pos": 18, + "pos": 17, "end": 22 } }, diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag5.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag5.json index fca64bcb430..f09001e97e2 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag5.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag5.json @@ -21,7 +21,7 @@ "typeParameters": { "0": { "kind": "TypeParameter", - "pos": 18, + "pos": 17, "end": 19, "name": { "kind": "Identifier", @@ -42,7 +42,7 @@ } }, "length": 2, - "pos": 18, + "pos": 17, "end": 23 } }, diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag6.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag6.json index 90158499b17..566a03b96ea 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag6.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.templateTag6.json @@ -21,7 +21,7 @@ "typeParameters": { "0": { "kind": "TypeParameter", - "pos": 18, + "pos": 17, "end": 19, "name": { "kind": "Identifier", @@ -42,7 +42,7 @@ } }, "length": 2, - "pos": 18, + "pos": 17, "end": 24 }, "comment": "Description of type parameters." diff --git a/tests/baselines/reference/enumTag.errors.txt b/tests/baselines/reference/enumTag.errors.txt index 0c2524a1dc1..4e995ba885a 100644 --- a/tests/baselines/reference/enumTag.errors.txt +++ b/tests/baselines/reference/enumTag.errors.txt @@ -15,7 +15,7 @@ tests/cases/conformance/jsdoc/a.js(37,16): error TS2339: Property 'UNKNOWN' does /** @type {number} */ OK_I_GUESS: 2 } - /** @enum {number} */ + /** @enum number */ const Second = { MISTAKE: "end", ~~~~~~~~~~~~~~ diff --git a/tests/baselines/reference/enumTag.symbols b/tests/baselines/reference/enumTag.symbols index ed0c11522f4..a54b9f4a3d8 100644 --- a/tests/baselines/reference/enumTag.symbols +++ b/tests/baselines/reference/enumTag.symbols @@ -19,7 +19,7 @@ const Target = { OK_I_GUESS: 2 >OK_I_GUESS : Symbol(OK_I_GUESS, Decl(a.js, 5, 15)) } -/** @enum {number} */ +/** @enum number */ const Second = { >Second : Symbol(Second, Decl(a.js, 10, 5)) diff --git a/tests/baselines/reference/enumTag.types b/tests/baselines/reference/enumTag.types index fa8e537b6f5..a8eddab88c7 100644 --- a/tests/baselines/reference/enumTag.types +++ b/tests/baselines/reference/enumTag.types @@ -25,7 +25,7 @@ const Target = { >OK_I_GUESS : number >2 : 2 } -/** @enum {number} */ +/** @enum number */ const Second = { >Second : { MISTAKE: string; OK: number; FINE: number; } >{ MISTAKE: "end", OK: 1, /** @type {number} */ FINE: 2,} : { MISTAKE: string; OK: number; FINE: number; } diff --git a/tests/baselines/reference/paramTagWrapping.errors.txt b/tests/baselines/reference/paramTagWrapping.errors.txt index 48100f0e746..3263443dbac 100644 --- a/tests/baselines/reference/paramTagWrapping.errors.txt +++ b/tests/baselines/reference/paramTagWrapping.errors.txt @@ -1,5 +1,5 @@ -tests/cases/conformance/jsdoc/bad.js(2,11): error TS1003: Identifier expected. -tests/cases/conformance/jsdoc/bad.js(2,11): error TS8024: JSDoc '@param' tag has name '', but there is no parameter with that name. +tests/cases/conformance/jsdoc/bad.js(2,10): error TS1003: Identifier expected. +tests/cases/conformance/jsdoc/bad.js(2,10): error TS8024: JSDoc '@param' tag has name '', but there is no parameter with that name. tests/cases/conformance/jsdoc/bad.js(5,4): error TS1003: Identifier expected. tests/cases/conformance/jsdoc/bad.js(5,4): error TS8024: JSDoc '@param' tag has name '', but there is no parameter with that name. tests/cases/conformance/jsdoc/bad.js(6,19): error TS1003: Identifier expected. @@ -27,9 +27,9 @@ tests/cases/conformance/jsdoc/bad.js(9,20): error TS7006: Parameter 'z' implicit ==== tests/cases/conformance/jsdoc/bad.js (9 errors) ==== /** * @param * - + !!! error TS1003: Identifier expected. - + !!! error TS8024: JSDoc '@param' tag has name '', but there is no parameter with that name. * {number} x Arg x. * @param {number} diff --git a/tests/cases/conformance/jsdoc/enumTag.ts b/tests/cases/conformance/jsdoc/enumTag.ts index bd740d879a1..a857d4eccce 100644 --- a/tests/cases/conformance/jsdoc/enumTag.ts +++ b/tests/cases/conformance/jsdoc/enumTag.ts @@ -11,7 +11,7 @@ const Target = { /** @type {number} */ OK_I_GUESS: 2 } -/** @enum {number} */ +/** @enum number */ const Second = { MISTAKE: "end", OK: 1, From ee7d0e21dad5ea53be7170e06a8636a19c0d8d6d Mon Sep 17 00:00:00 2001 From: Andy Date: Thu, 13 Sep 2018 15:49:42 -0700 Subject: [PATCH 66/83] getEditsForFileRename: Don't resolve to `a.js` when `a.ts` is moved (#27081) --- src/services/getEditsForFileRename.ts | 22 +++++++++++++------ ...tEditsForFileRename_notAffectedByJsFile.ts | 18 +++++++++++++++ 2 files changed, 33 insertions(+), 7 deletions(-) create mode 100644 tests/cases/fourslash/getEditsForFileRename_notAffectedByJsFile.ts diff --git a/src/services/getEditsForFileRename.ts b/src/services/getEditsForFileRename.ts index 07c3eb7ad22..a18fab4766f 100644 --- a/src/services/getEditsForFileRename.ts +++ b/src/services/getEditsForFileRename.ts @@ -196,15 +196,23 @@ namespace ts { } function getSourceFileToImportFromResolved(resolved: ResolvedModuleWithFailedLookupLocations | undefined, oldToNew: PathUpdater, host: LanguageServiceHost): ToImport | undefined { - return resolved && ( - (resolved.resolvedModule && getIfExists(resolved.resolvedModule.resolvedFileName)) || firstDefined(resolved.failedLookupLocations, getIfExists)); + // Search through all locations looking for a moved file, and only then test already existing files. + // This is because if `a.ts` is compiled to `a.js` and `a.ts` is moved, we don't want to resolve anything to `a.js`, but to `a.ts`'s new location. + return tryEach(tryGetNewFile) || tryEach(tryGetOldFile); - function getIfExists(oldLocation: string): ToImport | undefined { - const newLocation = oldToNew(oldLocation); + function tryEach(cb: (oldFileName: string) => ToImport | undefined): ToImport | undefined { + return resolved && ( + (resolved.resolvedModule && cb(resolved.resolvedModule.resolvedFileName)) || firstDefined(resolved.failedLookupLocations, cb)); + } - return host.fileExists!(oldLocation) || newLocation !== undefined && host.fileExists!(newLocation) // TODO: GH#18217 - ? newLocation !== undefined ? { newFileName: newLocation, updated: true } : { newFileName: oldLocation, updated: false } - : undefined; + function tryGetNewFile(oldFileName: string): ToImport | undefined { + const newFileName = oldToNew(oldFileName); + return newFileName !== undefined && host.fileExists!(newFileName) ? { newFileName, updated: true } : undefined; // TODO: GH#18217 + } + + function tryGetOldFile(oldFileName: string): ToImport | undefined { + const newFileName = oldToNew(oldFileName); + return host.fileExists!(oldFileName) ? newFileName !== undefined ? { newFileName, updated: true } : { newFileName: oldFileName, updated: false } : undefined; // TODO: GH#18217 } } diff --git a/tests/cases/fourslash/getEditsForFileRename_notAffectedByJsFile.ts b/tests/cases/fourslash/getEditsForFileRename_notAffectedByJsFile.ts new file mode 100644 index 00000000000..f1b1497f2ef --- /dev/null +++ b/tests/cases/fourslash/getEditsForFileRename_notAffectedByJsFile.ts @@ -0,0 +1,18 @@ +/// + +// @Filename: /a.ts +////export const x = 0; + +// @Filename: /a.js +////exports.x = 0; + +// @Filename: /b.ts +////import { x } from "./a"; + +verify.getEditsForFileRename({ + oldPath: "/a.ts", + newPath: "/a2.ts", + newFileContents: { + "/b.ts": 'import { x } from "./a2";', + }, +}); From 57a6dbd6fa7715e3176339743b30c1de7ed55d73 Mon Sep 17 00:00:00 2001 From: Benjamin Lichtman Date: Fri, 14 Sep 2018 08:50:18 -0700 Subject: [PATCH 67/83] Add clarifying comments --- src/services/codefixes/convertToAsyncFunction.ts | 3 ++- src/services/suggestionDiagnostics.ts | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/services/codefixes/convertToAsyncFunction.ts b/src/services/codefixes/convertToAsyncFunction.ts index ba230aa95e4..b12d4daf1c8 100644 --- a/src/services/codefixes/convertToAsyncFunction.ts +++ b/src/services/codefixes/convertToAsyncFunction.ts @@ -393,9 +393,10 @@ namespace ts.codefix { const shouldReturn = transformer.setOfExpressionsToReturn.get(getNodeId(parent).toString()); switch (func.kind) { case SyntaxKind.NullKeyword: - // do not produce a transformed statement for a null or undefined argument + // do not produce a transformed statement for a null argument break; case SyntaxKind.Identifier: + // identifier includes undefined if (!hasArgName) break; const synthCall = createCall(getSynthesizedDeepClone(func) as Identifier, /*typeArguments*/ undefined, [argName.identifier]); diff --git a/src/services/suggestionDiagnostics.ts b/src/services/suggestionDiagnostics.ts index 3df40c8d9df..66360948ea7 100644 --- a/src/services/suggestionDiagnostics.ts +++ b/src/services/suggestionDiagnostics.ts @@ -196,7 +196,7 @@ namespace ts { function isFixablePromiseArgument(arg: Expression): boolean { switch (arg.kind) { case SyntaxKind.NullKeyword: - case SyntaxKind.Identifier: + case SyntaxKind.Identifier: // identifier includes undefined case SyntaxKind.FunctionDeclaration: case SyntaxKind.FunctionExpression: case SyntaxKind.ArrowFunction: From 009dc0f1b9a624a535dd5f5f3ccc2b52536231f7 Mon Sep 17 00:00:00 2001 From: Andy Date: Fri, 14 Sep 2018 09:20:11 -0700 Subject: [PATCH 68/83] For completion in string literal union, don't include strings already in the union (#26755) --- src/services/completions.ts | 30 ++++++++++++------- .../fourslash/completionListForStringUnion.ts | 13 ++++---- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/src/services/completions.ts b/src/services/completions.ts index ff8c3147824..7744186126a 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -390,11 +390,12 @@ namespace ts.Completions { } type StringLiteralCompletion = { readonly kind: StringLiteralCompletionKind.Paths, readonly paths: ReadonlyArray } | StringLiteralCompletionsFromProperties | StringLiteralCompletionsFromTypes; function getStringLiteralCompletionEntries(sourceFile: SourceFile, node: StringLiteralLike, position: number, typeChecker: TypeChecker, compilerOptions: CompilerOptions, host: LanguageServiceHost): StringLiteralCompletion | undefined { - switch (node.parent.kind) { + const { parent } = node; + switch (parent.kind) { case SyntaxKind.LiteralType: - switch (node.parent.parent.kind) { + switch (parent.parent.kind) { case SyntaxKind.TypeReference: - return { kind: StringLiteralCompletionKind.Types, types: getStringLiteralTypes(typeChecker.getTypeArgumentConstraint(node.parent as LiteralTypeNode)), isNewIdentifier: false }; + return { kind: StringLiteralCompletionKind.Types, types: getStringLiteralTypes(typeChecker.getTypeArgumentConstraint(parent as LiteralTypeNode)), isNewIdentifier: false }; case SyntaxKind.IndexedAccessType: // Get all apparent property names // i.e. interface Foo { @@ -402,17 +403,21 @@ namespace ts.Completions { // bar: string; // } // let x: Foo["/*completion position*/"] - return stringLiteralCompletionsFromProperties(typeChecker.getTypeFromTypeNode((node.parent.parent as IndexedAccessTypeNode).objectType)); + return stringLiteralCompletionsFromProperties(typeChecker.getTypeFromTypeNode((parent.parent as IndexedAccessTypeNode).objectType)); case SyntaxKind.ImportType: return { kind: StringLiteralCompletionKind.Paths, paths: PathCompletions.getStringLiteralCompletionsFromModuleNames(sourceFile, node, compilerOptions, host, typeChecker) }; - case SyntaxKind.UnionType: - return isTypeReferenceNode(node.parent.parent.parent) ? { kind: StringLiteralCompletionKind.Types, types: getStringLiteralTypes(typeChecker.getTypeArgumentConstraint(node.parent.parent as UnionTypeNode)), isNewIdentifier: false } : undefined; + case SyntaxKind.UnionType: { + if (!isTypeReferenceNode(parent.parent.parent)) return undefined; + const alreadyUsedTypes = getAlreadyUsedTypesInStringLiteralUnion(parent.parent as UnionTypeNode, parent as LiteralTypeNode); + const types = getStringLiteralTypes(typeChecker.getTypeArgumentConstraint(parent.parent as UnionTypeNode)).filter(t => !contains(alreadyUsedTypes, t.value)); + return { kind: StringLiteralCompletionKind.Types, types, isNewIdentifier: false }; + } default: return undefined; } case SyntaxKind.PropertyAssignment: - if (isObjectLiteralExpression(node.parent.parent) && (node.parent).name === node) { + if (isObjectLiteralExpression(parent.parent) && (parent).name === node) { // Get quoted name of properties of the object literal expression // i.e. interface ConfigFiles { // 'jspm:dev': string @@ -425,12 +430,12 @@ namespace ts.Completions { // foo({ // '/*completion position*/' // }); - return stringLiteralCompletionsFromProperties(typeChecker.getContextualType(node.parent.parent)); + return stringLiteralCompletionsFromProperties(typeChecker.getContextualType(parent.parent)); } return fromContextualType(); case SyntaxKind.ElementAccessExpression: { - const { expression, argumentExpression } = node.parent as ElementAccessExpression; + const { expression, argumentExpression } = parent as ElementAccessExpression; if (node === argumentExpression) { // Get all names of properties on the expression // i.e. interface A { @@ -445,7 +450,7 @@ namespace ts.Completions { case SyntaxKind.CallExpression: case SyntaxKind.NewExpression: - if (!isRequireCall(node.parent, /*checkArgumentIsStringLiteralLike*/ false) && !isImportCall(node.parent)) { + if (!isRequireCall(parent, /*checkArgumentIsStringLiteralLike*/ false) && !isImportCall(parent)) { const argumentInfo = SignatureHelp.getArgumentInfoForCompletions(node, position, sourceFile); // Get string literal completions from specialized signatures of the target // i.e. declare function f(a: 'A'); @@ -476,6 +481,11 @@ namespace ts.Completions { } } + function getAlreadyUsedTypesInStringLiteralUnion(union: UnionTypeNode, current: LiteralTypeNode): ReadonlyArray { + return mapDefined(union.types, type => + type !== current && isLiteralTypeNode(type) && isStringLiteral(type.literal) ? type.literal.text : undefined); + } + function getStringLiteralCompletionsFromSignature(argumentInfo: SignatureHelp.ArgumentInfoForCompletions, checker: TypeChecker): StringLiteralCompletionsFromTypes { let isNewIdentifier = false; diff --git a/tests/cases/fourslash/completionListForStringUnion.ts b/tests/cases/fourslash/completionListForStringUnion.ts index 14e5979efbd..98755ea1e41 100644 --- a/tests/cases/fourslash/completionListForStringUnion.ts +++ b/tests/cases/fourslash/completionListForStringUnion.ts @@ -1,12 +1,11 @@ /// -//// type A = 'fooooo' | 'barrrrr'; +//// type A = 'foo' | 'bar' | 'baz'; //// type B = {}; -//// type C = B<'fooooo' | '/**/'> +//// type C = B<'foo' | '/**/'> - -goTo.marker(); -verify.completionListContains("fooooo"); -verify.completionListContains("barrrrr"); +verify.completions({ marker: "", exact: ["bar", "baz"] }); edit.insert("b"); -verify.completionListContains("barrrrr"); +verify.completions({ exact: ["bar", "baz"] }); +edit.insert("ar"); +verify.completions({ exact: ["bar", "baz"] }); From 95c1570c4b1156333980b35745722aa3ef85c4fd Mon Sep 17 00:00:00 2001 From: Andy Date: Fri, 14 Sep 2018 09:20:54 -0700 Subject: [PATCH 69/83] Fix bug: VariableDeclaration may have SemanticMeaning.All if an `@enum` in JS (#27085) --- src/services/utilities.ts | 4 +++- tests/cases/fourslash/findAllRefs_jsEnum.ts | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 tests/cases/fourslash/findAllRefs_jsEnum.ts diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 40a9936b605..25678ad72a6 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -23,8 +23,10 @@ namespace ts { export function getMeaningFromDeclaration(node: Node): SemanticMeaning { switch (node.kind) { - case SyntaxKind.Parameter: case SyntaxKind.VariableDeclaration: + return isInJSFile(node) && getJSDocEnumTag(node) ? SemanticMeaning.All : SemanticMeaning.Value; + + case SyntaxKind.Parameter: case SyntaxKind.BindingElement: case SyntaxKind.PropertyDeclaration: case SyntaxKind.PropertySignature: diff --git a/tests/cases/fourslash/findAllRefs_jsEnum.ts b/tests/cases/fourslash/findAllRefs_jsEnum.ts new file mode 100644 index 00000000000..c77b24256bf --- /dev/null +++ b/tests/cases/fourslash/findAllRefs_jsEnum.ts @@ -0,0 +1,16 @@ +/// + +// @allowJs: true + +// @Filename: /a.js +/////** @enum {string} */ +////const [|{| "isWriteAccess": true, "isDefinition": true |}E|] = { A: "" }; +////[|E|]["A"]; +/////** @type {[|E|]} */ +////const e = [|E|].A; + +verify.singleReferenceGroup( +`enum E +const E: { + A: string; +}`); From 98055ad54089faae5ed7f00747dfb985679d8b42 Mon Sep 17 00:00:00 2001 From: Benjamin Lichtman Date: Fri, 14 Sep 2018 09:46:58 -0700 Subject: [PATCH 70/83] Use separate map with smaller scope to track renames --- .../codefixes/convertToAsyncFunction.ts | 50 +++++++++++++------ 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/src/services/codefixes/convertToAsyncFunction.ts b/src/services/codefixes/convertToAsyncFunction.ts index bceee6811bb..94b311a1ea6 100644 --- a/src/services/codefixes/convertToAsyncFunction.ts +++ b/src/services/codefixes/convertToAsyncFunction.ts @@ -25,16 +25,15 @@ namespace ts.codefix { numberOfAssignmentsOriginal: number; } - interface SymbolAndIdentifierAndOriginalName { + interface SymbolAndIdentifier { identifier: Identifier; symbol: Symbol; - originalName: string; } interface Transformer { checker: TypeChecker; synthNamesMap: Map; // keys are the symbol id of the identifier - allVarNames: SymbolAndIdentifierAndOriginalName[]; + allVarNames: SymbolAndIdentifier[]; setOfExpressionsToReturn: Map; // keys are the node ids of the expressions constIdentifiers: Identifier[]; originalTypeMap: Map; // keys are the node id of the identifier @@ -61,7 +60,7 @@ namespace ts.codefix { const synthNamesMap: Map = createMap(); const originalTypeMap: Map = createMap(); - const allVarNames: SymbolAndIdentifierAndOriginalName[] = []; + const allVarNames: SymbolAndIdentifier[] = []; const isInJSFile = isInJavaScriptFile(functionToConvert); const setOfExpressionsToReturn = getAllPromiseExpressionsToReturn(functionToConvert, checker); const functionToConvertRenamed: FunctionLikeDeclaration = renameCollidingVarNames(functionToConvert, checker, synthNamesMap, context, setOfExpressionsToReturn, originalTypeMap, allVarNames); @@ -158,9 +157,10 @@ namespace ts.codefix { This function collects all existing identifier names and names of identifiers that will be created in the refactor. It then checks for any collisions and renames them through getSynthesizedDeepClone */ - function renameCollidingVarNames(nodeToRename: FunctionLikeDeclaration, checker: TypeChecker, synthNamesMap: Map, context: CodeFixContextBase, setOfAllExpressionsToReturn: Map, originalType: Map, allVarNames: SymbolAndIdentifierAndOriginalName[]): FunctionLikeDeclaration { + function renameCollidingVarNames(nodeToRename: FunctionLikeDeclaration, checker: TypeChecker, synthNamesMap: Map, context: CodeFixContextBase, setOfAllExpressionsToReturn: Map, originalType: Map, allVarNames: SymbolAndIdentifier[]): FunctionLikeDeclaration { const identsToRenameMap: Map = createMap(); // key is the symbol id + const collidingSymbolMap: Map = createMap(); forEachChild(nodeToRename, function visit(node: Node) { if (!isIdentifier(node)) { forEachChild(node, visit); @@ -180,27 +180,31 @@ namespace ts.codefix { if (lastCallSignature && lastCallSignature.parameters.length && !synthNamesMap.has(symbolIdString)) { const firstParameter = lastCallSignature.parameters[0]; const ident = isParameter(firstParameter.valueDeclaration) && tryCast(firstParameter.valueDeclaration.name, isIdentifier) || createOptimisticUniqueName("result"); - const synthName = getNewNameIfConflict(ident, allVarNames); + const synthName = getNewNameIfConflict(ident, collidingSymbolMap); synthNamesMap.set(symbolIdString, synthName); - allVarNames.push({ identifier: synthName.identifier, symbol, originalName: ident.text }); + allVarNames.push({ identifier: synthName.identifier, symbol }); + addNameToFrequencyMap(collidingSymbolMap, ident.text, symbol); } // we only care about identifiers that are parameters and declarations (don't care about other uses) else if (node.parent && (isParameter(node.parent) || isVariableDeclaration(node.parent))) { const originalName = node.text; + const collidingSymbols = collidingSymbolMap.get(originalName); // if the identifier name conflicts with a different identifier that we've already seen - if (allVarNames.some(ident => ident.originalName === node.text && ident.symbol !== symbol)) { - const newName = getNewNameIfConflict(node, allVarNames); + if (collidingSymbols && collidingSymbols.some(prevSymbol => prevSymbol !== symbol)) { + const newName = getNewNameIfConflict(node, collidingSymbolMap); identsToRenameMap.set(symbolIdString, newName.identifier); synthNamesMap.set(symbolIdString, newName); - allVarNames.push({ identifier: newName.identifier, symbol, originalName }); + allVarNames.push({ identifier: newName.identifier, symbol }); + addNameToFrequencyMap(collidingSymbolMap, originalName, symbol); } else { const identifier = getSynthesizedDeepClone(node); identsToRenameMap.set(symbolIdString, identifier); synthNamesMap.set(symbolIdString, { identifier, types: [], numberOfAssignmentsOriginal: allVarNames.filter(elem => elem.identifier.text === node.text).length/*, numberOfAssignmentsSynthesized: 0*/ }); if ((isParameter(node.parent) && isExpressionOrCallOnTypePromise(node.parent.parent)) || isVariableDeclaration(node.parent)) { - allVarNames.push({ identifier, symbol, originalName }); + allVarNames.push({ identifier, symbol }); + addNameToFrequencyMap(collidingSymbolMap, originalName, symbol); } } } @@ -243,8 +247,17 @@ namespace ts.codefix { } - function getNewNameIfConflict(name: Identifier, allVarNames: SymbolAndIdentifierAndOriginalName[]): SynthIdentifier { - const numVarsSameName = allVarNames.filter(elem => elem.originalName === name.text).length; + function addNameToFrequencyMap(renamedVarNameFrequencyMap: Map, originalName: string, symbol: Symbol) { + if (renamedVarNameFrequencyMap.has(originalName)) { + renamedVarNameFrequencyMap.get(originalName)!.push(symbol); + } + else { + renamedVarNameFrequencyMap.set(originalName, [symbol]); + } + } + + function getNewNameIfConflict(name: Identifier, originalNames: Map): SynthIdentifier { + const numVarsSameName = (originalNames.get(name.text) || []).length; const numberOfAssignmentsOriginal = 0; const identifier = numVarsSameName === 0 ? name : createIdentifier(name.text + "_" + numVarsSameName); return { identifier, types: [], numberOfAssignmentsOriginal }; @@ -289,13 +302,14 @@ namespace ts.codefix { prevArgName.numberOfAssignmentsOriginal = 2; // Try block and catch block transformer.synthNamesMap.forEach((val, key) => { if (val.identifier.text === prevArgName.identifier.text) { - transformer.synthNamesMap.set(key, getNewNameIfConflict(prevArgName.identifier, transformer.allVarNames)); + const newSynthName = createUniqueSynthName(prevArgName); + transformer.synthNamesMap.set(key, newSynthName); } }); // update the constIdentifiers list if (transformer.constIdentifiers.some(elem => elem.text === prevArgName.identifier.text)) { - transformer.constIdentifiers.push(getNewNameIfConflict(prevArgName.identifier, transformer.allVarNames).identifier); + transformer.constIdentifiers.push(createUniqueSynthName(prevArgName).identifier); } } @@ -321,6 +335,12 @@ namespace ts.codefix { return varDeclList ? [varDeclList, tryStatement] : [tryStatement]; } + function createUniqueSynthName(prevArgName: SynthIdentifier) { + const renamedPrevArg = createOptimisticUniqueName(prevArgName.identifier.text); + const newSynthName = { identifier: renamedPrevArg, types: [], numberOfAssignmentsOriginal: 0 }; + return newSynthName; + } + function transformThen(node: CallExpression, transformer: Transformer, outermostParent: CallExpression, prevArgName?: SynthIdentifier): Statement[] { const [res, rej] = node.arguments; From 513a16264b42849fd0160f28763a533ad15a1f26 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Fri, 14 Sep 2018 10:02:42 -0700 Subject: [PATCH 71/83] Make parseCommandLineWorker non generic --- src/compiler/commandLineParser.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 9391fac72ed..05113f812db 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -912,12 +912,12 @@ namespace ts { /** Tuple with error messages for 'unknown compiler option', 'option requires type' */ type ParseCommandLineWorkerDiagnostics = [DiagnosticMessage, DiagnosticMessage]; - function parseCommandLineWorker( + function parseCommandLineWorker( getOptionNameMap: () => OptionNameMap, [unknownOptionDiagnostic, optionTypeMismatchDiagnostic]: ParseCommandLineWorkerDiagnostics, commandLine: ReadonlyArray, readFile?: (path: string) => string | undefined) { - const options = {} as T; + const options = {} as OptionsBase; const fileNames: string[] = []; const errors: Diagnostic[] = []; @@ -1061,10 +1061,11 @@ namespace ts { export function parseBuildCommand(args: string[]): ParsedBuildCommand { let buildOptionNameMap: OptionNameMap | undefined; const returnBuildOptionNameMap = () => (buildOptionNameMap || (buildOptionNameMap = createOptionNameMap(buildOpts))); - const { options: buildOptions, fileNames: projects, errors } = parseCommandLineWorker(returnBuildOptionNameMap, [ + const { options, fileNames: projects, errors } = parseCommandLineWorker(returnBuildOptionNameMap, [ Diagnostics.Unknown_build_option_0, Diagnostics.Build_option_0_requires_a_value_of_type_1 ], args); + const buildOptions = options as BuildOptions; if (projects.length === 0) { // tsc -b invoked with no extra arguments; act as if invoked with "tsc -b ." From 20f671ede2d9f2eb4cd4088e4b36aeed9bd0472f Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Fri, 14 Sep 2018 11:07:22 -0700 Subject: [PATCH 72/83] PR feedback --- src/compiler/program.ts | 4 +++- src/compiler/utilities.ts | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 970689f93c3..d15b5935224 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -1017,13 +1017,14 @@ namespace ts { // If array of references is changed, we cant resue old program const oldProjectReferences = oldProgram.getProjectReferences(); - if (!arrayIsEqualTo(oldProjectReferences!, projectReferences, projectReferencesIsEqualTo)) { + if (!arrayIsEqualTo(oldProjectReferences!, projectReferences, projectReferenceIsEqualTo)) { return oldProgram.structureIsReused = StructureIsReused.Not; } // Check the json files for the project references const oldRefs = oldProgram.getResolvedProjectReferences(); if (projectReferences) { + // Resolved project referenced should be array if projectReferences provided are array Debug.assert(!!oldRefs); for (let i = 0; i < projectReferences.length; i++) { const oldRef = oldRefs![i]; @@ -1043,6 +1044,7 @@ namespace ts { } } else { + // Resolved project referenced should be undefined if projectReferences is undefined Debug.assert(!oldRefs); } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 51315dbf455..907e921b91f 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -249,7 +249,7 @@ namespace ts { sourceFile.resolvedTypeReferenceDirectiveNames.set(typeReferenceDirectiveName, resolvedTypeReferenceDirective); } - export function projectReferencesIsEqualTo(oldRef: ProjectReference, newRef: ProjectReference) { + export function projectReferenceIsEqualTo(oldRef: ProjectReference, newRef: ProjectReference) { return oldRef.path === newRef.path && !oldRef.prepend === !newRef.prepend && !oldRef.circular === !newRef.circular; From c63d58148a8abaf21f59a4f2bdf65ffa2372e635 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Fri, 14 Sep 2018 12:44:02 -0700 Subject: [PATCH 73/83] Fix the usage of createProgram in tsc --- src/tsc/tsc.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tsc/tsc.ts b/src/tsc/tsc.ts index 29cac24fdd0..ec2d029e60a 100644 --- a/src/tsc/tsc.ts +++ b/src/tsc/tsc.ts @@ -222,12 +222,12 @@ namespace ts { function updateWatchCompilationHost(watchCompilerHost: WatchCompilerHost) { const compileUsingBuilder = watchCompilerHost.createProgram; - watchCompilerHost.createProgram = (rootNames, options, host, oldProgram, configFileParsingDiagnostics) => { + watchCompilerHost.createProgram = (rootNames, options, host, oldProgram, configFileParsingDiagnostics, projectReferences) => { Debug.assert(rootNames !== undefined || (options === undefined && !!oldProgram)); if (options !== undefined) { enableStatistics(options); } - return compileUsingBuilder(rootNames, options, host, oldProgram, configFileParsingDiagnostics); + return compileUsingBuilder(rootNames, options, host, oldProgram, configFileParsingDiagnostics, projectReferences); }; const emitFilesUsingBuilder = watchCompilerHost.afterProgramCreate!; // TODO: GH#18217 watchCompilerHost.afterProgramCreate = builderProgram => { From d6ffdde059e92173d7dd4c05258198dce71c2936 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Fri, 14 Sep 2018 12:57:40 -0700 Subject: [PATCH 74/83] Revert the API change to resolveProjectReferencePath introduced in #27062 --- src/compiler/program.ts | 13 ++++++++++--- tests/baselines/reference/api/tsserverlibrary.d.ts | 4 ++++ tests/baselines/reference/api/typescript.d.ts | 4 ++++ 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 1ba3d3233cc..a9271d6fcbb 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -2820,13 +2820,20 @@ namespace ts { }; } + // For backward compatibility + /** @deprecated */ export interface ResolveProjectReferencePathHost { + fileExists(fileName: string): boolean; + } + /** * Returns the target config filename of a project reference. * Note: The file might not exist. */ - // TODO: Does this need to be exposed - export function resolveProjectReferencePath(ref: ProjectReference): ResolvedConfigFileName { - return resolveConfigFileProjectName(ref.path); + export function resolveProjectReferencePath(ref: ProjectReference): ResolvedConfigFileName; + /** @deprecated */ export function resolveProjectReferencePath(host: ResolveProjectReferencePathHost, ref: ProjectReference): ResolvedConfigFileName; + export function resolveProjectReferencePath(hostOrRef: ResolveProjectReferencePathHost | ProjectReference, ref?: ProjectReference): ResolvedConfigFileName { + const passedInRef = ref ? ref : hostOrRef as ProjectReference; + return resolveConfigFileProjectName(passedInRef.path); } /* @internal */ diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 388525096e1..d02e761f440 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -4182,11 +4182,15 @@ declare namespace ts { * @returns A 'Program' object. */ function createProgram(rootNames: ReadonlyArray, options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: ReadonlyArray): Program; + /** @deprecated */ interface ResolveProjectReferencePathHost { + fileExists(fileName: string): boolean; + } /** * Returns the target config filename of a project reference. * Note: The file might not exist. */ function resolveProjectReferencePath(ref: ProjectReference): ResolvedConfigFileName; + /** @deprecated */ function resolveProjectReferencePath(host: ResolveProjectReferencePathHost, ref: ProjectReference): ResolvedConfigFileName; } declare namespace ts { interface EmitOutput { diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 2a0dfb89b85..e6c104d3c5a 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -4182,11 +4182,15 @@ declare namespace ts { * @returns A 'Program' object. */ function createProgram(rootNames: ReadonlyArray, options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: ReadonlyArray): Program; + /** @deprecated */ interface ResolveProjectReferencePathHost { + fileExists(fileName: string): boolean; + } /** * Returns the target config filename of a project reference. * Note: The file might not exist. */ function resolveProjectReferencePath(ref: ProjectReference): ResolvedConfigFileName; + /** @deprecated */ function resolveProjectReferencePath(host: ResolveProjectReferencePathHost, ref: ProjectReference): ResolvedConfigFileName; } declare namespace ts { interface EmitOutput { From 4eb59a2d77acde13d808ec302f6a28f4fa49aa01 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Fri, 14 Sep 2018 14:18:47 -0700 Subject: [PATCH 75/83] Fixing react defaultize+generic default props interaction (#27088) * Add repro for fixed issue * Fix JSX propagating flags and contextual types * Accept slightly changed baselines * Add modern react.d.ts and regression test --- src/compiler/checker.ts | 14 +- ...xGenericTagHasCorrectInferences.errors.txt | 12 +- ...ypeContextualTypeSimplificationsSuceeds.js | 25 + ...ntextualTypeSimplificationsSuceeds.symbols | 68 + ...ContextualTypeSimplificationsSuceeds.types | 53 + ...xChildrenGenericContextualTypes.errors.txt | 4 +- .../jsxChildrenGenericContextualTypes.types | 6 +- ...actDefaultPropsInferenceSuccess.errors.txt | 67 + .../reactDefaultPropsInferenceSuccess.js | 112 + .../reactDefaultPropsInferenceSuccess.symbols | 131 + .../reactDefaultPropsInferenceSuccess.types | 146 + ...ypeContextualTypeSimplificationsSuceeds.ts | 16 + .../reactDefaultPropsInferenceSuccess.tsx | 54 + tests/lib/react16.d.ts | 2569 +++++++++++++++++ 14 files changed, 3261 insertions(+), 16 deletions(-) create mode 100644 tests/baselines/reference/conditionalTypeContextualTypeSimplificationsSuceeds.js create mode 100644 tests/baselines/reference/conditionalTypeContextualTypeSimplificationsSuceeds.symbols create mode 100644 tests/baselines/reference/conditionalTypeContextualTypeSimplificationsSuceeds.types create mode 100644 tests/baselines/reference/reactDefaultPropsInferenceSuccess.errors.txt create mode 100644 tests/baselines/reference/reactDefaultPropsInferenceSuccess.js create mode 100644 tests/baselines/reference/reactDefaultPropsInferenceSuccess.symbols create mode 100644 tests/baselines/reference/reactDefaultPropsInferenceSuccess.types create mode 100644 tests/cases/compiler/conditionalTypeContextualTypeSimplificationsSuceeds.ts create mode 100644 tests/cases/compiler/reactDefaultPropsInferenceSuccess.tsx create mode 100644 tests/lib/react16.d.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 3e9a3300726..c4cd1aa6051 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -17361,12 +17361,14 @@ namespace ts { let hasSpreadAnyType = false; let typeToIntersect: Type | undefined; let explicitlySpecifyChildrenAttribute = false; + let propagatingFlags: TypeFlags = 0; const jsxChildrenPropertyName = getJsxElementChildrenPropertyName(getJsxNamespaceAt(openingLikeElement)); for (const attributeDecl of attributes.properties) { const member = attributeDecl.symbol; if (isJsxAttribute(attributeDecl)) { const exprType = checkJsxAttribute(attributeDecl, checkMode); + propagatingFlags |= (exprType.flags & TypeFlags.PropagatingFlags); const attributeSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Transient | member.flags, member.escapedName); attributeSymbol.declarations = member.declarations; @@ -17384,7 +17386,7 @@ namespace ts { else { Debug.assert(attributeDecl.kind === SyntaxKind.JsxSpreadAttribute); if (attributesTable.size > 0) { - spread = getSpreadType(spread, createJsxAttributesType(), attributes.symbol, /*typeFlags*/ 0, ObjectFlags.JsxAttributes); + spread = getSpreadType(spread, createJsxAttributesType(), attributes.symbol, propagatingFlags, ObjectFlags.JsxAttributes); attributesTable = createSymbolTable(); } const exprType = checkExpressionCached(attributeDecl.expression, checkMode); @@ -17392,7 +17394,7 @@ namespace ts { hasSpreadAnyType = true; } if (isValidSpreadType(exprType)) { - spread = getSpreadType(spread, exprType, openingLikeElement.symbol, /*typeFlags*/ 0, ObjectFlags.JsxAttributes); + spread = getSpreadType(spread, exprType, openingLikeElement.symbol, propagatingFlags, ObjectFlags.JsxAttributes); } else { typeToIntersect = typeToIntersect ? getIntersectionType([typeToIntersect, exprType]) : exprType; @@ -17402,7 +17404,7 @@ namespace ts { if (!hasSpreadAnyType) { if (attributesTable.size > 0) { - spread = getSpreadType(spread, createJsxAttributesType(), attributes.symbol, /*typeFlags*/ 0, ObjectFlags.JsxAttributes); + spread = getSpreadType(spread, createJsxAttributesType(), attributes.symbol, propagatingFlags, ObjectFlags.JsxAttributes); } } @@ -17428,7 +17430,7 @@ namespace ts { const childPropMap = createSymbolTable(); childPropMap.set(jsxChildrenPropertyName, childrenPropSymbol); spread = getSpreadType(spread, createAnonymousType(attributes.symbol, childPropMap, emptyArray, emptyArray, /*stringIndexInfo*/ undefined, /*numberIndexInfo*/ undefined), - attributes.symbol, /*typeFlags*/ 0, ObjectFlags.JsxAttributes); + attributes.symbol, propagatingFlags, ObjectFlags.JsxAttributes); } } @@ -17448,7 +17450,7 @@ namespace ts { */ function createJsxAttributesType() { const result = createAnonymousType(attributes.symbol, attributesTable, emptyArray, emptyArray, /*stringIndexInfo*/ undefined, /*numberIndexInfo*/ undefined); - result.flags |= TypeFlags.ContainsObjectLiteral; + result.flags |= (propagatingFlags |= TypeFlags.ContainsObjectLiteral); result.objectFlags |= ObjectFlags.ObjectLiteral | ObjectFlags.JsxAttributes; return result; } @@ -21957,7 +21959,7 @@ namespace ts { } function getContextNode(node: Expression): Node { - if (node.kind === SyntaxKind.JsxAttributes) { + if (node.kind === SyntaxKind.JsxAttributes && !isJsxSelfClosingElement(node.parent)) { return node.parent.parent; // Needs to be the root JsxElement, so it encompasses the attributes _and_ the children (which are essentially part of the attributes) } return node; diff --git a/tests/baselines/reference/checkJsxGenericTagHasCorrectInferences.errors.txt b/tests/baselines/reference/checkJsxGenericTagHasCorrectInferences.errors.txt index 6b81ccd77e1..36ebc70b76c 100644 --- a/tests/baselines/reference/checkJsxGenericTagHasCorrectInferences.errors.txt +++ b/tests/baselines/reference/checkJsxGenericTagHasCorrectInferences.errors.txt @@ -1,5 +1,6 @@ -tests/cases/conformance/jsx/file.tsx(13,54): error TS2322: Type '(a: { x: string; }) => string' is not assignable to type '(cur: { x: string; }) => { x: string; }'. - Type 'string' is not assignable to type '{ x: string; }'. +tests/cases/conformance/jsx/file.tsx(13,54): error TS2322: Type '(a: { x: string; }) => string' is not assignable to type '((a: { x: string; }) => string) & ((cur: { x: string; }) => { x: string; })'. + Type '(a: { x: string; }) => string' is not assignable to type '(cur: { x: string; }) => { x: string; }'. + Type 'string' is not assignable to type '{ x: string; }'. ==== tests/cases/conformance/jsx/file.tsx (1 errors) ==== @@ -17,6 +18,7 @@ tests/cases/conformance/jsx/file.tsx(13,54): error TS2322: Type '(a: { x: string let c = ({ x: a.x })} />; // No Error let d = a.x} />; // Error - `string` is not assignable to `{x: string}` ~~~~~~~~~~ -!!! error TS2322: Type '(a: { x: string; }) => string' is not assignable to type '(cur: { x: string; }) => { x: string; }'. -!!! error TS2322: Type 'string' is not assignable to type '{ x: string; }'. -!!! related TS6500 tests/cases/conformance/jsx/file.tsx:13:54: The expected type comes from property 'nextValues' which is declared here on type 'IntrinsicAttributes & IntrinsicClassAttributes> & { initialValues: { x: string; }; nextValues: {}; } & BaseProps<{ x: string; }> & { children?: ReactNode; }' \ No newline at end of file +!!! error TS2322: Type '(a: { x: string; }) => string' is not assignable to type '((a: { x: string; }) => string) & ((cur: { x: string; }) => { x: string; })'. +!!! error TS2322: Type '(a: { x: string; }) => string' is not assignable to type '(cur: { x: string; }) => { x: string; }'. +!!! error TS2322: Type 'string' is not assignable to type '{ x: string; }'. +!!! related TS6500 tests/cases/conformance/jsx/file.tsx:13:54: The expected type comes from property 'nextValues' which is declared here on type 'IntrinsicAttributes & IntrinsicClassAttributes string; }, { x: string; }>> & { initialValues: { x: string; }; nextValues: (a: { x: string; }) => string; } & BaseProps<{ x: string; }> & { children?: ReactNode; }' \ No newline at end of file diff --git a/tests/baselines/reference/conditionalTypeContextualTypeSimplificationsSuceeds.js b/tests/baselines/reference/conditionalTypeContextualTypeSimplificationsSuceeds.js new file mode 100644 index 00000000000..7d140a32b42 --- /dev/null +++ b/tests/baselines/reference/conditionalTypeContextualTypeSimplificationsSuceeds.js @@ -0,0 +1,25 @@ +//// [conditionalTypeContextualTypeSimplificationsSuceeds.ts] +// repro from https://github.com/Microsoft/TypeScript/issues/26395 +interface Props { + when: (value: string) => boolean; +} + +function bad

( + attrs: string extends keyof P ? { [K in keyof P]: P[K] } : { [K in keyof P]: P[K] }) { } +function good1

( + attrs: string extends keyof P ? P : { [K in keyof P]: P[K] }) { } +function good2

( + attrs: { [K in keyof P]: P[K] }) { } + +bad({ when: value => false }); +good1({ when: value => false }); +good2({ when: value => false }); + +//// [conditionalTypeContextualTypeSimplificationsSuceeds.js] +"use strict"; +function bad(attrs) { } +function good1(attrs) { } +function good2(attrs) { } +bad({ when: function (value) { return false; } }); +good1({ when: function (value) { return false; } }); +good2({ when: function (value) { return false; } }); diff --git a/tests/baselines/reference/conditionalTypeContextualTypeSimplificationsSuceeds.symbols b/tests/baselines/reference/conditionalTypeContextualTypeSimplificationsSuceeds.symbols new file mode 100644 index 00000000000..e9620b38656 --- /dev/null +++ b/tests/baselines/reference/conditionalTypeContextualTypeSimplificationsSuceeds.symbols @@ -0,0 +1,68 @@ +=== tests/cases/compiler/conditionalTypeContextualTypeSimplificationsSuceeds.ts === +// repro from https://github.com/Microsoft/TypeScript/issues/26395 +interface Props { +>Props : Symbol(Props, Decl(conditionalTypeContextualTypeSimplificationsSuceeds.ts, 0, 0)) + + when: (value: string) => boolean; +>when : Symbol(Props.when, Decl(conditionalTypeContextualTypeSimplificationsSuceeds.ts, 1, 17)) +>value : Symbol(value, Decl(conditionalTypeContextualTypeSimplificationsSuceeds.ts, 2, 11)) +} + +function bad

( +>bad : Symbol(bad, Decl(conditionalTypeContextualTypeSimplificationsSuceeds.ts, 3, 1)) +>P : Symbol(P, Decl(conditionalTypeContextualTypeSimplificationsSuceeds.ts, 5, 13)) +>Props : Symbol(Props, Decl(conditionalTypeContextualTypeSimplificationsSuceeds.ts, 0, 0)) + + attrs: string extends keyof P ? { [K in keyof P]: P[K] } : { [K in keyof P]: P[K] }) { } +>attrs : Symbol(attrs, Decl(conditionalTypeContextualTypeSimplificationsSuceeds.ts, 5, 30)) +>P : Symbol(P, Decl(conditionalTypeContextualTypeSimplificationsSuceeds.ts, 5, 13)) +>K : Symbol(K, Decl(conditionalTypeContextualTypeSimplificationsSuceeds.ts, 6, 39)) +>P : Symbol(P, Decl(conditionalTypeContextualTypeSimplificationsSuceeds.ts, 5, 13)) +>P : Symbol(P, Decl(conditionalTypeContextualTypeSimplificationsSuceeds.ts, 5, 13)) +>K : Symbol(K, Decl(conditionalTypeContextualTypeSimplificationsSuceeds.ts, 6, 39)) +>K : Symbol(K, Decl(conditionalTypeContextualTypeSimplificationsSuceeds.ts, 6, 66)) +>P : Symbol(P, Decl(conditionalTypeContextualTypeSimplificationsSuceeds.ts, 5, 13)) +>P : Symbol(P, Decl(conditionalTypeContextualTypeSimplificationsSuceeds.ts, 5, 13)) +>K : Symbol(K, Decl(conditionalTypeContextualTypeSimplificationsSuceeds.ts, 6, 66)) + +function good1

( +>good1 : Symbol(good1, Decl(conditionalTypeContextualTypeSimplificationsSuceeds.ts, 6, 92)) +>P : Symbol(P, Decl(conditionalTypeContextualTypeSimplificationsSuceeds.ts, 7, 15)) +>Props : Symbol(Props, Decl(conditionalTypeContextualTypeSimplificationsSuceeds.ts, 0, 0)) + + attrs: string extends keyof P ? P : { [K in keyof P]: P[K] }) { } +>attrs : Symbol(attrs, Decl(conditionalTypeContextualTypeSimplificationsSuceeds.ts, 7, 32)) +>P : Symbol(P, Decl(conditionalTypeContextualTypeSimplificationsSuceeds.ts, 7, 15)) +>P : Symbol(P, Decl(conditionalTypeContextualTypeSimplificationsSuceeds.ts, 7, 15)) +>K : Symbol(K, Decl(conditionalTypeContextualTypeSimplificationsSuceeds.ts, 8, 43)) +>P : Symbol(P, Decl(conditionalTypeContextualTypeSimplificationsSuceeds.ts, 7, 15)) +>P : Symbol(P, Decl(conditionalTypeContextualTypeSimplificationsSuceeds.ts, 7, 15)) +>K : Symbol(K, Decl(conditionalTypeContextualTypeSimplificationsSuceeds.ts, 8, 43)) + +function good2

( +>good2 : Symbol(good2, Decl(conditionalTypeContextualTypeSimplificationsSuceeds.ts, 8, 69)) +>P : Symbol(P, Decl(conditionalTypeContextualTypeSimplificationsSuceeds.ts, 9, 15)) +>Props : Symbol(Props, Decl(conditionalTypeContextualTypeSimplificationsSuceeds.ts, 0, 0)) + + attrs: { [K in keyof P]: P[K] }) { } +>attrs : Symbol(attrs, Decl(conditionalTypeContextualTypeSimplificationsSuceeds.ts, 9, 32)) +>K : Symbol(K, Decl(conditionalTypeContextualTypeSimplificationsSuceeds.ts, 10, 14)) +>P : Symbol(P, Decl(conditionalTypeContextualTypeSimplificationsSuceeds.ts, 9, 15)) +>P : Symbol(P, Decl(conditionalTypeContextualTypeSimplificationsSuceeds.ts, 9, 15)) +>K : Symbol(K, Decl(conditionalTypeContextualTypeSimplificationsSuceeds.ts, 10, 14)) + +bad({ when: value => false }); +>bad : Symbol(bad, Decl(conditionalTypeContextualTypeSimplificationsSuceeds.ts, 3, 1)) +>when : Symbol(when, Decl(conditionalTypeContextualTypeSimplificationsSuceeds.ts, 12, 5)) +>value : Symbol(value, Decl(conditionalTypeContextualTypeSimplificationsSuceeds.ts, 12, 11)) + +good1({ when: value => false }); +>good1 : Symbol(good1, Decl(conditionalTypeContextualTypeSimplificationsSuceeds.ts, 6, 92)) +>when : Symbol(when, Decl(conditionalTypeContextualTypeSimplificationsSuceeds.ts, 13, 7)) +>value : Symbol(value, Decl(conditionalTypeContextualTypeSimplificationsSuceeds.ts, 13, 13)) + +good2({ when: value => false }); +>good2 : Symbol(good2, Decl(conditionalTypeContextualTypeSimplificationsSuceeds.ts, 8, 69)) +>when : Symbol(when, Decl(conditionalTypeContextualTypeSimplificationsSuceeds.ts, 14, 7)) +>value : Symbol(value, Decl(conditionalTypeContextualTypeSimplificationsSuceeds.ts, 14, 13)) + diff --git a/tests/baselines/reference/conditionalTypeContextualTypeSimplificationsSuceeds.types b/tests/baselines/reference/conditionalTypeContextualTypeSimplificationsSuceeds.types new file mode 100644 index 00000000000..cf55d7c3bcd --- /dev/null +++ b/tests/baselines/reference/conditionalTypeContextualTypeSimplificationsSuceeds.types @@ -0,0 +1,53 @@ +=== tests/cases/compiler/conditionalTypeContextualTypeSimplificationsSuceeds.ts === +// repro from https://github.com/Microsoft/TypeScript/issues/26395 +interface Props { + when: (value: string) => boolean; +>when : (value: string) => boolean +>value : string +} + +function bad

( +>bad :

(attrs: string extends keyof P ? { [K in keyof P]: P[K]; } : { [K in keyof P]: P[K]; }) => void + + attrs: string extends keyof P ? { [K in keyof P]: P[K] } : { [K in keyof P]: P[K] }) { } +>attrs : string extends keyof P ? { [K in keyof P]: P[K]; } : { [K in keyof P]: P[K]; } + +function good1

( +>good1 :

(attrs: string extends keyof P ? P : { [K in keyof P]: P[K]; }) => void + + attrs: string extends keyof P ? P : { [K in keyof P]: P[K] }) { } +>attrs : string extends keyof P ? P : { [K in keyof P]: P[K]; } + +function good2

( +>good2 :

(attrs: { [K in keyof P]: P[K]; }) => void + + attrs: { [K in keyof P]: P[K] }) { } +>attrs : { [K in keyof P]: P[K]; } + +bad({ when: value => false }); +>bad({ when: value => false }) : void +>bad :

(attrs: string extends keyof P ? { [K in keyof P]: P[K]; } : { [K in keyof P]: P[K]; }) => void +>{ when: value => false } : { when: (value: string) => false; } +>when : (value: string) => false +>value => false : (value: string) => false +>value : string +>false : false + +good1({ when: value => false }); +>good1({ when: value => false }) : void +>good1 :

(attrs: string extends keyof P ? P : { [K in keyof P]: P[K]; }) => void +>{ when: value => false } : { when: (value: string) => false; } +>when : (value: string) => false +>value => false : (value: string) => false +>value : string +>false : false + +good2({ when: value => false }); +>good2({ when: value => false }) : void +>good2 :

(attrs: { [K in keyof P]: P[K]; }) => void +>{ when: value => false } : { when: (value: string) => false; } +>when : (value: string) => false +>value => false : (value: string) => false +>value : string +>false : false + diff --git a/tests/baselines/reference/jsxChildrenGenericContextualTypes.errors.txt b/tests/baselines/reference/jsxChildrenGenericContextualTypes.errors.txt index 9c9b85fd04d..f9e193d104b 100644 --- a/tests/baselines/reference/jsxChildrenGenericContextualTypes.errors.txt +++ b/tests/baselines/reference/jsxChildrenGenericContextualTypes.errors.txt @@ -1,4 +1,4 @@ -tests/cases/compiler/jsxChildrenGenericContextualTypes.tsx(20,31): error TS2322: Type '(p: IntrinsicAttributes & LitProps<"x">) => "y"' is not assignable to type '(x: IntrinsicAttributes & LitProps<"x">) => "x"'. +tests/cases/compiler/jsxChildrenGenericContextualTypes.tsx(20,31): error TS2322: Type '(p: LitProps<"x">) => "y"' is not assignable to type '(x: IntrinsicAttributes & LitProps<"x">) => "x"'. Type '"y"' is not assignable to type '"x"'. tests/cases/compiler/jsxChildrenGenericContextualTypes.tsx(21,19): error TS2322: Type '{ children: (p: IntrinsicAttributes & LitProps<"x">) => "y"; prop: "x"; }' is not assignable to type 'IntrinsicAttributes & LitProps<"x" | "y">'. Type '{ children: (p: IntrinsicAttributes & LitProps<"x">) => "y"; prop: "x"; }' is not assignable to type 'LitProps<"x" | "y">'. @@ -39,7 +39,7 @@ tests/cases/compiler/jsxChildrenGenericContextualTypes.tsx(22,21): error TS2322: // Should error const arg = "y"} /> ~~~~~~~~ -!!! error TS2322: Type '(p: IntrinsicAttributes & LitProps<"x">) => "y"' is not assignable to type '(x: IntrinsicAttributes & LitProps<"x">) => "x"'. +!!! error TS2322: Type '(p: LitProps<"x">) => "y"' is not assignable to type '(x: IntrinsicAttributes & LitProps<"x">) => "x"'. !!! error TS2322: Type '"y"' is not assignable to type '"x"'. !!! related TS6500 tests/cases/compiler/jsxChildrenGenericContextualTypes.tsx:13:34: The expected type comes from property 'children' which is declared here on type 'IntrinsicAttributes & LitProps<"x">' const argchild = {p => "y"} diff --git a/tests/baselines/reference/jsxChildrenGenericContextualTypes.types b/tests/baselines/reference/jsxChildrenGenericContextualTypes.types index 9287a8a02de..0e5cf26d4c7 100644 --- a/tests/baselines/reference/jsxChildrenGenericContextualTypes.types +++ b/tests/baselines/reference/jsxChildrenGenericContextualTypes.types @@ -117,9 +117,9 @@ const arg = "y"} /> > "y"} /> : JSX.Element >ElemLit : (p: LitProps) => JSX.Element >prop : "x" ->children : (p: JSX.IntrinsicAttributes & LitProps<"x">) => "y" ->p => "y" : (p: JSX.IntrinsicAttributes & LitProps<"x">) => "y" ->p : JSX.IntrinsicAttributes & LitProps<"x"> +>children : (p: LitProps<"x">) => "y" +>p => "y" : (p: LitProps<"x">) => "y" +>p : LitProps<"x"> >"y" : "y" const argchild = {p => "y"} diff --git a/tests/baselines/reference/reactDefaultPropsInferenceSuccess.errors.txt b/tests/baselines/reference/reactDefaultPropsInferenceSuccess.errors.txt new file mode 100644 index 00000000000..2ec0fc09c92 --- /dev/null +++ b/tests/baselines/reference/reactDefaultPropsInferenceSuccess.errors.txt @@ -0,0 +1,67 @@ +tests/cases/compiler/reactDefaultPropsInferenceSuccess.tsx(26,36): error TS2322: Type '(value: string) => void' is not assignable to type '(value: string) => boolean'. + Type 'void' is not assignable to type 'boolean'. +tests/cases/compiler/reactDefaultPropsInferenceSuccess.tsx(48,37): error TS2322: Type '(value: string) => void' is not assignable to type '(value: string) => boolean'. + Type 'void' is not assignable to type 'boolean'. + + +==== tests/cases/compiler/reactDefaultPropsInferenceSuccess.tsx (2 errors) ==== + /// + + import React from 'react'; + + interface BaseProps { + when?: (value: string) => boolean; + } + + interface Props extends BaseProps { + } + + class FieldFeedback

extends React.Component

{ + static defaultProps = { + when: () => true + }; + + render() { + return

Hello
; + } + } + + // OK + const Test1 = () => !!value} />; + + // Error: Void not assignable to boolean + const Test2 = () => console.log(value)} />; + ~~~~ +!!! error TS2322: Type '(value: string) => void' is not assignable to type '(value: string) => boolean'. +!!! error TS2322: Type 'void' is not assignable to type 'boolean'. +!!! related TS6500 tests/cases/compiler/reactDefaultPropsInferenceSuccess.tsx:6:3: The expected type comes from property 'when' which is declared here on type 'IntrinsicAttributes & IntrinsicClassAttributes> & Pick & Readonly, "children"> & Partial & Readonly, "when">> & Partial boolean; }, never>>' + + + interface MyPropsProps extends Props { + when: (value: string) => boolean; + } + + class FieldFeedback2

extends FieldFeedback

{ + static defaultProps = { + when: () => true + }; + + render() { + this.props.when("now"); // OK, always defined + return

Hello
; + } + } + + // OK + const Test3 = () => !!value} />; + + // Error: Void not assignable to boolean + const Test4 = () => console.log(value)} />; + ~~~~ +!!! error TS2322: Type '(value: string) => void' is not assignable to type '(value: string) => boolean'. +!!! error TS2322: Type 'void' is not assignable to type 'boolean'. +!!! related TS6500 tests/cases/compiler/reactDefaultPropsInferenceSuccess.tsx:30:3: The expected type comes from property 'when' which is declared here on type 'IntrinsicAttributes & IntrinsicClassAttributes> & Pick & Readonly, "children"> & Partial & Readonly, "when">> & Partial boolean; }, never>>' + + // OK + const Test5 = () => ; + \ No newline at end of file diff --git a/tests/baselines/reference/reactDefaultPropsInferenceSuccess.js b/tests/baselines/reference/reactDefaultPropsInferenceSuccess.js new file mode 100644 index 00000000000..84db36ee4da --- /dev/null +++ b/tests/baselines/reference/reactDefaultPropsInferenceSuccess.js @@ -0,0 +1,112 @@ +//// [reactDefaultPropsInferenceSuccess.tsx] +/// + +import React from 'react'; + +interface BaseProps { + when?: (value: string) => boolean; +} + +interface Props extends BaseProps { +} + +class FieldFeedback

extends React.Component

{ + static defaultProps = { + when: () => true + }; + + render() { + return

Hello
; + } +} + +// OK +const Test1 = () => !!value} />; + +// Error: Void not assignable to boolean +const Test2 = () => console.log(value)} />; + + +interface MyPropsProps extends Props { + when: (value: string) => boolean; +} + +class FieldFeedback2

extends FieldFeedback

{ + static defaultProps = { + when: () => true + }; + + render() { + this.props.when("now"); // OK, always defined + return

Hello
; + } +} + +// OK +const Test3 = () => !!value} />; + +// Error: Void not assignable to boolean +const Test4 = () => console.log(value)} />; + +// OK +const Test5 = () => ; + + +//// [reactDefaultPropsInferenceSuccess.js] +"use strict"; +/// +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + } + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +exports.__esModule = true; +var react_1 = __importDefault(require("react")); +var FieldFeedback = /** @class */ (function (_super) { + __extends(FieldFeedback, _super); + function FieldFeedback() { + return _super !== null && _super.apply(this, arguments) || this; + } + FieldFeedback.prototype.render = function () { + return react_1["default"].createElement("div", null, "Hello"); + }; + FieldFeedback.defaultProps = { + when: function () { return true; } + }; + return FieldFeedback; +}(react_1["default"].Component)); +// OK +var Test1 = function () { return react_1["default"].createElement(FieldFeedback, { when: function (value) { return !!value; } }); }; +// Error: Void not assignable to boolean +var Test2 = function () { return react_1["default"].createElement(FieldFeedback, { when: function (value) { return console.log(value); } }); }; +var FieldFeedback2 = /** @class */ (function (_super) { + __extends(FieldFeedback2, _super); + function FieldFeedback2() { + return _super !== null && _super.apply(this, arguments) || this; + } + FieldFeedback2.prototype.render = function () { + this.props.when("now"); // OK, always defined + return react_1["default"].createElement("div", null, "Hello"); + }; + FieldFeedback2.defaultProps = { + when: function () { return true; } + }; + return FieldFeedback2; +}(FieldFeedback)); +// OK +var Test3 = function () { return react_1["default"].createElement(FieldFeedback2, { when: function (value) { return !!value; } }); }; +// Error: Void not assignable to boolean +var Test4 = function () { return react_1["default"].createElement(FieldFeedback2, { when: function (value) { return console.log(value); } }); }; +// OK +var Test5 = function () { return react_1["default"].createElement(FieldFeedback2, null); }; diff --git a/tests/baselines/reference/reactDefaultPropsInferenceSuccess.symbols b/tests/baselines/reference/reactDefaultPropsInferenceSuccess.symbols new file mode 100644 index 00000000000..dadaf9ea745 --- /dev/null +++ b/tests/baselines/reference/reactDefaultPropsInferenceSuccess.symbols @@ -0,0 +1,131 @@ +=== tests/cases/compiler/reactDefaultPropsInferenceSuccess.tsx === +/// + +import React from 'react'; +>React : Symbol(React, Decl(reactDefaultPropsInferenceSuccess.tsx, 2, 6)) + +interface BaseProps { +>BaseProps : Symbol(BaseProps, Decl(reactDefaultPropsInferenceSuccess.tsx, 2, 26)) + + when?: (value: string) => boolean; +>when : Symbol(BaseProps.when, Decl(reactDefaultPropsInferenceSuccess.tsx, 4, 21)) +>value : Symbol(value, Decl(reactDefaultPropsInferenceSuccess.tsx, 5, 10)) +} + +interface Props extends BaseProps { +>Props : Symbol(Props, Decl(reactDefaultPropsInferenceSuccess.tsx, 6, 1)) +>BaseProps : Symbol(BaseProps, Decl(reactDefaultPropsInferenceSuccess.tsx, 2, 26)) +} + +class FieldFeedback

extends React.Component

{ +>FieldFeedback : Symbol(FieldFeedback, Decl(reactDefaultPropsInferenceSuccess.tsx, 9, 1)) +>P : Symbol(P, Decl(reactDefaultPropsInferenceSuccess.tsx, 11, 20)) +>Props : Symbol(Props, Decl(reactDefaultPropsInferenceSuccess.tsx, 6, 1)) +>BaseProps : Symbol(BaseProps, Decl(reactDefaultPropsInferenceSuccess.tsx, 2, 26)) +>React.Component : Symbol(React.Component, Decl(react16.d.ts, 345, 54), Decl(react16.d.ts, 349, 94)) +>React : Symbol(React, Decl(reactDefaultPropsInferenceSuccess.tsx, 2, 6)) +>Component : Symbol(React.Component, Decl(react16.d.ts, 345, 54), Decl(react16.d.ts, 349, 94)) +>P : Symbol(P, Decl(reactDefaultPropsInferenceSuccess.tsx, 11, 20)) + + static defaultProps = { +>defaultProps : Symbol(FieldFeedback.defaultProps, Decl(reactDefaultPropsInferenceSuccess.tsx, 11, 77)) + + when: () => true +>when : Symbol(when, Decl(reactDefaultPropsInferenceSuccess.tsx, 12, 25)) + + }; + + render() { +>render : Symbol(FieldFeedback.render, Decl(reactDefaultPropsInferenceSuccess.tsx, 14, 4)) + + return

Hello
; +>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114)) + } +} + +// OK +const Test1 = () => !!value} />; +>Test1 : Symbol(Test1, Decl(reactDefaultPropsInferenceSuccess.tsx, 22, 5)) +>FieldFeedback : Symbol(FieldFeedback, Decl(reactDefaultPropsInferenceSuccess.tsx, 9, 1)) +>when : Symbol(when, Decl(reactDefaultPropsInferenceSuccess.tsx, 22, 34)) +>value : Symbol(value, Decl(reactDefaultPropsInferenceSuccess.tsx, 22, 41)) +>value : Symbol(value, Decl(reactDefaultPropsInferenceSuccess.tsx, 22, 41)) + +// Error: Void not assignable to boolean +const Test2 = () => console.log(value)} />; +>Test2 : Symbol(Test2, Decl(reactDefaultPropsInferenceSuccess.tsx, 25, 5)) +>FieldFeedback : Symbol(FieldFeedback, Decl(reactDefaultPropsInferenceSuccess.tsx, 9, 1)) +>when : Symbol(when, Decl(reactDefaultPropsInferenceSuccess.tsx, 25, 34)) +>value : Symbol(value, Decl(reactDefaultPropsInferenceSuccess.tsx, 25, 41)) +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>value : Symbol(value, Decl(reactDefaultPropsInferenceSuccess.tsx, 25, 41)) + + +interface MyPropsProps extends Props { +>MyPropsProps : Symbol(MyPropsProps, Decl(reactDefaultPropsInferenceSuccess.tsx, 25, 73)) +>Props : Symbol(Props, Decl(reactDefaultPropsInferenceSuccess.tsx, 6, 1)) + + when: (value: string) => boolean; +>when : Symbol(MyPropsProps.when, Decl(reactDefaultPropsInferenceSuccess.tsx, 28, 38)) +>value : Symbol(value, Decl(reactDefaultPropsInferenceSuccess.tsx, 29, 9)) +} + +class FieldFeedback2

extends FieldFeedback

{ +>FieldFeedback2 : Symbol(FieldFeedback2, Decl(reactDefaultPropsInferenceSuccess.tsx, 30, 1)) +>P : Symbol(P, Decl(reactDefaultPropsInferenceSuccess.tsx, 32, 21)) +>MyPropsProps : Symbol(MyPropsProps, Decl(reactDefaultPropsInferenceSuccess.tsx, 25, 73)) +>MyPropsProps : Symbol(MyPropsProps, Decl(reactDefaultPropsInferenceSuccess.tsx, 25, 73)) +>FieldFeedback : Symbol(FieldFeedback, Decl(reactDefaultPropsInferenceSuccess.tsx, 9, 1)) +>P : Symbol(P, Decl(reactDefaultPropsInferenceSuccess.tsx, 32, 21)) + + static defaultProps = { +>defaultProps : Symbol(FieldFeedback2.defaultProps, Decl(reactDefaultPropsInferenceSuccess.tsx, 32, 86)) + + when: () => true +>when : Symbol(when, Decl(reactDefaultPropsInferenceSuccess.tsx, 33, 25)) + + }; + + render() { +>render : Symbol(FieldFeedback2.render, Decl(reactDefaultPropsInferenceSuccess.tsx, 35, 4)) + + this.props.when("now"); // OK, always defined +>this.props.when : Symbol(when, Decl(reactDefaultPropsInferenceSuccess.tsx, 28, 38)) +>this.props : Symbol(React.Component.props, Decl(react16.d.ts, 367, 32)) +>this : Symbol(FieldFeedback2, Decl(reactDefaultPropsInferenceSuccess.tsx, 30, 1)) +>props : Symbol(React.Component.props, Decl(react16.d.ts, 367, 32)) +>when : Symbol(when, Decl(reactDefaultPropsInferenceSuccess.tsx, 28, 38)) + + return

Hello
; +>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114)) +>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114)) + } +} + +// OK +const Test3 = () => !!value} />; +>Test3 : Symbol(Test3, Decl(reactDefaultPropsInferenceSuccess.tsx, 44, 5)) +>FieldFeedback2 : Symbol(FieldFeedback2, Decl(reactDefaultPropsInferenceSuccess.tsx, 30, 1)) +>when : Symbol(when, Decl(reactDefaultPropsInferenceSuccess.tsx, 44, 35)) +>value : Symbol(value, Decl(reactDefaultPropsInferenceSuccess.tsx, 44, 42)) +>value : Symbol(value, Decl(reactDefaultPropsInferenceSuccess.tsx, 44, 42)) + +// Error: Void not assignable to boolean +const Test4 = () => console.log(value)} />; +>Test4 : Symbol(Test4, Decl(reactDefaultPropsInferenceSuccess.tsx, 47, 5)) +>FieldFeedback2 : Symbol(FieldFeedback2, Decl(reactDefaultPropsInferenceSuccess.tsx, 30, 1)) +>when : Symbol(when, Decl(reactDefaultPropsInferenceSuccess.tsx, 47, 35)) +>value : Symbol(value, Decl(reactDefaultPropsInferenceSuccess.tsx, 47, 42)) +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>value : Symbol(value, Decl(reactDefaultPropsInferenceSuccess.tsx, 47, 42)) + +// OK +const Test5 = () => ; +>Test5 : Symbol(Test5, Decl(reactDefaultPropsInferenceSuccess.tsx, 50, 5)) +>FieldFeedback2 : Symbol(FieldFeedback2, Decl(reactDefaultPropsInferenceSuccess.tsx, 30, 1)) + diff --git a/tests/baselines/reference/reactDefaultPropsInferenceSuccess.types b/tests/baselines/reference/reactDefaultPropsInferenceSuccess.types new file mode 100644 index 00000000000..91d918b0923 --- /dev/null +++ b/tests/baselines/reference/reactDefaultPropsInferenceSuccess.types @@ -0,0 +1,146 @@ +=== tests/cases/compiler/reactDefaultPropsInferenceSuccess.tsx === +/// + +import React from 'react'; +>React : typeof React + +interface BaseProps { + when?: (value: string) => boolean; +>when : ((value: string) => boolean) | undefined +>value : string +} + +interface Props extends BaseProps { +} + +class FieldFeedback

extends React.Component

{ +>FieldFeedback : FieldFeedback

+>React.Component : React.Component +>React : typeof React +>Component : typeof React.Component + + static defaultProps = { +>defaultProps : { when: () => boolean; } +>{ when: () => true } : { when: () => boolean; } + + when: () => true +>when : () => boolean +>() => true : () => boolean +>true : true + + }; + + render() { +>render : () => JSX.Element + + return

Hello
; +>
Hello
: JSX.Element +>div : any +>div : any + } +} + +// OK +const Test1 = () => !!value} />; +>Test1 : () => JSX.Element +>() => !!value} /> : () => JSX.Element +> !!value} /> : JSX.Element +>FieldFeedback : typeof FieldFeedback +>when : (value: string) => boolean +>value => !!value : (value: string) => boolean +>value : string +>!!value : boolean +>!value : boolean +>value : string + +// Error: Void not assignable to boolean +const Test2 = () => console.log(value)} />; +>Test2 : () => JSX.Element +>() => console.log(value)} /> : () => JSX.Element +> console.log(value)} /> : JSX.Element +>FieldFeedback : typeof FieldFeedback +>when : (value: string) => void +>value => console.log(value) : (value: string) => void +>value : string +>console.log(value) : void +>console.log : (message?: any, ...optionalParams: any[]) => void +>console : Console +>log : (message?: any, ...optionalParams: any[]) => void +>value : string + + +interface MyPropsProps extends Props { + when: (value: string) => boolean; +>when : (value: string) => boolean +>value : string +} + +class FieldFeedback2

extends FieldFeedback

{ +>FieldFeedback2 : FieldFeedback2

+>FieldFeedback : FieldFeedback

+ + static defaultProps = { +>defaultProps : { when: () => boolean; } +>{ when: () => true } : { when: () => boolean; } + + when: () => true +>when : () => boolean +>() => true : () => boolean +>true : true + + }; + + render() { +>render : () => JSX.Element + + this.props.when("now"); // OK, always defined +>this.props.when("now") : boolean +>this.props.when : P["when"] +>this.props : Readonly<{ children?: React.ReactNode; }> & Readonly

+>this : this +>props : Readonly<{ children?: React.ReactNode; }> & Readonly

+>when : P["when"] +>"now" : "now" + + return

Hello
; +>
Hello
: JSX.Element +>div : any +>div : any + } +} + +// OK +const Test3 = () => !!value} />; +>Test3 : () => JSX.Element +>() => !!value} /> : () => JSX.Element +> !!value} /> : JSX.Element +>FieldFeedback2 : typeof FieldFeedback2 +>when : (value: string) => boolean +>value => !!value : (value: string) => boolean +>value : string +>!!value : boolean +>!value : boolean +>value : string + +// Error: Void not assignable to boolean +const Test4 = () => console.log(value)} />; +>Test4 : () => JSX.Element +>() => console.log(value)} /> : () => JSX.Element +> console.log(value)} /> : JSX.Element +>FieldFeedback2 : typeof FieldFeedback2 +>when : (value: string) => void +>value => console.log(value) : (value: string) => void +>value : string +>console.log(value) : void +>console.log : (message?: any, ...optionalParams: any[]) => void +>console : Console +>log : (message?: any, ...optionalParams: any[]) => void +>value : string + +// OK +const Test5 = () => ; +>Test5 : () => JSX.Element +>() => : () => JSX.Element +> : JSX.Element +>FieldFeedback2 : typeof FieldFeedback2 + diff --git a/tests/cases/compiler/conditionalTypeContextualTypeSimplificationsSuceeds.ts b/tests/cases/compiler/conditionalTypeContextualTypeSimplificationsSuceeds.ts new file mode 100644 index 00000000000..f585022cccf --- /dev/null +++ b/tests/cases/compiler/conditionalTypeContextualTypeSimplificationsSuceeds.ts @@ -0,0 +1,16 @@ +// @strict: true +// repro from https://github.com/Microsoft/TypeScript/issues/26395 +interface Props { + when: (value: string) => boolean; +} + +function bad

( + attrs: string extends keyof P ? { [K in keyof P]: P[K] } : { [K in keyof P]: P[K] }) { } +function good1

( + attrs: string extends keyof P ? P : { [K in keyof P]: P[K] }) { } +function good2

( + attrs: { [K in keyof P]: P[K] }) { } + +bad({ when: value => false }); +good1({ when: value => false }); +good2({ when: value => false }); \ No newline at end of file diff --git a/tests/cases/compiler/reactDefaultPropsInferenceSuccess.tsx b/tests/cases/compiler/reactDefaultPropsInferenceSuccess.tsx new file mode 100644 index 00000000000..9de13d119df --- /dev/null +++ b/tests/cases/compiler/reactDefaultPropsInferenceSuccess.tsx @@ -0,0 +1,54 @@ +// @jsx: react +// @strict: true +// @esModuleInterop: true +/// + +import React from 'react'; + +interface BaseProps { + when?: (value: string) => boolean; +} + +interface Props extends BaseProps { +} + +class FieldFeedback

extends React.Component

{ + static defaultProps = { + when: () => true + }; + + render() { + return

Hello
; + } +} + +// OK +const Test1 = () => !!value} />; + +// Error: Void not assignable to boolean +const Test2 = () => console.log(value)} />; + + +interface MyPropsProps extends Props { + when: (value: string) => boolean; +} + +class FieldFeedback2

extends FieldFeedback

{ + static defaultProps = { + when: () => true + }; + + render() { + this.props.when("now"); // OK, always defined + return

Hello
; + } +} + +// OK +const Test3 = () => !!value} />; + +// Error: Void not assignable to boolean +const Test4 = () => console.log(value)} />; + +// OK +const Test5 = () => ; diff --git a/tests/lib/react16.d.ts b/tests/lib/react16.d.ts new file mode 100644 index 00000000000..4b91fb0c6fe --- /dev/null +++ b/tests/lib/react16.d.ts @@ -0,0 +1,2569 @@ +// Type definitions for React 16.4 +// Project: http://facebook.github.io/react/ +// Definitions by: Asana +// AssureSign +// Microsoft +// John Reilly +// Benoit Benezech +// Patricio Zavolinsky +// Digiguru +// Eric Anderson +// Albert Kurniawan +// Tanguy Krotoff +// Dovydas Navickas +// Stéphane Goetz +// Josh Rutherford +// Guilherme Hübner +// Ferdy Budhidharma +// Johann Rakotoharisoa +// Olivier Pascal +// Martin Hochel +// Frank Li +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// TypeScript Version: 2.8 + +interface HTMLWebViewElement extends HTMLElement {} + +declare module "prop-types" { + // Type definitions for prop-types 15.5 + // Project: https://github.com/reactjs/prop-types + // Definitions by: DovydasNavickas + // Ferdy Budhidharma + // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + // TypeScript Version: 2.8 + + import { ReactNode, ReactElement } from 'react'; + + export const nominalTypeHack: unique symbol; + + export type IsOptional = undefined | null extends T ? true : undefined extends T ? true : null extends T ? true : false; + + export type RequiredKeys = { [K in keyof V]: V[K] extends Validator ? IsOptional extends true ? never : K : never }[keyof V]; + export type OptionalKeys = Exclude>; + export type InferPropsInner = { [K in keyof V]: InferType; }; + + export interface Validator { + (props: object, propName: string, componentName: string, location: string, propFullName: string): Error | null; + [nominalTypeHack]?: T; + } + + export interface Requireable extends Validator { + isRequired: Validator>; + } + + export type ValidationMap = { [K in keyof T]-?: Validator }; + + export type InferType = V extends Validator ? T : any; + export type InferProps = + & InferPropsInner>> + & Partial>>>; + + export const any: Requireable; + export const array: Requireable; + export const bool: Requireable; + export const func: Requireable<(...args: any[]) => any>; + export const number: Requireable; + export const object: Requireable; + export const string: Requireable; + export const node: Requireable; + export const element: Requireable>; + export const symbol: Requireable; + export function instanceOf(expectedClass: new (...args: any[]) => T): Requireable; + export function oneOf(types: T[]): Requireable; + export function oneOfType>(types: T[]): Requireable>>; + export function arrayOf(type: Validator): Requireable; + export function objectOf(type: Validator): Requireable<{ [K in keyof any]: T; }>; + export function shape

>(type: P): Requireable>; + export function exact

>(type: P): Requireable>>; + + /** + * Assert that the values match with the type specs. + * Error messages are memorized and will only be shown once. + * + * @param typeSpecs Map of name to a ReactPropType + * @param values Runtime values that need to be type-checked + * @param location e.g. "prop", "context", "child context" + * @param componentName Name of the component for error messages. + * @param getStack Returns the component stack. + */ + export function checkPropTypes(typeSpecs: any, values: any, location: string, componentName: string, getStack?: () => any): void; + +} + +declare module "react" { + + import * as PropTypes from 'prop-types'; + + type NativeAnimationEvent = AnimationEvent; + type NativeClipboardEvent = ClipboardEvent; + type NativeCompositionEvent = CompositionEvent; + type NativeDragEvent = DragEvent; + type NativeFocusEvent = FocusEvent; + type NativeKeyboardEvent = KeyboardEvent; + type NativeMouseEvent = MouseEvent; + type NativeTouchEvent = TouchEvent; + type NativePointerEvent = PointerEvent; + type NativeTransitionEvent = TransitionEvent; + type NativeUIEvent = UIEvent; + type NativeWheelEvent = WheelEvent; + + // tslint:disable-next-line:export-just-namespace + export = React; + + namespace React { + // + // React Elements + // ---------------------------------------------------------------------- + + type ReactType

= string | ComponentType

; + type ComponentType

= ComponentClass

| StatelessComponent

; + + type Key = string | number; + + interface RefObject { + readonly current: T | null; + } + + type Ref = string | { bivarianceHack(instance: T | null): any }["bivarianceHack"] | RefObject; + + type ComponentState = any; + + interface Attributes { + key?: Key; + } + interface ClassAttributes extends Attributes { + ref?: Ref; + } + + interface ReactElement

{ + type: string | ComponentClass

| SFC

; + props: P; + key: Key | null; + } + + interface SFCElement

extends ReactElement

{ + type: SFC

; + } + + type CElement> = ComponentElement; + interface ComponentElement> extends ReactElement

{ + type: ComponentClass

; + ref?: Ref; + } + + type ClassicElement

= CElement>; + + // string fallback for custom web-components + interface DOMElement

| SVGAttributes, T extends Element> extends ReactElement

{ + type: string; + ref: Ref; + } + + // ReactHTML for ReactHTMLElement + // tslint:disable-next-line:no-empty-interface + interface ReactHTMLElement extends DetailedReactHTMLElement, T> { } + + interface DetailedReactHTMLElement

, T extends HTMLElement> extends DOMElement { + type: keyof ReactHTML; + } + + // ReactSVG for ReactSVGElement + interface ReactSVGElement extends DOMElement, SVGElement> { + type: keyof ReactSVG; + } + + interface ReactPortal extends ReactElement { + key: Key | null; + children: ReactNode; + } + + // + // Factories + // ---------------------------------------------------------------------- + + type Factory

= (props?: Attributes & P, ...children: ReactNode[]) => ReactElement

; + + type SFCFactory

= (props?: Attributes & P, ...children: ReactNode[]) => SFCElement

; + + type ComponentFactory> = + (props?: ClassAttributes & P, ...children: ReactNode[]) => CElement; + + type CFactory> = ComponentFactory; + type ClassicFactory

= CFactory>; + + type DOMFactory

, T extends Element> = + (props?: ClassAttributes & P | null, ...children: ReactNode[]) => DOMElement; + + // tslint:disable-next-line:no-empty-interface + interface HTMLFactory extends DetailedHTMLFactory, T> { } + + interface DetailedHTMLFactory

, T extends HTMLElement> extends DOMFactory { + (props?: ClassAttributes & P | null, ...children: ReactNode[]): DetailedReactHTMLElement; + } + + interface SVGFactory extends DOMFactory, SVGElement> { + (props?: ClassAttributes & SVGAttributes | null, ...children: ReactNode[]): ReactSVGElement; + } + + // + // React Nodes + // http://facebook.github.io/react/docs/glossary.html + // ---------------------------------------------------------------------- + + type ReactText = string | number; + type ReactChild = ReactElement | ReactText; + + interface ReactNodeArray extends Array { } + type ReactFragment = {} | ReactNodeArray; + type ReactNode = ReactChild | ReactFragment | ReactPortal | string | number | boolean | null | undefined; + + // + // Top Level API + // ---------------------------------------------------------------------- + + // DOM Elements + function createFactory( + type: keyof ReactHTML): HTMLFactory; + function createFactory( + type: keyof ReactSVG): SVGFactory; + function createFactory

, T extends Element>( + type: string): DOMFactory; + + // Custom components + function createFactory

(type: SFC

): SFCFactory

; + function createFactory

( + type: ClassType, ClassicComponentClass

>): CFactory>; + function createFactory, C extends ComponentClass

>( + type: ClassType): CFactory; + function createFactory

(type: ComponentClass

): Factory

; + + // DOM Elements + // TODO: generalize this to everything in `keyof ReactHTML`, not just "input" + function createElement( + type: "input", + props?: InputHTMLAttributes & ClassAttributes | null, + ...children: ReactNode[]): DetailedReactHTMLElement, HTMLInputElement>; + function createElement

, T extends HTMLElement>( + type: keyof ReactHTML, + props?: ClassAttributes & P | null, + ...children: ReactNode[]): DetailedReactHTMLElement; + function createElement

, T extends SVGElement>( + type: keyof ReactSVG, + props?: ClassAttributes & P | null, + ...children: ReactNode[]): ReactSVGElement; + function createElement

, T extends Element>( + type: string, + props?: ClassAttributes & P | null, + ...children: ReactNode[]): DOMElement; + + // Custom components + function createElement

( + type: SFC

, + props?: Attributes & P | null, + ...children: ReactNode[]): SFCElement

; + function createElement

( + type: ClassType, ClassicComponentClass

>, + props?: ClassAttributes> & P | null, + ...children: ReactNode[]): CElement>; + function createElement, C extends ComponentClass

>( + type: ClassType, + props?: ClassAttributes & P | null, + ...children: ReactNode[]): CElement; + function createElement

( + type: SFC

| ComponentClass

| string, + props?: Attributes & P | null, + ...children: ReactNode[]): ReactElement

; + + // DOM Elements + // ReactHTMLElement + function cloneElement

, T extends HTMLElement>( + element: DetailedReactHTMLElement, + props?: P, + ...children: ReactNode[]): DetailedReactHTMLElement; + // ReactHTMLElement, less specific + function cloneElement

, T extends HTMLElement>( + element: ReactHTMLElement, + props?: P, + ...children: ReactNode[]): ReactHTMLElement; + // SVGElement + function cloneElement

, T extends SVGElement>( + element: ReactSVGElement, + props?: P, + ...children: ReactNode[]): ReactSVGElement; + // DOM Element (has to be the last, because type checking stops at first overload that fits) + function cloneElement

, T extends Element>( + element: DOMElement, + props?: DOMAttributes & P, + ...children: ReactNode[]): DOMElement; + + // Custom components + function cloneElement

( + element: SFCElement

, + props?: Partial

& Attributes, + ...children: ReactNode[]): SFCElement

; + function cloneElement>( + element: CElement, + props?: Partial

& ClassAttributes, + ...children: ReactNode[]): CElement; + function cloneElement

( + element: ReactElement

, + props?: Partial

& Attributes, + ...children: ReactNode[]): ReactElement

; + + // Context via RenderProps + interface ProviderProps { + value: T; + children?: ReactNode; + } + + interface ConsumerProps { + children: (value: T) => ReactNode; + unstable_observedBits?: number; + } + + type Provider = ComponentType>; + type Consumer = ComponentType>; + interface Context { + Provider: Provider; + Consumer: Consumer; + } + function createContext( + defaultValue: T, + calculateChangedBits?: (prev: T, next: T) => number + ): Context; + + function isValidElement

(object: {} | null | undefined): object is ReactElement

; + + const Children: ReactChildren; + const Fragment: ComponentType; + const StrictMode: ComponentType; + const version: string; + + // + // Component API + // ---------------------------------------------------------------------- + + type ReactInstance = Component | Element; + + // Base component for plain JS classes + // tslint:disable-next-line:no-empty-interface + interface Component

extends ComponentLifecycle { } + class Component { + constructor(props: Readonly

); + /** + * @deprecated + * https://reactjs.org/docs/legacy-context.html + */ + constructor(props: P, context?: any); + + // We MUST keep setState() as a unified signature because it allows proper checking of the method return type. + // See: https://github.com/DefinitelyTyped/DefinitelyTyped/issues/18365#issuecomment-351013257 + // Also, the ` | S` allows intellisense to not be dumbisense + setState( + state: ((prevState: Readonly, props: Readonly

) => (Pick | S | null)) | (Pick | S | null), + callback?: () => void + ): void; + + forceUpdate(callBack?: () => void): void; + render(): ReactNode; + + // React.Props is now deprecated, which means that the `children` + // property is not available on `P` by default, even though you can + // always pass children as variadic arguments to `createElement`. + // In the future, if we can define its call signature conditionally + // on the existence of `children` in `P`, then we should remove this. + readonly props: Readonly<{ children?: ReactNode }> & Readonly

; + state: Readonly; + /** + * @deprecated + * https://reactjs.org/docs/legacy-context.html + */ + context: any; + /** + * @deprecated + * https://reactjs.org/docs/refs-and-the-dom.html#legacy-api-string-refs + */ + refs: { + [key: string]: ReactInstance + }; + } + + class PureComponent

extends Component { } + + interface ClassicComponent

extends Component { + replaceState(nextState: S, callback?: () => void): void; + isMounted(): boolean; + getInitialState?(): S; + } + + interface ChildContextProvider { + getChildContext(): CC; + } + + // + // Class Interfaces + // ---------------------------------------------------------------------- + + type SFC

= StatelessComponent

; + interface StatelessComponent

{ + (props: P & { children?: ReactNode }, context?: any): ReactElement | null; + propTypes?: ValidationMap

; + contextTypes?: ValidationMap; + defaultProps?: Partial

; + displayName?: string; + } + + interface RefForwardingComponent { + (props: P & { children?: ReactNode }, ref?: Ref): ReactElement | null; + propTypes?: ValidationMap

; + contextTypes?: ValidationMap; + defaultProps?: Partial

; + displayName?: string; + } + + interface ComponentClass

extends StaticLifecycle { + new(props: P, context?: any): Component; + propTypes?: ValidationMap

; + contextTypes?: ValidationMap; + childContextTypes?: ValidationMap; + defaultProps?: Partial

; + displayName?: string; + } + + interface ClassicComponentClass

extends ComponentClass

{ + new(props: P, context?: any): ClassicComponent; + getDefaultProps?(): P; + } + + /** + * We use an intersection type to infer multiple type parameters from + * a single argument, which is useful for many top-level API defs. + * See https://github.com/Microsoft/TypeScript/issues/7234 for more info. + */ + type ClassType, C extends ComponentClass

> = + C & + (new (props: P, context?: any) => T) & + (new (props: P, context?: any) => { props: P }); + + // + // Component Specs and Lifecycle + // ---------------------------------------------------------------------- + + // This should actually be something like `Lifecycle | DeprecatedLifecycle`, + // as React will _not_ call the deprecated lifecycle methods if any of the new lifecycle + // methods are present. + interface ComponentLifecycle extends NewLifecycle, DeprecatedLifecycle { + /** + * Called immediately after a component is mounted. Setting state here will trigger re-rendering. + */ + componentDidMount?(): void; + /** + * Called to determine whether the change in props and state should trigger a re-render. + * + * `Component` always returns true. + * `PureComponent` implements a shallow comparison on props and state and returns true if any + * props or states have changed. + * + * If false is returned, `Component#render`, `componentWillUpdate` + * and `componentDidUpdate` will not be called. + */ + shouldComponentUpdate?(nextProps: Readonly

, nextState: Readonly, nextContext: any): boolean; + /** + * Called immediately before a component is destroyed. Perform any necessary cleanup in this method, such as + * cancelled network requests, or cleaning up any DOM elements created in `componentDidMount`. + */ + componentWillUnmount?(): void; + /** + * Catches exceptions generated in descendant components. Unhandled exceptions will cause + * the entire component tree to unmount. + */ + componentDidCatch?(error: Error, errorInfo: ErrorInfo): void; + } + + // Unfortunately, we have no way of declaring that the component constructor must implement this + interface StaticLifecycle { + getDerivedStateFromProps?: GetDerivedStateFromProps; + } + + type GetDerivedStateFromProps = + /** + * Returns an update to a component's state based on its new props and old state. + * + * Note: its presence prevents any of the deprecated lifecycle methods from being invoked + */ + (nextProps: Readonly

, prevState: S) => Partial | null; + + // This should be "infer SS" but can't use it yet + interface NewLifecycle { + /** + * Runs before React applies the result of `render` to the document, and + * returns an object to be given to componentDidUpdate. Useful for saving + * things such as scroll position before `render` causes changes to it. + * + * Note: the presence of getSnapshotBeforeUpdate prevents any of the deprecated + * lifecycle events from running. + */ + getSnapshotBeforeUpdate?(prevProps: Readonly

, prevState: Readonly): SS | null; + /** + * Called immediately after updating occurs. Not called for the initial render. + * + * The snapshot is only present if getSnapshotBeforeUpdate is present and returns non-null. + */ + componentDidUpdate?(prevProps: Readonly

, prevState: Readonly, snapshot?: SS): void; + } + + interface DeprecatedLifecycle { + /** + * Called immediately before mounting occurs, and before `Component#render`. + * Avoid introducing any side-effects or subscriptions in this method. + * + * Note: the presence of getSnapshotBeforeUpdate or getDerivedStateFromProps + * prevents this from being invoked. + * + * @deprecated 16.3, use componentDidMount or the constructor instead; will stop working in React 17 + * @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#initializing-state + * @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#gradual-migration-path + */ + componentWillMount?(): void; + /** + * Called immediately before mounting occurs, and before `Component#render`. + * Avoid introducing any side-effects or subscriptions in this method. + * + * This method will not stop working in React 17. + * + * Note: the presence of getSnapshotBeforeUpdate or getDerivedStateFromProps + * prevents this from being invoked. + * + * @deprecated 16.3, use componentDidMount or the constructor instead + * @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#initializing-state + * @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#gradual-migration-path + */ + UNSAFE_componentWillMount?(): void; + /** + * Called when the component may be receiving new props. + * React may call this even if props have not changed, so be sure to compare new and existing + * props if you only want to handle changes. + * + * Calling `Component#setState` generally does not trigger this method. + * + * Note: the presence of getSnapshotBeforeUpdate or getDerivedStateFromProps + * prevents this from being invoked. + * + * @deprecated 16.3, use static getDerivedStateFromProps instead; will stop working in React 17 + * @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#updating-state-based-on-props + * @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#gradual-migration-path + */ + componentWillReceiveProps?(nextProps: Readonly

, nextContext: any): void; + /** + * Called when the component may be receiving new props. + * React may call this even if props have not changed, so be sure to compare new and existing + * props if you only want to handle changes. + * + * Calling `Component#setState` generally does not trigger this method. + * + * This method will not stop working in React 17. + * + * Note: the presence of getSnapshotBeforeUpdate or getDerivedStateFromProps + * prevents this from being invoked. + * + * @deprecated 16.3, use static getDerivedStateFromProps instead + * @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#updating-state-based-on-props + * @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#gradual-migration-path + */ + UNSAFE_componentWillReceiveProps?(nextProps: Readonly

, nextContext: any): void; + /** + * Called immediately before rendering when new props or state is received. Not called for the initial render. + * + * Note: You cannot call `Component#setState` here. + * + * Note: the presence of getSnapshotBeforeUpdate or getDerivedStateFromProps + * prevents this from being invoked. + * + * @deprecated 16.3, use getSnapshotBeforeUpdate instead; will stop working in React 17 + * @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#reading-dom-properties-before-an-update + * @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#gradual-migration-path + */ + componentWillUpdate?(nextProps: Readonly

, nextState: Readonly, nextContext: any): void; + /** + * Called immediately before rendering when new props or state is received. Not called for the initial render. + * + * Note: You cannot call `Component#setState` here. + * + * This method will not stop working in React 17. + * + * Note: the presence of getSnapshotBeforeUpdate or getDerivedStateFromProps + * prevents this from being invoked. + * + * @deprecated 16.3, use getSnapshotBeforeUpdate instead + * @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#reading-dom-properties-before-an-update + * @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#gradual-migration-path + */ + UNSAFE_componentWillUpdate?(nextProps: Readonly

, nextState: Readonly, nextContext: any): void; + } + + interface Mixin extends ComponentLifecycle { + mixins?: Array>; + statics?: { + [key: string]: any; + }; + + displayName?: string; + propTypes?: ValidationMap; + contextTypes?: ValidationMap; + childContextTypes?: ValidationMap; + + getDefaultProps?(): P; + getInitialState?(): S; + } + + interface ComponentSpec extends Mixin { + render(): ReactNode; + + [propertyName: string]: any; + } + + function createRef(): RefObject; + + function forwardRef(Component: RefForwardingComponent): ComponentType

>; + + // + // Event System + // ---------------------------------------------------------------------- + + interface SyntheticEvent { + bubbles: boolean; + /** + * A reference to the element on which the event listener is registered. + */ + currentTarget: EventTarget & T; + cancelable: boolean; + defaultPrevented: boolean; + eventPhase: number; + isTrusted: boolean; + nativeEvent: Event; + preventDefault(): void; + isDefaultPrevented(): boolean; + stopPropagation(): void; + isPropagationStopped(): boolean; + persist(): void; + // If you thought this should be `EventTarget & T`, see https://github.com/DefinitelyTyped/DefinitelyTyped/pull/12239 + /** + * A reference to the element from which the event was originally dispatched. + * This might be a child element to the element on which the event listener is registered. + * + * @see currentTarget + */ + target: EventTarget; + timeStamp: number; + type: string; + } + + interface ClipboardEvent extends SyntheticEvent { + clipboardData: DataTransfer; + nativeEvent: NativeClipboardEvent; + } + + interface CompositionEvent extends SyntheticEvent { + data: string; + nativeEvent: NativeCompositionEvent; + } + + interface DragEvent extends MouseEvent { + dataTransfer: DataTransfer; + nativeEvent: NativeDragEvent; + } + + interface PointerEvent extends MouseEvent { + pointerId: number; + pressure: number; + tiltX: number; + tiltY: number; + width: number; + height: number; + pointerType: 'mouse' | 'pen' | 'touch'; + isPrimary: boolean; + nativeEvent: NativePointerEvent; + } + + interface FocusEvent extends SyntheticEvent { + nativeEvent: NativeFocusEvent; + relatedTarget: EventTarget; + target: EventTarget & T; + } + + // tslint:disable-next-line:no-empty-interface + interface FormEvent extends SyntheticEvent { + } + + interface InvalidEvent extends SyntheticEvent { + target: EventTarget & T; + } + + interface ChangeEvent extends SyntheticEvent { + target: EventTarget & T; + } + + interface KeyboardEvent extends SyntheticEvent { + altKey: boolean; + charCode: number; + ctrlKey: boolean; + /** + * See [DOM Level 3 Events spec](https://www.w3.org/TR/uievents-key/#keys-modifier). for a list of valid (case-sensitive) arguments to this method. + */ + getModifierState(key: string): boolean; + /** + * See the [DOM Level 3 Events spec](https://www.w3.org/TR/uievents-key/#named-key-attribute-values). for possible values + */ + key: string; + keyCode: number; + locale: string; + location: number; + metaKey: boolean; + nativeEvent: NativeKeyboardEvent; + repeat: boolean; + shiftKey: boolean; + which: number; + } + + interface MouseEvent extends SyntheticEvent { + altKey: boolean; + button: number; + buttons: number; + clientX: number; + clientY: number; + ctrlKey: boolean; + /** + * See [DOM Level 3 Events spec](https://www.w3.org/TR/uievents-key/#keys-modifier). for a list of valid (case-sensitive) arguments to this method. + */ + getModifierState(key: string): boolean; + metaKey: boolean; + nativeEvent: NativeMouseEvent; + pageX: number; + pageY: number; + relatedTarget: EventTarget; + screenX: number; + screenY: number; + shiftKey: boolean; + } + + interface TouchEvent extends SyntheticEvent { + altKey: boolean; + changedTouches: TouchList; + ctrlKey: boolean; + /** + * See [DOM Level 3 Events spec](https://www.w3.org/TR/uievents-key/#keys-modifier). for a list of valid (case-sensitive) arguments to this method. + */ + getModifierState(key: string): boolean; + metaKey: boolean; + nativeEvent: NativeTouchEvent; + shiftKey: boolean; + targetTouches: TouchList; + touches: TouchList; + } + + interface UIEvent extends SyntheticEvent { + detail: number; + nativeEvent: NativeUIEvent; + view: AbstractView; + } + + interface WheelEvent extends MouseEvent { + deltaMode: number; + deltaX: number; + deltaY: number; + deltaZ: number; + nativeEvent: NativeWheelEvent; + } + + interface AnimationEvent extends SyntheticEvent { + animationName: string; + elapsedTime: number; + nativeEvent: NativeAnimationEvent; + pseudoElement: string; + } + + interface TransitionEvent extends SyntheticEvent { + elapsedTime: number; + nativeEvent: NativeTransitionEvent; + propertyName: string; + pseudoElement: string; + } + + // + // Event Handler Types + // ---------------------------------------------------------------------- + + type EventHandler> = { bivarianceHack(event: E): void }["bivarianceHack"]; + + type ReactEventHandler = EventHandler>; + + type ClipboardEventHandler = EventHandler>; + type CompositionEventHandler = EventHandler>; + type DragEventHandler = EventHandler>; + type FocusEventHandler = EventHandler>; + type FormEventHandler = EventHandler>; + type ChangeEventHandler = EventHandler>; + type KeyboardEventHandler = EventHandler>; + type MouseEventHandler = EventHandler>; + type TouchEventHandler = EventHandler>; + type PointerEventHandler = EventHandler>; + type UIEventHandler = EventHandler>; + type WheelEventHandler = EventHandler>; + type AnimationEventHandler = EventHandler>; + type TransitionEventHandler = EventHandler>; + + // + // Props / DOM Attributes + // ---------------------------------------------------------------------- + + /** + * @deprecated. This was used to allow clients to pass `ref` and `key` + * to `createElement`, which is no longer necessary due to intersection + * types. If you need to declare a props object before passing it to + * `createElement` or a factory, use `ClassAttributes`: + * + * ```ts + * var b: Button | null; + * var props: ButtonProps & ClassAttributes