mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-05 08:11:30 -06:00
Paste without imports (#59093)
This commit is contained in:
parent
962389313f
commit
7bd7dfc007
@ -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);
|
||||
|
||||
@ -129,6 +129,7 @@ import {
|
||||
PropertyAccessExpression,
|
||||
PropertyAssignment,
|
||||
QuotePreference,
|
||||
rangeContainsRange,
|
||||
RefactorContext,
|
||||
RefactorEditInfo,
|
||||
RequireOrImportCall,
|
||||
@ -145,6 +146,7 @@ import {
|
||||
SyntaxKind,
|
||||
takeWhile,
|
||||
textChanges,
|
||||
TextRange,
|
||||
TransformFlags,
|
||||
tryCast,
|
||||
TypeAliasDeclaration,
|
||||
@ -861,7 +863,7 @@ function isPureImport(node: Node): boolean {
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function getUsageInfo(oldFile: SourceFile, toMove: readonly Statement[], checker: TypeChecker, existingTargetLocals: ReadonlySet<Symbol> = new Set()): UsageInfo {
|
||||
export function getUsageInfo(oldFile: SourceFile, toMove: readonly Statement[], checker: TypeChecker, existingTargetLocals: ReadonlySet<Symbol> = new Set(), enclosingRange?: TextRange): UsageInfo {
|
||||
const movedSymbols = new Set<Symbol>();
|
||||
const oldImportsNeededByTargetFile = new Map<Symbol, [/*isValidTypeOnlyUseSite*/ boolean, codefix.ImportOrRequireAliasDeclaration | undefined]>();
|
||||
const targetFileImportsFromOldFile = new Map<Symbol, /*isValidTypeOnlyUseSite*/ boolean>();
|
||||
@ -880,7 +882,7 @@ export function getUsageInfo(oldFile: SourceFile, toMove: readonly Statement[],
|
||||
|
||||
const unusedImportsFromOldFile = new Set<Symbol>();
|
||||
for (const statement of toMove) {
|
||||
forEachReference(statement, checker, (symbol, isValidTypeOnlyUseSite) => {
|
||||
forEachReference(statement, checker, enclosingRange, (symbol, isValidTypeOnlyUseSite) => {
|
||||
if (!symbol.declarations || isGlobalType(checker, symbol)) {
|
||||
return;
|
||||
}
|
||||
@ -916,7 +918,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);
|
||||
});
|
||||
@ -959,9 +961,12 @@ function inferNewFileName(importsFromNewFile: Map<Symbol, unknown>, 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));
|
||||
}
|
||||
@ -1140,7 +1145,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);
|
||||
|
||||
@ -0,0 +1,310 @@
|
||||
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
|
||||
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}
|
||||
/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
|
||||
25
tests/cases/fourslash/server/pasteEdits_noImportNeeded.ts
Normal file
25
tests/cases/fourslash/server/pasteEdits_noImportNeeded.ts
Normal file
@ -0,0 +1,25 @@
|
||||
/// <reference path="../fourslash.ts" />
|
||||
|
||||
// @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`
|
||||
}
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user