diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 4988e2091b..765b5de4f3 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2748,6 +2748,10 @@ "category": "Message", "code": 6128 }, + "The config file '{0}' found doesn't contain any source files.": { + "category": "Error", + "code": 6129 + }, "Variable '{0}' implicitly has an '{1}' type.": { "category": "Error", "code": 7005 diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 32beec0542..ae628e713d 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -1096,12 +1096,12 @@ 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) { - this.openOrUpdateConfiguredProjectForFile(fileName); + openClientFile(fileName: string, fileContent?: string, scriptKind?: ScriptKind): { info: ScriptInfo, configFileName?: string, configFileErrors?: Diagnostic[] } { + const { configFileName, configFileErrors } = this.openOrUpdateConfiguredProjectForFile(fileName); const info = this.openFile(fileName, /*openedByClient*/ true, fileContent, scriptKind); this.addOpenFile(info); this.printProjects(); - return info; + return { info, configFileName, configFileErrors }; } /** @@ -1109,7 +1109,7 @@ 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. */ - openOrUpdateConfiguredProjectForFile(fileName: string) { + openOrUpdateConfiguredProjectForFile(fileName: string): { configFileName?: string, configFileErrors?: Diagnostic[] } { const searchPath = ts.normalizePath(getDirectoryPath(fileName)); this.log("Search path: " + searchPath, "Info"); const configFileName = this.findConfigFile(searchPath); @@ -1119,7 +1119,7 @@ namespace ts.server { if (!project) { const configResult = this.openConfigFile(configFileName, fileName); if (!configResult.success) { - this.log("Error opening config file " + configFileName + " " + configResult.errorMsg); + return { configFileName, configFileErrors: configResult.errors }; } else { this.log("Opened configuration file " + configFileName, "Info"); @@ -1133,6 +1133,7 @@ namespace ts.server { else { this.log("No config files found."); } + return {}; } /** @@ -1222,24 +1223,25 @@ namespace ts.server { return undefined; } - configFileToProjectOptions(configFilename: string): { succeeded: boolean, projectOptions?: ProjectOptions, error?: ProjectOpenResult } { + configFileToProjectOptions(configFilename: string): { succeeded: boolean, projectOptions?: ProjectOptions, errors?: Diagnostic[] } { configFilename = ts.normalizePath(configFilename); // file references will be relative to dirPath (or absolute) const dirPath = ts.getDirectoryPath(configFilename); const contents = this.host.readFile(configFilename); const rawConfig: { config?: ProjectOptions; error?: Diagnostic; } = ts.parseConfigFileTextToJson(configFilename, contents); if (rawConfig.error) { - return { succeeded: false, error: rawConfig.error }; + return { succeeded: false, errors: [rawConfig.error] }; } else { const parsedCommandLine = ts.parseJsonConfigFileContent(rawConfig.config, this.host, dirPath, /*existingOptions*/ {}, configFilename); Debug.assert(!!parsedCommandLine.fileNames); if (parsedCommandLine.errors && (parsedCommandLine.errors.length > 0)) { - return { succeeded: false, error: { errorMsg: "tsconfig option errors" } }; + return { succeeded: false, errors: parsedCommandLine.errors }; } else if (parsedCommandLine.fileNames.length === 0) { - return { succeeded: false, error: { errorMsg: "no files found" } }; + const error = createCompilerDiagnostic(Diagnostics.The_config_file_0_found_doesn_t_contain_any_source_files, configFilename); + return { succeeded: false, errors: [error] }; } else { const projectOptions: ProjectOptions = { @@ -1252,10 +1254,10 @@ namespace ts.server { } - openConfigFile(configFilename: string, clientFileName?: string): ProjectOpenResult { - const { succeeded, projectOptions, error } = this.configFileToProjectOptions(configFilename); + openConfigFile(configFilename: string, clientFileName?: string): { success: boolean, project?: Project, errors?: Diagnostic[] } { + const { succeeded, projectOptions, errors } = this.configFileToProjectOptions(configFilename); if (!succeeded) { - return error; + return { success: false, errors }; } else { const project = this.createProject(configFilename, projectOptions); @@ -1265,7 +1267,8 @@ namespace ts.server { project.addRoot(info); } else { - return { errorMsg: "specified file " + rootFilename + " not found" }; + const error = createCompilerDiagnostic(Diagnostics.File_0_not_found, rootFilename); + return { success: false, errors: [error] }; } } project.finishGraph(); @@ -1286,9 +1289,9 @@ namespace ts.server { this.removeProject(project); } else { - const { succeeded, projectOptions, error } = this.configFileToProjectOptions(project.projectFilename); + const { succeeded, projectOptions, errors } = this.configFileToProjectOptions(project.projectFilename); if (!succeeded) { - return error; + return errors; } else { const oldFileNames = project.compilerService.host.roots.map(info => info.fileName); diff --git a/src/server/session.ts b/src/server/session.ts index e043fff224..2ddccc94c8 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -561,7 +561,10 @@ namespace ts.server { */ private openClientFile(fileName: string, fileContent?: string, scriptKind?: ScriptKind) { const file = ts.normalizePath(fileName); - this.projectService.openClientFile(file, fileContent, scriptKind); + const { info, configFileName, configFileErrors } = this.projectService.openClientFile(file, fileContent, scriptKind); + if (configFileErrors) { + this.event({ triggerFile: fileName, configFile: configFileName, diagnostics: configFileErrors }, "configFileDiag"); + } } private getQuickInfo(line: number, offset: number, fileName: string): protocol.QuickInfoResponseBody {