diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f50e8aff474..274439d2cb6 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -574,7 +574,7 @@ namespace ts { recordMergedSymbol(target, source); } else if (target.flags & SymbolFlags.NamespaceModule) { - error(source.valueDeclaration.name, Diagnostics.Cannot_augment_module_0_with_value_exports_because_it_resolves_to_a_non_module_entity, symbolToString(target)); + error(source.declarations[0].name, Diagnostics.Cannot_augment_module_0_with_value_exports_because_it_resolves_to_a_non_module_entity, symbolToString(target)); } else { const message = target.flags & SymbolFlags.BlockScopedVariable || source.flags & SymbolFlags.BlockScopedVariable diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 9a2f19dcc13..a5990a5a31b 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -1111,10 +1111,11 @@ namespace ts { const jsonOptions = json["typeAcquisition"] || json["typingOptions"]; const typeAcquisition: TypeAcquisition = convertTypeAcquisitionFromJsonWorker(jsonOptions, basePath, errors, configFileName); + let baseCompileOnSave: boolean; if (json["extends"]) { let [include, exclude, files, baseOptions]: [string[], string[], string[], CompilerOptions] = [undefined, undefined, undefined, {}]; if (typeof json["extends"] === "string") { - [include, exclude, files, baseOptions] = (tryExtendsName(json["extends"]) || [include, exclude, files, baseOptions]); + [include, exclude, files, baseCompileOnSave, baseOptions] = (tryExtendsName(json["extends"]) || [include, exclude, files, baseCompileOnSave, baseOptions]); } else { errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, "extends", "string")); @@ -1135,7 +1136,10 @@ namespace ts { options.configFilePath = configFileName; const { fileNames, wildcardDirectories } = getFileNames(errors); - const compileOnSave = convertCompileOnSaveOptionFromJson(json, basePath, errors); + let compileOnSave = convertCompileOnSaveOptionFromJson(json, basePath, errors); + if (baseCompileOnSave && json[compileOnSaveCommandLineOption.name] === undefined) { + compileOnSave = baseCompileOnSave; + } return { options, @@ -1147,7 +1151,7 @@ namespace ts { compileOnSave }; - function tryExtendsName(extendedConfig: string): [string[], string[], string[], CompilerOptions] { + function tryExtendsName(extendedConfig: string): [string[], string[], string[], boolean, CompilerOptions] { // If the path isn't a rooted or relative path, don't try to resolve it (we reserve the right to special case module-id like paths in the future) if (!(isRootedDiskPath(extendedConfig) || startsWith(normalizeSlashes(extendedConfig), "./") || startsWith(normalizeSlashes(extendedConfig), "../"))) { errors.push(createCompilerDiagnostic(Diagnostics.A_path_in_an_extends_option_must_be_relative_or_rooted_but_0_is_not, extendedConfig)); @@ -1177,7 +1181,7 @@ namespace ts { return map(extendedResult.config[key], updatePath); } }); - return [include, exclude, files, result.options]; + return [include, exclude, files, result.compileOnSave, result.options]; } function getFileNames(errors: Diagnostic[]): ExpandResult { @@ -1245,7 +1249,7 @@ namespace ts { } } - export function convertCompileOnSaveOptionFromJson(jsonOption: any, basePath: string, errors: Diagnostic[]): boolean { + export function convertCompileOnSaveOptionFromJson(jsonOption: any, basePath: string, errors: Diagnostic[]): boolean | undefined { if (!hasProperty(jsonOption, compileOnSaveCommandLineOption.name)) { return false; } diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 0971adfc098..347e6e97ebd 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -908,6 +908,13 @@ namespace ts { function getSemanticDiagnosticsForFileNoCache(sourceFile: SourceFile, cancellationToken: CancellationToken): Diagnostic[] { return runWithCancellationToken(() => { + // If skipLibCheck is enabled, skip reporting errors if file is a declaration file. + // If skipDefaultLibCheck is enabled, skip reporting errors if file contains a + // '/// ' directive. + if (options.skipLibCheck && sourceFile.isDeclarationFile || options.skipDefaultLibCheck && sourceFile.hasNoDefaultLib) { + return emptyArray; + } + const typeChecker = getDiagnosticsProducingTypeChecker(); Debug.assert(!!sourceFile.bindDiagnostics); diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index f8ecf6bdcff..3ac5dc5d878 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -2714,9 +2714,8 @@ namespace ts { loopBody = createBlock([loopBody], /*multiline*/ true); } - const isAsyncBlockContainingAwait = - hierarchyFacts & HierarchyFacts.AsyncFunctionBody - && (node.statement.transformFlags & TransformFlags.ContainsYield) !== 0; + const containsYield = (node.statement.transformFlags & TransformFlags.ContainsYield) !== 0; + const isAsyncBlockContainingAwait = containsYield && (hierarchyFacts & HierarchyFacts.AsyncFunctionBody) !== 0; let loopBodyFlags: EmitFlags = 0; if (currentState.containsLexicalThis) { @@ -2739,7 +2738,7 @@ namespace ts { setEmitFlags( createFunctionExpression( /*modifiers*/ undefined, - isAsyncBlockContainingAwait ? createToken(SyntaxKind.AsteriskToken) : undefined, + containsYield ? createToken(SyntaxKind.AsteriskToken) : undefined, /*name*/ undefined, /*typeParameters*/ undefined, loopParameters, @@ -2833,7 +2832,7 @@ namespace ts { )); } - const convertedLoopBodyStatements = generateCallToConvertedLoop(functionName, loopParameters, currentState, isAsyncBlockContainingAwait); + const convertedLoopBodyStatements = generateCallToConvertedLoop(functionName, loopParameters, currentState, containsYield); let loop: Statement; if (convert) { diff --git a/src/harness/unittests/compileOnSave.ts b/src/harness/unittests/compileOnSave.ts index 506559bd3d9..eaab86b4ebc 100644 --- a/src/harness/unittests/compileOnSave.ts +++ b/src/harness/unittests/compileOnSave.ts @@ -317,6 +317,29 @@ namespace ts.projectSystem { sendAffectedFileRequestAndCheckResult(session, moduleFile1FileListRequest, []); }); + it("should save when compileOnSave is enabled in base tsconfig.json", () => { + configFile = { + path: "/a/b/tsconfig.json", + content: `{ + "extends": "/a/tsconfig.json" + }` + }; + + const configFile2: FileOrFolder = { + path: "/a/tsconfig.json", + content: `{ + "compileOnSave": true + }` + }; + + const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, configFile2, configFile, libFile]); + const typingsInstaller = createTestTypingsInstaller(host); + const session = createSession(host, typingsInstaller); + + openFilesForSession([moduleFile1, file1Consumer1], session); + sendAffectedFileRequestAndCheckResult(session, moduleFile1FileListRequest, [{ projectFileName: configFile.path, files: [moduleFile1, file1Consumer1, file1Consumer2] }]); + }); + it("should always return the file itself if '--isolatedModules' is specified", () => { configFile = { path: "/a/b/tsconfig.json", diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 66d9cb087b6..33838b5805f 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -3204,6 +3204,122 @@ namespace ts.projectSystem { const errorResult = session.executeCommand(dTsFileGetErrRequest).response; assert.isTrue(errorResult.length === 0); }); + + it("should not report bind errors for declaration files with skipLibCheck=true", () => { + const jsconfigFile = { + path: "/a/jsconfig.json", + content: "{}" + }; + const jsFile = { + path: "/a/jsFile.js", + content: "let x = 1;" + }; + const dTsFile1 = { + path: "/a/dTsFile1.d.ts", + content: ` + declare var x: number;` + }; + const dTsFile2 = { + path: "/a/dTsFile2.d.ts", + content: ` + declare var x: string;` + }; + const host = createServerHost([jsconfigFile, jsFile, dTsFile1, dTsFile2]); + const session = createSession(host); + openFilesForSession([jsFile], session); + + const dTsFile1GetErrRequest = makeSessionRequest( + CommandNames.SemanticDiagnosticsSync, + { file: dTsFile1.path } + ); + const error1Result = session.executeCommand(dTsFile1GetErrRequest).response; + assert.isTrue(error1Result.length === 0); + + const dTsFile2GetErrRequest = makeSessionRequest( + CommandNames.SemanticDiagnosticsSync, + { file: dTsFile2.path } + ); + const error2Result = session.executeCommand(dTsFile2GetErrRequest).response; + assert.isTrue(error2Result.length === 0); + }); + + it("should report semanitc errors for loose JS files with '// @ts-check' and skipLibCheck=true", () => { + const jsFile = { + path: "/a/jsFile.js", + content: ` + // @ts-check + let x = 1; + x === "string";` + }; + + const host = createServerHost([jsFile]); + const session = createSession(host); + openFilesForSession([jsFile], session); + + const getErrRequest = makeSessionRequest( + CommandNames.SemanticDiagnosticsSync, + { file: jsFile.path } + ); + const errorResult = session.executeCommand(getErrRequest).response; + assert.isTrue(errorResult.length === 1); + assert.equal(errorResult[0].code, Diagnostics.Operator_0_cannot_be_applied_to_types_1_and_2.code); + }); + + it("should report semanitc errors for configured js project with '// @ts-check' and skipLibCheck=true", () => { + const jsconfigFile = { + path: "/a/jsconfig.json", + content: "{}" + }; + + const jsFile = { + path: "/a/jsFile.js", + content: ` + // @ts-check + let x = 1; + x === "string";` + }; + + const host = createServerHost([jsconfigFile, jsFile]); + const session = createSession(host); + openFilesForSession([jsFile], session); + + const getErrRequest = makeSessionRequest( + CommandNames.SemanticDiagnosticsSync, + { file: jsFile.path } + ); + const errorResult = session.executeCommand(getErrRequest).response; + assert.isTrue(errorResult.length === 1); + assert.equal(errorResult[0].code, Diagnostics.Operator_0_cannot_be_applied_to_types_1_and_2.code); + }); + + it("should report semanitc errors for configured js project with checkJs=true and skipLibCheck=true", () => { + const jsconfigFile = { + path: "/a/jsconfig.json", + content: JSON.stringify({ + compilerOptions: { + checkJs: true, + skipLibCheck: true + }, + }) + }; + const jsFile = { + path: "/a/jsFile.js", + content: `let x = 1; + x === "string";` + }; + + const host = createServerHost([jsconfigFile, jsFile]); + const session = createSession(host); + openFilesForSession([jsFile], session); + + const getErrRequest = makeSessionRequest( + CommandNames.SemanticDiagnosticsSync, + { file: jsFile.path } + ); + const errorResult = session.executeCommand(getErrRequest).response; + assert.isTrue(errorResult.length === 1); + assert.equal(errorResult[0].code, Diagnostics.Operator_0_cannot_be_applied_to_types_1_and_2.code); + }); }); describe("non-existing directories listed in config file input array", () => { @@ -3493,6 +3609,30 @@ namespace ts.projectSystem { }); }); + describe("searching for config file", () => { + it("should stop at projectRootPath if given", () => { + const f1 = { + path: "/a/file1.ts", + content: "" + }; + const configFile = { + path: "/tsconfig.json", + content: "{}" + }; + const host = createServerHost([f1, configFile]); + const service = createProjectService(host); + service.openClientFile(f1.path, /*fileContent*/ undefined, /*scriptKind*/ undefined, "/a"); + + checkNumberOfConfiguredProjects(service, 0); + checkNumberOfInferredProjects(service, 1); + + service.closeClientFile(f1.path); + service.openClientFile(f1.path); + checkNumberOfConfiguredProjects(service, 1); + checkNumberOfInferredProjects(service, 0); + }); + }); + describe("cancellationToken", () => { it("is attached to request", () => { const f1 = { diff --git a/src/lib/es2015.collection.d.ts b/src/lib/es2015.collection.d.ts index 038ed1ed58c..9b35fcbeffb 100644 --- a/src/lib/es2015.collection.d.ts +++ b/src/lib/es2015.collection.d.ts @@ -58,7 +58,7 @@ interface ReadonlySet { readonly size: number; } -interface WeakSet { +interface WeakSet { add(value: T): this; delete(value: T): boolean; has(value: T): boolean; diff --git a/src/lib/es2015.iterable.d.ts b/src/lib/es2015.iterable.d.ts index d242d14b663..2f8a1efba76 100644 --- a/src/lib/es2015.iterable.d.ts +++ b/src/lib/es2015.iterable.d.ts @@ -118,7 +118,7 @@ interface SetConstructor { new (iterable: Iterable): Set; } -interface WeakSet { } +interface WeakSet { } interface WeakSetConstructor { new (iterable: Iterable): WeakSet; diff --git a/src/lib/es2015.symbol.wellknown.d.ts b/src/lib/es2015.symbol.wellknown.d.ts index 3d030f37d49..578cf0acbc2 100644 --- a/src/lib/es2015.symbol.wellknown.d.ts +++ b/src/lib/es2015.symbol.wellknown.d.ts @@ -118,7 +118,7 @@ interface Set { readonly [Symbol.toStringTag]: "Set"; } -interface WeakSet { +interface WeakSet { readonly [Symbol.toStringTag]: "WeakSet"; } diff --git a/src/lib/es5.d.ts b/src/lib/es5.d.ts index 69460f40c16..23805495b69 100644 --- a/src/lib/es5.d.ts +++ b/src/lib/es5.d.ts @@ -1742,13 +1742,6 @@ interface Int8Array { */ reverse(): Int8Array; - /** - * Sets a value or an array of values. - * @param index The index of the location to set. - * @param value The value to set. - */ - set(index: number, value: number): void; - /** * Sets a value or an array of values. * @param array A typed or untyped array of values to set. @@ -2033,13 +2026,6 @@ interface Uint8Array { */ reverse(): Uint8Array; - /** - * Sets a value or an array of values. - * @param index The index of the location to set. - * @param value The value to set. - */ - set(index: number, value: number): void; - /** * Sets a value or an array of values. * @param array A typed or untyped array of values to set. @@ -2325,19 +2311,12 @@ interface Uint8ClampedArray { */ reverse(): Uint8ClampedArray; - /** - * Sets a value or an array of values. - * @param index The index of the location to set. - * @param value The value to set. - */ - set(index: number, value: number): void; - /** * Sets a value or an array of values. * @param array A typed or untyped array of values to set. * @param offset The index in the current array at which the values are to be written. */ - set(array: Uint8ClampedArray, offset?: number): void; + set(array: ArrayLike, offset?: number): void; /** * Returns a section of an array. @@ -2616,13 +2595,6 @@ interface Int16Array { */ reverse(): Int16Array; - /** - * Sets a value or an array of values. - * @param index The index of the location to set. - * @param value The value to set. - */ - set(index: number, value: number): void; - /** * Sets a value or an array of values. * @param array A typed or untyped array of values to set. @@ -2908,13 +2880,6 @@ interface Uint16Array { */ reverse(): Uint16Array; - /** - * Sets a value or an array of values. - * @param index The index of the location to set. - * @param value The value to set. - */ - set(index: number, value: number): void; - /** * Sets a value or an array of values. * @param array A typed or untyped array of values to set. @@ -3199,13 +3164,6 @@ interface Int32Array { */ reverse(): Int32Array; - /** - * Sets a value or an array of values. - * @param index The index of the location to set. - * @param value The value to set. - */ - set(index: number, value: number): void; - /** * Sets a value or an array of values. * @param array A typed or untyped array of values to set. @@ -3490,13 +3448,6 @@ interface Uint32Array { */ reverse(): Uint32Array; - /** - * Sets a value or an array of values. - * @param index The index of the location to set. - * @param value The value to set. - */ - set(index: number, value: number): void; - /** * Sets a value or an array of values. * @param array A typed or untyped array of values to set. @@ -3781,13 +3732,6 @@ interface Float32Array { */ reverse(): Float32Array; - /** - * Sets a value or an array of values. - * @param index The index of the location to set. - * @param value The value to set. - */ - set(index: number, value: number): void; - /** * Sets a value or an array of values. * @param array A typed or untyped array of values to set. @@ -4073,13 +4017,6 @@ interface Float64Array { */ reverse(): Float64Array; - /** - * Sets a value or an array of values. - * @param index The index of the location to set. - * @param value The value to set. - */ - set(index: number, value: number): void; - /** * Sets a value or an array of values. * @param array A typed or untyped array of values to set. diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index d45bb283384..4699e1a1d4d 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -787,12 +787,12 @@ namespace ts.server { * we first detect if there is already a configured project created for it: if so, we re-read * the tsconfig file content and update the project; otherwise we create a new one. */ - private openOrUpdateConfiguredProjectForFile(fileName: NormalizedPath): OpenConfiguredProjectResult { + private openOrUpdateConfiguredProjectForFile(fileName: NormalizedPath, projectRootPath?: NormalizedPath): OpenConfiguredProjectResult { const searchPath = getDirectoryPath(fileName); this.logger.info(`Search path: ${searchPath}`); // check if this file is already included in one of external projects - const configFileName = this.findConfigFile(asNormalizedPath(searchPath)); + const configFileName = this.findConfigFile(asNormalizedPath(searchPath), projectRootPath); if (!configFileName) { this.logger.info("No config files found."); return {}; @@ -826,8 +826,8 @@ namespace ts.server { // current directory (the directory in which tsc was invoked). // The server must start searching from the directory containing // the newly opened file. - private findConfigFile(searchPath: NormalizedPath): NormalizedPath { - while (true) { + private findConfigFile(searchPath: NormalizedPath, projectRootPath?: NormalizedPath): NormalizedPath { + while (!projectRootPath || searchPath.indexOf(projectRootPath) >= 0) { const tsconfigFileName = asNormalizedPath(combinePaths(searchPath, "tsconfig.json")); if (this.host.fileExists(tsconfigFileName)) { return tsconfigFileName; @@ -1326,17 +1326,17 @@ namespace ts.server { * @param filename is absolute pathname * @param fileContent is a known version of the file content that is more up to date than the one on disk */ - openClientFile(fileName: string, fileContent?: string, scriptKind?: ScriptKind): OpenConfiguredProjectResult { - return this.openClientFileWithNormalizedPath(toNormalizedPath(fileName), fileContent, scriptKind); + openClientFile(fileName: string, fileContent?: string, scriptKind?: ScriptKind, projectRootPath?: string): OpenConfiguredProjectResult { + return this.openClientFileWithNormalizedPath(toNormalizedPath(fileName), fileContent, scriptKind, /*hasMixedContent*/ false, projectRootPath ? toNormalizedPath(projectRootPath) : undefined); } - openClientFileWithNormalizedPath(fileName: NormalizedPath, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean): OpenConfiguredProjectResult { + openClientFileWithNormalizedPath(fileName: NormalizedPath, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, projectRootPath?: NormalizedPath): OpenConfiguredProjectResult { let configFileName: NormalizedPath; let configFileErrors: Diagnostic[]; let project: ConfiguredProject | ExternalProject = this.findContainingExternalProject(fileName); if (!project) { - ({ configFileName, configFileErrors } = this.openOrUpdateConfiguredProjectForFile(fileName)); + ({ configFileName, configFileErrors } = this.openOrUpdateConfiguredProjectForFile(fileName, projectRootPath)); if (configFileName) { project = this.findConfiguredProjectByProjectName(configFileName); } diff --git a/src/server/protocol.ts b/src/server/protocol.ts index 71998666fed..8e3c6c2c07f 100644 --- a/src/server/protocol.ts +++ b/src/server/protocol.ts @@ -1041,6 +1041,11 @@ namespace ts.server.protocol { * "TS", "JS", "TSX", "JSX" */ scriptKindName?: ScriptKindName; + /** + * Used to limit the searching for project config file. If given the searching will stop at this + * root path; otherwise it will go all the way up to the dist root path. + */ + projectRootPath?: string; } export type ScriptKindName = "TS" | "JS" | "TSX" | "JSX"; diff --git a/src/server/session.ts b/src/server/session.ts index 742f8a3c228..8c8c6387926 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -25,15 +25,26 @@ namespace ts.server { return ((1e9 * seconds) + nanoseconds) / 1000000.0; } - function shouldSkipSemanticCheck(project: Project) { - if (project.projectKind === ProjectKind.Inferred || project.projectKind === ProjectKind.External) { - return project.isJsOnlyProject(); - } - else { - // For configured projects, require that skipLibCheck be set also - const options = project.getCompilerOptions(); - return options.skipLibCheck && !options.checkJs && project.isJsOnlyProject(); + function isDeclarationFileInJSOnlyNonConfiguredProject(project: Project, file: NormalizedPath) { + // Checking for semantic diagnostics is an expensive process. We want to avoid it if we + // know for sure it is not needed. + // For instance, .d.ts files injected by ATA automatically do not produce any relevant + // errors to a JS- only project. + // + // Note that configured projects can set skipLibCheck (on by default in jsconfig.json) to + // disable checking for declaration files. We only need to verify for inferred projects (e.g. + // miscellaneous context in VS) and external projects(e.g.VS.csproj project) with only JS + // files. + // + // We still want to check .js files in a JS-only inferred or external project (e.g. if the + // file has '// @ts-check'). + + if ((project.projectKind === ProjectKind.Inferred || project.projectKind === ProjectKind.External) && + project.isJsOnlyProject()) { + const scriptInfo = project.getScriptInfoForNormalizedPath(file); + return scriptInfo && !scriptInfo.isJavaScript(); } + return false; } interface FileStart { @@ -489,7 +500,7 @@ namespace ts.server { private semanticCheck(file: NormalizedPath, project: Project) { try { let diags: Diagnostic[] = []; - if (!shouldSkipSemanticCheck(project)) { + if (!isDeclarationFileInJSOnlyNonConfiguredProject(project, file)) { diags = project.getLanguageService().getSemanticDiagnostics(file); } @@ -597,7 +608,7 @@ namespace ts.server { private getDiagnosticsWorker(args: protocol.FileRequestArgs, isSemantic: boolean, selector: (project: Project, file: string) => Diagnostic[], includeLinePosition: boolean) { const { project, file } = this.getFileAndProject(args); - if (isSemantic && shouldSkipSemanticCheck(project)) { + if (isSemantic && isDeclarationFileInJSOnlyNonConfiguredProject(project, file)) { return []; } const scriptInfo = project.getScriptInfoForNormalizedPath(file); @@ -979,8 +990,8 @@ namespace ts.server { * @param fileName is the name of the file to be opened * @param fileContent is a version of the file content that is known to be more up to date than the one on disk */ - private openClientFile(fileName: NormalizedPath, fileContent?: string, scriptKind?: ScriptKind) { - const { configFileName, configFileErrors } = this.projectService.openClientFileWithNormalizedPath(fileName, fileContent, scriptKind); + private openClientFile(fileName: NormalizedPath, fileContent?: string, scriptKind?: ScriptKind, projectRootPath?: NormalizedPath) { + const { configFileName, configFileErrors } = this.projectService.openClientFileWithNormalizedPath(fileName, fileContent, scriptKind, /*hasMixedContent*/ false, projectRootPath); if (this.eventHandler) { this.eventHandler({ eventName: "configFileDiag", @@ -1659,7 +1670,11 @@ namespace ts.server { return this.requiredResponse(this.getRenameInfo(request.arguments)); }, [CommandNames.Open]: (request: protocol.OpenRequest) => { - this.openClientFile(toNormalizedPath(request.arguments.file), request.arguments.fileContent, convertScriptKindName(request.arguments.scriptKindName)); + this.openClientFile( + toNormalizedPath(request.arguments.file), + request.arguments.fileContent, + convertScriptKindName(request.arguments.scriptKindName), + request.arguments.projectRootPath ? toNormalizedPath(request.arguments.projectRootPath) : undefined); return this.notRequired(); }, [CommandNames.Quickinfo]: (request: protocol.QuickInfoRequest) => { diff --git a/src/services/goToImplementation.ts b/src/services/goToImplementation.ts deleted file mode 100644 index 1d9f48ae5e8..00000000000 --- a/src/services/goToImplementation.ts +++ /dev/null @@ -1,27 +0,0 @@ -/* @internal */ -namespace ts.GoToImplementation { - export function getImplementationAtPosition(typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFiles: SourceFile[], node: Node): ImplementationLocation[] { - const context = new FindAllReferences.FindImplementationsContext(typeChecker, cancellationToken); - // If invoked directly on a shorthand property assignment, then return - // the declaration of the symbol being assigned (not the symbol being assigned to). - if (node.parent.kind === SyntaxKind.ShorthandPropertyAssignment) { - const result: ImplementationLocation[] = []; - FindAllReferences.getReferenceEntriesForShorthandPropertyAssignment(node, context, result); - return result.length > 0 ? result : undefined; - } - else if (node.kind === SyntaxKind.SuperKeyword || isSuperProperty(node.parent)) { - // References to and accesses on the super keyword only have one possible implementation, so no - // need to "Find all References" - const symbol = typeChecker.getSymbolAtLocation(node); - return symbol.valueDeclaration && [context.getReferenceEntryFromNode(symbol.valueDeclaration)]; - } - else { - // Perform "Find all References" and retrieve only those that are implementations - const referencedSymbols = FindAllReferences.getReferencedSymbolsForNode(context, - node, sourceFiles, /*findInStrings*/ false, /*findInComments*/ false, /*isForRename*/ false, /*implementations*/ true); - const result = flatMap(referencedSymbols, symbol => symbol.references); - - return result && result.length > 0 ? result : undefined; - } - } -} diff --git a/tests/baselines/reference/blockScopedBindingsInDownlevelGenerator.js b/tests/baselines/reference/blockScopedBindingsInDownlevelGenerator.js new file mode 100644 index 00000000000..be2bcd0bb0c --- /dev/null +++ b/tests/baselines/reference/blockScopedBindingsInDownlevelGenerator.js @@ -0,0 +1,93 @@ +//// [blockScopedBindingsInDownlevelGenerator.ts] +function* a() { + for (const i of [1,2,3]) { + (() => i)() + yield i + } +} + +//// [blockScopedBindingsInDownlevelGenerator.js] +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [0, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +var __values = (this && this.__values) || function (o) { + var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0; + if (m) return m.call(o); + return { + next: function () { + if (o && i >= o.length) o = void 0; + return { value: o && o[i++], done: !o }; + } + }; +}; +function a() { + var _loop_1, _a, _b, i, e_1_1, e_1, _c; + return __generator(this, function (_d) { + switch (_d.label) { + case 0: + _loop_1 = function (i) { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + (function () { return i; })(); + return [4 /*yield*/, i]; + case 1: + _a.sent(); + return [2 /*return*/]; + } + }); + }; + _d.label = 1; + case 1: + _d.trys.push([1, 6, 7, 8]); + _a = __values([1, 2, 3]), _b = _a.next(); + _d.label = 2; + case 2: + if (!!_b.done) return [3 /*break*/, 5]; + i = _b.value; + return [5 /*yield**/, _loop_1(i)]; + case 3: + _d.sent(); + _d.label = 4; + case 4: + _b = _a.next(); + return [3 /*break*/, 2]; + case 5: return [3 /*break*/, 8]; + case 6: + e_1_1 = _d.sent(); + e_1 = { error: e_1_1 }; + return [3 /*break*/, 8]; + case 7: + try { + if (_b && !_b.done && (_c = _a.return)) _c.call(_a); + } + finally { if (e_1) throw e_1.error; } + return [7 /*endfinally*/]; + case 8: return [2 /*return*/]; + } + }); +} diff --git a/tests/baselines/reference/blockScopedBindingsInDownlevelGenerator.symbols b/tests/baselines/reference/blockScopedBindingsInDownlevelGenerator.symbols new file mode 100644 index 00000000000..8caaed47a64 --- /dev/null +++ b/tests/baselines/reference/blockScopedBindingsInDownlevelGenerator.symbols @@ -0,0 +1,14 @@ +=== tests/cases/compiler/blockScopedBindingsInDownlevelGenerator.ts === +function* a() { +>a : Symbol(a, Decl(blockScopedBindingsInDownlevelGenerator.ts, 0, 0)) + + for (const i of [1,2,3]) { +>i : Symbol(i, Decl(blockScopedBindingsInDownlevelGenerator.ts, 1, 12)) + + (() => i)() +>i : Symbol(i, Decl(blockScopedBindingsInDownlevelGenerator.ts, 1, 12)) + + yield i +>i : Symbol(i, Decl(blockScopedBindingsInDownlevelGenerator.ts, 1, 12)) + } +} diff --git a/tests/baselines/reference/blockScopedBindingsInDownlevelGenerator.types b/tests/baselines/reference/blockScopedBindingsInDownlevelGenerator.types new file mode 100644 index 00000000000..cf93e7c2f4d --- /dev/null +++ b/tests/baselines/reference/blockScopedBindingsInDownlevelGenerator.types @@ -0,0 +1,22 @@ +=== tests/cases/compiler/blockScopedBindingsInDownlevelGenerator.ts === +function* a() { +>a : () => IterableIterator + + for (const i of [1,2,3]) { +>i : number +>[1,2,3] : number[] +>1 : 1 +>2 : 2 +>3 : 3 + + (() => i)() +>(() => i)() : number +>(() => i) : () => number +>() => i : () => number +>i : number + + yield i +>yield i : any +>i : number + } +} diff --git a/tests/baselines/reference/noSymbolForMergeCrash.errors.txt b/tests/baselines/reference/noSymbolForMergeCrash.errors.txt new file mode 100644 index 00000000000..1f8cd7897e0 --- /dev/null +++ b/tests/baselines/reference/noSymbolForMergeCrash.errors.txt @@ -0,0 +1,12 @@ +tests/cases/compiler/final.ts(1,6): error TS2649: Cannot augment module 'A' with value exports because it resolves to a non-module entity. + + +==== tests/cases/compiler/initial.ts (0 errors) ==== + interface A { } + namespace A {} + +==== tests/cases/compiler/final.ts (1 errors) ==== + type A = {} + ~ +!!! error TS2649: Cannot augment module 'A' with value exports because it resolves to a non-module entity. + \ No newline at end of file diff --git a/tests/baselines/reference/noSymbolForMergeCrash.js b/tests/baselines/reference/noSymbolForMergeCrash.js new file mode 100644 index 00000000000..341c9313982 --- /dev/null +++ b/tests/baselines/reference/noSymbolForMergeCrash.js @@ -0,0 +1,12 @@ +//// [tests/cases/compiler/noSymbolForMergeCrash.ts] //// + +//// [initial.ts] +interface A { } +namespace A {} + +//// [final.ts] +type A = {} + + +//// [initial.js] +//// [final.js] diff --git a/tests/cases/compiler/blockScopedBindingsInDownlevelGenerator.ts b/tests/cases/compiler/blockScopedBindingsInDownlevelGenerator.ts new file mode 100644 index 00000000000..ff2bb87149b --- /dev/null +++ b/tests/cases/compiler/blockScopedBindingsInDownlevelGenerator.ts @@ -0,0 +1,9 @@ +// @target: es5 +// @downlevelIteration: true +// @lib: es2015 +function* a() { + for (const i of [1,2,3]) { + (() => i)() + yield i + } +} \ No newline at end of file diff --git a/tests/cases/compiler/noDefaultLib.ts b/tests/cases/compiler/noDefaultLib.ts index 92c8a63fc64..fa1230e4cfe 100644 --- a/tests/cases/compiler/noDefaultLib.ts +++ b/tests/cases/compiler/noDefaultLib.ts @@ -1,3 +1,4 @@ +// @skipDefaultLibCheck: false /// var x; diff --git a/tests/cases/compiler/noSymbolForMergeCrash.ts b/tests/cases/compiler/noSymbolForMergeCrash.ts new file mode 100644 index 00000000000..a4e5eec8a19 --- /dev/null +++ b/tests/cases/compiler/noSymbolForMergeCrash.ts @@ -0,0 +1,6 @@ +// @Filename: initial.ts +interface A { } +namespace A {} + +// @Filename: final.ts +type A = {} diff --git a/tests/cases/compiler/variableDeclarationInStrictMode1.ts b/tests/cases/compiler/variableDeclarationInStrictMode1.ts index 266e5af44ae..5785beb32aa 100644 --- a/tests/cases/compiler/variableDeclarationInStrictMode1.ts +++ b/tests/cases/compiler/variableDeclarationInStrictMode1.ts @@ -1,2 +1,3 @@ +// @skipDefaultLibCheck: false "use strict"; var eval; \ No newline at end of file