From de400008149a20f1bb09a707b4c7de1fa4ba4b2e Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Mon, 13 Feb 2017 12:19:33 -0800 Subject: [PATCH] switch FileExtensionInfo to always mean .js file and deduplicate entries in getSupportedExtensions (#14046) * - switch FileExtensionInfo to always mean .js file - deduplicate entries in getSupportedExtensions * (PR feedback): updated comment --- src/compiler/commandLineParser.ts | 8 ++--- src/compiler/core.ts | 26 +++++++------- src/compiler/types.ts | 3 +- .../unittests/tsserverProjectSystem.ts | 35 +++++++++++++++++++ src/server/editorServices.ts | 4 +-- src/server/protocol.ts | 4 +-- 6 files changed, 56 insertions(+), 24 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 4ee76d7b817..52804dcd336 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -840,7 +840,7 @@ namespace ts { * @param basePath A root directory to resolve relative path entries in the config * file to. e.g. outDir */ - export function parseJsonConfigFileContent(json: any, host: ParseConfigHost, basePath: string, existingOptions: CompilerOptions = {}, configFileName?: string, resolutionStack: Path[] = [], extraFileExtensions: FileExtensionInfo[] = []): ParsedCommandLine { + export function parseJsonConfigFileContent(json: any, host: ParseConfigHost, basePath: string, existingOptions: CompilerOptions = {}, configFileName?: string, resolutionStack: Path[] = [], extraFileExtensions: JsFileExtensionInfo[] = []): ParsedCommandLine { const errors: Diagnostic[] = []; basePath = normalizeSlashes(basePath); const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames); @@ -1186,7 +1186,7 @@ namespace ts { * @param host The host used to resolve files and directories. * @param errors An array for diagnostic reporting. */ - function matchFileNames(fileNames: string[], include: string[], exclude: string[], basePath: string, options: CompilerOptions, host: ParseConfigHost, errors: Diagnostic[], extraFileExtensions: FileExtensionInfo[]): ExpandResult { + function matchFileNames(fileNames: string[], include: string[], exclude: string[], basePath: string, options: CompilerOptions, host: ParseConfigHost, errors: Diagnostic[], extraFileExtensions: JsFileExtensionInfo[]): ExpandResult { basePath = normalizePath(basePath); // The exclude spec list is converted into a regular expression, which allows us to quickly @@ -1361,7 +1361,7 @@ namespace ts { */ function hasFileWithHigherPriorityExtension(file: string, literalFiles: Map, wildcardFiles: Map, extensions: string[], keyMapper: (value: string) => string) { const extensionPriority = getExtensionPriority(file, extensions); - const adjustedExtensionPriority = adjustExtensionPriority(extensionPriority); + const adjustedExtensionPriority = adjustExtensionPriority(extensionPriority, extensions); for (let i = ExtensionPriority.Highest; i < adjustedExtensionPriority; i++) { const higherPriorityExtension = extensions[i]; const higherPriorityPath = keyMapper(changeExtension(file, higherPriorityExtension)); @@ -1383,7 +1383,7 @@ namespace ts { */ function removeWildcardFilesWithLowerPriorityExtension(file: string, wildcardFiles: Map, extensions: string[], keyMapper: (value: string) => string) { const extensionPriority = getExtensionPriority(file, extensions); - const nextExtensionPriority = getNextLowestExtensionPriority(extensionPriority); + const nextExtensionPriority = getNextLowestExtensionPriority(extensionPriority, extensions); for (let i = nextExtensionPriority; i < extensions.length; i++) { const lowerPriorityExtension = extensions[i]; const lowerPriorityPath = keyMapper(changeExtension(file, lowerPriorityExtension)); diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 94e32dfdbb3..43bbf86509e 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -2020,14 +2020,14 @@ namespace ts { export const supportedJavascriptExtensions = [".js", ".jsx"]; const allSupportedExtensions = supportedTypeScriptExtensions.concat(supportedJavascriptExtensions); - export function getSupportedExtensions(options?: CompilerOptions, extraFileExtensions?: FileExtensionInfo[]): string[] { + export function getSupportedExtensions(options?: CompilerOptions, extraFileExtensions?: JsFileExtensionInfo[]): string[] { const needAllExtensions = options && options.allowJs; - if (!extraFileExtensions || extraFileExtensions.length === 0) { + if (!extraFileExtensions || extraFileExtensions.length === 0 || !needAllExtensions) { return needAllExtensions ? allSupportedExtensions : supportedTypeScriptExtensions; } - const extensions = (needAllExtensions ? allSupportedExtensions : supportedTypeScriptExtensions).slice(0); + const extensions = allSupportedExtensions.slice(0); for (const extInfo of extraFileExtensions) { - if (needAllExtensions || extInfo.scriptKind === ScriptKind.TS) { + if (extensions.indexOf(extInfo.extension) === -1) { extensions.push(extInfo.extension); } } @@ -2042,7 +2042,7 @@ namespace ts { return forEach(supportedTypeScriptExtensions, extension => fileExtensionIs(fileName, extension)); } - export function isSupportedSourceFileName(fileName: string, compilerOptions?: CompilerOptions, extraFileExtensions?: FileExtensionInfo[]) { + export function isSupportedSourceFileName(fileName: string, compilerOptions?: CompilerOptions, extraFileExtensions?: JsFileExtensionInfo[]) { if (!fileName) { return false; } for (const extension of getSupportedExtensions(compilerOptions, extraFileExtensions)) { @@ -2061,7 +2061,6 @@ namespace ts { export const enum ExtensionPriority { TypeScriptFiles = 0, DeclarationAndJavaScriptFiles = 2, - Limit = 5, Highest = TypeScriptFiles, Lowest = DeclarationAndJavaScriptFiles, @@ -2070,7 +2069,7 @@ namespace ts { export function getExtensionPriority(path: string, supportedExtensions: string[]): ExtensionPriority { for (let i = supportedExtensions.length - 1; i >= 0; i--) { if (fileExtensionIs(path, supportedExtensions[i])) { - return adjustExtensionPriority(i); + return adjustExtensionPriority(i, supportedExtensions); } } @@ -2082,27 +2081,26 @@ namespace ts { /** * Adjusts an extension priority to be the highest priority within the same range. */ - export function adjustExtensionPriority(extensionPriority: ExtensionPriority): ExtensionPriority { + export function adjustExtensionPriority(extensionPriority: ExtensionPriority, supportedExtensions: string[]): ExtensionPriority { if (extensionPriority < ExtensionPriority.DeclarationAndJavaScriptFiles) { return ExtensionPriority.TypeScriptFiles; } - else if (extensionPriority < ExtensionPriority.Limit) { + else if (extensionPriority < supportedExtensions.length) { return ExtensionPriority.DeclarationAndJavaScriptFiles; } else { - return ExtensionPriority.Limit; - } - } + return supportedExtensions.length; + } } /** * Gets the next lowest extension priority for a given priority. */ - export function getNextLowestExtensionPriority(extensionPriority: ExtensionPriority): ExtensionPriority { + export function getNextLowestExtensionPriority(extensionPriority: ExtensionPriority, supportedExtensions: string[]): ExtensionPriority { if (extensionPriority < ExtensionPriority.DeclarationAndJavaScriptFiles) { return ExtensionPriority.DeclarationAndJavaScriptFiles; } else { - return ExtensionPriority.Limit; + return supportedExtensions.length; } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index b93e4eff9f4..e3128723aff 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3153,9 +3153,8 @@ ThisProperty } - export interface FileExtensionInfo { + export interface JsFileExtensionInfo { extension: string; - scriptKind: ScriptKind; isMixedContent: boolean; } diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index e6f4abde382..40a6c933242 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -1589,6 +1589,41 @@ namespace ts.projectSystem { checkProjectActualFiles(projectService.inferredProjects[1], [file2.path]); }); + it ("loading files with correct priority", () => { + const f1 = { + path: "/a/main.ts", + content: "let x = 1" + }; + const f2 = { + path: "/a/main.js", + content: "var y = 1" + }; + const config = { + path: "/a/tsconfig.json", + content: JSON.stringify({ + compilerOptions: { allowJs: true } + }) + }; + const host = createServerHost([f1, f2, config]); + const projectService = createProjectService(host); + projectService.setHostConfiguration({ + extraFileExtensions: [ + { extension: ".js", isMixedContent: false }, + { extension: ".html", isMixedContent: true } + ] + }); + projectService.openClientFile(f1.path); + projectService.checkNumberOfProjects({ configuredProjects: 1 }); + checkProjectActualFiles(projectService.configuredProjects[0], [ f1.path ]); + + projectService.closeClientFile(f1.path); + + projectService.openClientFile(f2.path); + projectService.checkNumberOfProjects({ configuredProjects: 1, inferredProjects: 1 }); + checkProjectActualFiles(projectService.configuredProjects[0], [ f1.path ]); + checkProjectActualFiles(projectService.inferredProjects[0], [ f2.path ]); + }); + it("tsconfig script block support", () => { const file1 = { path: "/a/b/f1.ts", diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index edc4fab9a19..36aa3939c83 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -107,7 +107,7 @@ namespace ts.server { export interface HostConfiguration { formatCodeOptions: FormatCodeSettings; hostInfo: string; - extraFileExtensions?: FileExtensionInfo[]; + extraFileExtensions?: JsFileExtensionInfo[]; } interface ConfigFileConversionResult { @@ -132,7 +132,7 @@ namespace ts.server { interface FilePropertyReader { getFileName(f: T): string; getScriptKind(f: T): ScriptKind; - hasMixedContent(f: T, extraFileExtensions: FileExtensionInfo[]): boolean; + hasMixedContent(f: T, extraFileExtensions: JsFileExtensionInfo[]): boolean; } const fileNamePropertyReader: FilePropertyReader = { diff --git a/src/server/protocol.ts b/src/server/protocol.ts index c1b78e9dbaa..e82eca86ba9 100644 --- a/src/server/protocol.ts +++ b/src/server/protocol.ts @@ -1001,9 +1001,9 @@ namespace ts.server.protocol { formatOptions?: FormatCodeSettings; /** - * The host's additional supported file extensions + * The host's additional supported .js file extensions */ - extraFileExtensions?: FileExtensionInfo[]; + extraFileExtensions?: JsFileExtensionInfo[]; } /**