Improve error message when scriptInfo is missing in mapTextChangeToCodeEdit (#28258)

* Improve error message when scriptInfo is missing in mapTextChangeToCodeEdit

* Include both fileName and path, and use in more places

* Move logErrorForScriptInfoNotFound to editorServices.ts

* Update API
This commit is contained in:
Andy 2018-11-02 16:12:46 -07:00 committed by GitHub
parent ce85ee5115
commit 92a48d8880
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 22 additions and 11 deletions

View file

@ -867,7 +867,7 @@ namespace ts.server {
private doEnsureDefaultProjectForFile(fileName: NormalizedPath): Project {
this.ensureProjectStructuresUptoDate();
const scriptInfo = this.getScriptInfoForNormalizedPath(fileName);
return scriptInfo ? scriptInfo.getDefaultProject() : Errors.ThrowNoProject();
return scriptInfo ? scriptInfo.getDefaultProject() : (this.logErrorForScriptInfoNotFound(fileName), Errors.ThrowNoProject());
}
getScriptInfoEnsuringProjectsUptoDate(uncheckedFileName: string) {
@ -1966,6 +1966,12 @@ namespace ts.server {
return configProject && configProject.getCompilerOptions().configFile;
}
/* @internal */
logErrorForScriptInfoNotFound(fileName: string): void {
const names = arrayFrom(this.filenameToScriptInfo.entries()).map(([path, scriptInfo]) => ({ path, fileName: scriptInfo.fileName }));
this.logger.msg(`Could not find file ${JSON.stringify(fileName)}.\nAll files are: ${JSON.stringify(names)}`, Msg.Err);
}
/**
* Returns the projects that contain script info through SymLink
* Note that this does not return projects in info.containingProjects

View file

@ -1157,7 +1157,9 @@ namespace ts.server {
this.projectService.getScriptInfoEnsuringProjectsUptoDate(args.file) :
this.projectService.getScriptInfo(args.file);
if (!scriptInfo) {
return ignoreNoProjectError ? emptyArray : Errors.ThrowNoProject();
if (ignoreNoProjectError) return emptyArray;
this.projectService.logErrorForScriptInfoNotFound(args.file);
return Errors.ThrowNoProject();
}
projects = scriptInfo.containingProjects;
symLinkedProjects = this.projectService.getSymlinkedProjects(scriptInfo);
@ -1165,6 +1167,7 @@ namespace ts.server {
// filter handles case when 'projects' is undefined
projects = filter(projects, p => p.languageServiceEnabled && !p.isOrphan());
if (!ignoreNoProjectError && (!projects || !projects.length) && !symLinkedProjects) {
this.projectService.logErrorForScriptInfoNotFound(args.file);
return Errors.ThrowNoProject();
}
return symLinkedProjects ? { projects: projects!, symLinkedProjects } : projects!; // TODO: GH#18217
@ -1908,8 +1911,17 @@ namespace ts.server {
return textChanges.map(change => this.mapTextChangeToCodeEdit(change));
}
private mapTextChangeToCodeEdit(change: FileTextChanges): protocol.FileCodeEdits {
return mapTextChangesToCodeEdits(change, this.projectService.getScriptInfoOrConfig(change.fileName));
private mapTextChangeToCodeEdit(textChanges: FileTextChanges): protocol.FileCodeEdits {
const scriptInfo = this.projectService.getScriptInfoOrConfig(textChanges.fileName);
if (!!textChanges.isNewFile === !!scriptInfo) {
if (!scriptInfo) { // and !isNewFile
this.projectService.logErrorForScriptInfoNotFound(textChanges.fileName);
}
Debug.fail("Expected isNewFile for (only) new files. " + JSON.stringify({ isNewFile: !!textChanges.isNewFile, hasScriptInfo: !!scriptInfo }));
}
return scriptInfo
? { fileName: textChanges.fileName, textChanges: textChanges.textChanges.map(textChange => convertTextChangeToCodeEdit(textChange, scriptInfo)) }
: convertNewFileTextChangeToCodeEdit(textChanges);
}
private convertTextChangeToCodeEdit(change: TextChange, scriptInfo: ScriptInfo): protocol.CodeEdit {
@ -2431,13 +2443,6 @@ namespace ts.server {
return { file: fileName, start: scriptInfo.positionToLineOffset(textSpan.start), end: scriptInfo.positionToLineOffset(textSpanEnd(textSpan)) };
}
function mapTextChangesToCodeEdits(textChanges: FileTextChanges, scriptInfo: ScriptInfoOrConfig | undefined): protocol.FileCodeEdits {
Debug.assert(!!textChanges.isNewFile === !scriptInfo, "Expected isNewFile for (only) new files", () => JSON.stringify({ isNewFile: !!textChanges.isNewFile, hasScriptInfo: !!scriptInfo }));
return scriptInfo
? { fileName: textChanges.fileName, textChanges: textChanges.textChanges.map(textChange => convertTextChangeToCodeEdit(textChange, scriptInfo)) }
: convertNewFileTextChangeToCodeEdit(textChanges);
}
function convertTextChangeToCodeEdit(change: TextChange, scriptInfo: ScriptInfoOrConfig): protocol.CodeEdit {
return { start: positionToLineOffset(scriptInfo, change.span.start), end: positionToLineOffset(scriptInfo, textSpanEnd(change.span)), newText: change.newText };
}