Skip to content

Commit 399ae51

Browse files
author
Andy
authored
Support 'tsconfig.json' when converting TextChanges to CodeEdits (microsoft#24667)
* Support 'tsconfig.json' when converting TextChanges to CodeEdits * Create Project#getSourceFileOrConfigFile to use instead
1 parent fde6f22 commit 399ae51

4 files changed

Lines changed: 102 additions & 24 deletions

File tree

src/harness/unittests/tsserverProjectSystem.ts

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,7 @@ namespace ts.projectSystem {
466466
return newRequest;
467467
}
468468

469-
export function openFilesForSession(files: File[], session: server.Session) {
469+
export function openFilesForSession(files: ReadonlyArray<File>, session: server.Session) {
470470
for (const file of files) {
471471
const request = makeSessionRequest<protocol.OpenRequestArgs>(CommandNames.Open, { file: file.path });
472472
session.executeCommand(request);
@@ -6192,6 +6192,69 @@ namespace ts.projectSystem {
61926192
renameLocation: { line: 2, offset: 3 },
61936193
});
61946194
});
6195+
6196+
it("handles text changes in tsconfig.json", () => {
6197+
const aTs = {
6198+
path: "/a.ts",
6199+
content: "export const a = 0;",
6200+
};
6201+
const tsconfig = {
6202+
path: "/tsconfig.json",
6203+
content: '{ "files": ["./a.ts"] }',
6204+
};
6205+
6206+
const session = createSession(createServerHost([aTs, tsconfig]));
6207+
openFilesForSession([aTs], session);
6208+
6209+
const response1 = session.executeCommandSeq<server.protocol.GetEditsForRefactorRequest>({
6210+
command: server.protocol.CommandTypes.GetEditsForRefactor,
6211+
arguments: {
6212+
refactor: "Move to a new file",
6213+
action: "Move to a new file",
6214+
file: "/a.ts",
6215+
startLine: 1,
6216+
startOffset: 1,
6217+
endLine: 1,
6218+
endOffset: 20,
6219+
},
6220+
}).response;
6221+
assert.deepEqual(response1, {
6222+
edits: [
6223+
{
6224+
fileName: "/a.ts",
6225+
textChanges: [
6226+
{
6227+
start: { line: 1, offset: 1 },
6228+
end: { line: 1, offset: 20 },
6229+
newText: "",
6230+
},
6231+
],
6232+
},
6233+
{
6234+
fileName: "/tsconfig.json",
6235+
textChanges: [
6236+
{
6237+
start: { line: 1, offset: 21 },
6238+
end: { line: 1, offset: 21 },
6239+
newText: ", \"./a.1.ts\"",
6240+
},
6241+
],
6242+
},
6243+
{
6244+
fileName: "/a.1.ts",
6245+
textChanges: [
6246+
{
6247+
start: { line: 0, offset: 0 },
6248+
end: { line: 0, offset: 0 },
6249+
newText: "export const a = 0;",
6250+
},
6251+
],
6252+
}
6253+
],
6254+
renameFilename: undefined,
6255+
renameLocation: undefined,
6256+
});
6257+
});
61956258
});
61966259

61976260
describe("tsserverProjectSystem CachingFileSystemInformation", () => {

src/server/project.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,12 @@ namespace ts.server {
550550
return this.program.getSourceFileByPath(path);
551551
}
552552

553+
/* @internal */
554+
getSourceFileOrConfigFile(path: Path): SourceFile | undefined {
555+
const options = this.program.getCompilerOptions();
556+
return path === options.configFilePath ? options.configFile : this.getSourceFile(path);
557+
}
558+
553559
close() {
554560
if (this.program) {
555561
// if we have a program - release all files that are enlisted in program but arent root

src/server/session.ts

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1771,20 +1771,10 @@ namespace ts.server {
17711771
}
17721772

17731773
private mapTextChangesToCodeEdits(project: Project, textChanges: ReadonlyArray<FileTextChanges>): protocol.FileCodeEdits[] {
1774-
return textChanges.map(change => this.mapTextChangesToCodeEditsUsingScriptinfo(change, project.getScriptInfoForNormalizedPath(toNormalizedPath(change.fileName))!));
1775-
}
1776-
1777-
private mapTextChangesToCodeEditsUsingScriptinfo(textChanges: FileTextChanges, scriptInfo: ScriptInfo | undefined): protocol.FileCodeEdits {
1778-
Debug.assert(!!textChanges.isNewFile === !scriptInfo);
1779-
if (scriptInfo) {
1780-
return {
1781-
fileName: textChanges.fileName,
1782-
textChanges: textChanges.textChanges.map(textChange => this.convertTextChangeToCodeEdit(textChange, scriptInfo))
1783-
};
1784-
}
1785-
else {
1786-
return this.convertNewFileTextChangeToCodeEdit(textChanges);
1787-
}
1774+
return textChanges.map(change => {
1775+
const path = normalizedPathToPath(toNormalizedPath(change.fileName), this.host.getCurrentDirectory(), fileName => this.getCanonicalFileName(fileName));
1776+
return mapTextChangesToCodeEdits(change, project.getSourceFileOrConfigFile(path));
1777+
});
17881778
}
17891779

17901780
private convertTextChangeToCodeEdit(change: TextChange, scriptInfo: ScriptInfo): protocol.CodeEdit {
@@ -1795,13 +1785,6 @@ namespace ts.server {
17951785
};
17961786
}
17971787

1798-
private convertNewFileTextChangeToCodeEdit(textChanges: FileTextChanges): protocol.FileCodeEdits {
1799-
Debug.assert(textChanges.textChanges.length === 1);
1800-
const change = first(textChanges.textChanges);
1801-
Debug.assert(change.span.start === 0 && change.span.length === 0);
1802-
return { fileName: textChanges.fileName, textChanges: [{ start: { line: 0, offset: 0 }, end: { line: 0, offset: 0 }, newText: change.newText }] };
1803-
}
1804-
18051788
private getBraceMatching(args: protocol.FileLocationRequestArgs, simplifiedResult: boolean): protocol.TextSpan[] | TextSpan[] | undefined {
18061789
const { file, languageService } = this.getFileAndLanguageServiceForSyntacticOperation(args);
18071790
const scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file)!;
@@ -2280,6 +2263,34 @@ namespace ts.server {
22802263
}
22812264
}
22822265

2266+
function mapTextChangesToCodeEdits(textChanges: FileTextChanges, sourceFile: SourceFile | undefined): protocol.FileCodeEdits {
2267+
Debug.assert(!!textChanges.isNewFile === !sourceFile);
2268+
if (sourceFile) {
2269+
return {
2270+
fileName: textChanges.fileName,
2271+
textChanges: textChanges.textChanges.map(textChange => convertTextChangeToCodeEdit(textChange, sourceFile)),
2272+
};
2273+
}
2274+
else {
2275+
return convertNewFileTextChangeToCodeEdit(textChanges);
2276+
}
2277+
}
2278+
2279+
function convertTextChangeToCodeEdit(change: TextChange, sourceFile: SourceFile): protocol.CodeEdit {
2280+
return {
2281+
start: convertToLocation(sourceFile.getLineAndCharacterOfPosition(change.span.start)),
2282+
end: convertToLocation(sourceFile.getLineAndCharacterOfPosition(change.span.start + change.span.length)),
2283+
newText: change.newText ? change.newText : "",
2284+
};
2285+
}
2286+
2287+
function convertNewFileTextChangeToCodeEdit(textChanges: FileTextChanges): protocol.FileCodeEdits {
2288+
Debug.assert(textChanges.textChanges.length === 1);
2289+
const change = first(textChanges.textChanges);
2290+
Debug.assert(change.span.start === 0 && change.span.length === 0);
2291+
return { fileName: textChanges.fileName, textChanges: [{ start: { line: 0, offset: 0 }, end: { line: 0, offset: 0 }, newText: change.newText }] };
2292+
}
2293+
22832294
export interface HandlerResponse {
22842295
response?: {};
22852296
responseRequired?: boolean;

tests/baselines/reference/api/tsserverlibrary.d.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8564,9 +8564,7 @@ declare namespace ts.server {
85648564
private mapCodeAction;
85658565
private mapCodeFixAction;
85668566
private mapTextChangesToCodeEdits;
8567-
private mapTextChangesToCodeEditsUsingScriptinfo;
85688567
private convertTextChangeToCodeEdit;
8569-
private convertNewFileTextChangeToCodeEdit;
85708568
private getBraceMatching;
85718569
private getDiagnosticsForProject;
85728570
getCanonicalFileName(fileName: string): string;

0 commit comments

Comments
 (0)