From ded36b21ac5d47b7336fc83568f9d24caec479bd Mon Sep 17 00:00:00 2001 From: navya9singh <108360753+navya9singh@users.noreply.github.com> Date: Tue, 9 Jul 2024 10:27:41 -0700 Subject: [PATCH] pasteEdits returns no edit when there are no imports needed (#59189) --- src/harness/client.ts | 2 +- src/services/pasteEdits.ts | 10 ++++- .../unittests/tsserver/pasteEdits.ts | 7 ++- .../pasteEdits_noImportNeeded.js | 19 +------- .../pasteEdits_pasteComments.js | 19 +------- .../pasteEdits_pasteIntoSameFile.js | 19 +------- .../tsserver/pasteEdits/adds-paste-edits.js | 44 ++++++++++++++++--- .../server/pasteEdits_noImportNeeded.ts | 5 +-- .../server/pasteEdits_pasteComments.ts | 12 +---- .../server/pasteEdits_pasteIntoSameFile.ts | 9 +--- .../server/pasteEdits_unknownSourceFile.ts | 1 - 11 files changed, 60 insertions(+), 87 deletions(-) diff --git a/src/harness/client.ts b/src/harness/client.ts index 248624e4323..dc8561a2f3f 100644 --- a/src/harness/client.ts +++ b/src/harness/client.ts @@ -1029,7 +1029,7 @@ export class SessionClient implements LanguageService { }; const request = this.processRequest(protocol.CommandTypes.GetPasteEdits, args); const response = this.processResponse(request); - if (!response.body) { + if (response.body.edits.length === 0) { return { edits: [] }; } const edits: FileTextChanges[] = this.convertCodeEditsToTextChanges(response.body.edits); diff --git a/src/services/pasteEdits.ts b/src/services/pasteEdits.ts index 2aad38e571a..f3b35081678 100644 --- a/src/services/pasteEdits.ts +++ b/src/services/pasteEdits.ts @@ -71,8 +71,9 @@ function pasteEdits( newText = actualPastedText ? newText.slice(0, pos) + actualPastedText[0] + newText.slice(end) : newText.slice(0, pos) + pastedText[i] + newText.slice(end); } + let importAdder: codefix.ImportAdder; Debug.checkDefined(host.runWithTemporaryFileUpdate).call(host, targetFile.fileName, newText, (updatedProgram: Program, originalProgram: Program | undefined, updatedFile: SourceFile) => { - const importAdder = codefix.createImportAdder(updatedFile, updatedProgram, preferences, host); + importAdder = codefix.createImportAdder(updatedFile, updatedProgram, preferences, host); if (copiedFrom?.range) { Debug.assert(copiedFrom.range.length === pastedText.length); copiedFrom.range.forEach(copy => { @@ -115,6 +116,13 @@ function pasteEdits( } importAdder.writeFixes(changes, getQuotePreference(copiedFrom ? copiedFrom.file : targetFile, preferences)); }); + + /** + * If there are no import fixes, getPasteEdits should return without making any changes to the file. + */ + if (!importAdder!.hasFixes()) { + return; + } pasteLocations.forEach((paste, i) => { changes.replaceRangeWithText( targetFile, diff --git a/src/testRunner/unittests/tsserver/pasteEdits.ts b/src/testRunner/unittests/tsserver/pasteEdits.ts index 2af5d748040..82c2cd448ae 100644 --- a/src/testRunner/unittests/tsserver/pasteEdits.ts +++ b/src/testRunner/unittests/tsserver/pasteEdits.ts @@ -18,6 +18,11 @@ describe("unittests:: tsserver:: pasteEdits", () => { content: `const a = 1; const b = 2; const c = 3;`, + }; + const file1: File = { + path: "/project/a/file1.ts", + content: `export const r = 1; +export const s = 2;`, }; const tsconfig: File = { path: "/project/tsconfig.json", @@ -27,7 +32,7 @@ const c = 3;`, function e(); const f = r + s;`; - const host = createServerHost([target, tsconfig, libFile]); + const host = createServerHost([target, file1, tsconfig, libFile]); const session = new TestSession(host); openFilesForSession([target], session); diff --git a/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_noImportNeeded.js b/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_noImportNeeded.js index 9ef264793ba..f62638fbe1f 100644 --- a/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_noImportNeeded.js +++ b/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_noImportNeeded.js @@ -259,24 +259,7 @@ Info seq [hh:mm:ss:mss] response: "updateGraphDurationMs": * }, "body": { - "edits": [ - { - "fileName": "/b.ts", - "textChanges": [ - { - "start": { - "line": 1, - "offset": 1 - }, - "end": { - "line": 1, - "offset": 1 - }, - "newText": "export" - } - ] - } - ], + "edits": [], "fixId": "providePostPasteEdits" } } diff --git a/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_pasteComments.js b/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_pasteComments.js index b22f1c0b89d..23fa4420a90 100644 --- a/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_pasteComments.js +++ b/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_pasteComments.js @@ -229,24 +229,7 @@ Info seq [hh:mm:ss:mss] response: "updateGraphDurationMs": * }, "body": { - "edits": [ - { - "fileName": "/target.ts", - "textChanges": [ - { - "start": { - "line": 2, - "offset": 14 - }, - "end": { - "line": 2, - "offset": 14 - }, - "newText": "/**\n* Testing comment line 1\n* line 2\n* line 3\n* line 4\n*/" - } - ] - } - ], + "edits": [], "fixId": "providePostPasteEdits" } } diff --git a/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_pasteIntoSameFile.js b/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_pasteIntoSameFile.js index d0a9a96c500..5bc45bd498b 100644 --- a/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_pasteIntoSameFile.js +++ b/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_pasteIntoSameFile.js @@ -246,24 +246,7 @@ Info seq [hh:mm:ss:mss] response: "updateGraphDurationMs": * }, "body": { - "edits": [ - { - "fileName": "/target.ts", - "textChanges": [ - { - "start": { - "line": 4, - "offset": 1 - }, - "end": { - "line": 4, - "offset": 1 - }, - "newText": "console.log(k);" - } - ] - } - ], + "edits": [], "fixId": "providePostPasteEdits" } } diff --git a/tests/baselines/reference/tsserver/pasteEdits/adds-paste-edits.js b/tests/baselines/reference/tsserver/pasteEdits/adds-paste-edits.js index c64809b7709..95c35efd4af 100644 --- a/tests/baselines/reference/tsserver/pasteEdits/adds-paste-edits.js +++ b/tests/baselines/reference/tsserver/pasteEdits/adds-paste-edits.js @@ -6,6 +6,10 @@ const a = 1; const b = 2; const c = 3; +//// [/project/a/file1.ts] +export const r = 1; +export const s = 2; + //// [/project/tsconfig.json] {} @@ -47,6 +51,7 @@ Info seq [hh:mm:ss:mss] event: } Info seq [hh:mm:ss:mss] Config: /project/tsconfig.json : { "rootNames": [ + "/project/a/file1.ts", "/project/a/target.ts" ], "options": { @@ -55,17 +60,21 @@ Info seq [hh:mm:ss:mss] Config: /project/tsconfig.json : { } Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /project 1 undefined Config: /project/tsconfig.json WatchType: Wild card directory Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /project 1 undefined Config: /project/tsconfig.json WatchType: Wild card directory +Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /project/a/file1.ts 500 undefined WatchType: Closed Script info Info seq [hh:mm:ss:mss] Starting updateGraphWorker: Project: /project/tsconfig.json Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 500 undefined WatchType: Closed Script info Info seq [hh:mm:ss:mss] Finishing updateGraphWorker: Project: /project/tsconfig.json projectStateVersion: 1 projectProgramVersion: 0 structureChanged: true structureIsReused:: Not Elapsed:: *ms Info seq [hh:mm:ss:mss] Project '/project/tsconfig.json' (Configured) -Info seq [hh:mm:ss:mss] Files (2) +Info seq [hh:mm:ss:mss] Files (3) /a/lib/lib.d.ts Text-1 "/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }" + /project/a/file1.ts Text-1 "export const r = 1;\nexport const s = 2;" /project/a/target.ts SVC-1-0 "const a = 1;\nconst b = 2;\nconst c = 3;" ../a/lib/lib.d.ts Default library for target 'es5' + a/file1.ts + Matched by default include pattern '**/*' a/target.ts Matched by default include pattern '**/*' @@ -93,8 +102,8 @@ Info seq [hh:mm:ss:mss] event: "jsSize": 0, "jsx": 0, "jsxSize": 0, - "ts": 1, - "tsSize": 38, + "ts": 2, + "tsSize": 77, "tsx": 0, "tsxSize": 0, "dts": 1, @@ -132,7 +141,7 @@ Info seq [hh:mm:ss:mss] event: } } Info seq [hh:mm:ss:mss] Project '/project/tsconfig.json' (Configured) -Info seq [hh:mm:ss:mss] Files (2) +Info seq [hh:mm:ss:mss] Files (3) Info seq [hh:mm:ss:mss] ----------------------------------------------- Info seq [hh:mm:ss:mss] Open files: @@ -154,6 +163,8 @@ After request FsWatches:: /a/lib/lib.d.ts: *new* {} +/project/a/file1.ts: *new* + {} /project/tsconfig.json: *new* {} @@ -171,6 +182,10 @@ ScriptInfos:: version: Text-1 containingProjects: 1 /project/tsconfig.json +/project/a/file1.ts *new* + version: Text-1 + containingProjects: 1 + /project/tsconfig.json /project/a/target.ts (Open) *new* version: SVC-1-0 containingProjects: 1 @@ -205,8 +220,9 @@ Info seq [hh:mm:ss:mss] request: Info seq [hh:mm:ss:mss] Starting updateGraphWorker: Project: /project/tsconfig.json Info seq [hh:mm:ss:mss] Finishing updateGraphWorker: Project: /project/tsconfig.json projectStateVersion: 2 projectProgramVersion: 1 structureChanged: false structureIsReused:: Completely Elapsed:: *ms Info seq [hh:mm:ss:mss] Project '/project/tsconfig.json' (Configured) -Info seq [hh:mm:ss:mss] Files (2) +Info seq [hh:mm:ss:mss] Files (3) /a/lib/lib.d.ts Text-1 "/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }" + /project/a/file1.ts Text-1 "export const r = 1;\nexport const s = 2;" /project/a/target.ts SVC-1-1 "const a = 1;const q = 1;\nfunction e();\nconst f = r + s;\nconst b = 2;\nconst c = 3;" Info seq [hh:mm:ss:mss] ----------------------------------------------- @@ -217,6 +233,17 @@ Info seq [hh:mm:ss:mss] response: { "fileName": "/project/a/target.ts", "textChanges": [ + { + "start": { + "line": 1, + "offset": 1 + }, + "end": { + "line": 1, + "offset": 1 + }, + "newText": "import { r, s } from \"./file1\";\n\n" + }, { "start": { "line": 1, @@ -251,6 +278,10 @@ ScriptInfos:: version: Text-1 containingProjects: 1 /project/tsconfig.json +/project/a/file1.ts + version: Text-1 + containingProjects: 1 + /project/tsconfig.json /project/a/target.ts (Open) *changed* version: SVC-1-2 *changed* containingProjects: 1 @@ -281,8 +312,9 @@ Before running Timeout callback:: count: 1 Info seq [hh:mm:ss:mss] Starting updateGraphWorker: Project: /project/tsconfig.json Info seq [hh:mm:ss:mss] Finishing updateGraphWorker: Project: /project/tsconfig.json projectStateVersion: 3 projectProgramVersion: 1 structureChanged: false structureIsReused:: Completely Elapsed:: *ms Info seq [hh:mm:ss:mss] Project '/project/tsconfig.json' (Configured) -Info seq [hh:mm:ss:mss] Files (2) +Info seq [hh:mm:ss:mss] Files (3) /a/lib/lib.d.ts Text-1 "/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }" + /project/a/file1.ts Text-1 "export const r = 1;\nexport const s = 2;" /project/a/target.ts SVC-1-2 "const a = 1;\nconst b = 2;\nconst c = 3;" Info seq [hh:mm:ss:mss] ----------------------------------------------- diff --git a/tests/cases/fourslash/server/pasteEdits_noImportNeeded.ts b/tests/cases/fourslash/server/pasteEdits_noImportNeeded.ts index c23f3d69f30..156386a86ac 100644 --- a/tests/cases/fourslash/server/pasteEdits_noImportNeeded.ts +++ b/tests/cases/fourslash/server/pasteEdits_noImportNeeded.ts @@ -18,8 +18,5 @@ verify.pasteEdits({ pasteLocations: [range[0]], copiedFrom: { file: "a.ts", range: [range[1]] }, }, - newFileContents: { - "/b.ts": -`export` - } + newFileContents: {} }); diff --git a/tests/cases/fourslash/server/pasteEdits_pasteComments.ts b/tests/cases/fourslash/server/pasteEdits_pasteComments.ts index 49d621d2138..aa2d9ba943f 100644 --- a/tests/cases/fourslash/server/pasteEdits_pasteComments.ts +++ b/tests/cases/fourslash/server/pasteEdits_pasteComments.ts @@ -19,15 +19,5 @@ verify.pasteEdits({ */`], pasteLocations: [range[0]], }, - newFileContents: { - "/target.ts": -`const a = 10; -const b = 10;/** -* Testing comment line 1 -* line 2 -* line 3 -* line 4 -*/ -const c = 10;` - } + newFileContents: {} }); \ No newline at end of file diff --git a/tests/cases/fourslash/server/pasteEdits_pasteIntoSameFile.ts b/tests/cases/fourslash/server/pasteEdits_pasteIntoSameFile.ts index 068d4234447..06bedadcd17 100644 --- a/tests/cases/fourslash/server/pasteEdits_pasteIntoSameFile.ts +++ b/tests/cases/fourslash/server/pasteEdits_pasteIntoSameFile.ts @@ -17,12 +17,5 @@ verify.pasteEdits({ pasteLocations: [range[1]], copiedFrom: { file: "target.ts", range: [range[0]] }, }, - newFileContents: { - "/target.ts": -`const k = 1; -console.log(k); - -console.log(k); -console.log("test");` - } + newFileContents: {} }); diff --git a/tests/cases/fourslash/server/pasteEdits_unknownSourceFile.ts b/tests/cases/fourslash/server/pasteEdits_unknownSourceFile.ts index f8175850ff1..afd370f875a 100644 --- a/tests/cases/fourslash/server/pasteEdits_unknownSourceFile.ts +++ b/tests/cases/fourslash/server/pasteEdits_unknownSourceFile.ts @@ -38,5 +38,4 @@ interface Testing { test4: Test4; }const c = 10;` }, - fixId: "providePostPasteEdits" }); \ No newline at end of file