diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 91d400ff263..1b9ea292357 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -304,7 +304,7 @@ namespace ts.server { return this.projectService.openFile(filename, false); } - getFileNameList() { + getFileNames() { let sourceFiles = this.program.getSourceFiles(); return sourceFiles.map(sourceFile => sourceFile.fileName); } diff --git a/src/server/protocol.d.ts b/src/server/protocol.d.ts index 017a8c1d81a..a40ca1f1318 100644 --- a/src/server/protocol.d.ts +++ b/src/server/protocol.d.ts @@ -116,7 +116,7 @@ declare namespace ts.server.protocol { /** * The list of normalized file name in the project, including 'lib.d.ts' */ - fileNameList?: string[]; + fileNames?: string[]; } /** @@ -854,6 +854,31 @@ declare namespace ts.server.protocol { export interface SignatureHelpResponse extends Response { body?: SignatureHelpItems; } + + /** + * Arguments for geterrForProject request. + */ + export interface GeterrForProjectRequestArgs { + /** + * the file requesting project error list + */ + file: string; + + /** + * Delay in milliseconds to wait before starting to compute + * errors for the files in the file list + */ + delay: number; + } + + /** + * GeterrForProjectRequest request; value of command field is + * "geterrForProject". It works similarly with 'Geterr', only + * it request for every file in this project. + */ + export interface GeterrForProjectRequest extends Request { + arguments: GeterrForProjectRequestArgs + } /** * Arguments for geterr messages. diff --git a/src/server/session.ts b/src/server/session.ts index c95b1a7cc1b..c35cdedffe9 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -86,6 +86,7 @@ namespace ts.server { export const Format = "format"; export const Formatonkey = "formatonkey"; export const Geterr = "geterr"; + export const GeterrForProject = "geterrForProject"; export const NavBar = "navbar"; export const Navto = "navto"; export const Occurrences = "occurrences"; @@ -344,15 +345,15 @@ namespace ts.server { } getProjectInfo(fileName: string, needFileNameList: boolean): protocol.ProjectInfo { - fileName = ts.normalizePath(fileName) - let project = this.projectService.getProjectForFile(fileName) + fileName = ts.normalizePath(fileName); + let project = this.projectService.getProjectForFile(fileName); let projectInfo: protocol.ProjectInfo = { configFileName: project.projectFilename } if (needFileNameList) { - projectInfo.fileNameList = project.getFileNameList(); + projectInfo.fileNames = project.getFileNames(); } return projectInfo; @@ -836,6 +837,51 @@ namespace ts.server { })); } + getDiagnosticsForProject(delay: number, fileName: string) { + let { configFileName, fileNames: fileNamesInProject } = this.getProjectInfo(fileName, true); + // No need to analyze lib.d.ts + fileNamesInProject = fileNamesInProject.filter((value, index, array) => value.indexOf("lib.d.ts") < 0); + + // Sort the file name list to make the recently touched files come first + let highPriorityFiles: string[] = []; + let mediumPriorityFiles: string[] = []; + let lowPriorityFiles: string[] = []; + let veryLowPriorityFiles: string[] = []; + let normalizedFileName = ts.normalizePath(fileName); + let project = this.projectService.getProjectForFile(normalizedFileName); + for (let fileNameInProject of fileNamesInProject) { + if (this.getCanonicalFileName(fileNameInProject) == this.getCanonicalFileName(fileName)) + highPriorityFiles.push(fileNameInProject); + else { + let info = this.projectService.getScriptInfo(fileNameInProject); + if (!info || !info.isOpen) { + if (fileNameInProject.indexOf(".d.ts") > 0) + veryLowPriorityFiles.push(fileNameInProject); + else + lowPriorityFiles.push(fileNameInProject); + } + else + mediumPriorityFiles.push(fileNameInProject); + } + } + + fileNamesInProject = highPriorityFiles.concat(mediumPriorityFiles).concat(lowPriorityFiles).concat(veryLowPriorityFiles); + + if (fileNamesInProject.length > 0) { + let checkList = fileNamesInProject.map((fileName: string) => { + let normalizedFileName = ts.normalizePath(fileName); + return { fileName: normalizedFileName, project }; + }); + this.updateErrorCheck(checkList, this.changeSeq, (n) => n == this.changeSeq, delay); + } + } + + getCanonicalFileName(fileName: string) { + let name = this.host.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(); + this.logger.info(ts.normalizePath(name)); + return ts.normalizePath(name); + } + exit() { } @@ -919,6 +965,13 @@ namespace ts.server { responseRequired = false; break; } + case CommandNames.GeterrForProject: { + this.logger.info(request.arguments); + let { file, delay } = request.arguments; + response = this.getDiagnosticsForProject(delay, file); + responseRequired = false; + break; + } case CommandNames.Change: { var changeArgs = request.arguments; this.change(changeArgs.line, changeArgs.offset, changeArgs.endLine, changeArgs.endOffset,