diff --git a/src/services/codefixes/importFixes.ts b/src/services/codefixes/importFixes.ts index 6eedc5b8e38c0..a05d4cc9375d3 100644 --- a/src/services/codefixes/importFixes.ts +++ b/src/services/codefixes/importFixes.ts @@ -82,6 +82,7 @@ import { isFullSourceFile, isIdentifier, isImportableFile, + isImportClause, isImportDeclaration, isImportEqualsDeclaration, isIntrinsicJsxName, @@ -227,6 +228,7 @@ export interface ImportAdder { addImportFromExportedSymbol: (exportedSymbol: Symbol, isValidTypeOnlyUseSite?: boolean, referenceImport?: ImportOrRequireAliasDeclaration) => void; addImportForNonExistentExport: (exportName: string, exportingFileName: string, exportKind: ExportKind, exportedMeanings: SymbolFlags, isImportUsageValidAsTypeOnly: boolean) => void; addImportForUnresolvedIdentifier: (context: CodeFixContextBase, symbolToken: Identifier, useAutoImportProvider: boolean) => void; + addImportForExternalModuleSymbol: (symbol: Symbol, symbolName: string, isValidTypeOnlyUseSite: boolean, referenceImport?: ImportOrRequireAliasDeclaration) => void; addVerbatimImport: (declaration: AnyImportOrRequireStatement | ImportOrRequireAliasDeclaration) => void; removeExistingImport: (declaration: ImportOrRequireAliasDeclaration) => void; writeFixes: (changeTracker: textChanges.ChangeTracker, oldFileQuotePreference?: QuotePreference) => void; @@ -255,7 +257,7 @@ function createImportAdderWorker(sourceFile: SourceFile | FutureSourceFile, prog type NewImportsKey = `${0 | 1}|${string}`; /** Use `getNewImportEntry` for access */ const newImports = new Map>(); - return { addImportFromDiagnostic, addImportFromExportedSymbol, writeFixes, hasFixes, addImportForUnresolvedIdentifier, addImportForNonExistentExport, removeExistingImport, addVerbatimImport }; + return { addImportFromDiagnostic, addImportFromExportedSymbol, writeFixes, hasFixes, addImportForUnresolvedIdentifier, addImportForNonExistentExport, addImportForExternalModuleSymbol, removeExistingImport, addVerbatimImport }; function addVerbatimImport(declaration: AnyImportOrRequireStatement | ImportOrRequireAliasDeclaration) { verbatimImports.add(declaration); @@ -356,6 +358,35 @@ function createImportAdderWorker(sourceFile: SourceFile | FutureSourceFile, prog } } + function addImportForExternalModuleSymbol(symbol: Symbol, symbolName: string, isValidTypeOnlyUseSite: boolean, referenceImport?: ImportOrRequireAliasDeclaration) { + const useRequire = shouldUseRequire(sourceFile, program); + const moduleSpecifier = moduleSpecifiers.getLocalModuleSpecifierBetweenFileNames( + sourceFile, + Debug.checkDefined(symbol.valueDeclaration).getSourceFile().fileName, + compilerOptions, + createModuleSpecifierResolutionHost(program, host), + ); + let info: FixInfo = { + fix: { kind: ImportFixKind.AddNew, importKind: ImportKind.Namespace, addAsTypeOnly: isValidTypeOnlyUseSite ? AddAsTypeOnly.Allowed : AddAsTypeOnly.NotAllowed, useRequire, moduleSpecifierKind: undefined, moduleSpecifier }, + symbolName, + errorIdentifierText: undefined, + }; + if (referenceImport && isValidTypeOnlyUseSite && isImportClause(referenceImport)) { + info = { + ...info, + fix: { + kind: ImportFixKind.AddNew, + importKind: isNamespaceImport(referenceImport) ? ImportKind.Namespace : ImportKind.Default, + addAsTypeOnly: isTypeOnlyImportDeclaration(referenceImport) ? AddAsTypeOnly.Required : AddAsTypeOnly.Allowed, + useRequire, + moduleSpecifierKind: undefined, + moduleSpecifier, + }, + }; + } + addImport(info); + } + function removeExistingImport(declaration: ImportOrRequireAliasDeclaration) { if (declaration.kind === SyntaxKind.ImportClause) { Debug.assertIsDefined(declaration.name, "ImportClause should have a name if it's being removed"); diff --git a/src/services/refactors/helpers.ts b/src/services/refactors/helpers.ts index 459979c3ef0dc..52f9f0b8a67a5 100644 --- a/src/services/refactors/helpers.ts +++ b/src/services/refactors/helpers.ts @@ -8,6 +8,7 @@ import { identifierToKeywordKind, isAnyImportOrRequireStatement, isClassLike, + isExternalModuleSymbol, isPrivateIdentifier, isPropertyAccessExpression, ModuleBlock, @@ -81,7 +82,7 @@ export function addTargetFileImports( importAdder.addVerbatimImport(Debug.checkDefined(declaration ?? findAncestor(symbol.declarations?.[0], isAnyImportOrRequireStatement))); } else { - importAdder.addImportFromExportedSymbol(targetSymbol, isValidTypeOnlyUseSite, declaration); + isExternalModuleSymbol(targetSymbol) ? importAdder.addImportForExternalModuleSymbol(targetSymbol, symbol.name, isValidTypeOnlyUseSite, declaration) : importAdder.addImportFromExportedSymbol(targetSymbol, isValidTypeOnlyUseSite, declaration); } }); diff --git a/src/services/refactors/moveToFile.ts b/src/services/refactors/moveToFile.ts index da6d806a06f30..2de8fdfbc44be 100644 --- a/src/services/refactors/moveToFile.ts +++ b/src/services/refactors/moveToFile.ts @@ -19,6 +19,7 @@ import { contains, createFutureSourceFile, createModuleSpecifierResolutionHost, + createTextRangeFromNode, createTextRangeFromSpan, Debug, Declaration, @@ -962,9 +963,10 @@ function inferNewFileName(importsFromNewFile: Map, movedSymbols } function forEachReference(node: Node, checker: TypeChecker, enclosingRange: TextRange | undefined, onReference: (s: Symbol, isValidTypeOnlyUseSite: boolean) => void) { + const sourceFile = node.getSourceFile(); node.forEachChild(function cb(node) { if (isIdentifier(node) && !isDeclarationName(node)) { - if (enclosingRange && !rangeContainsRange(enclosingRange, node)) { + if (enclosingRange && !rangeContainsRange(enclosingRange, createTextRangeFromNode(node, sourceFile))) { return; } const sym = checker.getSymbolAtLocation(node); @@ -1125,18 +1127,26 @@ export function getExistingLocals(sourceFile: SourceFile, statements: readonly S const declaration = importFromModuleSpecifier(moduleSpecifier); if ( isImportDeclaration(declaration) && declaration.importClause && - declaration.importClause.namedBindings && isNamedImports(declaration.importClause.namedBindings) + declaration.importClause.namedBindings ) { - for (const e of declaration.importClause.namedBindings.elements) { - const symbol = checker.getSymbolAtLocation(e.propertyName || e.name); + if (isNamespaceImport(declaration.importClause.namedBindings)) { + const symbol = declaration.importClause.namedBindings.symbol; if (symbol) { existingLocals.add(skipAlias(symbol, checker)); } } + else if (isNamedImports(declaration.importClause.namedBindings)) { + for (const e of declaration.importClause.namedBindings.elements) { + const symbol = e.symbol; + if (symbol) { + existingLocals.add(skipAlias(symbol, checker)); + } + } + } } if (isVariableDeclarationInitializedToRequire(declaration.parent) && isObjectBindingPattern(declaration.parent.name)) { for (const e of declaration.parent.name.elements) { - const symbol = checker.getSymbolAtLocation(e.propertyName || e.name); + const symbol = e.symbol; if (symbol) { existingLocals.add(skipAlias(symbol, checker)); } diff --git a/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_defaultExport.js b/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_defaultExport.js new file mode 100644 index 0000000000000..206d100da0bcf --- /dev/null +++ b/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_defaultExport.js @@ -0,0 +1,344 @@ +currentDirectory:: / useCaseSensitiveFileNames: false +Info seq [hh:mm:ss:mss] Provided types map file "/typesMap.json" doesn't exist +//// [/a.ts] +export default function foo(name: string): void { + console.log(name); +} + +//// [/b.ts] +import foo from "./a"; +foo("bar"); + +//// [/folder/c.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": ["/folder/c.ts", "/a.ts", "/b.ts"] } + + +Info seq [hh:mm:ss:mss] request: + { + "seq": 0, + "type": "request", + "arguments": { + "file": "/folder/c.ts" + }, + "command": "open" + } +Info seq [hh:mm:ss:mss] getConfigFileNameForFile:: File: /folder/c.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 /folder/c.ts to open" + } + } +Info seq [hh:mm:ss:mss] Config: /tsconfig.json : { + "rootNames": [ + "/folder/c.ts", + "/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] FileWatcher:: Added:: WatchInfo: /b.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 (6) + /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 + /folder/c.ts SVC-1-0 "" + /a.ts Text-1 "export default function foo(name: string): void {\n console.log(name);\n}" + /b.ts Text-1 "import foo from \"./a\";\nfoo(\"bar\");" + + + 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' + folder/c.ts + Part of 'files' list in tsconfig.json + a.ts + Part of 'files' list in tsconfig.json + Imported via "./a" from file 'b.ts' + 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": "/folder/c.ts", + "configFile": "/tsconfig.json", + "diagnostics": [] + } + } +Info seq [hh:mm:ss:mss] Project '/tsconfig.json' (Configured) +Info seq [hh:mm:ss:mss] Files (6) + +Info seq [hh:mm:ss:mss] ----------------------------------------------- +Info seq [hh:mm:ss:mss] Open files: +Info seq [hh:mm:ss:mss] FileName: /folder/c.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* + {"pollingInterval":500} +/b.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 *new* + version: Text-1 + containingProjects: 1 + /tsconfig.json +/folder/c.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": "/folder/c.ts", + "pastedText": [ + "foo(\"bar\");" + ], + "pasteLocations": [ + { + "start": { + "line": 1, + "offset": 1 + }, + "end": { + "line": 1, + "offset": 1 + } + } + ], + "copiedFrom": { + "file": "/b.ts", + "spans": [ + { + "start": { + "line": 2, + "offset": 1 + }, + "end": { + "line": 2, + "offset": 12 + } + } + ] + } + }, + "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 (6) + /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 + /folder/c.ts SVC-1-1 "foo(\"bar\");" + /a.ts Text-1 "export default function foo(name: string): void {\n console.log(name);\n}" + /b.ts Text-1 "import foo from \"./a\";\nfoo(\"bar\");" + +Info seq [hh:mm:ss:mss] ----------------------------------------------- +Info seq [hh:mm:ss:mss] getExportInfoMap: cache miss or empty; calculating new results +Info seq [hh:mm:ss:mss] getExportInfoMap: done in * ms +Info seq [hh:mm:ss:mss] response: + { + "seq": 0, + "type": "response", + "command": "getPasteEdits", + "request_seq": 2, + "success": true, + "performanceData": { + "updateGraphDurationMs": * + }, + "body": { + "edits": [ + { + "fileName": "/folder/c.ts", + "textChanges": [ + { + "start": { + "line": 1, + "offset": 1 + }, + "end": { + "line": 1, + "offset": 1 + }, + "newText": "import foo from \"../a\";\n\n" + }, + { + "start": { + "line": 1, + "offset": 1 + }, + "end": { + "line": 1, + "offset": 1 + }, + "newText": "foo(\"bar\");" + } + ] + } + ], + "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 + version: Text-1 + containingProjects: 1 + /tsconfig.json +/folder/c.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/baselines/reference/tsserver/fourslashServer/pasteEdits_externalModuleSymbolImport1.js b/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_externalModuleSymbolImport1.js new file mode 100644 index 0000000000000..be2e7368e4696 --- /dev/null +++ b/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_externalModuleSymbolImport1.js @@ -0,0 +1,350 @@ +currentDirectory:: / useCaseSensitiveFileNames: false +Info seq [hh:mm:ss:mss] Provided types map file "/typesMap.json" doesn't exist +//// [/a.ts] +const abc = 10; +const def = 20; +export interface testInterface { + abc: number; + def: number; +} + +//// [/b.ts] +import * as test from "./a"; + +function foo(abc: test.testInterface, def: test.testInterface) { + console.log(abc); + console.log(def); +} + + +//// [/folder/c.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": ["/folder/c.ts", "/a.ts", "/b.ts"] } + + +Info seq [hh:mm:ss:mss] request: + { + "seq": 0, + "type": "request", + "arguments": { + "file": "/folder/c.ts" + }, + "command": "open" + } +Info seq [hh:mm:ss:mss] getConfigFileNameForFile:: File: /folder/c.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 /folder/c.ts to open" + } + } +Info seq [hh:mm:ss:mss] Config: /tsconfig.json : { + "rootNames": [ + "/folder/c.ts", + "/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] FileWatcher:: Added:: WatchInfo: /b.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 (6) + /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 + /folder/c.ts SVC-1-0 "" + /a.ts Text-1 "const abc = 10;\nconst def = 20;\nexport interface testInterface {\n abc: number;\n def: number;\n}" + /b.ts Text-1 "import * as test from \"./a\";\n\nfunction foo(abc: test.testInterface, def: test.testInterface) {\n console.log(abc);\n console.log(def);\n}\n" + + + 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' + folder/c.ts + Part of 'files' list in tsconfig.json + a.ts + Part of 'files' list in tsconfig.json + Imported via "./a" from file 'b.ts' + 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": "/folder/c.ts", + "configFile": "/tsconfig.json", + "diagnostics": [] + } + } +Info seq [hh:mm:ss:mss] Project '/tsconfig.json' (Configured) +Info seq [hh:mm:ss:mss] Files (6) + +Info seq [hh:mm:ss:mss] ----------------------------------------------- +Info seq [hh:mm:ss:mss] Open files: +Info seq [hh:mm:ss:mss] FileName: /folder/c.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* + {"pollingInterval":500} +/b.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 *new* + version: Text-1 + containingProjects: 1 + /tsconfig.json +/folder/c.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": "/folder/c.ts", + "pastedText": [ + "function foo(abc: test.abc, def: test.def) {\nconsole.log(abc);\nconsole.log(def);\n}" + ], + "pasteLocations": [ + { + "start": { + "line": 1, + "offset": 1 + }, + "end": { + "line": 1, + "offset": 1 + } + } + ], + "copiedFrom": { + "file": "/b.ts", + "spans": [ + { + "start": { + "line": 3, + "offset": 1 + }, + "end": { + "line": 6, + "offset": 2 + } + } + ] + } + }, + "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 (6) + /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 + /folder/c.ts SVC-1-1 "function foo(abc: test.abc, def: test.def) {\nconsole.log(abc);\nconsole.log(def);\n}" + /a.ts Text-1 "const abc = 10;\nconst def = 20;\nexport interface testInterface {\n abc: number;\n def: number;\n}" + /b.ts Text-1 "import * as test from \"./a\";\n\nfunction foo(abc: test.testInterface, def: test.testInterface) {\n console.log(abc);\n console.log(def);\n}\n" + +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": "/folder/c.ts", + "textChanges": [ + { + "start": { + "line": 1, + "offset": 1 + }, + "end": { + "line": 1, + "offset": 1 + }, + "newText": "import * as test from \"../a\";\n\n" + }, + { + "start": { + "line": 1, + "offset": 1 + }, + "end": { + "line": 1, + "offset": 1 + }, + "newText": "function foo(abc: test.abc, def: test.def) {\nconsole.log(abc);\nconsole.log(def);\n}" + } + ] + } + ], + "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 + version: Text-1 + containingProjects: 1 + /tsconfig.json +/folder/c.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/baselines/reference/tsserver/fourslashServer/pasteEdits_externalModuleSymbolImport2.js b/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_externalModuleSymbolImport2.js new file mode 100644 index 0000000000000..86b6ff1e1be37 --- /dev/null +++ b/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_externalModuleSymbolImport2.js @@ -0,0 +1,357 @@ +currentDirectory:: / useCaseSensitiveFileNames: false +Info seq [hh:mm:ss:mss] Provided types map file "/typesMap.json" doesn't exist +//// [/a.ts] +const abc = 10; +const def = 20; +export interface testInterface { + abc: number; + def: number; +} + +//// [/b.mts] +import test from "./a.js"; + +function foo(abc: test.testInterface, def: test.testInterface) { + console.log(abc); + console.log(def); +} + + +//// [/folder/c.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] +{ "compilerOptions": { "module": "nodenext" }, "files": ["/folder/c.ts", "/a.ts", "/b.mts"] } + + +Info seq [hh:mm:ss:mss] request: + { + "seq": 0, + "type": "request", + "arguments": { + "file": "/folder/c.ts" + }, + "command": "open" + } +Info seq [hh:mm:ss:mss] getConfigFileNameForFile:: File: /folder/c.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 /folder/c.ts to open" + } + } +Info seq [hh:mm:ss:mss] Config: /tsconfig.json : { + "rootNames": [ + "/folder/c.ts", + "/a.ts", + "/b.mts" + ], + "options": { + "module": 199, + "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] FileWatcher:: Added:: WatchInfo: /b.mts 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.esnext.full.d.ts 500 undefined Project: /tsconfig.json WatchType: Missing file +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 (3) + /folder/c.ts SVC-1-0 "" + /a.ts Text-1 "const abc = 10;\nconst def = 20;\nexport interface testInterface {\n abc: number;\n def: number;\n}" + /b.mts Text-1 "import test from \"./a.js\";\n\nfunction foo(abc: test.testInterface, def: test.testInterface) {\n console.log(abc);\n console.log(def);\n}\n" + + + folder/c.ts + Part of 'files' list in tsconfig.json + File is CommonJS module because 'package.json' was not found + a.ts + Part of 'files' list in tsconfig.json + Imported via "./a.js" from file 'b.mts' + File is CommonJS module because 'package.json' was not found + b.mts + 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": "/folder/c.ts", + "configFile": "/tsconfig.json", + "diagnostics": [ + { + "text": "File '/lib.esnext.full.d.ts' not found.\n The file is in the program because:\n Default library for target 'esnext'", + "code": 6053, + "category": "error" + }, + { + "text": "Cannot find global type 'Array'.", + "code": 2318, + "category": "error" + }, + { + "text": "Cannot find global type 'Boolean'.", + "code": 2318, + "category": "error" + }, + { + "text": "Cannot find global type 'Function'.", + "code": 2318, + "category": "error" + }, + { + "text": "Cannot find global type 'IArguments'.", + "code": 2318, + "category": "error" + }, + { + "text": "Cannot find global type 'Number'.", + "code": 2318, + "category": "error" + }, + { + "text": "Cannot find global type 'Object'.", + "code": 2318, + "category": "error" + }, + { + "text": "Cannot find global type 'RegExp'.", + "code": 2318, + "category": "error" + }, + { + "text": "Cannot find global type 'String'.", + "code": 2318, + "category": "error" + } + ] + } + } +Info seq [hh:mm:ss:mss] Project '/tsconfig.json' (Configured) +Info seq [hh:mm:ss:mss] Files (3) + +Info seq [hh:mm:ss:mss] ----------------------------------------------- +Info seq [hh:mm:ss:mss] Open files: +Info seq [hh:mm:ss:mss] FileName: /folder/c.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* + {"pollingInterval":500} +/b.mts: *new* + {"pollingInterval":500} +/lib.esnext.full.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.mts *new* + version: Text-1 + containingProjects: 1 + /tsconfig.json +/folder/c.ts (Open) *new* + version: SVC-1-0 + containingProjects: 1 + /tsconfig.json *default* + +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": "/folder/c.ts", + "pastedText": [ + "function foo(abc: test.abc, def: test.def) {\nconsole.log(abc);\nconsole.log(def);\n}" + ], + "pasteLocations": [ + { + "start": { + "line": 1, + "offset": 1 + }, + "end": { + "line": 1, + "offset": 1 + } + } + ], + "copiedFrom": { + "file": "/b.mts", + "spans": [ + { + "start": { + "line": 3, + "offset": 1 + }, + "end": { + "line": 6, + "offset": 2 + } + } + ] + } + }, + "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 (3) + /folder/c.ts SVC-1-1 "function foo(abc: test.abc, def: test.def) {\nconsole.log(abc);\nconsole.log(def);\n}" + /a.ts Text-1 "const abc = 10;\nconst def = 20;\nexport interface testInterface {\n abc: number;\n def: number;\n}" + /b.mts Text-1 "import test from \"./a.js\";\n\nfunction foo(abc: test.testInterface, def: test.testInterface) {\n console.log(abc);\n console.log(def);\n}\n" + +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": "/folder/c.ts", + "textChanges": [ + { + "start": { + "line": 1, + "offset": 1 + }, + "end": { + "line": 1, + "offset": 1 + }, + "newText": "import test from \"../a\";\n\n" + }, + { + "start": { + "line": 1, + "offset": 1 + }, + "end": { + "line": 1, + "offset": 1 + }, + "newText": "function foo(abc: test.abc, def: test.def) {\nconsole.log(abc);\nconsole.log(def);\n}" + } + ] + } + ], + "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.mts + version: Text-1 + containingProjects: 1 + /tsconfig.json +/folder/c.ts (Open) *changed* + version: SVC-1-2 *changed* + containingProjects: 1 + /tsconfig.json *default* diff --git a/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_externalModuleSymbolImport3.js b/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_externalModuleSymbolImport3.js new file mode 100644 index 0000000000000..c2543f11e30f2 --- /dev/null +++ b/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_externalModuleSymbolImport3.js @@ -0,0 +1,351 @@ +currentDirectory:: / useCaseSensitiveFileNames: false +Info seq [hh:mm:ss:mss] Provided types map file "/typesMap.json" doesn't exist +//// [/a.ts] +const abc = 10; +const def = 20; +export interface testInterface { + abc: number; + def: number; +} + +//// [/b.ts] +import test = require("./a"); + +function foo(abc: test.testInterface, def: test.testInterface) { + console.log(abc); + console.log(def); +} + + +//// [/folder/c.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] +{ "compilerOptions": { "module": "commonjs" }, "files": ["/folder/c.ts", "/a.ts", "/b.ts"] } + + +Info seq [hh:mm:ss:mss] request: + { + "seq": 0, + "type": "request", + "arguments": { + "file": "/folder/c.ts" + }, + "command": "open" + } +Info seq [hh:mm:ss:mss] getConfigFileNameForFile:: File: /folder/c.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 /folder/c.ts to open" + } + } +Info seq [hh:mm:ss:mss] Config: /tsconfig.json : { + "rootNames": [ + "/folder/c.ts", + "/a.ts", + "/b.ts" + ], + "options": { + "module": 1, + "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] FileWatcher:: Added:: WatchInfo: /b.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 (6) + /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 + /folder/c.ts SVC-1-0 "" + /a.ts Text-1 "const abc = 10;\nconst def = 20;\nexport interface testInterface {\n abc: number;\n def: number;\n}" + /b.ts Text-1 "import test = require(\"./a\");\n\nfunction foo(abc: test.testInterface, def: test.testInterface) {\n console.log(abc);\n console.log(def);\n}\n" + + + 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' + folder/c.ts + Part of 'files' list in tsconfig.json + a.ts + Part of 'files' list in tsconfig.json + Imported via "./a" from file 'b.ts' + 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": "/folder/c.ts", + "configFile": "/tsconfig.json", + "diagnostics": [] + } + } +Info seq [hh:mm:ss:mss] Project '/tsconfig.json' (Configured) +Info seq [hh:mm:ss:mss] Files (6) + +Info seq [hh:mm:ss:mss] ----------------------------------------------- +Info seq [hh:mm:ss:mss] Open files: +Info seq [hh:mm:ss:mss] FileName: /folder/c.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* + {"pollingInterval":500} +/b.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 *new* + version: Text-1 + containingProjects: 1 + /tsconfig.json +/folder/c.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": "/folder/c.ts", + "pastedText": [ + "function foo(abc: test.abc, def: test.def) {\nconsole.log(abc);\nconsole.log(def);\n}" + ], + "pasteLocations": [ + { + "start": { + "line": 1, + "offset": 1 + }, + "end": { + "line": 1, + "offset": 1 + } + } + ], + "copiedFrom": { + "file": "/b.ts", + "spans": [ + { + "start": { + "line": 3, + "offset": 1 + }, + "end": { + "line": 6, + "offset": 2 + } + } + ] + } + }, + "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 (6) + /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 + /folder/c.ts SVC-1-1 "function foo(abc: test.abc, def: test.def) {\nconsole.log(abc);\nconsole.log(def);\n}" + /a.ts Text-1 "const abc = 10;\nconst def = 20;\nexport interface testInterface {\n abc: number;\n def: number;\n}" + /b.ts Text-1 "import test = require(\"./a\");\n\nfunction foo(abc: test.testInterface, def: test.testInterface) {\n console.log(abc);\n console.log(def);\n}\n" + +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": "/folder/c.ts", + "textChanges": [ + { + "start": { + "line": 1, + "offset": 1 + }, + "end": { + "line": 1, + "offset": 1 + }, + "newText": "import * as test from \"../a\";\n\n" + }, + { + "start": { + "line": 1, + "offset": 1 + }, + "end": { + "line": 1, + "offset": 1 + }, + "newText": "function foo(abc: test.abc, def: test.def) {\nconsole.log(abc);\nconsole.log(def);\n}" + } + ] + } + ], + "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 + version: Text-1 + containingProjects: 1 + /tsconfig.json +/folder/c.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_defaultExport.ts b/tests/cases/fourslash/server/pasteEdits_defaultExport.ts new file mode 100644 index 0000000000000..9d500d17efa79 --- /dev/null +++ b/tests/cases/fourslash/server/pasteEdits_defaultExport.ts @@ -0,0 +1,32 @@ +/// + +// @Filename: /folder/c.ts +//// [||] + +// @Filename: /a.ts +//// export default function foo(name: string): void { +//// console.log(name); +//// } + +// @Filename: /b.ts +////import foo from "./a"; +////[|foo("bar");|] + +// @Filename: /tsconfig.json +////{ "files": ["/folder/c.ts", "/a.ts", "/b.ts"] } + +const range = test.ranges(); +verify.pasteEdits({ + args: { + pastedText: [`foo("bar");`], + pasteLocations: [range[0]], + copiedFrom: { file: "/b.ts", range: [range[1]] }, + }, + newFileContents: { + "/folder/c.ts": +`import foo from "../a"; + +foo("bar");` + } +}); + diff --git a/tests/cases/fourslash/server/pasteEdits_externalModuleSymbolImport1.ts b/tests/cases/fourslash/server/pasteEdits_externalModuleSymbolImport1.ts new file mode 100644 index 0000000000000..bbd66060fbfc0 --- /dev/null +++ b/tests/cases/fourslash/server/pasteEdits_externalModuleSymbolImport1.ts @@ -0,0 +1,47 @@ +/// + +// @Filename: /folder/c.ts +//// [||] + + +// @Filename: /a.ts +//// const abc = 10; +//// const def = 20; +//// export interface testInterface { +//// abc: number; +//// def: number; +//// } + +// @Filename: /b.ts +//// import * as test from "./a"; +//// +//// [|function foo(abc: test.testInterface, def: test.testInterface) { +//// console.log(abc); +//// console.log(def); +//// }|] +//// + +// @Filename: /tsconfig.json +////{ "files": ["/folder/c.ts", "/a.ts", "/b.ts"] } + +const range = test.ranges(); +verify.pasteEdits({ + args: { + pastedText: [`function foo(abc: test.abc, def: test.def) { +console.log(abc); +console.log(def); +}`], + pasteLocations: [range[0]], + copiedFrom: { file: "/b.ts", range: [range[1]] }, + }, + newFileContents: { + "/folder/c.ts": +`import * as test from "../a"; + +function foo(abc: test.abc, def: test.def) { +console.log(abc); +console.log(def); +}` + } +}); + diff --git a/tests/cases/fourslash/server/pasteEdits_externalModuleSymbolImport2.ts b/tests/cases/fourslash/server/pasteEdits_externalModuleSymbolImport2.ts new file mode 100644 index 0000000000000..9b144e4bafe14 --- /dev/null +++ b/tests/cases/fourslash/server/pasteEdits_externalModuleSymbolImport2.ts @@ -0,0 +1,46 @@ +/// + +// @Filename: /folder/c.ts +//// [||] + + +// @Filename: /a.ts +//// const abc = 10; +//// const def = 20; +//// export interface testInterface { +//// abc: number; +//// def: number; +//// } + +// @Filename: /b.mts +//// import test from "./a.js"; +//// +//// [|function foo(abc: test.testInterface, def: test.testInterface) { +//// console.log(abc); +//// console.log(def); +//// }|] +//// + +// @Filename: /tsconfig.json +////{ "compilerOptions": { "module": "nodenext" }, "files": ["/folder/c.ts", "/a.ts", "/b.mts"] } + +const range = test.ranges(); +verify.pasteEdits({ + args: { + pastedText: [`function foo(abc: test.abc, def: test.def) { +console.log(abc); +console.log(def); +}`], + pasteLocations: [range[0]], + copiedFrom: { file: "/b.mts", range: [range[1]] }, + }, + newFileContents: { + "/folder/c.ts": +`import test from "../a"; + +function foo(abc: test.abc, def: test.def) { +console.log(abc); +console.log(def); +}` + } +}); diff --git a/tests/cases/fourslash/server/pasteEdits_externalModuleSymbolImport3.ts b/tests/cases/fourslash/server/pasteEdits_externalModuleSymbolImport3.ts new file mode 100644 index 0000000000000..4d193d7289cac --- /dev/null +++ b/tests/cases/fourslash/server/pasteEdits_externalModuleSymbolImport3.ts @@ -0,0 +1,46 @@ +/// + +// @Filename: /folder/c.ts +//// [||] + +// @Filename: /a.ts +//// const abc = 10; +//// const def = 20; +//// export interface testInterface { +//// abc: number; +//// def: number; +//// } + +// @Filename: /b.ts +//// import test = require("./a"); +//// +//// [|function foo(abc: test.testInterface, def: test.testInterface) { +//// console.log(abc); +//// console.log(def); +//// }|] +//// + +// @Filename: /tsconfig.json +////{ "compilerOptions": { "module": "commonjs" }, "files": ["/folder/c.ts", "/a.ts", "/b.ts"] } + +const range = test.ranges(); +verify.pasteEdits({ + args: { + pastedText: [`function foo(abc: test.abc, def: test.def) { +console.log(abc); +console.log(def); +}`], + pasteLocations: [range[0]], + copiedFrom: { file: "/b.ts", range: [range[1]] }, + }, + newFileContents: { + "/folder/c.ts": +`import * as test from "../a"; + +function foo(abc: test.abc, def: test.def) { +console.log(abc); +console.log(def); +}` + } +}); +