Support 'tsconfig.json' when converting TextChanges to CodeEdits (#24667)

* Support 'tsconfig.json' when converting TextChanges to CodeEdits

* Create Project#getSourceFileOrConfigFile to use instead
This commit is contained in:
Andy 2018-06-07 14:30:19 -07:00 committed by GitHub
parent fde6f22408
commit 399ae51406
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 102 additions and 24 deletions

View File

@ -466,7 +466,7 @@ namespace ts.projectSystem {
return newRequest;
}
export function openFilesForSession(files: File[], session: server.Session) {
export function openFilesForSession(files: ReadonlyArray<File>, session: server.Session) {
for (const file of files) {
const request = makeSessionRequest<protocol.OpenRequestArgs>(CommandNames.Open, { file: file.path });
session.executeCommand(request);
@ -6192,6 +6192,69 @@ namespace ts.projectSystem {
renameLocation: { line: 2, offset: 3 },
});
});
it("handles text changes in tsconfig.json", () => {
const aTs = {
path: "/a.ts",
content: "export const a = 0;",
};
const tsconfig = {
path: "/tsconfig.json",
content: '{ "files": ["./a.ts"] }',
};
const session = createSession(createServerHost([aTs, tsconfig]));
openFilesForSession([aTs], session);
const response1 = session.executeCommandSeq<server.protocol.GetEditsForRefactorRequest>({
command: server.protocol.CommandTypes.GetEditsForRefactor,
arguments: {
refactor: "Move to a new file",
action: "Move to a new file",
file: "/a.ts",
startLine: 1,
startOffset: 1,
endLine: 1,
endOffset: 20,
},
}).response;
assert.deepEqual(response1, {
edits: [
{
fileName: "/a.ts",
textChanges: [
{
start: { line: 1, offset: 1 },
end: { line: 1, offset: 20 },
newText: "",
},
],
},
{
fileName: "/tsconfig.json",
textChanges: [
{
start: { line: 1, offset: 21 },
end: { line: 1, offset: 21 },
newText: ", \"./a.1.ts\"",
},
],
},
{
fileName: "/a.1.ts",
textChanges: [
{
start: { line: 0, offset: 0 },
end: { line: 0, offset: 0 },
newText: "export const a = 0;",
},
],
}
],
renameFilename: undefined,
renameLocation: undefined,
});
});
});
describe("tsserverProjectSystem CachingFileSystemInformation", () => {

View File

@ -550,6 +550,12 @@ namespace ts.server {
return this.program.getSourceFileByPath(path);
}
/* @internal */
getSourceFileOrConfigFile(path: Path): SourceFile | undefined {
const options = this.program.getCompilerOptions();
return path === options.configFilePath ? options.configFile : this.getSourceFile(path);
}
close() {
if (this.program) {
// if we have a program - release all files that are enlisted in program but arent root

View File

@ -1771,20 +1771,10 @@ namespace ts.server {
}
private mapTextChangesToCodeEdits(project: Project, textChanges: ReadonlyArray<FileTextChanges>): protocol.FileCodeEdits[] {
return textChanges.map(change => this.mapTextChangesToCodeEditsUsingScriptinfo(change, project.getScriptInfoForNormalizedPath(toNormalizedPath(change.fileName))!));
}
private mapTextChangesToCodeEditsUsingScriptinfo(textChanges: FileTextChanges, scriptInfo: ScriptInfo | undefined): protocol.FileCodeEdits {
Debug.assert(!!textChanges.isNewFile === !scriptInfo);
if (scriptInfo) {
return {
fileName: textChanges.fileName,
textChanges: textChanges.textChanges.map(textChange => this.convertTextChangeToCodeEdit(textChange, scriptInfo))
};
}
else {
return this.convertNewFileTextChangeToCodeEdit(textChanges);
}
return textChanges.map(change => {
const path = normalizedPathToPath(toNormalizedPath(change.fileName), this.host.getCurrentDirectory(), fileName => this.getCanonicalFileName(fileName));
return mapTextChangesToCodeEdits(change, project.getSourceFileOrConfigFile(path));
});
}
private convertTextChangeToCodeEdit(change: TextChange, scriptInfo: ScriptInfo): protocol.CodeEdit {
@ -1795,13 +1785,6 @@ namespace ts.server {
};
}
private convertNewFileTextChangeToCodeEdit(textChanges: FileTextChanges): protocol.FileCodeEdits {
Debug.assert(textChanges.textChanges.length === 1);
const change = first(textChanges.textChanges);
Debug.assert(change.span.start === 0 && change.span.length === 0);
return { fileName: textChanges.fileName, textChanges: [{ start: { line: 0, offset: 0 }, end: { line: 0, offset: 0 }, newText: change.newText }] };
}
private getBraceMatching(args: protocol.FileLocationRequestArgs, simplifiedResult: boolean): protocol.TextSpan[] | TextSpan[] | undefined {
const { file, languageService } = this.getFileAndLanguageServiceForSyntacticOperation(args);
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!;
@ -2280,6 +2263,34 @@ namespace ts.server {
}
}
function mapTextChangesToCodeEdits(textChanges: FileTextChanges, sourceFile: SourceFile | undefined): protocol.FileCodeEdits {
Debug.assert(!!textChanges.isNewFile === !sourceFile);
if (sourceFile) {
return {
fileName: textChanges.fileName,
textChanges: textChanges.textChanges.map(textChange => convertTextChangeToCodeEdit(textChange, sourceFile)),
};
}
else {
return convertNewFileTextChangeToCodeEdit(textChanges);
}
}
function convertTextChangeToCodeEdit(change: TextChange, sourceFile: SourceFile): protocol.CodeEdit {
return {
start: convertToLocation(sourceFile.getLineAndCharacterOfPosition(change.span.start)),
end: convertToLocation(sourceFile.getLineAndCharacterOfPosition(change.span.start + change.span.length)),
newText: change.newText ? change.newText : "",
};
}
function convertNewFileTextChangeToCodeEdit(textChanges: FileTextChanges): protocol.FileCodeEdits {
Debug.assert(textChanges.textChanges.length === 1);
const change = first(textChanges.textChanges);
Debug.assert(change.span.start === 0 && change.span.length === 0);
return { fileName: textChanges.fileName, textChanges: [{ start: { line: 0, offset: 0 }, end: { line: 0, offset: 0 }, newText: change.newText }] };
}
export interface HandlerResponse {
response?: {};
responseRequired?: boolean;

View File

@ -8564,9 +8564,7 @@ declare namespace ts.server {
private mapCodeAction;
private mapCodeFixAction;
private mapTextChangesToCodeEdits;
private mapTextChangesToCodeEditsUsingScriptinfo;
private convertTextChangeToCodeEdit;
private convertNewFileTextChangeToCodeEdit;
private getBraceMatching;
private getDiagnosticsForProject;
getCanonicalFileName(fileName: string): string;