From 57202316e2e5054479cb525ac7405276ef4faac0 Mon Sep 17 00:00:00 2001 From: navya9singh Date: Mon, 1 Jul 2024 11:39:48 -0700 Subject: [PATCH 1/5] fixes for not adding imports that are not needed --- src/services/pasteEdits.ts | 2 +- src/services/refactors/moveToFile.ts | 15 +- .../pasteEdits_noImportNeeded.js | 299 ++++++++++++++++++ .../server/pasteEdits_noImportNeeded.ts | 25 ++ 4 files changed, 335 insertions(+), 6 deletions(-) create mode 100644 tests/baselines/reference/tsserver/fourslashServer/pasteEdits_noImportNeeded.js create mode 100644 tests/cases/fourslash/server/pasteEdits_noImportNeeded.ts diff --git a/src/services/pasteEdits.ts b/src/services/pasteEdits.ts index 9b67d62e96576..2aad38e571ae3 100644 --- a/src/services/pasteEdits.ts +++ b/src/services/pasteEdits.ts @@ -90,7 +90,7 @@ function pasteEdits( } statements.push(...statementsInSourceFile.slice(startNodeIndex, endNodeIndex === -1 ? statementsInSourceFile.length : endNodeIndex + 1)); }); - const usage = getUsageInfo(copiedFrom.file, statements, originalProgram!.getTypeChecker(), getExistingLocals(updatedFile, statements, originalProgram!.getTypeChecker())); + const usage = getUsageInfo(copiedFrom.file, statements, originalProgram!.getTypeChecker(), getExistingLocals(updatedFile, statements, originalProgram!.getTypeChecker()), { pos: copiedFrom.range[0].pos, end: copiedFrom.range[copiedFrom.range.length - 1].end }); Debug.assertIsDefined(originalProgram); const useEsModuleSyntax = !fileShouldUseJavaScriptRequire(targetFile.fileName, originalProgram, host, !!copiedFrom.file.commonJsModuleIndicator); addExportsInOldFile(copiedFrom.file, usage.targetFileImportsFromOldFile, changes, useEsModuleSyntax); diff --git a/src/services/refactors/moveToFile.ts b/src/services/refactors/moveToFile.ts index 8f94d31327d4e..4b248c04c0b14 100644 --- a/src/services/refactors/moveToFile.ts +++ b/src/services/refactors/moveToFile.ts @@ -129,6 +129,7 @@ import { PropertyAccessExpression, PropertyAssignment, QuotePreference, + rangeContainsRange, RefactorContext, RefactorEditInfo, RequireOrImportCall, @@ -145,6 +146,7 @@ import { SyntaxKind, takeWhile, textChanges, + TextRange, TransformFlags, tryCast, TypeAliasDeclaration, @@ -871,7 +873,7 @@ function isPureImport(node: Node): boolean { } /** @internal */ -export function getUsageInfo(oldFile: SourceFile, toMove: readonly Statement[], checker: TypeChecker, existingTargetLocals: ReadonlySet = new Set()): UsageInfo { +export function getUsageInfo(oldFile: SourceFile, toMove: readonly Statement[], checker: TypeChecker, existingTargetLocals: ReadonlySet = new Set(), enclosingRange?: TextRange): UsageInfo { const movedSymbols = new Set(); const oldImportsNeededByTargetFile = new Map(); const targetFileImportsFromOldFile = new Map(); @@ -890,7 +892,7 @@ export function getUsageInfo(oldFile: SourceFile, toMove: readonly Statement[], const unusedImportsFromOldFile = new Set(); for (const statement of toMove) { - forEachReference(statement, checker, (symbol, isValidTypeOnlyUseSite) => { + forEachReference(statement, checker, enclosingRange, (symbol, isValidTypeOnlyUseSite) => { if (!symbol.declarations || isGlobalType(checker, symbol)) { return; } @@ -926,7 +928,7 @@ export function getUsageInfo(oldFile: SourceFile, toMove: readonly Statement[], unusedImportsFromOldFile.delete(jsxNamespaceSymbol); } - forEachReference(statement, checker, (symbol, isValidTypeOnlyUseSite) => { + forEachReference(statement, checker, enclosingRange, (symbol, isValidTypeOnlyUseSite) => { if (movedSymbols.has(symbol)) oldFileImportsFromTargetFile.set(symbol, isValidTypeOnlyUseSite); unusedImportsFromOldFile.delete(symbol); }); @@ -969,9 +971,12 @@ function inferNewFileName(importsFromNewFile: Map, movedSymbols return forEachKey(importsFromNewFile, symbolNameNoDefault) || forEachKey(movedSymbols, symbolNameNoDefault) || "newFile"; } -function forEachReference(node: Node, checker: TypeChecker, onReference: (s: Symbol, isValidTypeOnlyUseSite: boolean) => void) { +function forEachReference(node: Node, checker: TypeChecker, enclosingRange: TextRange | undefined, onReference: (s: Symbol, isValidTypeOnlyUseSite: boolean) => void) { node.forEachChild(function cb(node) { if (isIdentifier(node) && !isDeclarationName(node)) { + if (enclosingRange && !rangeContainsRange(enclosingRange, node)) { + return; + } const sym = checker.getSymbolAtLocation(node); if (sym) onReference(sym, isValidTypeOnlyAliasUseSite(node)); } @@ -1151,7 +1156,7 @@ export function getExistingLocals(sourceFile: SourceFile, statements: readonly S } for (const statement of statements) { - forEachReference(statement, checker, s => { + forEachReference(statement, checker, /*enclosingRange*/ undefined, s => { const symbol = skipAlias(s, checker); if (symbol.valueDeclaration && getSourceFileOfNode(symbol.valueDeclaration).path === sourceFile.path) { existingLocals.add(symbol); diff --git a/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_noImportNeeded.js b/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_noImportNeeded.js new file mode 100644 index 0000000000000..2958f8984091f --- /dev/null +++ b/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_noImportNeeded.js @@ -0,0 +1,299 @@ +currentDirectory:: / useCaseSensitiveFileNames: false +Info seq [hh:mm:ss:mss] Provided types map file "/typesMap.json" doesn't exist +//// [/a.ts] +export interface Foo { } + +export const foo: Foo = {} + +//// [/b.ts] + + +//// [/lib.d.ts] +lib.d.ts-Text + +//// [/lib.decorators.d.ts] +lib.decorators.d.ts-Text + +//// [/lib.decorators.legacy.d.ts] +lib.decorators.legacy.d.ts-Text + +//// [/tsconfig.json] +{ "files": ["a.ts", "b.ts"] } + + +Info seq [hh:mm:ss:mss] request: + { + "seq": 0, + "type": "request", + "arguments": { + "file": "/b.ts" + }, + "command": "open" + } +Info seq [hh:mm:ss:mss] getConfigFileNameForFile:: File: /b.ts ProjectRootPath: undefined:: Result: /tsconfig.json +Info seq [hh:mm:ss:mss] Creating configuration project /tsconfig.json +Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /tsconfig.json 2000 undefined Project: /tsconfig.json WatchType: Config file +Info seq [hh:mm:ss:mss] event: + { + "seq": 0, + "type": "event", + "event": "projectLoadingStart", + "body": { + "projectName": "/tsconfig.json", + "reason": "Creating possible configured project for /b.ts to open" + } + } +Info seq [hh:mm:ss:mss] Config: /tsconfig.json : { + "rootNames": [ + "/a.ts", + "/b.ts" + ], + "options": { + "configFilePath": "/tsconfig.json" + } +} +Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /a.ts 500 undefined WatchType: Closed Script info +Info seq [hh:mm:ss:mss] Starting updateGraphWorker: Project: /tsconfig.json +Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /lib.d.ts 500 undefined WatchType: Closed Script info +Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /lib.decorators.d.ts 500 undefined WatchType: Closed Script info +Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /lib.decorators.legacy.d.ts 500 undefined WatchType: Closed Script info +Info seq [hh:mm:ss:mss] Finishing updateGraphWorker: Project: /tsconfig.json projectStateVersion: 1 projectProgramVersion: 0 structureChanged: true structureIsReused:: Not Elapsed:: *ms +Info seq [hh:mm:ss:mss] Project '/tsconfig.json' (Configured) +Info seq [hh:mm:ss:mss] Files (5) + /lib.d.ts Text-1 lib.d.ts-Text + /lib.decorators.d.ts Text-1 lib.decorators.d.ts-Text + /lib.decorators.legacy.d.ts Text-1 lib.decorators.legacy.d.ts-Text + /a.ts Text-1 "export interface Foo { }\n\nexport const foo: Foo = {}" + /b.ts SVC-1-0 "" + + + lib.d.ts + Default library for target 'es5' + lib.decorators.d.ts + Library referenced via 'decorators' from file 'lib.d.ts' + lib.decorators.legacy.d.ts + Library referenced via 'decorators.legacy' from file 'lib.d.ts' + a.ts + Part of 'files' list in tsconfig.json + b.ts + Part of 'files' list in tsconfig.json + +Info seq [hh:mm:ss:mss] ----------------------------------------------- +Info seq [hh:mm:ss:mss] event: + { + "seq": 0, + "type": "event", + "event": "projectLoadingFinish", + "body": { + "projectName": "/tsconfig.json" + } + } +Info seq [hh:mm:ss:mss] event: + { + "seq": 0, + "type": "event", + "event": "configFileDiag", + "body": { + "triggerFile": "/b.ts", + "configFile": "/tsconfig.json", + "diagnostics": [] + } + } +Info seq [hh:mm:ss:mss] Project '/tsconfig.json' (Configured) +Info seq [hh:mm:ss:mss] Files (5) + +Info seq [hh:mm:ss:mss] ----------------------------------------------- +Info seq [hh:mm:ss:mss] Open files: +Info seq [hh:mm:ss:mss] FileName: /b.ts ProjectRootPath: undefined +Info seq [hh:mm:ss:mss] Projects: /tsconfig.json +After Request +watchedFiles:: +/a.ts: *new* + {"pollingInterval":500} +/lib.d.ts: *new* + {"pollingInterval":500} +/lib.decorators.d.ts: *new* + {"pollingInterval":500} +/lib.decorators.legacy.d.ts: *new* + {"pollingInterval":500} +/tsconfig.json: *new* + {"pollingInterval":2000} + +Projects:: +/tsconfig.json (Configured) *new* + projectStateVersion: 1 + projectProgramVersion: 1 + +ScriptInfos:: +/a.ts *new* + version: Text-1 + containingProjects: 1 + /tsconfig.json +/b.ts (Open) *new* + version: SVC-1-0 + containingProjects: 1 + /tsconfig.json *default* +/lib.d.ts *new* + version: Text-1 + containingProjects: 1 + /tsconfig.json +/lib.decorators.d.ts *new* + version: Text-1 + containingProjects: 1 + /tsconfig.json +/lib.decorators.legacy.d.ts *new* + version: Text-1 + containingProjects: 1 + /tsconfig.json + +Info seq [hh:mm:ss:mss] request: + { + "seq": 1, + "type": "request", + "arguments": { + "formatOptions": { + "indentSize": 4, + "tabSize": 4, + "newLineCharacter": "\n", + "convertTabsToSpaces": true, + "indentStyle": 2, + "insertSpaceAfterConstructor": false, + "insertSpaceAfterCommaDelimiter": true, + "insertSpaceAfterSemicolonInForStatements": true, + "insertSpaceBeforeAndAfterBinaryOperators": true, + "insertSpaceAfterKeywordsInControlFlowStatements": true, + "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, + "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, + "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, + "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true, + "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false, + "insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false, + "insertSpaceBeforeFunctionParenthesis": false, + "placeOpenBraceOnNewLineForFunctions": false, + "placeOpenBraceOnNewLineForControlBlocks": false, + "semicolons": "ignore", + "trimTrailingWhitespace": true, + "indentSwitchCase": true + } + }, + "command": "configure" + } +Info seq [hh:mm:ss:mss] Format host information updated +Info seq [hh:mm:ss:mss] response: + { + "seq": 0, + "type": "response", + "command": "configure", + "request_seq": 1, + "success": true + } +Info seq [hh:mm:ss:mss] request: + { + "seq": 2, + "type": "request", + "arguments": { + "file": "/b.ts", + "pastedText": [ + "export" + ], + "pasteLocations": [ + { + "start": { + "line": 1, + "offset": 1 + }, + "end": { + "line": 1, + "offset": 1 + } + } + ], + "copiedFrom": { + "file": "a.ts", + "spans": [ + { + "start": { + "line": 3, + "offset": 1 + }, + "end": { + "line": 3, + "offset": 7 + } + } + ] + } + }, + "command": "getPasteEdits" + } +Info seq [hh:mm:ss:mss] Starting updateGraphWorker: Project: /tsconfig.json +Info seq [hh:mm:ss:mss] Finishing updateGraphWorker: Project: /tsconfig.json projectStateVersion: 2 projectProgramVersion: 1 structureChanged: false structureIsReused:: Completely Elapsed:: *ms +Info seq [hh:mm:ss:mss] Project '/tsconfig.json' (Configured) +Info seq [hh:mm:ss:mss] Files (5) + /lib.d.ts Text-1 lib.d.ts-Text + /lib.decorators.d.ts Text-1 lib.decorators.d.ts-Text + /lib.decorators.legacy.d.ts Text-1 lib.decorators.legacy.d.ts-Text + /a.ts Text-1 "export interface Foo { }\n\nexport const foo: Foo = {}" + /b.ts SVC-1-1 "export" + +Info seq [hh:mm:ss:mss] ----------------------------------------------- +Info seq [hh:mm:ss:mss] response: + { + "seq": 0, + "type": "response", + "command": "getPasteEdits", + "request_seq": 2, + "success": true, + "performanceData": { + "updateGraphDurationMs": * + }, + "body": { + "edits": [ + { + "fileName": "/b.ts", + "textChanges": [ + { + "start": { + "line": 1, + "offset": 1 + }, + "end": { + "line": 1, + "offset": 1 + }, + "newText": "export" + } + ] + } + ], + "fixId": "providePostPasteEdits" + } + } +After Request +Projects:: +/tsconfig.json (Configured) *changed* + projectStateVersion: 3 *changed* + projectProgramVersion: 1 + dirty: true *changed* + +ScriptInfos:: +/a.ts + version: Text-1 + containingProjects: 1 + /tsconfig.json +/b.ts (Open) *changed* + version: SVC-1-2 *changed* + containingProjects: 1 + /tsconfig.json *default* +/lib.d.ts + version: Text-1 + containingProjects: 1 + /tsconfig.json +/lib.decorators.d.ts + version: Text-1 + containingProjects: 1 + /tsconfig.json +/lib.decorators.legacy.d.ts + version: Text-1 + containingProjects: 1 + /tsconfig.json diff --git a/tests/cases/fourslash/server/pasteEdits_noImportNeeded.ts b/tests/cases/fourslash/server/pasteEdits_noImportNeeded.ts new file mode 100644 index 0000000000000..c23f3d69f30d3 --- /dev/null +++ b/tests/cases/fourslash/server/pasteEdits_noImportNeeded.ts @@ -0,0 +1,25 @@ +/// + +// @Filename: /b.ts +////[||] + +// @Filename: /a.ts +//// export interface Foo { } +//// +//// [|export|] const foo: Foo = {} + +// @Filename: /tsconfig.json +////{ "files": ["a.ts", "b.ts"] } + +const range = test.ranges(); +verify.pasteEdits({ + args: { + pastedText: [`export`], + pasteLocations: [range[0]], + copiedFrom: { file: "a.ts", range: [range[1]] }, + }, + newFileContents: { + "/b.ts": +`export` + } +}); From c98a8da2fc4ed5cf9cf8d40f4ad017fd6cf96682 Mon Sep 17 00:00:00 2001 From: navya9singh Date: Mon, 1 Jul 2024 13:23:09 -0700 Subject: [PATCH 2/5] fixing baselines --- .../fourslashServer/pasteEdits_noImportNeeded.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_noImportNeeded.js b/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_noImportNeeded.js index 2958f8984091f..9ef264793ba3e 100644 --- a/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_noImportNeeded.js +++ b/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_noImportNeeded.js @@ -106,6 +106,17 @@ Info seq [hh:mm:ss:mss] ----------------------------------------------- Info seq [hh:mm:ss:mss] Open files: Info seq [hh:mm:ss:mss] FileName: /b.ts ProjectRootPath: undefined Info seq [hh:mm:ss:mss] Projects: /tsconfig.json +Info seq [hh:mm:ss:mss] response: + { + "seq": 0, + "type": "response", + "command": "open", + "request_seq": 0, + "success": true, + "performanceData": { + "updateGraphDurationMs": * + } + } After Request watchedFiles:: /a.ts: *new* From e66685b45a32b88c668c9c8d3afdfa20e41279d5 Mon Sep 17 00:00:00 2001 From: navya9singh Date: Mon, 8 Jul 2024 14:42:20 -0700 Subject: [PATCH 3/5] getPasteEdits returns edits only if there are any import fixes --- src/harness/client.ts | 2 +- src/services/pasteEdits.ts | 9 ++++ .../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(+), 86 deletions(-) diff --git a/src/harness/client.ts b/src/harness/client.ts index 248624e4323b1..dc8561a2f3f39 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 2aad38e571ae3..2d384b3a6e83f 100644 --- a/src/services/pasteEdits.ts +++ b/src/services/pasteEdits.ts @@ -71,6 +71,7 @@ function pasteEdits( newText = actualPastedText ? newText.slice(0, pos) + actualPastedText[0] + newText.slice(end) : newText.slice(0, pos) + pastedText[i] + newText.slice(end); } + let returnImportEdits = true; Debug.checkDefined(host.runWithTemporaryFileUpdate).call(host, targetFile.fileName, newText, (updatedProgram: Program, originalProgram: Program | undefined, updatedFile: SourceFile) => { const importAdder = codefix.createImportAdder(updatedFile, updatedProgram, preferences, host); if (copiedFrom?.range) { @@ -114,7 +115,15 @@ function pasteEdits( }); } importAdder.writeFixes(changes, getQuotePreference(copiedFrom ? copiedFrom.file : targetFile, preferences)); + returnImportEdits = importAdder.hasFixes(); }); + + /** + * If there are no import fixes, getPasteEdits should return without making any changes to the file. + */ + if (!returnImportEdits) { + 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 2af5d74804098..82c2cd448ae92 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 9ef264793ba3e..f62638fbe1fe1 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 b22f1c0b89d47..23fa4420a901e 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 d0a9a96c5006e..5bc45bd498b73 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 f37ef84d7fcdd..2854123821184 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 c23f3d69f30d3..156386a86ac7a 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 49d621d21387f..aa2d9ba943f26 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 068d42344470a..06bedadcd1724 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 f8175850ff17e..afd370f875a74 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 From a7e16d0324112c0360c4a17ad444863db541c280 Mon Sep 17 00:00:00 2001 From: navya9singh Date: Mon, 8 Jul 2024 14:46:56 -0700 Subject: [PATCH 4/5] fixing baselines --- .../pasteEdits_noImportNeeded.js | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_noImportNeeded.js b/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_noImportNeeded.js index 7fb5712b79bad..f62638fbe1fe1 100644 --- a/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_noImportNeeded.js +++ b/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_noImportNeeded.js @@ -1,25 +1,25 @@ currentDirectory:: / useCaseSensitiveFileNames: false Info seq [hh:mm:ss:mss] Provided types map file "/typesMap.json" doesn't exist -//// [/a.ts] +//// [/a.ts] export interface Foo { } -export const foo: Foo = {} - -//// [/b.ts] - - -//// [/lib.d.ts] -lib.d.ts-Text - -//// [/lib.decorators.d.ts] -lib.decorators.d.ts-Text - -//// [/lib.decorators.legacy.d.ts] -lib.decorators.legacy.d.ts-Text - -//// [/tsconfig.json] -{ "files": ["a.ts", "b.ts"] } - +export const foo: Foo = {} + +//// [/b.ts] + + +//// [/lib.d.ts] +lib.d.ts-Text + +//// [/lib.decorators.d.ts] +lib.decorators.d.ts-Text + +//// [/lib.decorators.legacy.d.ts] +lib.decorators.legacy.d.ts-Text + +//// [/tsconfig.json] +{ "files": ["a.ts", "b.ts"] } + Info seq [hh:mm:ss:mss] request: { From a7e99333ca6ec5a0a910bb55b804deb15e87fccc Mon Sep 17 00:00:00 2001 From: navya9singh Date: Tue, 9 Jul 2024 10:07:58 -0700 Subject: [PATCH 5/5] removing extra variable --- src/services/pasteEdits.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/services/pasteEdits.ts b/src/services/pasteEdits.ts index 2d384b3a6e83f..f3b350816781e 100644 --- a/src/services/pasteEdits.ts +++ b/src/services/pasteEdits.ts @@ -71,9 +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 returnImportEdits = true; + 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,13 +115,12 @@ function pasteEdits( }); } importAdder.writeFixes(changes, getQuotePreference(copiedFrom ? copiedFrom.file : targetFile, preferences)); - returnImportEdits = importAdder.hasFixes(); }); /** * If there are no import fixes, getPasteEdits should return without making any changes to the file. */ - if (!returnImportEdits) { + if (!importAdder!.hasFixes()) { return; } pasteLocations.forEach((paste, i) => {