From 10be994a23fc1cd5573b4287efd242b36bcb9a7a Mon Sep 17 00:00:00 2001 From: navya9singh Date: Tue, 23 Jul 2024 11:01:26 -0700 Subject: [PATCH 01/19] cherry pick with fixes --- package-lock.json | 34 +++++++ package.json | 4 + src/compiler/_namespaces/ts.ts | 3 +- src/compiler/perfLogger.ts | 44 +++++++++ src/server/session.ts | 3 +- src/tsserver/nodeServer.ts | 163 ++++++++++++++++++++++++++++--- src/tsserver/server.ts | 6 +- src/typescript/_namespaces/ts.ts | 2 +- src/typescript/typescript.ts | 2 +- 9 files changed, 238 insertions(+), 23 deletions(-) create mode 100644 src/compiler/perfLogger.ts diff --git a/package-lock.json b/package-lock.json index 2edf3e259a50b..e1456d50ce2bf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,9 @@ "name": "typescript", "version": "5.6.0", "license": "Apache-2.0", + "dependencies": { + "@microsoft/typescript-etw": "^0.1.0" + }, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -20,6 +23,7 @@ "@octokit/rest": "^21.0.1", "@types/chai": "^4.3.16", "@types/diff": "^5.2.1", + "@types/microsoft__typescript-etw": "^0.1.3", "@types/minimist": "^1.2.5", "@types/mocha": "^10.0.7", "@types/ms": "^0.7.34", @@ -805,6 +809,19 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@microsoft/typescript-etw": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@microsoft/typescript-etw/-/typescript-etw-0.1.0.tgz", + "integrity": "sha512-P6ohPmiIMNH406IGkh95ZSQ3sZhGLF3xPFA9F7/9F4dXT8yV5dBPA297jlRF1ZNjroi3g9pasCM/LoqrxP+SqQ==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "hasInstallScript": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 8.9.0" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1038,6 +1055,12 @@ "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", "dev": true }, + "node_modules/@types/microsoft__typescript-etw": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@types/microsoft__typescript-etw/-/microsoft__typescript-etw-0.1.3.tgz", + "integrity": "sha512-qbO0IoTPJERhGWOvdw9iQbRjM7OGc6+fHVziSKcw566BDSQpEdkGxXcE8BKSHJOP6mkTRobf4QxqRE/aKhrCxg==", + "dev": true + }, "node_modules/@types/minimist": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", @@ -5271,6 +5294,11 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "@microsoft/typescript-etw": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@microsoft/typescript-etw/-/typescript-etw-0.1.0.tgz", + "integrity": "sha512-P6ohPmiIMNH406IGkh95ZSQ3sZhGLF3xPFA9F7/9F4dXT8yV5dBPA297jlRF1ZNjroi3g9pasCM/LoqrxP+SqQ==" + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -5448,6 +5476,12 @@ "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", "dev": true }, + "@types/microsoft__typescript-etw": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@types/microsoft__typescript-etw/-/microsoft__typescript-etw-0.1.3.tgz", + "integrity": "sha512-qbO0IoTPJERhGWOvdw9iQbRjM7OGc6+fHVziSKcw566BDSQpEdkGxXcE8BKSHJOP6mkTRobf4QxqRE/aKhrCxg==", + "dev": true + }, "@types/minimist": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", diff --git a/package.json b/package.json index 2917f5b42414e..e73af350e89dc 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,7 @@ "@octokit/rest": "^21.0.1", "@types/chai": "^4.3.16", "@types/diff": "^5.2.1", + "@types/microsoft__typescript-etw": "^0.1.3", "@types/minimist": "^1.2.5", "@types/mocha": "^10.0.7", "@types/ms": "^0.7.34", @@ -113,5 +114,8 @@ "volta": { "node": "20.1.0", "npm": "8.19.4" + }, + "dependencies": { + "@microsoft/typescript-etw": "^0.1.0" } } diff --git a/src/compiler/_namespaces/ts.ts b/src/compiler/_namespaces/ts.ts index 94fb16857d38e..bbd273b39cce7 100644 --- a/src/compiler/_namespaces/ts.ts +++ b/src/compiler/_namespaces/ts.ts @@ -5,6 +5,7 @@ export * from "../core.js"; export * from "../debug.js"; export * from "../semver.js"; export * from "../performanceCore.js"; +export * from "../perfLogger.js"; export * from "../tracing.js"; export * from "../types.js"; export * from "../sys.js"; @@ -75,4 +76,4 @@ export * from "../expressionToTypeNode.js"; import * as moduleSpecifiers from "./ts.moduleSpecifiers.js"; export { moduleSpecifiers }; import * as performance from "./ts.performance.js"; -export { performance }; +export { performance }; \ No newline at end of file diff --git a/src/compiler/perfLogger.ts b/src/compiler/perfLogger.ts new file mode 100644 index 0000000000000..64c10a69ea80d --- /dev/null +++ b/src/compiler/perfLogger.ts @@ -0,0 +1,44 @@ +/** @internal */ +export interface PerfLogger { + logEvent(msg: string): void; + logErrEvent(msg: string): void; + logPerfEvent(msg: string): void; + logInfoEvent(msg: string): void; + logStartCommand(command: string, msg: string): void; + logStopCommand(command: string, msg: string): void; + logStartUpdateProgram(msg: string): void; + logStopUpdateProgram(msg: string): void; + logStartUpdateGraph(): void; + logStopUpdateGraph(): void; + logStartResolveModule(name: string): void; + logStopResolveModule(success: string): void; + logStartParseSourceFile(filename: string): void; + logStopParseSourceFile(): void; + logStartReadFile(filename: string): void; + logStopReadFile(): void; + logStartBindFile(filename: string): void; + logStopBindFile(): void; + logStartScheduledOperation(operationId: string): void; + logStopScheduledOperation(): void; +} + +// Load optional module to enable Event Tracing for Windows +// See https://github.com/microsoft/typescript-etw for more information +let etwModule: typeof import("@microsoft/typescript-etw") | undefined; +try { + const etwModulePath = process.env.TS_ETW_MODULE_PATH ?? "./node_modules/@microsoft/typescript-etw"; + + // require() will throw an exception if the module is not found + // It may also return undefined if not installed properly + etwModule = require(etwModulePath); +} +catch (e) { + etwModule = undefined; +} + +/** + * Performance logger that will generate ETW events if possible - check for `logEvent` member, as `etwModule` will be `{}` when browserified + * + * @internal + */ +export const perfLogger: PerfLogger | undefined = etwModule?.logEvent ? etwModule : undefined; \ No newline at end of file diff --git a/src/server/session.ts b/src/server/session.ts index 5951733c8392e..9715e5176f079 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -3804,6 +3804,7 @@ export class Session implements EventSender { let relevantFile: protocol.FileRequestArgs | undefined; try { request = this.parseMessage(message); + console.log(`${request.seq}:: ${request.command}`); relevantFile = request.arguments && (request as protocol.FileRequest).arguments.file ? (request as protocol.FileRequest).arguments : undefined; tracing?.instant(tracing.Phase.Session, "request", { seq: request.seq, command: request.command }); @@ -3854,7 +3855,7 @@ export class Session implements EventSender { this.doOutput({ canceled: true }, request!.command, request!.seq, /*success*/ true, this.performanceData); return; } - + console.log(`${request?.seq}:: ${request?.command}:: Exception`, err); this.logErrorWorker(err, this.toStringMessage(message), relevantFile); tracing?.instant(tracing.Phase.Session, "commandError", { seq: request?.seq, command: request?.command, message: (err as Error).message }); diff --git a/src/tsserver/nodeServer.ts b/src/tsserver/nodeServer.ts index 6e89f665fe436..abf05f9d3276f 100644 --- a/src/tsserver/nodeServer.ts +++ b/src/tsserver/nodeServer.ts @@ -1,8 +1,3 @@ -import childProcess from "child_process"; -import fs from "fs"; -import net from "net"; -import os from "os"; -import readline from "readline"; import { CharacterCodes, combinePaths, @@ -10,14 +5,18 @@ import { Debug, directorySeparator, DirectoryWatcherCallback, + emptyArray, + endsWith, FileWatcher, getDirectoryPath, getRootLength, LanguageServiceMode, + MapLike, noop, noopFileWatcher, normalizePath, normalizeSlashes, + perfLogger, startTracing, stripQuotes, sys, @@ -41,6 +40,24 @@ interface LogOptions { logToFile?: boolean; } +interface NodeChildProcess { + send(message: any, sendHandle?: any): void; + on(message: "message" | "exit", f: (m: any) => void): void; + kill(): void; + pid: number; +} + +interface ReadLineOptions { + input: NodeJS.ReadableStream; + output?: NodeJS.WritableStream; + terminal?: boolean; + historySize?: number; +} + +interface NodeSocket { + write(data: string, encoding: string): boolean; +} + function parseLoggingEnvironmentString(logEnvStr: string | undefined): LogOptions { if (!logEnvStr) { return {}; @@ -109,6 +126,41 @@ function parseServerMode(): LanguageServiceMode | string | undefined { /** @internal */ export function initializeNodeSystem(): StartInput { const sys = Debug.checkDefined(ts.sys) as ts.server.ServerHost; + const childProcess: { + execFileSync(file: string, args: string[], options: { stdio: "ignore"; env: MapLike; }): string | Buffer; + } = require("child_process"); + + interface Stats { + isFile(): boolean; + isDirectory(): boolean; + isBlockDevice(): boolean; + isCharacterDevice(): boolean; + isSymbolicLink(): boolean; + isFIFO(): boolean; + isSocket(): boolean; + dev: number; + ino: number; + mode: number; + nlink: number; + uid: number; + gid: number; + rdev: number; + size: number; + blksize: number; + blocks: number; + atime: Date; + mtime: Date; + ctime: Date; + birthtime: Date; + } + + const fs: { + openSync(path: string, options: string): number; + close(fd: number, callback: (err: NodeJS.ErrnoException) => void): void; + writeSync(fd: number, buffer: Buffer, offset: number, length: number, position?: number): number; + statSync(path: string): Stats; + stat(path: string, callback?: (err: NodeJS.ErrnoException, stats: Stats) => any): void; + } = require("fs"); class Logger implements Logger { private seq = 0; @@ -163,6 +215,18 @@ export function initializeNodeSystem(): StartInput { return this.loggingEnabled() && this.level >= level; } msg(s: string, type: ts.server.Msg = ts.server.Msg.Err) { + switch (type) { + case ts.server.Msg.Info: + perfLogger?.logInfoEvent(s); + break; + case ts.server.Msg.Perf: + perfLogger?.logPerfEvent(s); + break; + default: // Msg.Err + perfLogger?.logErrEvent(s); + break; + } + if (!this.canWrite()) return; s = `[${ts.server.nowString()}] ${s}\n`; @@ -182,7 +246,7 @@ export function initializeNodeSystem(): StartInput { if (this.fd >= 0) { const buf = Buffer.from(s); // eslint-disable-next-line no-restricted-syntax - fs.writeSync(this.fd, buf, 0, buf.length, /*position*/ null); + fs.writeSync(this.fd, buf, 0, buf.length, /*position*/ null!); // TODO: GH#18217 } if (this.traceToConsole) { console.warn(s); @@ -277,7 +341,7 @@ export function initializeNodeSystem(): StartInput { let cancellationToken: ts.server.ServerCancellationToken; try { - const factory = require("./cancellationToken.js"); + const factory = require("./cancellationToken"); cancellationToken = factory(sys.args); } catch (e) { @@ -390,14 +454,34 @@ function parseEventPort(eventPortStr: string | undefined) { return eventPort !== undefined && !isNaN(eventPort) ? eventPort : undefined; } function startNodeSession(options: StartSessionOptions, logger: ts.server.Logger, cancellationToken: ts.server.ServerCancellationToken) { - const rl = readline.createInterface({ - input: process.stdin, - output: process.stdout, - terminal: false, - }); + const childProcess: { + fork(modulePath: string, args: string[], options?: { execArgv: string[]; env?: MapLike; }): NodeChildProcess; + } = require("child_process"); + + const os: { + homedir?(): string; + tmpdir(): string; + } = require("os"); + + const net: { + connect(options: { port: number; }, onConnect?: () => void): NodeSocket; + } = require("net"); + + const readline: { + createInterface(options: ReadLineOptions): NodeJS.EventEmitter; + } = require("readline"); + + const fs: { + readFileSync(path: string, options: { encoding: string; flag?: string; } | string): string; + writeFileSync(path: string, data: string): string; + } = require("fs"); + + const stream: { + Readable: { from(str: string): NodeJS.ReadStream; }; + } = require("stream"); class NodeTypingsInstallerAdapter extends ts.server.TypingsInstallerAdapter { - protected override installer!: childProcess.ChildProcess; + protected override installer!: NodeChildProcess; // This number is essentially arbitrary. Processing more than one typings request // at a time makes sense, but having too many in the pipe results in a hang // (see https://github.com/nodejs/node/issues/7657). @@ -467,7 +551,7 @@ function startNodeSession(options: StartSessionOptions, logger: ts.server.Logger const typingsInstaller = combinePaths(getDirectoryPath(sys.getExecutingFilePath()), "typingsInstaller.js"); this.installer = childProcess.fork(typingsInstaller, args, { execArgv }); - this.installer.on("message", m => this.handleMessage(m as any)); + this.installer.on("message", m => this.handleMessage(m)); // We have to schedule this event to the next tick // cause this fn will be called during @@ -484,7 +568,7 @@ function startNodeSession(options: StartSessionOptions, logger: ts.server.Logger class IOSession extends ts.server.Session { private eventPort: number | undefined; - private eventSocket: net.Socket | undefined; + private eventSocket: NodeSocket | undefined; private socketEventQueue: { body: any; eventName: string; }[] | undefined; /** No longer needed if syntax target is es6 or above. Any access to "this" before initialized will be a runtime error. */ private constructed: boolean | undefined; @@ -619,6 +703,12 @@ function startNodeSession(options: StartSessionOptions, logger: ts.server.Logger startTracing("server", traceDir); } + const inputStream = getInputReadStream(ts.server.findArgument("--inputRequestsFile"), ts.server.findArgument("--inputLogFile"), ts.server.findArgument("--createRequestsFile")); + const rl = readline.createInterface({ + input: inputStream || process.stdin, + output: process.stdout, + terminal: false, + }); const ioSession = useNodeIpc ? new IpcIOSession() : new IOSession(); process.on("uncaughtException", err => { ioSession.logError(err, "unknown"); @@ -628,6 +718,47 @@ function startNodeSession(options: StartSessionOptions, logger: ts.server.Logger // Start listening ioSession.listen(); + function getInputReadStream(inputRequestsFile: string | undefined, inputLogFile: string | undefined, requestFile: string | undefined) { + if (!inputRequestsFile && !inputLogFile) return undefined; + let result: any[]; + if (inputRequestsFile) { + const text = fs.readFileSync(stripQuotes(inputRequestsFile), "utf8"); + try { + result = text ? JSON.parse(text) : emptyArray; + } + catch (e) { + result = []; + } + } + else { + const lines = fs.readFileSync(stripQuotes(inputLogFile!), "utf8")?.split(/\r?\n/) || []; + result = []; + for (let i = 0; i < lines.length; i++) { + const line = lines[i]; + if (!endsWith(line, "] request:")) continue; + const texts: string[] = []; + for (i++; i < lines.length; i++) { + if (lines[i].search(/((Info)|(Perf)|(Err))\s[0-9]+\s*\[/) === 0) { + i--; + break; + } + texts.push(lines[i]); + } + const text = texts.join(""); + try { + const json = JSON.parse(text); + if (json && json.type === "request") { + result.push(json); + } + } + catch (e) {} // eslint-disable-line no-empty + } + } + if (requestFile) fs.writeFileSync(stripQuotes(requestFile), JSON.stringify(result, /*replacer*/ undefined, " ")); + console.log(`Requests:: ${result.length}`); + return stream.Readable.from(result.map(r => JSON.stringify(r)).join("\n")); + } + function getGlobalTypingsCacheLocation() { switch (process.platform) { case "win32": { @@ -667,4 +798,4 @@ function startNodeSession(options: StartSessionOptions, logger: ts.server.Logger : ".cache"; return combinePaths(normalizeSlashes(homePath), cacheFolder); } -} +} \ No newline at end of file diff --git a/src/tsserver/server.ts b/src/tsserver/server.ts index d74ca4f04d645..919c4aaf73b4f 100644 --- a/src/tsserver/server.ts +++ b/src/tsserver/server.ts @@ -32,9 +32,9 @@ function start({ args, logger, cancellationToken, serverMode, unknownServerMode, // the log. This is so that language service plugins which use // console.log don't break the message passing between tsserver // and the client - console.log = (...args) => logger.msg(args.length === 1 ? args[0] : args.join(", "), ts.server.Msg.Info); - console.warn = (...args) => logger.msg(args.length === 1 ? args[0] : args.join(", "), ts.server.Msg.Err); - console.error = (...args) => logger.msg(args.length === 1 ? args[0] : args.join(", "), ts.server.Msg.Err); + // console.log = (...args) => logger.msg(args.length === 1 ? args[0] : args.join(", "), ts.server.Msg.Info); + // console.warn = (...args) => logger.msg(args.length === 1 ? args[0] : args.join(", "), ts.server.Msg.Err); + // console.error = (...args) => logger.msg(args.length === 1 ? args[0] : args.join(", "), ts.server.Msg.Err); startServer( { diff --git a/src/typescript/_namespaces/ts.ts b/src/typescript/_namespaces/ts.ts index 1c1a9fcb82264..3e2ef4e54d917 100644 --- a/src/typescript/_namespaces/ts.ts +++ b/src/typescript/_namespaces/ts.ts @@ -5,4 +5,4 @@ export * from "../../jsTyping/_namespaces/ts.js"; export * from "../../services/_namespaces/ts.js"; export * from "../../server/_namespaces/ts.js"; import * as server from "./ts.server.js"; -export { server }; +export { server }; \ No newline at end of file diff --git a/src/typescript/typescript.ts b/src/typescript/typescript.ts index 9e54bbe9c15b0..18eea5580827a 100644 --- a/src/typescript/typescript.ts +++ b/src/typescript/typescript.ts @@ -22,4 +22,4 @@ if (typeof console !== "undefined") { }; } -export * from "./_namespaces/ts.js"; +export * from "./_namespaces/ts.js"; \ No newline at end of file From 0d5380b0e6a86210ef02289305e47345ed489071 Mon Sep 17 00:00:00 2001 From: navya9singh Date: Tue, 23 Jul 2024 11:01:52 -0700 Subject: [PATCH 02/19] Revert "Fixing range for primary edit (#59369)" This reverts commit b04c8a0edd3a750cf5ae701d82fd164daa594381. --- src/server/project.ts | 4 +- .../pasteEdits_addInNextLine.js | 328 ------------------ .../server/pasteEdits_addInNextLine.ts | 37 -- 3 files changed, 2 insertions(+), 367 deletions(-) delete mode 100644 tests/baselines/reference/tsserver/fourslashServer/pasteEdits_addInNextLine.js delete mode 100644 tests/cases/fourslash/server/pasteEdits_addInNextLine.ts diff --git a/src/server/project.ts b/src/server/project.ts index 3bb2253621442..cf4167040ccc4 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -2319,7 +2319,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo runWithTemporaryFileUpdate(rootFile: string, updatedText: string, cb: (updatedProgram: Program, originalProgram: Program | undefined, updatedFile: SourceFile) => void) { const originalProgram = this.program; const rootSourceFile = Debug.checkDefined(this.program?.getSourceFile(rootFile), "Expected file to be part of program"); - const originalText = Debug.checkDefined(rootSourceFile.getFullText()); + const originalText = Debug.checkDefined(rootSourceFile.getText()); this.getScriptInfo(rootFile)?.editContent(0, originalText.length, updatedText); this.updateGraph(); @@ -2327,7 +2327,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo cb(this.program!, originalProgram, (this.program?.getSourceFile(rootFile))!); } finally { - this.getScriptInfo(rootFile)?.editContent(0, updatedText.length, originalText); + this.getScriptInfo(rootFile)?.editContent(0, this.program!.getSourceFile(rootFile)!.getText().length, originalText); } } diff --git a/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_addInNextLine.js b/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_addInNextLine.js deleted file mode 100644 index df847da18a2f4..0000000000000 --- a/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_addInNextLine.js +++ /dev/null @@ -1,328 +0,0 @@ -currentDirectory:: / useCaseSensitiveFileNames: false -Info seq [hh:mm:ss:mss] Provided types map file "/typesMap.json" doesn't exist -//// [/a.ts] - - - - - - -//// [/b.ts] -export interface Foo { } -export const a = 1; -export const t = 1; - -export const foo: Foo = { }; -export const k = a+ t; - -//// [/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": "/a.ts" - }, - "command": "open" - } -Info seq [hh:mm:ss:mss] getConfigFileNameForFile:: File: /a.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 /a.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: /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 (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 SVC-1-0 "\n\n\n\n" - /b.ts Text-1 "export interface Foo { }\nexport const a = 1;\nexport const t = 1;\n\nexport const foo: Foo = { };\nexport const k = a+ t;" - - - 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": "/a.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: /a.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:: -/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 (Open) *new* - version: SVC-1-0 - containingProjects: 1 - /tsconfig.json *default* -/b.ts *new* - version: Text-1 - containingProjects: 1 - /tsconfig.json -/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": "/a.ts", - "pastedText": [ - "export const foo: Foo = {};" - ], - "pasteLocations": [ - { - "start": { - "line": 4, - "offset": 1 - }, - "end": { - "line": 4, - "offset": 1 - } - } - ], - "copiedFrom": { - "file": "b.ts", - "spans": [ - { - "start": { - "line": 5, - "offset": 1 - }, - "end": { - "line": 5, - "offset": 29 - } - } - ] - } - }, - "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 SVC-1-1 "\n\n\nexport const foo: Foo = {};\n" - /b.ts Text-1 "export interface Foo { }\nexport const a = 1;\nexport const t = 1;\n\nexport const foo: Foo = { };\nexport const k = a+ t;" - -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": "/a.ts", - "textChanges": [ - { - "start": { - "line": 1, - "offset": 1 - }, - "end": { - "line": 1, - "offset": 1 - }, - "newText": "import { Foo } from \"./b\";\n" - }, - { - "start": { - "line": 4, - "offset": 1 - }, - "end": { - "line": 4, - "offset": 1 - }, - "newText": "export const foo: Foo = {};" - } - ] - } - ], - "fixId": "providePostPasteEdits" - } - } -After Request -Projects:: -/tsconfig.json (Configured) *changed* - projectStateVersion: 3 *changed* - projectProgramVersion: 1 - dirty: true *changed* - -ScriptInfos:: -/a.ts (Open) *changed* - version: SVC-1-2 *changed* - containingProjects: 1 - /tsconfig.json *default* -/b.ts - version: Text-1 - containingProjects: 1 - /tsconfig.json -/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_addInNextLine.ts b/tests/cases/fourslash/server/pasteEdits_addInNextLine.ts deleted file mode 100644 index ce3919b85c3f3..0000000000000 --- a/tests/cases/fourslash/server/pasteEdits_addInNextLine.ts +++ /dev/null @@ -1,37 +0,0 @@ -/// - -// @Filename: /a.ts -//// -//// -//// -//// [||] -//// - -// @Filename: /b.ts -//// export interface Foo { } -//// export const a = 1; -//// export const t = 1; -//// -//// [|export const foo: Foo = { };|] -//// [|export const k = a+ t;|] - -// @Filename: /tsconfig.json -////{ "files": ["a.ts", "b.ts"] } - -const range = test.ranges(); -verify.pasteEdits({ - args: { - pastedText: [`export const foo: Foo = {};`], - pasteLocations: [range[0]], - copiedFrom: { file: "b.ts", range: [range[1]] }, - }, - newFileContents: { - "/a.ts": -`import { Foo } from "./b"; - - - -export const foo: Foo = {}; -` - } -}); From 7b1d203bc5178c5ead302e3b9afe3faf521404a9 Mon Sep 17 00:00:00 2001 From: navya9singh Date: Wed, 24 Jul 2024 10:41:59 -0700 Subject: [PATCH 03/19] Reapply "Fixing range for primary edit (#59369)" This reverts commit 0d5380b0e6a86210ef02289305e47345ed489071. --- src/server/project.ts | 4 +- .../pasteEdits_addInNextLine.js | 328 ++++++++++++++++++ .../server/pasteEdits_addInNextLine.ts | 37 ++ 3 files changed, 367 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/tsserver/fourslashServer/pasteEdits_addInNextLine.js create mode 100644 tests/cases/fourslash/server/pasteEdits_addInNextLine.ts diff --git a/src/server/project.ts b/src/server/project.ts index cf4167040ccc4..3bb2253621442 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -2319,7 +2319,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo runWithTemporaryFileUpdate(rootFile: string, updatedText: string, cb: (updatedProgram: Program, originalProgram: Program | undefined, updatedFile: SourceFile) => void) { const originalProgram = this.program; const rootSourceFile = Debug.checkDefined(this.program?.getSourceFile(rootFile), "Expected file to be part of program"); - const originalText = Debug.checkDefined(rootSourceFile.getText()); + const originalText = Debug.checkDefined(rootSourceFile.getFullText()); this.getScriptInfo(rootFile)?.editContent(0, originalText.length, updatedText); this.updateGraph(); @@ -2327,7 +2327,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo cb(this.program!, originalProgram, (this.program?.getSourceFile(rootFile))!); } finally { - this.getScriptInfo(rootFile)?.editContent(0, this.program!.getSourceFile(rootFile)!.getText().length, originalText); + this.getScriptInfo(rootFile)?.editContent(0, updatedText.length, originalText); } } diff --git a/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_addInNextLine.js b/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_addInNextLine.js new file mode 100644 index 0000000000000..df847da18a2f4 --- /dev/null +++ b/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_addInNextLine.js @@ -0,0 +1,328 @@ +currentDirectory:: / useCaseSensitiveFileNames: false +Info seq [hh:mm:ss:mss] Provided types map file "/typesMap.json" doesn't exist +//// [/a.ts] + + + + + + +//// [/b.ts] +export interface Foo { } +export const a = 1; +export const t = 1; + +export const foo: Foo = { }; +export const k = a+ t; + +//// [/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": "/a.ts" + }, + "command": "open" + } +Info seq [hh:mm:ss:mss] getConfigFileNameForFile:: File: /a.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 /a.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: /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 (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 SVC-1-0 "\n\n\n\n" + /b.ts Text-1 "export interface Foo { }\nexport const a = 1;\nexport const t = 1;\n\nexport const foo: Foo = { };\nexport const k = a+ t;" + + + 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": "/a.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: /a.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:: +/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 (Open) *new* + version: SVC-1-0 + containingProjects: 1 + /tsconfig.json *default* +/b.ts *new* + version: Text-1 + containingProjects: 1 + /tsconfig.json +/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": "/a.ts", + "pastedText": [ + "export const foo: Foo = {};" + ], + "pasteLocations": [ + { + "start": { + "line": 4, + "offset": 1 + }, + "end": { + "line": 4, + "offset": 1 + } + } + ], + "copiedFrom": { + "file": "b.ts", + "spans": [ + { + "start": { + "line": 5, + "offset": 1 + }, + "end": { + "line": 5, + "offset": 29 + } + } + ] + } + }, + "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 SVC-1-1 "\n\n\nexport const foo: Foo = {};\n" + /b.ts Text-1 "export interface Foo { }\nexport const a = 1;\nexport const t = 1;\n\nexport const foo: Foo = { };\nexport const k = a+ t;" + +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": "/a.ts", + "textChanges": [ + { + "start": { + "line": 1, + "offset": 1 + }, + "end": { + "line": 1, + "offset": 1 + }, + "newText": "import { Foo } from \"./b\";\n" + }, + { + "start": { + "line": 4, + "offset": 1 + }, + "end": { + "line": 4, + "offset": 1 + }, + "newText": "export const foo: Foo = {};" + } + ] + } + ], + "fixId": "providePostPasteEdits" + } + } +After Request +Projects:: +/tsconfig.json (Configured) *changed* + projectStateVersion: 3 *changed* + projectProgramVersion: 1 + dirty: true *changed* + +ScriptInfos:: +/a.ts (Open) *changed* + version: SVC-1-2 *changed* + containingProjects: 1 + /tsconfig.json *default* +/b.ts + version: Text-1 + containingProjects: 1 + /tsconfig.json +/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_addInNextLine.ts b/tests/cases/fourslash/server/pasteEdits_addInNextLine.ts new file mode 100644 index 0000000000000..ce3919b85c3f3 --- /dev/null +++ b/tests/cases/fourslash/server/pasteEdits_addInNextLine.ts @@ -0,0 +1,37 @@ +/// + +// @Filename: /a.ts +//// +//// +//// +//// [||] +//// + +// @Filename: /b.ts +//// export interface Foo { } +//// export const a = 1; +//// export const t = 1; +//// +//// [|export const foo: Foo = { };|] +//// [|export const k = a+ t;|] + +// @Filename: /tsconfig.json +////{ "files": ["a.ts", "b.ts"] } + +const range = test.ranges(); +verify.pasteEdits({ + args: { + pastedText: [`export const foo: Foo = {};`], + pasteLocations: [range[0]], + copiedFrom: { file: "b.ts", range: [range[1]] }, + }, + newFileContents: { + "/a.ts": +`import { Foo } from "./b"; + + + +export const foo: Foo = {}; +` + } +}); From b56a4afa548da4ee2012e7c9eedde2b76b7b94e1 Mon Sep 17 00:00:00 2001 From: navya9singh Date: Wed, 31 Jul 2024 10:11:22 -0700 Subject: [PATCH 04/19] approach 1 --- src/services/pasteEdits.ts | 46 ++++++++++++++++--- .../fourslash/server/pasteEdits_fixDElay.ts | 38 +++++++++++++++ 2 files changed, 77 insertions(+), 7 deletions(-) create mode 100644 tests/cases/fourslash/server/pasteEdits_fixDElay.ts diff --git a/src/services/pasteEdits.ts b/src/services/pasteEdits.ts index f3b350816781e..2c4631104ec22 100644 --- a/src/services/pasteEdits.ts +++ b/src/services/pasteEdits.ts @@ -1,6 +1,7 @@ -import { findIndex } from "../compiler/core.js"; +import { findIndex, forEach } from "../compiler/core.js"; import { CancellationToken, + Node, Program, SourceFile, Statement, @@ -15,7 +16,9 @@ import { forEachChild, formatting, getQuotePreference, + getTokenAtPosition, isIdentifier, + rangeContainsPosition, textChanges, } from "./_namespaces/ts.js"; import { addTargetFileImports } from "./refactors/helpers.js"; @@ -64,6 +67,7 @@ function pasteEdits( } const statements: Statement[] = []; + const newStatements: Statement[] = []; let newText = targetFile.text; for (let i = pasteLocations.length - 1; i >= 0; i--) { @@ -106,12 +110,40 @@ function pasteEdits( preferences, formatContext, }; - forEachChild(updatedFile, function cb(node) { - if (isIdentifier(node) && !originalProgram?.getTypeChecker().resolveName(node.text, node, SymbolFlags.All, /*excludeGlobals*/ false)) { - // generate imports - importAdder.addImportForUnresolvedIdentifier(context, node, /*useAutoImportProvider*/ true); - } - node.forEachChild(cb); + + for (const location of pasteLocations) { + const statementsInSourceFile = updatedFile.statements; + const startNodeIndex = findIndex(statementsInSourceFile, s => s.end > location.pos); + if (startNodeIndex === -1) return undefined; + const endNodeIndex = findIndex(statementsInSourceFile, s => s.end >= ( actualPastedText ? actualPastedText[0].length + location.pos : location.end ), startNodeIndex); + newStatements.push(...statementsInSourceFile.slice(startNodeIndex, endNodeIndex === -1 ? statementsInSourceFile.length : endNodeIndex + 1)); + // if (actualPastedText) { + // break; + // } + } + newStatements.forEach((statement, i) => { + forEachChild(statement, function cb(node) { + if (isIdentifier(node) && !originalProgram?.getTypeChecker().resolveName(node.text, node, SymbolFlags.All, /*excludeGlobals*/ false)) { + if (!actualPastedText && rangeContainsPosition({pos: pasteLocations[i].pos, end: pasteLocations[i].pos + pastedText[i].length}, node.getStart())) { + importAdder.addImportForUnresolvedIdentifier(context, node, /*useAutoImportProvider*/ true); + } + else if(actualPastedText && rangeContainsPosition({pos: pasteLocations[i].pos, end: pasteLocations[i].pos + actualPastedText[0].length}, node.getStart())) { + /** + * If actualPastedText is added at a position like, const t = 1;[||] + * This can be true only for the first statement in `pastedText` because the rest will be added to newStatements as separate statements. + */ + // if (i === 0 && statement.getStart() !== pasteLocations[0].pos) { + // if (rangeContainsPosition({pos: pasteLocations[0].pos, end: pasteLocations[0].pos + pastedText[0].length}, node.getStart())) { + // importAdder.addImportForUnresolvedIdentifier(context, node, /*useAutoImportProvider*/ true); + // } + // } + // else { + importAdder.addImportForUnresolvedIdentifier(context, node, /*useAutoImportProvider*/ true); + // } + } + } + node.forEachChild(cb); + }); }); } importAdder.writeFixes(changes, getQuotePreference(copiedFrom ? copiedFrom.file : targetFile, preferences)); diff --git a/tests/cases/fourslash/server/pasteEdits_fixDElay.ts b/tests/cases/fourslash/server/pasteEdits_fixDElay.ts new file mode 100644 index 0000000000000..e4e8ec6031631 --- /dev/null +++ b/tests/cases/fourslash/server/pasteEdits_fixDElay.ts @@ -0,0 +1,38 @@ +/// + +// @Filename: /a.ts +//// const ll = kkk; +//// +//// function foo() {[||] +//// const oip = 123; +//// [||] +//// } +//// [||] +//// + +// @Filename: /b.ts +//// export const a = 1; +//// export const t = 1; +//// export function foo() {} +//// export const kkk = a + t; + +// @Filename: /tsconfig.json +////{ "files": ["a.ts", "b.ts"] } + +const range = test.ranges(); +verify.pasteEdits({ + args: { + pastedText: [`export const kkk = a + t;`, `const yuy = 1;`], + pasteLocations: [range[0], range[1], range[2]], + }, + newFileContents: { + "/a.ts": +`import { a, t } from "./b"; + +const ll = kkk; + + +export const kkk = a + t; +` + } +}); From 4544ad3d19cfc2cceffe415b3b1430dc70c6b9fa Mon Sep 17 00:00:00 2001 From: navya9singh Date: Tue, 6 Aug 2024 16:58:00 -0700 Subject: [PATCH 05/19] new approach that fixes delay --- src/services/pasteEdits.ts | 64 ++- .../pasteEdits_multiplePastes5.js | 392 ++++++++++++++++++ .../fourslash/server/pasteEdits_fixDElay.ts | 38 -- .../server/pasteEdits_multiplePastes5.ts | 73 ++++ 4 files changed, 494 insertions(+), 73 deletions(-) create mode 100644 tests/baselines/reference/tsserver/fourslashServer/pasteEdits_multiplePastes5.js delete mode 100644 tests/cases/fourslash/server/pasteEdits_fixDElay.ts create mode 100644 tests/cases/fourslash/server/pasteEdits_multiplePastes5.ts diff --git a/src/services/pasteEdits.ts b/src/services/pasteEdits.ts index 2c4631104ec22..a6033601eb1af 100644 --- a/src/services/pasteEdits.ts +++ b/src/services/pasteEdits.ts @@ -1,7 +1,8 @@ -import { findIndex, forEach } from "../compiler/core.js"; +import { + findIndex, +} from "../compiler/core.js"; import { CancellationToken, - Node, Program, SourceFile, Statement, @@ -13,6 +14,7 @@ import { codefix, Debug, fileShouldUseJavaScriptRequire, + findAncestor, forEachChild, formatting, getQuotePreference, @@ -67,8 +69,6 @@ function pasteEdits( } const statements: Statement[] = []; - const newStatements: Statement[] = []; - let newText = targetFile.text; for (let i = pasteLocations.length - 1; i >= 0; i--) { const { pos, end } = pasteLocations[i]; @@ -111,38 +111,32 @@ function pasteEdits( formatContext, }; - for (const location of pasteLocations) { - const statementsInSourceFile = updatedFile.statements; - const startNodeIndex = findIndex(statementsInSourceFile, s => s.end > location.pos); - if (startNodeIndex === -1) return undefined; - const endNodeIndex = findIndex(statementsInSourceFile, s => s.end >= ( actualPastedText ? actualPastedText[0].length + location.pos : location.end ), startNodeIndex); - newStatements.push(...statementsInSourceFile.slice(startNodeIndex, endNodeIndex === -1 ? statementsInSourceFile.length : endNodeIndex + 1)); - // if (actualPastedText) { - // break; - // } - } - newStatements.forEach((statement, i) => { - forEachChild(statement, function cb(node) { - if (isIdentifier(node) && !originalProgram?.getTypeChecker().resolveName(node.text, node, SymbolFlags.All, /*excludeGlobals*/ false)) { - if (!actualPastedText && rangeContainsPosition({pos: pasteLocations[i].pos, end: pasteLocations[i].pos + pastedText[i].length}, node.getStart())) { - importAdder.addImportForUnresolvedIdentifier(context, node, /*useAutoImportProvider*/ true); - } - else if(actualPastedText && rangeContainsPosition({pos: pasteLocations[i].pos, end: pasteLocations[i].pos + actualPastedText[0].length}, node.getStart())) { - /** - * If actualPastedText is added at a position like, const t = 1;[||] - * This can be true only for the first statement in `pastedText` because the rest will be added to newStatements as separate statements. - */ - // if (i === 0 && statement.getStart() !== pasteLocations[0].pos) { - // if (rangeContainsPosition({pos: pasteLocations[0].pos, end: pasteLocations[0].pos + pastedText[0].length}, node.getStart())) { - // importAdder.addImportForUnresolvedIdentifier(context, node, /*useAutoImportProvider*/ true); - // } - // } - // else { - importAdder.addImportForUnresolvedIdentifier(context, node, /*useAutoImportProvider*/ true); - // } - } + /** + * `updatedRanges` represent the new ranges that account for the offset changes caused by pasting new text and + * `offset` represents by how much the starting position of `pasteLocations` needs to be changed. + * + * We iterate over each updated range to get the node that wholly encloses the updated range. For each child of that node, it is checked if the + * identifier lies within the updated range and if it is not resolved, we try resolving it. + */ + const updatedRanges: TextRange[] = []; + let offset = 0; + pasteLocations.forEach((location, i) => { + const deletionNeeded = location.pos === location.end ? 0 : location.end - location.pos + 1; + const textToBePasted = actualPastedText ? actualPastedText[0] : pastedText[i]; + const startPos = location.pos - offset; + const endPos = startPos + textToBePasted.length - 1; + updatedRanges.push({ pos: startPos, end: endPos }); + offset += deletionNeeded - textToBePasted.length; + }); + + updatedRanges.forEach(range => { + const enclosingNode = findAncestor(getTokenAtPosition(context.sourceFile, range.pos), cb => rangeContainsPosition({ pos: cb.pos, end: cb.end }, range.end)); + if (!enclosingNode) return; + forEachChild(enclosingNode, function cb(node) { + if (isIdentifier(node) && rangeContainsPosition(range, node.getStart()) && !originalProgram?.getTypeChecker().resolveName(node.text, node, SymbolFlags.All, /*excludeGlobals*/ false)) { + importAdder.addImportForUnresolvedIdentifier(context, node, /*useAutoImportProvider*/ true); } - node.forEachChild(cb); + node.forEachChild(cb); }); }); } diff --git a/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_multiplePastes5.js b/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_multiplePastes5.js new file mode 100644 index 0000000000000..6cd5ecc0724b7 --- /dev/null +++ b/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_multiplePastes5.js @@ -0,0 +1,392 @@ +currentDirectory:: / useCaseSensitiveFileNames: false +Info seq [hh:mm:ss:mss] Provided types map file "/typesMap.json" doesn't exist +//// [/a.ts] +function foo() { + console.log("Hello"); +} +class bar { + constructor() { + function a() { + console.log("hii"); + } + a(); + function b() { + function c() { + console.log("hola"); + } + } + b(); + } + c() { + console.log("hello again"); + + } +} + +//// [/b.ts] +export const juice = 1; +export const sauce = 2; +export const tomato = 3; + +//// [/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": "/a.ts" + }, + "command": "open" + } +Info seq [hh:mm:ss:mss] getConfigFileNameForFile:: File: /a.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 /a.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: /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 (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 SVC-1-0 "function foo() {\n console.log(\"Hello\");\n}\nclass bar {\n constructor() {\n function a() {\n console.log(\"hii\");\n }\n a();\n function b() {\n function c() {\n console.log(\"hola\");\n } \n }\n b();\n }\n c() {\n console.log(\"hello again\");\n \n }\n}" + /b.ts Text-1 "export const juice = 1;\nexport const sauce = 2;\nexport const tomato = 3;" + + + 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": "/a.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: /a.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:: +/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 (Open) *new* + version: SVC-1-0 + containingProjects: 1 + /tsconfig.json *default* +/b.ts *new* + version: Text-1 + containingProjects: 1 + /tsconfig.json +/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": "/a.ts", + "pastedText": [ + "const mango = 2 + sauce;", + "const apple = 1 + juice", + "const strawberry = 1;", + "function k() {\n const cherry = 3 + tomato + cucumber;\n }" + ], + "pasteLocations": [ + { + "start": { + "line": 2, + "offset": 13 + }, + "end": { + "line": 2, + "offset": 26 + } + }, + { + "start": { + "line": 5, + "offset": 5 + }, + "end": { + "line": 5, + "offset": 12 + } + }, + { + "start": { + "line": 12, + "offset": 16 + }, + "end": { + "line": 12, + "offset": 36 + } + }, + { + "start": { + "line": 19, + "offset": 9 + }, + "end": { + "line": 19, + "offset": 9 + } + } + ] + }, + "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 SVC-1-1 "function foo() {\n console.const mango = 2 + sauce;\n}\nclass bar {\n const apple = 1 + juicector() {\n function a() {\n console.log(\"hii\");\n }\n a();\n function b() {\n function c() {\n const strawberry = 1;\n } \n }\n b();\n }\n c() {\n console.log(\"hello again\");\n function k() {\n const cherry = 3 + tomato + cucumber;\n }\n }\n}" + /b.ts Text-1 "export const juice = 1;\nexport const sauce = 2;\nexport const tomato = 3;" + +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": "/a.ts", + "textChanges": [ + { + "start": { + "line": 1, + "offset": 1 + }, + "end": { + "line": 1, + "offset": 1 + }, + "newText": "import { sauce, tomato } from \"./b\";\n\n" + }, + { + "start": { + "line": 2, + "offset": 13 + }, + "end": { + "line": 2, + "offset": 26 + }, + "newText": "const mango = 2 + sauce;" + }, + { + "start": { + "line": 5, + "offset": 5 + }, + "end": { + "line": 5, + "offset": 12 + }, + "newText": "const apple = 1 + juice" + }, + { + "start": { + "line": 12, + "offset": 16 + }, + "end": { + "line": 12, + "offset": 36 + }, + "newText": "const strawberry = 1;" + }, + { + "start": { + "line": 19, + "offset": 9 + }, + "end": { + "line": 19, + "offset": 9 + }, + "newText": "function k() {\n const cherry = 3 + tomato + cucumber;\n }" + } + ] + } + ], + "fixId": "providePostPasteEdits" + } + } +After Request +Projects:: +/tsconfig.json (Configured) *changed* + projectStateVersion: 3 *changed* + projectProgramVersion: 1 + dirty: true *changed* + +ScriptInfos:: +/a.ts (Open) *changed* + version: SVC-1-2 *changed* + containingProjects: 1 + /tsconfig.json *default* +/b.ts + version: Text-1 + containingProjects: 1 + /tsconfig.json +/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_fixDElay.ts b/tests/cases/fourslash/server/pasteEdits_fixDElay.ts deleted file mode 100644 index e4e8ec6031631..0000000000000 --- a/tests/cases/fourslash/server/pasteEdits_fixDElay.ts +++ /dev/null @@ -1,38 +0,0 @@ -/// - -// @Filename: /a.ts -//// const ll = kkk; -//// -//// function foo() {[||] -//// const oip = 123; -//// [||] -//// } -//// [||] -//// - -// @Filename: /b.ts -//// export const a = 1; -//// export const t = 1; -//// export function foo() {} -//// export const kkk = a + t; - -// @Filename: /tsconfig.json -////{ "files": ["a.ts", "b.ts"] } - -const range = test.ranges(); -verify.pasteEdits({ - args: { - pastedText: [`export const kkk = a + t;`, `const yuy = 1;`], - pasteLocations: [range[0], range[1], range[2]], - }, - newFileContents: { - "/a.ts": -`import { a, t } from "./b"; - -const ll = kkk; - - -export const kkk = a + t; -` - } -}); diff --git a/tests/cases/fourslash/server/pasteEdits_multiplePastes5.ts b/tests/cases/fourslash/server/pasteEdits_multiplePastes5.ts new file mode 100644 index 0000000000000..420e7246bddc1 --- /dev/null +++ b/tests/cases/fourslash/server/pasteEdits_multiplePastes5.ts @@ -0,0 +1,73 @@ +/// + +// @Filename: /a.ts +//// function foo() { +//// console.[|log("Hello");|] +//// } +//// class bar { +//// [|constru|]ctor() { +//// function a() { +//// console.log("hii"); +//// } +//// a(); +//// function b() { +//// function c() { +//// [|console.log("hola");|] +//// } +//// } +//// b(); +//// } +//// c() { +//// console.log("hello again"); +//// [||] +//// } +//// } + +// @Filename: /b.ts +//// export const juice = 1; +//// export const sauce = 2; +//// export const tomato = 3; + +// @Filename: /tsconfig.json +////{ "files": ["a.ts", "b.ts"] } + +const range = test.ranges(); +verify.pasteEdits({ + args: { + pastedText: [ `const mango = 2 + sauce;`,`const apple = 1 + juice`, + `const strawberry = 1;`, + `function k() { + const cherry = 3 + tomato + cucumber; + }` +], + pasteLocations: [range[0], range[1], range[2], range[3]], + }, + newFileContents: { + "/a.ts": +`import { sauce, tomato } from "./b"; + +function foo() { + console.const mango = 2 + sauce; +} +class bar { + const apple = 1 + juicector() { + function a() { + console.log("hii"); + } + a(); + function b() { + function c() { + const strawberry = 1; + } + } + b(); + } + c() { + console.log("hello again"); + function k() { + const cherry = 3 + tomato + cucumber; + } + } +}` + } +}); From 44626c4f859485b09ed575ff47d7903b62a93562 Mon Sep 17 00:00:00 2001 From: navya9singh Date: Tue, 6 Aug 2024 17:00:50 -0700 Subject: [PATCH 06/19] Revert "cherry pick with fixes" This reverts commit 10be994a23fc1cd5573b4287efd242b36bcb9a7a. --- package-lock.json | 34 ------- package.json | 4 - src/compiler/_namespaces/ts.ts | 3 +- src/compiler/perfLogger.ts | 44 --------- src/server/session.ts | 3 +- src/tsserver/nodeServer.ts | 163 +++---------------------------- src/tsserver/server.ts | 6 +- src/typescript/_namespaces/ts.ts | 2 +- src/typescript/typescript.ts | 2 +- 9 files changed, 23 insertions(+), 238 deletions(-) delete mode 100644 src/compiler/perfLogger.ts diff --git a/package-lock.json b/package-lock.json index e1456d50ce2bf..2edf3e259a50b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,9 +8,6 @@ "name": "typescript", "version": "5.6.0", "license": "Apache-2.0", - "dependencies": { - "@microsoft/typescript-etw": "^0.1.0" - }, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -23,7 +20,6 @@ "@octokit/rest": "^21.0.1", "@types/chai": "^4.3.16", "@types/diff": "^5.2.1", - "@types/microsoft__typescript-etw": "^0.1.3", "@types/minimist": "^1.2.5", "@types/mocha": "^10.0.7", "@types/ms": "^0.7.34", @@ -809,19 +805,6 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@microsoft/typescript-etw": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@microsoft/typescript-etw/-/typescript-etw-0.1.0.tgz", - "integrity": "sha512-P6ohPmiIMNH406IGkh95ZSQ3sZhGLF3xPFA9F7/9F4dXT8yV5dBPA297jlRF1ZNjroi3g9pasCM/LoqrxP+SqQ==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", - "hasInstallScript": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 8.9.0" - } - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1055,12 +1038,6 @@ "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", "dev": true }, - "node_modules/@types/microsoft__typescript-etw": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@types/microsoft__typescript-etw/-/microsoft__typescript-etw-0.1.3.tgz", - "integrity": "sha512-qbO0IoTPJERhGWOvdw9iQbRjM7OGc6+fHVziSKcw566BDSQpEdkGxXcE8BKSHJOP6mkTRobf4QxqRE/aKhrCxg==", - "dev": true - }, "node_modules/@types/minimist": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", @@ -5294,11 +5271,6 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "@microsoft/typescript-etw": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@microsoft/typescript-etw/-/typescript-etw-0.1.0.tgz", - "integrity": "sha512-P6ohPmiIMNH406IGkh95ZSQ3sZhGLF3xPFA9F7/9F4dXT8yV5dBPA297jlRF1ZNjroi3g9pasCM/LoqrxP+SqQ==" - }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -5476,12 +5448,6 @@ "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", "dev": true }, - "@types/microsoft__typescript-etw": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@types/microsoft__typescript-etw/-/microsoft__typescript-etw-0.1.3.tgz", - "integrity": "sha512-qbO0IoTPJERhGWOvdw9iQbRjM7OGc6+fHVziSKcw566BDSQpEdkGxXcE8BKSHJOP6mkTRobf4QxqRE/aKhrCxg==", - "dev": true - }, "@types/minimist": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", diff --git a/package.json b/package.json index e73af350e89dc..2917f5b42414e 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,6 @@ "@octokit/rest": "^21.0.1", "@types/chai": "^4.3.16", "@types/diff": "^5.2.1", - "@types/microsoft__typescript-etw": "^0.1.3", "@types/minimist": "^1.2.5", "@types/mocha": "^10.0.7", "@types/ms": "^0.7.34", @@ -114,8 +113,5 @@ "volta": { "node": "20.1.0", "npm": "8.19.4" - }, - "dependencies": { - "@microsoft/typescript-etw": "^0.1.0" } } diff --git a/src/compiler/_namespaces/ts.ts b/src/compiler/_namespaces/ts.ts index bbd273b39cce7..94fb16857d38e 100644 --- a/src/compiler/_namespaces/ts.ts +++ b/src/compiler/_namespaces/ts.ts @@ -5,7 +5,6 @@ export * from "../core.js"; export * from "../debug.js"; export * from "../semver.js"; export * from "../performanceCore.js"; -export * from "../perfLogger.js"; export * from "../tracing.js"; export * from "../types.js"; export * from "../sys.js"; @@ -76,4 +75,4 @@ export * from "../expressionToTypeNode.js"; import * as moduleSpecifiers from "./ts.moduleSpecifiers.js"; export { moduleSpecifiers }; import * as performance from "./ts.performance.js"; -export { performance }; \ No newline at end of file +export { performance }; diff --git a/src/compiler/perfLogger.ts b/src/compiler/perfLogger.ts deleted file mode 100644 index 64c10a69ea80d..0000000000000 --- a/src/compiler/perfLogger.ts +++ /dev/null @@ -1,44 +0,0 @@ -/** @internal */ -export interface PerfLogger { - logEvent(msg: string): void; - logErrEvent(msg: string): void; - logPerfEvent(msg: string): void; - logInfoEvent(msg: string): void; - logStartCommand(command: string, msg: string): void; - logStopCommand(command: string, msg: string): void; - logStartUpdateProgram(msg: string): void; - logStopUpdateProgram(msg: string): void; - logStartUpdateGraph(): void; - logStopUpdateGraph(): void; - logStartResolveModule(name: string): void; - logStopResolveModule(success: string): void; - logStartParseSourceFile(filename: string): void; - logStopParseSourceFile(): void; - logStartReadFile(filename: string): void; - logStopReadFile(): void; - logStartBindFile(filename: string): void; - logStopBindFile(): void; - logStartScheduledOperation(operationId: string): void; - logStopScheduledOperation(): void; -} - -// Load optional module to enable Event Tracing for Windows -// See https://github.com/microsoft/typescript-etw for more information -let etwModule: typeof import("@microsoft/typescript-etw") | undefined; -try { - const etwModulePath = process.env.TS_ETW_MODULE_PATH ?? "./node_modules/@microsoft/typescript-etw"; - - // require() will throw an exception if the module is not found - // It may also return undefined if not installed properly - etwModule = require(etwModulePath); -} -catch (e) { - etwModule = undefined; -} - -/** - * Performance logger that will generate ETW events if possible - check for `logEvent` member, as `etwModule` will be `{}` when browserified - * - * @internal - */ -export const perfLogger: PerfLogger | undefined = etwModule?.logEvent ? etwModule : undefined; \ No newline at end of file diff --git a/src/server/session.ts b/src/server/session.ts index 9715e5176f079..5951733c8392e 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -3804,7 +3804,6 @@ export class Session implements EventSender { let relevantFile: protocol.FileRequestArgs | undefined; try { request = this.parseMessage(message); - console.log(`${request.seq}:: ${request.command}`); relevantFile = request.arguments && (request as protocol.FileRequest).arguments.file ? (request as protocol.FileRequest).arguments : undefined; tracing?.instant(tracing.Phase.Session, "request", { seq: request.seq, command: request.command }); @@ -3855,7 +3854,7 @@ export class Session implements EventSender { this.doOutput({ canceled: true }, request!.command, request!.seq, /*success*/ true, this.performanceData); return; } - console.log(`${request?.seq}:: ${request?.command}:: Exception`, err); + this.logErrorWorker(err, this.toStringMessage(message), relevantFile); tracing?.instant(tracing.Phase.Session, "commandError", { seq: request?.seq, command: request?.command, message: (err as Error).message }); diff --git a/src/tsserver/nodeServer.ts b/src/tsserver/nodeServer.ts index abf05f9d3276f..6e89f665fe436 100644 --- a/src/tsserver/nodeServer.ts +++ b/src/tsserver/nodeServer.ts @@ -1,3 +1,8 @@ +import childProcess from "child_process"; +import fs from "fs"; +import net from "net"; +import os from "os"; +import readline from "readline"; import { CharacterCodes, combinePaths, @@ -5,18 +10,14 @@ import { Debug, directorySeparator, DirectoryWatcherCallback, - emptyArray, - endsWith, FileWatcher, getDirectoryPath, getRootLength, LanguageServiceMode, - MapLike, noop, noopFileWatcher, normalizePath, normalizeSlashes, - perfLogger, startTracing, stripQuotes, sys, @@ -40,24 +41,6 @@ interface LogOptions { logToFile?: boolean; } -interface NodeChildProcess { - send(message: any, sendHandle?: any): void; - on(message: "message" | "exit", f: (m: any) => void): void; - kill(): void; - pid: number; -} - -interface ReadLineOptions { - input: NodeJS.ReadableStream; - output?: NodeJS.WritableStream; - terminal?: boolean; - historySize?: number; -} - -interface NodeSocket { - write(data: string, encoding: string): boolean; -} - function parseLoggingEnvironmentString(logEnvStr: string | undefined): LogOptions { if (!logEnvStr) { return {}; @@ -126,41 +109,6 @@ function parseServerMode(): LanguageServiceMode | string | undefined { /** @internal */ export function initializeNodeSystem(): StartInput { const sys = Debug.checkDefined(ts.sys) as ts.server.ServerHost; - const childProcess: { - execFileSync(file: string, args: string[], options: { stdio: "ignore"; env: MapLike; }): string | Buffer; - } = require("child_process"); - - interface Stats { - isFile(): boolean; - isDirectory(): boolean; - isBlockDevice(): boolean; - isCharacterDevice(): boolean; - isSymbolicLink(): boolean; - isFIFO(): boolean; - isSocket(): boolean; - dev: number; - ino: number; - mode: number; - nlink: number; - uid: number; - gid: number; - rdev: number; - size: number; - blksize: number; - blocks: number; - atime: Date; - mtime: Date; - ctime: Date; - birthtime: Date; - } - - const fs: { - openSync(path: string, options: string): number; - close(fd: number, callback: (err: NodeJS.ErrnoException) => void): void; - writeSync(fd: number, buffer: Buffer, offset: number, length: number, position?: number): number; - statSync(path: string): Stats; - stat(path: string, callback?: (err: NodeJS.ErrnoException, stats: Stats) => any): void; - } = require("fs"); class Logger implements Logger { private seq = 0; @@ -215,18 +163,6 @@ export function initializeNodeSystem(): StartInput { return this.loggingEnabled() && this.level >= level; } msg(s: string, type: ts.server.Msg = ts.server.Msg.Err) { - switch (type) { - case ts.server.Msg.Info: - perfLogger?.logInfoEvent(s); - break; - case ts.server.Msg.Perf: - perfLogger?.logPerfEvent(s); - break; - default: // Msg.Err - perfLogger?.logErrEvent(s); - break; - } - if (!this.canWrite()) return; s = `[${ts.server.nowString()}] ${s}\n`; @@ -246,7 +182,7 @@ export function initializeNodeSystem(): StartInput { if (this.fd >= 0) { const buf = Buffer.from(s); // eslint-disable-next-line no-restricted-syntax - fs.writeSync(this.fd, buf, 0, buf.length, /*position*/ null!); // TODO: GH#18217 + fs.writeSync(this.fd, buf, 0, buf.length, /*position*/ null); } if (this.traceToConsole) { console.warn(s); @@ -341,7 +277,7 @@ export function initializeNodeSystem(): StartInput { let cancellationToken: ts.server.ServerCancellationToken; try { - const factory = require("./cancellationToken"); + const factory = require("./cancellationToken.js"); cancellationToken = factory(sys.args); } catch (e) { @@ -454,34 +390,14 @@ function parseEventPort(eventPortStr: string | undefined) { return eventPort !== undefined && !isNaN(eventPort) ? eventPort : undefined; } function startNodeSession(options: StartSessionOptions, logger: ts.server.Logger, cancellationToken: ts.server.ServerCancellationToken) { - const childProcess: { - fork(modulePath: string, args: string[], options?: { execArgv: string[]; env?: MapLike; }): NodeChildProcess; - } = require("child_process"); - - const os: { - homedir?(): string; - tmpdir(): string; - } = require("os"); - - const net: { - connect(options: { port: number; }, onConnect?: () => void): NodeSocket; - } = require("net"); - - const readline: { - createInterface(options: ReadLineOptions): NodeJS.EventEmitter; - } = require("readline"); - - const fs: { - readFileSync(path: string, options: { encoding: string; flag?: string; } | string): string; - writeFileSync(path: string, data: string): string; - } = require("fs"); - - const stream: { - Readable: { from(str: string): NodeJS.ReadStream; }; - } = require("stream"); + const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, + terminal: false, + }); class NodeTypingsInstallerAdapter extends ts.server.TypingsInstallerAdapter { - protected override installer!: NodeChildProcess; + protected override installer!: childProcess.ChildProcess; // This number is essentially arbitrary. Processing more than one typings request // at a time makes sense, but having too many in the pipe results in a hang // (see https://github.com/nodejs/node/issues/7657). @@ -551,7 +467,7 @@ function startNodeSession(options: StartSessionOptions, logger: ts.server.Logger const typingsInstaller = combinePaths(getDirectoryPath(sys.getExecutingFilePath()), "typingsInstaller.js"); this.installer = childProcess.fork(typingsInstaller, args, { execArgv }); - this.installer.on("message", m => this.handleMessage(m)); + this.installer.on("message", m => this.handleMessage(m as any)); // We have to schedule this event to the next tick // cause this fn will be called during @@ -568,7 +484,7 @@ function startNodeSession(options: StartSessionOptions, logger: ts.server.Logger class IOSession extends ts.server.Session { private eventPort: number | undefined; - private eventSocket: NodeSocket | undefined; + private eventSocket: net.Socket | undefined; private socketEventQueue: { body: any; eventName: string; }[] | undefined; /** No longer needed if syntax target is es6 or above. Any access to "this" before initialized will be a runtime error. */ private constructed: boolean | undefined; @@ -703,12 +619,6 @@ function startNodeSession(options: StartSessionOptions, logger: ts.server.Logger startTracing("server", traceDir); } - const inputStream = getInputReadStream(ts.server.findArgument("--inputRequestsFile"), ts.server.findArgument("--inputLogFile"), ts.server.findArgument("--createRequestsFile")); - const rl = readline.createInterface({ - input: inputStream || process.stdin, - output: process.stdout, - terminal: false, - }); const ioSession = useNodeIpc ? new IpcIOSession() : new IOSession(); process.on("uncaughtException", err => { ioSession.logError(err, "unknown"); @@ -718,47 +628,6 @@ function startNodeSession(options: StartSessionOptions, logger: ts.server.Logger // Start listening ioSession.listen(); - function getInputReadStream(inputRequestsFile: string | undefined, inputLogFile: string | undefined, requestFile: string | undefined) { - if (!inputRequestsFile && !inputLogFile) return undefined; - let result: any[]; - if (inputRequestsFile) { - const text = fs.readFileSync(stripQuotes(inputRequestsFile), "utf8"); - try { - result = text ? JSON.parse(text) : emptyArray; - } - catch (e) { - result = []; - } - } - else { - const lines = fs.readFileSync(stripQuotes(inputLogFile!), "utf8")?.split(/\r?\n/) || []; - result = []; - for (let i = 0; i < lines.length; i++) { - const line = lines[i]; - if (!endsWith(line, "] request:")) continue; - const texts: string[] = []; - for (i++; i < lines.length; i++) { - if (lines[i].search(/((Info)|(Perf)|(Err))\s[0-9]+\s*\[/) === 0) { - i--; - break; - } - texts.push(lines[i]); - } - const text = texts.join(""); - try { - const json = JSON.parse(text); - if (json && json.type === "request") { - result.push(json); - } - } - catch (e) {} // eslint-disable-line no-empty - } - } - if (requestFile) fs.writeFileSync(stripQuotes(requestFile), JSON.stringify(result, /*replacer*/ undefined, " ")); - console.log(`Requests:: ${result.length}`); - return stream.Readable.from(result.map(r => JSON.stringify(r)).join("\n")); - } - function getGlobalTypingsCacheLocation() { switch (process.platform) { case "win32": { @@ -798,4 +667,4 @@ function startNodeSession(options: StartSessionOptions, logger: ts.server.Logger : ".cache"; return combinePaths(normalizeSlashes(homePath), cacheFolder); } -} \ No newline at end of file +} diff --git a/src/tsserver/server.ts b/src/tsserver/server.ts index 919c4aaf73b4f..d74ca4f04d645 100644 --- a/src/tsserver/server.ts +++ b/src/tsserver/server.ts @@ -32,9 +32,9 @@ function start({ args, logger, cancellationToken, serverMode, unknownServerMode, // the log. This is so that language service plugins which use // console.log don't break the message passing between tsserver // and the client - // console.log = (...args) => logger.msg(args.length === 1 ? args[0] : args.join(", "), ts.server.Msg.Info); - // console.warn = (...args) => logger.msg(args.length === 1 ? args[0] : args.join(", "), ts.server.Msg.Err); - // console.error = (...args) => logger.msg(args.length === 1 ? args[0] : args.join(", "), ts.server.Msg.Err); + console.log = (...args) => logger.msg(args.length === 1 ? args[0] : args.join(", "), ts.server.Msg.Info); + console.warn = (...args) => logger.msg(args.length === 1 ? args[0] : args.join(", "), ts.server.Msg.Err); + console.error = (...args) => logger.msg(args.length === 1 ? args[0] : args.join(", "), ts.server.Msg.Err); startServer( { diff --git a/src/typescript/_namespaces/ts.ts b/src/typescript/_namespaces/ts.ts index 3e2ef4e54d917..1c1a9fcb82264 100644 --- a/src/typescript/_namespaces/ts.ts +++ b/src/typescript/_namespaces/ts.ts @@ -5,4 +5,4 @@ export * from "../../jsTyping/_namespaces/ts.js"; export * from "../../services/_namespaces/ts.js"; export * from "../../server/_namespaces/ts.js"; import * as server from "./ts.server.js"; -export { server }; \ No newline at end of file +export { server }; diff --git a/src/typescript/typescript.ts b/src/typescript/typescript.ts index 18eea5580827a..9e54bbe9c15b0 100644 --- a/src/typescript/typescript.ts +++ b/src/typescript/typescript.ts @@ -22,4 +22,4 @@ if (typeof console !== "undefined") { }; } -export * from "./_namespaces/ts.js"; \ No newline at end of file +export * from "./_namespaces/ts.js"; From e12d2cf49ad89546987914d58d7c93940fb6d9bb Mon Sep 17 00:00:00 2001 From: navya9singh Date: Tue, 6 Aug 2024 17:20:25 -0700 Subject: [PATCH 07/19] fixing import --- src/services/pasteEdits.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/services/pasteEdits.ts b/src/services/pasteEdits.ts index a6033601eb1af..f1cee68e8413a 100644 --- a/src/services/pasteEdits.ts +++ b/src/services/pasteEdits.ts @@ -1,6 +1,3 @@ -import { - findIndex, -} from "../compiler/core.js"; import { CancellationToken, Program, @@ -15,6 +12,7 @@ import { Debug, fileShouldUseJavaScriptRequire, findAncestor, + findIndex, forEachChild, formatting, getQuotePreference, From 30e5e2dc2174de92ddffe19bf5325e2fad32a62d Mon Sep 17 00:00:00 2001 From: navya9singh Date: Mon, 12 Aug 2024 10:29:19 -0700 Subject: [PATCH 08/19] adressing pr comments --- src/services/pasteEdits.ts | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/services/pasteEdits.ts b/src/services/pasteEdits.ts index 96fa92eb85bc3..73c095f7ff6c4 100644 --- a/src/services/pasteEdits.ts +++ b/src/services/pasteEdits.ts @@ -3,6 +3,7 @@ import { codefix, Debug, fileShouldUseJavaScriptRequire, + findAncestor, findIndex, forEachChild, formatting, @@ -10,6 +11,7 @@ import { getTokenAtPosition, isIdentifier, Program, + rangeContainsPosition, SourceFile, Statement, SymbolFlags, @@ -104,30 +106,29 @@ function pasteEdits( preferences, formatContext, }; - - /** - * `updatedRanges` represent the new ranges that account for the offset changes caused by pasting new text and - * `offset` represents by how much the starting position of `pasteLocations` needs to be changed. - * - * We iterate over each updated range to get the node that wholly encloses the updated range. For each child of that node, it is checked if the - * identifier lies within the updated range and if it is not resolved, we try resolving it. - */ + + // `updatedRanges` represent the new ranges that account for the offset changes caused by pasting new text and + // `offset` represents by how much the starting position of `pasteLocations` needs to be changed. + // + // We iterate over each updated range to get the node that wholly encloses the updated range. For each child of that node, it is checked if the + // identifier lies within the updated range and if it is not resolved, we try resolving it. + const updatedRanges: TextRange[] = []; let offset = 0; pasteLocations.forEach((location, i) => { - const deletionNeeded = location.pos === location.end ? 0 : location.end - location.pos + 1; + const deletionNeeded = location.pos === location.end ? 0 : location.end - location.pos; const textToBePasted = actualPastedText ? actualPastedText[0] : pastedText[i]; const startPos = location.pos - offset; - const endPos = startPos + textToBePasted.length - 1; + const endPos = startPos + textToBePasted.length; updatedRanges.push({ pos: startPos, end: endPos }); offset += deletionNeeded - textToBePasted.length; }); updatedRanges.forEach(range => { - const enclosingNode = findAncestor(getTokenAtPosition(context.sourceFile, range.pos), cb => rangeContainsPosition({ pos: cb.pos, end: cb.end }, range.end)); + const enclosingNode = findAncestor(getTokenAtPosition(context.sourceFile, range.pos), ancestorNode => rangeContainsPosition(ancestorNode, range.end)); if (!enclosingNode) return; forEachChild(enclosingNode, function cb(node) { - if (isIdentifier(node) && rangeContainsPosition(range, node.getStart()) && !originalProgram?.getTypeChecker().resolveName(node.text, node, SymbolFlags.All, /*excludeGlobals*/ false)) { + if (isIdentifier(node) && rangeContainsPosition(range, node.getStart(updatedFile)) && !originalProgram?.getTypeChecker().resolveName(node.text, node, SymbolFlags.All, /*excludeGlobals*/ false)) { importAdder.addImportForUnresolvedIdentifier(context, node, /*useAutoImportProvider*/ true); } node.forEachChild(cb); From 8248ff85f91d5fb55771a31961c1a4a1b5d8c62c Mon Sep 17 00:00:00 2001 From: navya9singh Date: Mon, 12 Aug 2024 10:32:15 -0700 Subject: [PATCH 09/19] fix formatting --- src/services/pasteEdits.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/services/pasteEdits.ts b/src/services/pasteEdits.ts index 73c095f7ff6c4..19362235f8aac 100644 --- a/src/services/pasteEdits.ts +++ b/src/services/pasteEdits.ts @@ -106,13 +106,13 @@ function pasteEdits( preferences, formatContext, }; - + // `updatedRanges` represent the new ranges that account for the offset changes caused by pasting new text and // `offset` represents by how much the starting position of `pasteLocations` needs to be changed. // // We iterate over each updated range to get the node that wholly encloses the updated range. For each child of that node, it is checked if the // identifier lies within the updated range and if it is not resolved, we try resolving it. - + const updatedRanges: TextRange[] = []; let offset = 0; pasteLocations.forEach((location, i) => { From c0b13565d7913258e7facc29a4a9e66ba68a1a87 Mon Sep 17 00:00:00 2001 From: navya9singh Date: Mon, 12 Aug 2024 10:54:58 -0700 Subject: [PATCH 10/19] adding +1 -1 back --- src/services/pasteEdits.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/services/pasteEdits.ts b/src/services/pasteEdits.ts index 19362235f8aac..61df65cb8eac0 100644 --- a/src/services/pasteEdits.ts +++ b/src/services/pasteEdits.ts @@ -116,10 +116,10 @@ function pasteEdits( const updatedRanges: TextRange[] = []; let offset = 0; pasteLocations.forEach((location, i) => { - const deletionNeeded = location.pos === location.end ? 0 : location.end - location.pos; + const deletionNeeded = location.pos === location.end ? 0 : location.end - location.pos + 1; const textToBePasted = actualPastedText ? actualPastedText[0] : pastedText[i]; const startPos = location.pos - offset; - const endPos = startPos + textToBePasted.length; + const endPos = startPos + textToBePasted.length - 1; updatedRanges.push({ pos: startPos, end: endPos }); offset += deletionNeeded - textToBePasted.length; }); From b660771a0b3b17d988e4c57910c6a11564f65271 Mon Sep 17 00:00:00 2001 From: navya9singh Date: Tue, 13 Aug 2024 13:03:24 -0700 Subject: [PATCH 11/19] adding more test cases --- src/services/pasteEdits.ts | 9 +- ..._multiplePastesConsistentlyLargerInSize.js | 396 +++++++++++++++++ ...multiplePastesConsistentlySmallerInSize.js | 403 +++++++++++++++++ .../pasteEdits_multiplePastesEqualInSize.js | 395 +++++++++++++++++ ...multiplePastesGrowingAndShrinkingInSize.js | 392 +++++++++++++++++ .../pasteEdits_multiplePastesGrowingInSize.js | 412 ++++++++++++++++++ ...asteEdits_multiplePastesShrinkingInSize.js | 412 ++++++++++++++++++ ..._multiplePastesConsistentlyLargerInSize.ts | 78 ++++ ...multiplePastesConsistentlySmallerInSize.ts | 92 ++++ .../pasteEdits_multiplePastesEqualInSize.ts | 76 ++++ ...ultiplePastesGrowingAndShrinkingInSize.ts} | 12 +- .../pasteEdits_multiplePastesGrowingInSize.ts | 77 ++++ ...asteEdits_multiplePastesShrinkingInSize.ts | 77 ++++ 13 files changed, 2820 insertions(+), 11 deletions(-) create mode 100644 tests/baselines/reference/tsserver/fourslashServer/pasteEdits_multiplePastesConsistentlyLargerInSize.js create mode 100644 tests/baselines/reference/tsserver/fourslashServer/pasteEdits_multiplePastesConsistentlySmallerInSize.js create mode 100644 tests/baselines/reference/tsserver/fourslashServer/pasteEdits_multiplePastesEqualInSize.js create mode 100644 tests/baselines/reference/tsserver/fourslashServer/pasteEdits_multiplePastesGrowingAndShrinkingInSize.js create mode 100644 tests/baselines/reference/tsserver/fourslashServer/pasteEdits_multiplePastesGrowingInSize.js create mode 100644 tests/baselines/reference/tsserver/fourslashServer/pasteEdits_multiplePastesShrinkingInSize.js create mode 100644 tests/cases/fourslash/server/pasteEdits_multiplePastesConsistentlyLargerInSize.ts create mode 100644 tests/cases/fourslash/server/pasteEdits_multiplePastesConsistentlySmallerInSize.ts create mode 100644 tests/cases/fourslash/server/pasteEdits_multiplePastesEqualInSize.ts rename tests/cases/fourslash/server/{pasteEdits_multiplePastes5.ts => pasteEdits_multiplePastesGrowingAndShrinkingInSize.ts} (82%) create mode 100644 tests/cases/fourslash/server/pasteEdits_multiplePastesGrowingInSize.ts create mode 100644 tests/cases/fourslash/server/pasteEdits_multiplePastesShrinkingInSize.ts diff --git a/src/services/pasteEdits.ts b/src/services/pasteEdits.ts index 61df65cb8eac0..2a08d88f6e60d 100644 --- a/src/services/pasteEdits.ts +++ b/src/services/pasteEdits.ts @@ -112,16 +112,15 @@ function pasteEdits( // // We iterate over each updated range to get the node that wholly encloses the updated range. For each child of that node, it is checked if the // identifier lies within the updated range and if it is not resolved, we try resolving it. - const updatedRanges: TextRange[] = []; let offset = 0; pasteLocations.forEach((location, i) => { - const deletionNeeded = location.pos === location.end ? 0 : location.end - location.pos + 1; + const oldTextLength = location.end - location.pos; const textToBePasted = actualPastedText ? actualPastedText[0] : pastedText[i]; - const startPos = location.pos - offset; - const endPos = startPos + textToBePasted.length - 1; + const startPos = location.pos + offset; + const endPos = startPos + textToBePasted.length; updatedRanges.push({ pos: startPos, end: endPos }); - offset += deletionNeeded - textToBePasted.length; + offset += textToBePasted.length - oldTextLength; }); updatedRanges.forEach(range => { diff --git a/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_multiplePastesConsistentlyLargerInSize.js b/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_multiplePastesConsistentlyLargerInSize.js new file mode 100644 index 0000000000000..78ab9b41c0ac3 --- /dev/null +++ b/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_multiplePastesConsistentlyLargerInSize.js @@ -0,0 +1,396 @@ +currentDirectory:: / useCaseSensitiveFileNames: false +Info seq [hh:mm:ss:mss] Provided types map file "/typesMap.json" doesn't exist +//// [/a.ts] +function foo() { + const p = 1; + console.log("yes"); +} +class bar { + constructor() { + function a() { + console.log("have a good day"); + } + a(); + function b() { + function c() { + const test = 1 + 2 + 3; + } + } + b(); + } + c() { + console.log("hello again"); + function k() { + const happy = banana + avocados; + } + } +} + +//// [/b.ts] +export const juice = 1; +export const sauce = 2; +export const fig = 3; +export const tomato = 4; + +//// [/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": "/a.ts" + }, + "command": "open" + } +Info seq [hh:mm:ss:mss] getConfigFileNameForFile:: File: /a.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 /a.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: /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 (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 SVC-1-0 "function foo() {\n const p = 1;\n console.log(\"yes\");\n}\nclass bar {\n constructor() {\n function a() {\n console.log(\"have a good day\");\n }\n a();\n function b() {\n function c() {\n const test = 1 + 2 + 3;\n } \n }\n b();\n }\n c() {\n console.log(\"hello again\");\n function k() {\n const happy = banana + avocados;\n }\n }\n}" + /b.ts Text-1 "export const juice = 1;\nexport const sauce = 2;\nexport const fig = 3;\nexport const tomato = 4;" + + + 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": "/a.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: /a.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:: +/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 (Open) *new* + version: SVC-1-0 + containingProjects: 1 + /tsconfig.json *default* +/b.ts *new* + version: Text-1 + containingProjects: 1 + /tsconfig.json +/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": "/a.ts", + "pastedText": [ + "const t = 1 + juice + p;", + "function avacado() { return sauce; }", + "fig + kiwi", + "function k() {\n const cherry = 3 + tomato + cucumber;\n }" + ], + "pasteLocations": [ + { + "start": { + "line": 3, + "offset": 4 + }, + "end": { + "line": 3, + "offset": 23 + } + }, + { + "start": { + "line": 8, + "offset": 13 + }, + "end": { + "line": 8, + "offset": 44 + } + }, + { + "start": { + "line": 13, + "offset": 29 + }, + "end": { + "line": 13, + "offset": 34 + } + }, + { + "start": { + "line": 20, + "offset": 9 + }, + "end": { + "line": 22, + "offset": 10 + } + } + ] + }, + "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 SVC-1-1 "function foo() {\n const p = 1;\n const t = 1 + juice + p;\n}\nclass bar {\n constructor() {\n function a() {\n function avacado() { return sauce; }\n }\n a();\n function b() {\n function c() {\n const test = fig + kiwi + 3;\n } \n }\n b();\n }\n c() {\n console.log(\"hello again\");\n function k() {\n const cherry = 3 + tomato + cucumber;\n }\n }\n}" + /b.ts Text-1 "export const juice = 1;\nexport const sauce = 2;\nexport const fig = 3;\nexport const tomato = 4;" + +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": "/a.ts", + "textChanges": [ + { + "start": { + "line": 1, + "offset": 1 + }, + "end": { + "line": 1, + "offset": 1 + }, + "newText": "import { juice, sauce, fig, tomato } from \"./b\";\n\n" + }, + { + "start": { + "line": 3, + "offset": 4 + }, + "end": { + "line": 3, + "offset": 23 + }, + "newText": "const t = 1 + juice + p;" + }, + { + "start": { + "line": 8, + "offset": 13 + }, + "end": { + "line": 8, + "offset": 44 + }, + "newText": "function avacado() { return sauce; }" + }, + { + "start": { + "line": 13, + "offset": 29 + }, + "end": { + "line": 13, + "offset": 34 + }, + "newText": "fig + kiwi" + }, + { + "start": { + "line": 20, + "offset": 9 + }, + "end": { + "line": 22, + "offset": 10 + }, + "newText": "function k() {\n const cherry = 3 + tomato + cucumber;\n }" + } + ] + } + ], + "fixId": "providePostPasteEdits" + } + } +After Request +Projects:: +/tsconfig.json (Configured) *changed* + projectStateVersion: 3 *changed* + projectProgramVersion: 1 + dirty: true *changed* + +ScriptInfos:: +/a.ts (Open) *changed* + version: SVC-1-2 *changed* + containingProjects: 1 + /tsconfig.json *default* +/b.ts + version: Text-1 + containingProjects: 1 + /tsconfig.json +/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_multiplePastesConsistentlySmallerInSize.js b/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_multiplePastesConsistentlySmallerInSize.js new file mode 100644 index 0000000000000..bf2203d796453 --- /dev/null +++ b/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_multiplePastesConsistentlySmallerInSize.js @@ -0,0 +1,403 @@ +currentDirectory:: / useCaseSensitiveFileNames: false +Info seq [hh:mm:ss:mss] Provided types map file "/typesMap.json" doesn't exist +//// [/a.ts] +function foo() { + const p = 1; + function bar() { + console.log("Testing"); + } + console.log("yes"); +} +class bar { + constructor() { + function a() { + function aa() { + console.log("have a good day"); + } + + } + a(); + function b() { + function c() { + export const testing = 1; + const test = 1 + testing + 3; + } + } + b(); + } + c() { + console.log("hello again"); + function k() { + const happy = banana + avocados; + } + } +} + +//// [/b.ts] +export const juice = 1; +export const sauce = 2; +export const fig = 3; +export const tomato = 4; + +//// [/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": "/a.ts" + }, + "command": "open" + } +Info seq [hh:mm:ss:mss] getConfigFileNameForFile:: File: /a.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 /a.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: /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 (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 SVC-1-0 "function foo() {\n const p = 1;\n function bar() {\n console.log(\"Testing\");\n }\n console.log(\"yes\");\n}\nclass bar {\n constructor() {\n function a() {\n function aa() {\n console.log(\"have a good day\");\n }\n \n }\n a();\n function b() {\n function c() {\n export const testing = 1;\n const test = 1 + testing + 3;\n }\n }\n b();\n }\n c() {\n console.log(\"hello again\");\n function k() {\n const happy = banana + avocados;\n }\n }\n}" + /b.ts Text-1 "export const juice = 1;\nexport const sauce = 2;\nexport const fig = 3;\nexport const tomato = 4;" + + + 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": "/a.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: /a.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:: +/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 (Open) *new* + version: SVC-1-0 + containingProjects: 1 + /tsconfig.json *default* +/b.ts *new* + version: Text-1 + containingProjects: 1 + /tsconfig.json +/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": "/a.ts", + "pastedText": [ + "juice", + "sole.log(sauce + juice);", + "fig + kiwi", + "function k() {\n const cherry =tomato + kiwi;\n }" + ], + "pasteLocations": [ + { + "start": { + "line": 4, + "offset": 20 + }, + "end": { + "line": 4, + "offset": 29 + } + }, + { + "start": { + "line": 12, + "offset": 19 + }, + "end": { + "line": 12, + "offset": 47 + } + }, + { + "start": { + "line": 20, + "offset": 29 + }, + "end": { + "line": 20, + "offset": 43 + } + }, + { + "start": { + "line": 27, + "offset": 9 + }, + "end": { + "line": 29, + "offset": 10 + } + } + ] + }, + "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 SVC-1-1 "function foo() {\n const p = 1;\n function bar() {\n console.log(juice);\n }\n console.log(\"yes\");\n}\nclass bar {\n constructor() {\n function a() {\n function aa() {\n console.log(sauce + juice);\n }\n \n }\n a();\n function b() {\n function c() {\n export const testing = 1;\n const test = fig + kiwi3;\n }\n }\n b();\n }\n c() {\n console.log(\"hello again\");\n function k() {\n const cherry =tomato + kiwi;\n }\n }\n}" + /b.ts Text-1 "export const juice = 1;\nexport const sauce = 2;\nexport const fig = 3;\nexport const tomato = 4;" + +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": "/a.ts", + "textChanges": [ + { + "start": { + "line": 1, + "offset": 1 + }, + "end": { + "line": 1, + "offset": 1 + }, + "newText": "import { sauce, juice, fig, tomato } from \"./b\";\n\n" + }, + { + "start": { + "line": 4, + "offset": 20 + }, + "end": { + "line": 4, + "offset": 29 + }, + "newText": "juice" + }, + { + "start": { + "line": 12, + "offset": 19 + }, + "end": { + "line": 12, + "offset": 47 + }, + "newText": "sole.log(sauce + juice);" + }, + { + "start": { + "line": 20, + "offset": 29 + }, + "end": { + "line": 20, + "offset": 43 + }, + "newText": "fig + kiwi" + }, + { + "start": { + "line": 27, + "offset": 9 + }, + "end": { + "line": 29, + "offset": 10 + }, + "newText": "function k() {\n const cherry =tomato + kiwi;\n }" + } + ] + } + ], + "fixId": "providePostPasteEdits" + } + } +After Request +Projects:: +/tsconfig.json (Configured) *changed* + projectStateVersion: 3 *changed* + projectProgramVersion: 1 + dirty: true *changed* + +ScriptInfos:: +/a.ts (Open) *changed* + version: SVC-1-2 *changed* + containingProjects: 1 + /tsconfig.json *default* +/b.ts + version: Text-1 + containingProjects: 1 + /tsconfig.json +/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_multiplePastesEqualInSize.js b/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_multiplePastesEqualInSize.js new file mode 100644 index 0000000000000..0a98e82e17d6a --- /dev/null +++ b/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_multiplePastesEqualInSize.js @@ -0,0 +1,395 @@ +currentDirectory:: / useCaseSensitiveFileNames: false +Info seq [hh:mm:ss:mss] Provided types map file "/typesMap.json" doesn't exist +//// [/a.ts] +function foo() { + console.log("yes"); +} +class bar { + constructor() { + function a() { + console.log("have a good day"); + } + a(); + function b() { + function c() { + const test = 1 + 2 + 3; + } + } + b(); + } + c() { + console.log("hello again"); + function k() { + const happy = 1 + banana + avocados; + } + } +} + +//// [/b.ts] +export const juice = 1; +export const sauce = 2; +export const apple = 3; +export const tomato = 4; + +//// [/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": "/a.ts" + }, + "command": "open" + } +Info seq [hh:mm:ss:mss] getConfigFileNameForFile:: File: /a.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 /a.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: /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 (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 SVC-1-0 "function foo() {\n console.log(\"yes\");\n}\nclass bar {\n constructor() {\n function a() {\n console.log(\"have a good day\");\n }\n a();\n function b() {\n function c() {\n const test = 1 + 2 + 3;\n }\n }\n b();\n }\n c() {\n console.log(\"hello again\");\n function k() {\n const happy = 1 + banana + avocados;\n }\n }\n}" + /b.ts Text-1 "export const juice = 1;\nexport const sauce = 2;\nexport const apple = 3;\nexport const tomato = 4;" + + + 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": "/a.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: /a.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:: +/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 (Open) *new* + version: SVC-1-0 + containingProjects: 1 + /tsconfig.json *default* +/b.ts *new* + version: Text-1 + containingProjects: 1 + /tsconfig.json +/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": "/a.ts", + "pastedText": [ + "console.log(juice);", + "function kl() { return sauce; }", + "apple", + "function k() {\n const cherry = 3 + tomato + cucumber;\n }" + ], + "pasteLocations": [ + { + "start": { + "line": 2, + "offset": 5 + }, + "end": { + "line": 2, + "offset": 24 + } + }, + { + "start": { + "line": 7, + "offset": 13 + }, + "end": { + "line": 7, + "offset": 44 + } + }, + { + "start": { + "line": 12, + "offset": 29 + }, + "end": { + "line": 12, + "offset": 34 + } + }, + { + "start": { + "line": 19, + "offset": 9 + }, + "end": { + "line": 21, + "offset": 10 + } + } + ] + }, + "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 SVC-1-1 "function foo() {\n console.log(juice);\n}\nclass bar {\n constructor() {\n function a() {\n function kl() { return sauce; }\n }\n a();\n function b() {\n function c() {\n const test = apple + 3;\n }\n }\n b();\n }\n c() {\n console.log(\"hello again\");\n function k() {\n const cherry = 3 + tomato + cucumber;\n }\n }\n}" + /b.ts Text-1 "export const juice = 1;\nexport const sauce = 2;\nexport const apple = 3;\nexport const tomato = 4;" + +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": "/a.ts", + "textChanges": [ + { + "start": { + "line": 1, + "offset": 1 + }, + "end": { + "line": 1, + "offset": 1 + }, + "newText": "import { juice, sauce, tomato } from \"./b\";\n\n" + }, + { + "start": { + "line": 2, + "offset": 5 + }, + "end": { + "line": 2, + "offset": 24 + }, + "newText": "console.log(juice);" + }, + { + "start": { + "line": 7, + "offset": 13 + }, + "end": { + "line": 7, + "offset": 44 + }, + "newText": "function kl() { return sauce; }" + }, + { + "start": { + "line": 12, + "offset": 29 + }, + "end": { + "line": 12, + "offset": 34 + }, + "newText": "apple" + }, + { + "start": { + "line": 19, + "offset": 9 + }, + "end": { + "line": 21, + "offset": 10 + }, + "newText": "function k() {\n const cherry = 3 + tomato + cucumber;\n }" + } + ] + } + ], + "fixId": "providePostPasteEdits" + } + } +After Request +Projects:: +/tsconfig.json (Configured) *changed* + projectStateVersion: 3 *changed* + projectProgramVersion: 1 + dirty: true *changed* + +ScriptInfos:: +/a.ts (Open) *changed* + version: SVC-1-2 *changed* + containingProjects: 1 + /tsconfig.json *default* +/b.ts + version: Text-1 + containingProjects: 1 + /tsconfig.json +/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_multiplePastesGrowingAndShrinkingInSize.js b/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_multiplePastesGrowingAndShrinkingInSize.js new file mode 100644 index 0000000000000..3ff982d88d1f0 --- /dev/null +++ b/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_multiplePastesGrowingAndShrinkingInSize.js @@ -0,0 +1,392 @@ +currentDirectory:: / useCaseSensitiveFileNames: false +Info seq [hh:mm:ss:mss] Provided types map file "/typesMap.json" doesn't exist +//// [/a.ts] +function foo() { + console.log("Hello"); +} +class bar { + constructor() { + function a() { + console.log("hii"); + } + a(); + function b() { + function c() { + console.log("hola"); + } + } + b(); + } + c() { + console.log("hello again"); + + } +} + +//// [/b.ts] +export const juice = 1; +export const sauce = 2; +export const tomato = 3; + +//// [/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": "/a.ts" + }, + "command": "open" + } +Info seq [hh:mm:ss:mss] getConfigFileNameForFile:: File: /a.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 /a.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: /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 (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 SVC-1-0 "function foo() {\n console.log(\"Hello\");\n}\nclass bar {\n constructor() {\n function a() {\n console.log(\"hii\");\n }\n a();\n function b() {\n function c() {\n console.log(\"hola\");\n }\n }\n b();\n }\n c() {\n console.log(\"hello again\");\n \n }\n}" + /b.ts Text-1 "export const juice = 1;\nexport const sauce = 2;\nexport const tomato = 3;" + + + 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": "/a.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: /a.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:: +/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 (Open) *new* + version: SVC-1-0 + containingProjects: 1 + /tsconfig.json *default* +/b.ts *new* + version: Text-1 + containingProjects: 1 + /tsconfig.json +/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": "/a.ts", + "pastedText": [ + "log(sauce);", + "const apple = 1 + juice", + "const kiwi = 1;", + "function k() {\n const cherry = 3 + tomato + cucumber;\n }" + ], + "pasteLocations": [ + { + "start": { + "line": 2, + "offset": 13 + }, + "end": { + "line": 2, + "offset": 26 + } + }, + { + "start": { + "line": 5, + "offset": 5 + }, + "end": { + "line": 5, + "offset": 12 + } + }, + { + "start": { + "line": 12, + "offset": 16 + }, + "end": { + "line": 12, + "offset": 36 + } + }, + { + "start": { + "line": 19, + "offset": 9 + }, + "end": { + "line": 19, + "offset": 9 + } + } + ] + }, + "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 SVC-1-1 "function foo() {\n console.log(sauce);\n}\nclass bar {\n const apple = 1 + juicector() {\n function a() {\n console.log(\"hii\");\n }\n a();\n function b() {\n function c() {\n const kiwi = 1;\n }\n }\n b();\n }\n c() {\n console.log(\"hello again\");\n function k() {\n const cherry = 3 + tomato + cucumber;\n }\n }\n}" + /b.ts Text-1 "export const juice = 1;\nexport const sauce = 2;\nexport const tomato = 3;" + +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": "/a.ts", + "textChanges": [ + { + "start": { + "line": 1, + "offset": 1 + }, + "end": { + "line": 1, + "offset": 1 + }, + "newText": "import { sauce, tomato } from \"./b\";\n\n" + }, + { + "start": { + "line": 2, + "offset": 13 + }, + "end": { + "line": 2, + "offset": 26 + }, + "newText": "log(sauce);" + }, + { + "start": { + "line": 5, + "offset": 5 + }, + "end": { + "line": 5, + "offset": 12 + }, + "newText": "const apple = 1 + juice" + }, + { + "start": { + "line": 12, + "offset": 16 + }, + "end": { + "line": 12, + "offset": 36 + }, + "newText": "const kiwi = 1;" + }, + { + "start": { + "line": 19, + "offset": 9 + }, + "end": { + "line": 19, + "offset": 9 + }, + "newText": "function k() {\n const cherry = 3 + tomato + cucumber;\n }" + } + ] + } + ], + "fixId": "providePostPasteEdits" + } + } +After Request +Projects:: +/tsconfig.json (Configured) *changed* + projectStateVersion: 3 *changed* + projectProgramVersion: 1 + dirty: true *changed* + +ScriptInfos:: +/a.ts (Open) *changed* + version: SVC-1-2 *changed* + containingProjects: 1 + /tsconfig.json *default* +/b.ts + version: Text-1 + containingProjects: 1 + /tsconfig.json +/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_multiplePastesGrowingInSize.js b/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_multiplePastesGrowingInSize.js new file mode 100644 index 0000000000000..b73c74561d734 --- /dev/null +++ b/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_multiplePastesGrowingInSize.js @@ -0,0 +1,412 @@ +currentDirectory:: / useCaseSensitiveFileNames: false +Info seq [hh:mm:ss:mss] Provided types map file "/typesMap.json" doesn't exist +//// [/a.ts] +function foo() { + const p = 1; +} +function too() { + function k(t: string) { + console.log(t); + } +} +class bar { + constructor() { + function a() { + console.log("hello"); + } + a(); + } + c() { + console.log("hello again"); + function k() { + const happy = banana + avocados; + } + } +} + +//// [/b.ts] +export const juices = 1; +export const sauce = 2; + +//// [/c.ts] +export const figs = 3; +export const tomato = 4; + +//// [/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", "c.ts"] } + + +Info seq [hh:mm:ss:mss] request: + { + "seq": 0, + "type": "request", + "arguments": { + "file": "/a.ts" + }, + "command": "open" + } +Info seq [hh:mm:ss:mss] getConfigFileNameForFile:: File: /a.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 /a.ts to open" + } + } +Info seq [hh:mm:ss:mss] Config: /tsconfig.json : { + "rootNames": [ + "/a.ts", + "/b.ts", + "/c.ts" + ], + "options": { + "configFilePath": "/tsconfig.json" + } +} +Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /b.ts 500 undefined WatchType: Closed Script info +Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /c.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 + /a.ts SVC-1-0 "function foo() {\n const p = 1;\n}\nfunction too() {\n function k(t: string) {\n console.log(t);\n }\n}\nclass bar {\n constructor() {\n function a() {\n console.log(\"hello\");\n }\n a();\n }\n c() {\n console.log(\"hello again\");\n function k() {\n const happy = banana + avocados;\n }\n }\n}" + /b.ts Text-1 "export const juices = 1;\nexport const sauce = 2;" + /c.ts Text-1 "export const figs = 3;\nexport const tomato = 4;" + + + 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 + c.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": "/a.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: /a.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:: +/b.ts: *new* + {"pollingInterval":500} +/c.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 (Open) *new* + version: SVC-1-0 + containingProjects: 1 + /tsconfig.json *default* +/b.ts *new* + version: Text-1 + containingProjects: 1 + /tsconfig.json +/c.ts *new* + version: Text-1 + containingProjects: 1 + /tsconfig.json +/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": "/a.ts", + "pastedText": [ + "const t = figs;", + "apples : number", + " console.log(sauce + tomato); ", + "//function k(i:string) {\n const cherry = 3 + juices + cucumber;\n// }" + ], + "pasteLocations": [ + { + "start": { + "line": 2, + "offset": 4 + }, + "end": { + "line": 2, + "offset": 16 + } + }, + { + "start": { + "line": 5, + "offset": 15 + }, + "end": { + "line": 5, + "offset": 24 + } + }, + { + "start": { + "line": 12, + "offset": 1 + }, + "end": { + "line": 12, + "offset": 34 + } + }, + { + "start": { + "line": 18, + "offset": 9 + }, + "end": { + "line": 20, + "offset": 10 + } + } + ] + }, + "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 + /a.ts SVC-1-1 "function foo() {\n const t = figs;\n}\nfunction too() {\n function k(apples : number) {\n console.log(t);\n }\n}\nclass bar {\n constructor() {\n function a() {\n console.log(sauce + tomato); \n }\n a();\n }\n c() {\n console.log(\"hello again\");\n //function k(i:string) {\n const cherry = 3 + juices + cucumber;\n// }\n }\n}" + /b.ts Text-1 "export const juices = 1;\nexport const sauce = 2;" + /c.ts Text-1 "export const figs = 3;\nexport const tomato = 4;" + +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": "/a.ts", + "textChanges": [ + { + "start": { + "line": 1, + "offset": 1 + }, + "end": { + "line": 1, + "offset": 1 + }, + "newText": "import { sauce, juices } from \"./b\";\nimport { figs, tomato } from \"./c\";\n\n" + }, + { + "start": { + "line": 2, + "offset": 4 + }, + "end": { + "line": 2, + "offset": 16 + }, + "newText": "const t = figs;" + }, + { + "start": { + "line": 5, + "offset": 15 + }, + "end": { + "line": 5, + "offset": 24 + }, + "newText": "apples : number" + }, + { + "start": { + "line": 12, + "offset": 1 + }, + "end": { + "line": 12, + "offset": 34 + }, + "newText": " console.log(sauce + tomato); " + }, + { + "start": { + "line": 18, + "offset": 9 + }, + "end": { + "line": 20, + "offset": 10 + }, + "newText": "//function k(i:string) {\n const cherry = 3 + juices + cucumber;\n// }" + } + ] + } + ], + "fixId": "providePostPasteEdits" + } + } +After Request +Projects:: +/tsconfig.json (Configured) *changed* + projectStateVersion: 3 *changed* + projectProgramVersion: 1 + dirty: true *changed* + +ScriptInfos:: +/a.ts (Open) *changed* + version: SVC-1-2 *changed* + containingProjects: 1 + /tsconfig.json *default* +/b.ts + version: Text-1 + containingProjects: 1 + /tsconfig.json +/c.ts + version: Text-1 + containingProjects: 1 + /tsconfig.json +/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_multiplePastesShrinkingInSize.js b/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_multiplePastesShrinkingInSize.js new file mode 100644 index 0000000000000..0f1ad0b71e624 --- /dev/null +++ b/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_multiplePastesShrinkingInSize.js @@ -0,0 +1,412 @@ +currentDirectory:: / useCaseSensitiveFileNames: false +Info seq [hh:mm:ss:mss] Provided types map file "/typesMap.json" doesn't exist +//// [/a.ts] +function foo() { + console.log("Good day"); +} +function too() { + function k(t: string) { + console.log("Happy Holidays"); + } +} +class bar { + constructor() { + function a() { + console.log("hello"); + } + a(); + } + c() { + console.log("hello again"); + function k() { + const happy = banana + avocados; + } + } +} + +//// [/b.ts] +export const juices = 1; +export const sauce = 2; + +//// [/c.ts] +export const figs = 3; +export const tomato = 4; + +//// [/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", "c.ts"] } + + +Info seq [hh:mm:ss:mss] request: + { + "seq": 0, + "type": "request", + "arguments": { + "file": "/a.ts" + }, + "command": "open" + } +Info seq [hh:mm:ss:mss] getConfigFileNameForFile:: File: /a.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 /a.ts to open" + } + } +Info seq [hh:mm:ss:mss] Config: /tsconfig.json : { + "rootNames": [ + "/a.ts", + "/b.ts", + "/c.ts" + ], + "options": { + "configFilePath": "/tsconfig.json" + } +} +Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /b.ts 500 undefined WatchType: Closed Script info +Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /c.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 + /a.ts SVC-1-0 "function foo() {\n console.log(\"Good day\");\n}\nfunction too() {\n function k(t: string) {\n console.log(\"Happy Holidays\");\n }\n}\nclass bar {\n constructor() {\n function a() {\n console.log(\"hello\");\n }\n a();\n }\n c() {\n console.log(\"hello again\");\n function k() {\n const happy = banana + avocados;\n }\n }\n}" + /b.ts Text-1 "export const juices = 1;\nexport const sauce = 2;" + /c.ts Text-1 "export const figs = 3;\nexport const tomato = 4;" + + + 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 + c.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": "/a.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: /a.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:: +/b.ts: *new* + {"pollingInterval":500} +/c.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 (Open) *new* + version: SVC-1-0 + containingProjects: 1 + /tsconfig.json *default* +/b.ts *new* + version: Text-1 + containingProjects: 1 + /tsconfig.json +/c.ts *new* + version: Text-1 + containingProjects: 1 + /tsconfig.json +/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": "/a.ts", + "pastedText": [ + "console.log(\"Good \");", + "const k = figs + juices;", + " console.log(tomato);", + "(kiwi: string) {\n const cherry=tomato;\n }" + ], + "pasteLocations": [ + { + "start": { + "line": 2, + "offset": 4 + }, + "end": { + "line": 2, + "offset": 28 + } + }, + { + "start": { + "line": 6, + "offset": 8 + }, + "end": { + "line": 6, + "offset": 38 + } + }, + { + "start": { + "line": 12, + "offset": 1 + }, + "end": { + "line": 12, + "offset": 34 + } + }, + { + "start": { + "line": 18, + "offset": 19 + }, + "end": { + "line": 20, + "offset": 10 + } + } + ] + }, + "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 + /a.ts SVC-1-1 "function foo() {\n console.log(\"Good \");\n}\nfunction too() {\n function k(t: string) {\n const k = figs + juices;\n }\n}\nclass bar {\n constructor() {\n function a() {\n console.log(tomato);\n }\n a();\n }\n c() {\n console.log(\"hello again\");\n function k(kiwi: string) {\n const cherry=tomato;\n }\n }\n}" + /b.ts Text-1 "export const juices = 1;\nexport const sauce = 2;" + /c.ts Text-1 "export const figs = 3;\nexport const tomato = 4;" + +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": "/a.ts", + "textChanges": [ + { + "start": { + "line": 1, + "offset": 1 + }, + "end": { + "line": 1, + "offset": 1 + }, + "newText": "import { juices } from \"./b\";\nimport { figs, tomato } from \"./c\";\n\n" + }, + { + "start": { + "line": 2, + "offset": 4 + }, + "end": { + "line": 2, + "offset": 28 + }, + "newText": "console.log(\"Good \");" + }, + { + "start": { + "line": 6, + "offset": 8 + }, + "end": { + "line": 6, + "offset": 38 + }, + "newText": "const k = figs + juices;" + }, + { + "start": { + "line": 12, + "offset": 1 + }, + "end": { + "line": 12, + "offset": 34 + }, + "newText": " console.log(tomato);" + }, + { + "start": { + "line": 18, + "offset": 19 + }, + "end": { + "line": 20, + "offset": 10 + }, + "newText": "(kiwi: string) {\n const cherry=tomato;\n }" + } + ] + } + ], + "fixId": "providePostPasteEdits" + } + } +After Request +Projects:: +/tsconfig.json (Configured) *changed* + projectStateVersion: 3 *changed* + projectProgramVersion: 1 + dirty: true *changed* + +ScriptInfos:: +/a.ts (Open) *changed* + version: SVC-1-2 *changed* + containingProjects: 1 + /tsconfig.json *default* +/b.ts + version: Text-1 + containingProjects: 1 + /tsconfig.json +/c.ts + version: Text-1 + containingProjects: 1 + /tsconfig.json +/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_multiplePastesConsistentlyLargerInSize.ts b/tests/cases/fourslash/server/pasteEdits_multiplePastesConsistentlyLargerInSize.ts new file mode 100644 index 0000000000000..0f89ddcfa3f85 --- /dev/null +++ b/tests/cases/fourslash/server/pasteEdits_multiplePastesConsistentlyLargerInSize.ts @@ -0,0 +1,78 @@ +/// + +// @Filename: /a.ts +//// function foo() { +//// const p = 1; +//// [|console.log("yes");|] +//// } +//// class bar { +//// constructor() { +//// function a() { +//// [|console.log("have a good day");|] +//// } +//// a(); +//// function b() { +//// function c() { +//// const test = [|1 + 2|] + 3; +//// } +//// } +//// b(); +//// } +//// c() { +//// console.log("hello again"); +//// [|function k() { +//// const happy = banana + avocados; +//// }|] +//// } +//// } + +// @Filename: /b.ts +//// export const juice = 1; +//// export const sauce = 2; +//// export const fig = 3; +//// export const tomato = 4; + +// @Filename: /tsconfig.json +////{ "files": ["a.ts", "b.ts"] } + +const range = test.ranges(); +verify.pasteEdits({ + args: { + pastedText: [ `const t = 1 + juice + p;`,`function avacado() { return sauce; }`, + `fig + kiwi`, +`function k() { + const cherry = 3 + tomato + cucumber; + }` +], + pasteLocations: [range[0], range[1], range[2], range[3]], + }, + newFileContents: { + "/a.ts": +`import { juice, sauce, fig, tomato } from "./b"; + +function foo() { + const p = 1; + const t = 1 + juice + p; +} +class bar { + constructor() { + function a() { + function avacado() { return sauce; } + } + a(); + function b() { + function c() { + const test = fig + kiwi + 3; + } + } + b(); + } + c() { + console.log("hello again"); + function k() { + const cherry = 3 + tomato + cucumber; + } + } +}` + } +}); diff --git a/tests/cases/fourslash/server/pasteEdits_multiplePastesConsistentlySmallerInSize.ts b/tests/cases/fourslash/server/pasteEdits_multiplePastesConsistentlySmallerInSize.ts new file mode 100644 index 0000000000000..cdc6dfa818f4f --- /dev/null +++ b/tests/cases/fourslash/server/pasteEdits_multiplePastesConsistentlySmallerInSize.ts @@ -0,0 +1,92 @@ +/// + +// @Filename: /a.ts +//// function foo() { +//// const p = 1; +//// function bar() { +//// console.log([|"Testing"|]); +//// } +//// console.log("yes"); +//// } +//// class bar { +//// constructor() { +//// function a() { +//// function aa() { +//// con[|sole.log("have a good day");|] +//// } +//// +//// } +//// a(); +//// function b() { +//// function c() { +//// export const testing = 1; +//// const test = [|1 + testing + |]3; +//// } +//// } +//// b(); +//// } +//// c() { +//// console.log("hello again"); +//// [|function k() { +//// const happy = banana + avocados; +//// }|] +//// } +//// } + +// @Filename: /b.ts +//// export const juice = 1; +//// export const sauce = 2; +//// export const fig = 3; +//// export const tomato = 4; + +// @Filename: /tsconfig.json +////{ "files": ["a.ts", "b.ts"] } + +const range = test.ranges(); +verify.pasteEdits({ + args: { + pastedText: [ `juice`,`sole.log(sauce + juice);`, + `fig + kiwi`, +`function k() { + const cherry =tomato + kiwi; + }` +], + pasteLocations: [range[0], range[1], range[2], range[3]], + }, + newFileContents: { + "/a.ts": +`import { sauce, juice, fig, tomato } from "./b"; + +function foo() { + const p = 1; + function bar() { + console.log(juice); + } + console.log("yes"); +} +class bar { + constructor() { + function a() { + function aa() { + console.log(sauce + juice); + } + + } + a(); + function b() { + function c() { + export const testing = 1; + const test = fig + kiwi3; + } + } + b(); + } + c() { + console.log("hello again"); + function k() { + const cherry =tomato + kiwi; + } + } +}` + } +}); diff --git a/tests/cases/fourslash/server/pasteEdits_multiplePastesEqualInSize.ts b/tests/cases/fourslash/server/pasteEdits_multiplePastesEqualInSize.ts new file mode 100644 index 0000000000000..b641d609f594b --- /dev/null +++ b/tests/cases/fourslash/server/pasteEdits_multiplePastesEqualInSize.ts @@ -0,0 +1,76 @@ +/// + +// @Filename: /a.ts +//// function foo() { +//// [|console.log("yes");|] +//// } +//// class bar { +//// constructor() { +//// function a() { +//// [|console.log("have a good day");|] +//// } +//// a(); +//// function b() { +//// function c() { +//// const test = [|1 + 2|] + 3; +//// } +//// } +//// b(); +//// } +//// c() { +//// console.log("hello again"); +//// [|function k() { +//// const happy = 1 + banana + avocados; +//// }|] +//// } +//// } + +// @Filename: /b.ts +//// export const juice = 1; +//// export const sauce = 2; +//// export const apple = 3; +//// export const tomato = 4; + +// @Filename: /tsconfig.json +////{ "files": ["a.ts", "b.ts"] } + +const range = test.ranges(); +verify.pasteEdits({ + args: { + pastedText: [ `console.log(juice);`,`function kl() { return sauce; }`, + `apple`, +`function k() { + const cherry = 3 + tomato + cucumber; + }` +], + pasteLocations: [range[0], range[1], range[2], range[3]], + }, + newFileContents: { + "/a.ts": +`import { juice, sauce, tomato } from "./b"; + +function foo() { + console.log(juice); +} +class bar { + constructor() { + function a() { + function kl() { return sauce; } + } + a(); + function b() { + function c() { + const test = apple + 3; + } + } + b(); + } + c() { + console.log("hello again"); + function k() { + const cherry = 3 + tomato + cucumber; + } + } +}` + } +}); diff --git a/tests/cases/fourslash/server/pasteEdits_multiplePastes5.ts b/tests/cases/fourslash/server/pasteEdits_multiplePastesGrowingAndShrinkingInSize.ts similarity index 82% rename from tests/cases/fourslash/server/pasteEdits_multiplePastes5.ts rename to tests/cases/fourslash/server/pasteEdits_multiplePastesGrowingAndShrinkingInSize.ts index 420e7246bddc1..195d718703392 100644 --- a/tests/cases/fourslash/server/pasteEdits_multiplePastes5.ts +++ b/tests/cases/fourslash/server/pasteEdits_multiplePastesGrowingAndShrinkingInSize.ts @@ -13,7 +13,7 @@ //// function b() { //// function c() { //// [|console.log("hola");|] -//// } +//// } //// } //// b(); //// } @@ -34,8 +34,8 @@ const range = test.ranges(); verify.pasteEdits({ args: { - pastedText: [ `const mango = 2 + sauce;`,`const apple = 1 + juice`, - `const strawberry = 1;`, + pastedText: [ `log(sauce);`,`const apple = 1 + juice`, + `const kiwi = 1;`, `function k() { const cherry = 3 + tomato + cucumber; }` @@ -47,7 +47,7 @@ verify.pasteEdits({ `import { sauce, tomato } from "./b"; function foo() { - console.const mango = 2 + sauce; + console.log(sauce); } class bar { const apple = 1 + juicector() { @@ -57,8 +57,8 @@ class bar { a(); function b() { function c() { - const strawberry = 1; - } + const kiwi = 1; + } } b(); } diff --git a/tests/cases/fourslash/server/pasteEdits_multiplePastesGrowingInSize.ts b/tests/cases/fourslash/server/pasteEdits_multiplePastesGrowingInSize.ts new file mode 100644 index 0000000000000..3f97d1da3bfdc --- /dev/null +++ b/tests/cases/fourslash/server/pasteEdits_multiplePastesGrowingInSize.ts @@ -0,0 +1,77 @@ +/// + +// @Filename: /a.ts +//// function foo() { +//// [|const p = 1;|] +//// } +//// function too() { +//// function k([|t: string|]) { +//// console.log(t); +//// } +//// } +//// class bar { +//// constructor() { +//// function a() { +//// [| console.log("hello");|] +//// } +//// a(); +//// } +//// c() { +//// console.log("hello again"); +//// [|function k() { +//// const happy = banana + avocados; +//// }|] +//// } +//// } + +// @Filename: /b.ts +//// export const juices = 1; +//// export const sauce = 2; + +// @Filename: /c.ts +//// export const figs = 3; +//// export const tomato = 4; + +// @Filename: /tsconfig.json +////{ "files": ["a.ts", "b.ts", "c.ts"] } + +const range = test.ranges(); +verify.pasteEdits({ + args: { + pastedText: [ `const t = figs;`,`apples : number`, + ` console.log(sauce + tomato); `, +`//function k(i:string) { + const cherry = 3 + juices + cucumber; +// }` +], + pasteLocations: [range[0], range[1], range[2], range[3]], + }, + newFileContents: { + "/a.ts": +`import { sauce, juices } from "./b"; +import { figs, tomato } from "./c"; + +function foo() { + const t = figs; +} +function too() { + function k(apples : number) { + console.log(t); + } +} +class bar { + constructor() { + function a() { + console.log(sauce + tomato); + } + a(); + } + c() { + console.log("hello again"); + //function k(i:string) { + const cherry = 3 + juices + cucumber; +// } + } +}` + } +}); diff --git a/tests/cases/fourslash/server/pasteEdits_multiplePastesShrinkingInSize.ts b/tests/cases/fourslash/server/pasteEdits_multiplePastesShrinkingInSize.ts new file mode 100644 index 0000000000000..1030c0c23317a --- /dev/null +++ b/tests/cases/fourslash/server/pasteEdits_multiplePastesShrinkingInSize.ts @@ -0,0 +1,77 @@ +/// + +// @Filename: /a.ts +//// function foo() { +//// [|console.log("Good day");|] +//// } +//// function too() { +//// function k(t: string) { +//// [|console.log("Happy Holidays");|] +//// } +//// } +//// class bar { +//// constructor() { +//// function a() { +//// [| console.log("hello");|] +//// } +//// a(); +//// } +//// c() { +//// console.log("hello again"); +//// function k[|() { +//// const happy = banana + avocados; +//// }|] +//// } +//// } + +// @Filename: /b.ts +//// export const juices = 1; +//// export const sauce = 2; + +// @Filename: /c.ts +//// export const figs = 3; +//// export const tomato = 4; + +// @Filename: /tsconfig.json +////{ "files": ["a.ts", "b.ts", "c.ts"] } + +const range = test.ranges(); +verify.pasteEdits({ + args: { + pastedText: [ `console.log("Good ");`,`const k = figs + juices;`, + ` console.log(tomato);`, +`(kiwi: string) { + const cherry=tomato; + }` +], + pasteLocations: [range[0], range[1], range[2], range[3]], + }, + newFileContents: { + "/a.ts": +`import { juices } from "./b"; +import { figs, tomato } from "./c"; + +function foo() { + console.log("Good "); +} +function too() { + function k(t: string) { + const k = figs + juices; + } +} +class bar { + constructor() { + function a() { + console.log(tomato); + } + a(); + } + c() { + console.log("hello again"); + function k(kiwi: string) { + const cherry=tomato; + } + } +}` + } +}); From c0f61dea745380fa327740181559b339efdfa93b Mon Sep 17 00:00:00 2001 From: navya9singh Date: Tue, 13 Aug 2024 13:06:41 -0700 Subject: [PATCH 12/19] deleting old baseline --- .../pasteEdits_multiplePastes5.js | 392 ------------------ 1 file changed, 392 deletions(-) delete mode 100644 tests/baselines/reference/tsserver/fourslashServer/pasteEdits_multiplePastes5.js diff --git a/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_multiplePastes5.js b/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_multiplePastes5.js deleted file mode 100644 index 6cd5ecc0724b7..0000000000000 --- a/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_multiplePastes5.js +++ /dev/null @@ -1,392 +0,0 @@ -currentDirectory:: / useCaseSensitiveFileNames: false -Info seq [hh:mm:ss:mss] Provided types map file "/typesMap.json" doesn't exist -//// [/a.ts] -function foo() { - console.log("Hello"); -} -class bar { - constructor() { - function a() { - console.log("hii"); - } - a(); - function b() { - function c() { - console.log("hola"); - } - } - b(); - } - c() { - console.log("hello again"); - - } -} - -//// [/b.ts] -export const juice = 1; -export const sauce = 2; -export const tomato = 3; - -//// [/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": "/a.ts" - }, - "command": "open" - } -Info seq [hh:mm:ss:mss] getConfigFileNameForFile:: File: /a.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 /a.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: /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 (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 SVC-1-0 "function foo() {\n console.log(\"Hello\");\n}\nclass bar {\n constructor() {\n function a() {\n console.log(\"hii\");\n }\n a();\n function b() {\n function c() {\n console.log(\"hola\");\n } \n }\n b();\n }\n c() {\n console.log(\"hello again\");\n \n }\n}" - /b.ts Text-1 "export const juice = 1;\nexport const sauce = 2;\nexport const tomato = 3;" - - - 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": "/a.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: /a.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:: -/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 (Open) *new* - version: SVC-1-0 - containingProjects: 1 - /tsconfig.json *default* -/b.ts *new* - version: Text-1 - containingProjects: 1 - /tsconfig.json -/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": "/a.ts", - "pastedText": [ - "const mango = 2 + sauce;", - "const apple = 1 + juice", - "const strawberry = 1;", - "function k() {\n const cherry = 3 + tomato + cucumber;\n }" - ], - "pasteLocations": [ - { - "start": { - "line": 2, - "offset": 13 - }, - "end": { - "line": 2, - "offset": 26 - } - }, - { - "start": { - "line": 5, - "offset": 5 - }, - "end": { - "line": 5, - "offset": 12 - } - }, - { - "start": { - "line": 12, - "offset": 16 - }, - "end": { - "line": 12, - "offset": 36 - } - }, - { - "start": { - "line": 19, - "offset": 9 - }, - "end": { - "line": 19, - "offset": 9 - } - } - ] - }, - "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 SVC-1-1 "function foo() {\n console.const mango = 2 + sauce;\n}\nclass bar {\n const apple = 1 + juicector() {\n function a() {\n console.log(\"hii\");\n }\n a();\n function b() {\n function c() {\n const strawberry = 1;\n } \n }\n b();\n }\n c() {\n console.log(\"hello again\");\n function k() {\n const cherry = 3 + tomato + cucumber;\n }\n }\n}" - /b.ts Text-1 "export const juice = 1;\nexport const sauce = 2;\nexport const tomato = 3;" - -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": "/a.ts", - "textChanges": [ - { - "start": { - "line": 1, - "offset": 1 - }, - "end": { - "line": 1, - "offset": 1 - }, - "newText": "import { sauce, tomato } from \"./b\";\n\n" - }, - { - "start": { - "line": 2, - "offset": 13 - }, - "end": { - "line": 2, - "offset": 26 - }, - "newText": "const mango = 2 + sauce;" - }, - { - "start": { - "line": 5, - "offset": 5 - }, - "end": { - "line": 5, - "offset": 12 - }, - "newText": "const apple = 1 + juice" - }, - { - "start": { - "line": 12, - "offset": 16 - }, - "end": { - "line": 12, - "offset": 36 - }, - "newText": "const strawberry = 1;" - }, - { - "start": { - "line": 19, - "offset": 9 - }, - "end": { - "line": 19, - "offset": 9 - }, - "newText": "function k() {\n const cherry = 3 + tomato + cucumber;\n }" - } - ] - } - ], - "fixId": "providePostPasteEdits" - } - } -After Request -Projects:: -/tsconfig.json (Configured) *changed* - projectStateVersion: 3 *changed* - projectProgramVersion: 1 - dirty: true *changed* - -ScriptInfos:: -/a.ts (Open) *changed* - version: SVC-1-2 *changed* - containingProjects: 1 - /tsconfig.json *default* -/b.ts - version: Text-1 - containingProjects: 1 - /tsconfig.json -/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 From 9acc51a04a118e51887b7599c2395c2ae5f21501 Mon Sep 17 00:00:00 2001 From: navya9singh Date: Tue, 13 Aug 2024 14:44:31 -0700 Subject: [PATCH 13/19] fixing tests --- src/services/pasteEdits.ts | 8 +++++--- ...asteEdits_multiplePastesConsistentlyLargerInSize.ts | 10 +++++----- ...steEdits_multiplePastesConsistentlySmallerInSize.ts | 8 ++++---- .../server/pasteEdits_multiplePastesEqualInSize.ts | 8 ++++---- ...steEdits_multiplePastesGrowingAndShrinkingInSize.ts | 6 +++--- .../server/pasteEdits_multiplePastesGrowingInSize.ts | 8 ++++---- .../server/pasteEdits_multiplePastesShrinkingInSize.ts | 8 ++++---- 7 files changed, 29 insertions(+), 27 deletions(-) diff --git a/src/services/pasteEdits.ts b/src/services/pasteEdits.ts index 2a08d88f6e60d..da8fedbd65ca0 100644 --- a/src/services/pasteEdits.ts +++ b/src/services/pasteEdits.ts @@ -12,6 +12,7 @@ import { isIdentifier, Program, rangeContainsPosition, + rangeContainsRange, SourceFile, Statement, SymbolFlags, @@ -124,13 +125,14 @@ function pasteEdits( }); updatedRanges.forEach(range => { - const enclosingNode = findAncestor(getTokenAtPosition(context.sourceFile, range.pos), ancestorNode => rangeContainsPosition(ancestorNode, range.end)); + const enclosingNode = findAncestor(getTokenAtPosition(context.sourceFile, range.pos), ancestorNode => rangeContainsRange(ancestorNode, range)); if (!enclosingNode) return; - forEachChild(enclosingNode, function cb(node) { + forEachChild(enclosingNode, function importUnresolvedIdentifiers(node) { if (isIdentifier(node) && rangeContainsPosition(range, node.getStart(updatedFile)) && !originalProgram?.getTypeChecker().resolveName(node.text, node, SymbolFlags.All, /*excludeGlobals*/ false)) { importAdder.addImportForUnresolvedIdentifier(context, node, /*useAutoImportProvider*/ true); + return; } - node.forEachChild(cb); + node.forEachChild(importUnresolvedIdentifiers); }); }); } diff --git a/tests/cases/fourslash/server/pasteEdits_multiplePastesConsistentlyLargerInSize.ts b/tests/cases/fourslash/server/pasteEdits_multiplePastesConsistentlyLargerInSize.ts index 0f89ddcfa3f85..8ee905672665f 100644 --- a/tests/cases/fourslash/server/pasteEdits_multiplePastesConsistentlyLargerInSize.ts +++ b/tests/cases/fourslash/server/pasteEdits_multiplePastesConsistentlyLargerInSize.ts @@ -35,16 +35,16 @@ // @Filename: /tsconfig.json ////{ "files": ["a.ts", "b.ts"] } -const range = test.ranges(); verify.pasteEdits({ args: { - pastedText: [ `const t = 1 + juice + p;`,`function avacado() { return sauce; }`, + pastedText: [ + `const t = 1 + juice + p;`,`function avacado() { return sauce; }`, `fig + kiwi`, -`function k() { + `function k() { const cherry = 3 + tomato + cucumber; }` -], - pasteLocations: [range[0], range[1], range[2], range[3]], + ], + pasteLocations: test.ranges(), }, newFileContents: { "/a.ts": diff --git a/tests/cases/fourslash/server/pasteEdits_multiplePastesConsistentlySmallerInSize.ts b/tests/cases/fourslash/server/pasteEdits_multiplePastesConsistentlySmallerInSize.ts index cdc6dfa818f4f..403a9e52544a8 100644 --- a/tests/cases/fourslash/server/pasteEdits_multiplePastesConsistentlySmallerInSize.ts +++ b/tests/cases/fourslash/server/pasteEdits_multiplePastesConsistentlySmallerInSize.ts @@ -42,16 +42,16 @@ // @Filename: /tsconfig.json ////{ "files": ["a.ts", "b.ts"] } -const range = test.ranges(); verify.pasteEdits({ args: { - pastedText: [ `juice`,`sole.log(sauce + juice);`, + pastedText: [ + `juice`,`sole.log(sauce + juice);`, `fig + kiwi`, -`function k() { + `function k() { const cherry =tomato + kiwi; }` ], - pasteLocations: [range[0], range[1], range[2], range[3]], + pasteLocations: test.ranges(), }, newFileContents: { "/a.ts": diff --git a/tests/cases/fourslash/server/pasteEdits_multiplePastesEqualInSize.ts b/tests/cases/fourslash/server/pasteEdits_multiplePastesEqualInSize.ts index b641d609f594b..7294d619e3be5 100644 --- a/tests/cases/fourslash/server/pasteEdits_multiplePastesEqualInSize.ts +++ b/tests/cases/fourslash/server/pasteEdits_multiplePastesEqualInSize.ts @@ -34,16 +34,16 @@ // @Filename: /tsconfig.json ////{ "files": ["a.ts", "b.ts"] } -const range = test.ranges(); verify.pasteEdits({ args: { - pastedText: [ `console.log(juice);`,`function kl() { return sauce; }`, + pastedText: [ + `console.log(juice);`,`function kl() { return sauce; }`, `apple`, -`function k() { + `function k() { const cherry = 3 + tomato + cucumber; }` ], - pasteLocations: [range[0], range[1], range[2], range[3]], + pasteLocations: test.ranges(), }, newFileContents: { "/a.ts": diff --git a/tests/cases/fourslash/server/pasteEdits_multiplePastesGrowingAndShrinkingInSize.ts b/tests/cases/fourslash/server/pasteEdits_multiplePastesGrowingAndShrinkingInSize.ts index 195d718703392..65c84d10d3536 100644 --- a/tests/cases/fourslash/server/pasteEdits_multiplePastesGrowingAndShrinkingInSize.ts +++ b/tests/cases/fourslash/server/pasteEdits_multiplePastesGrowingAndShrinkingInSize.ts @@ -31,16 +31,16 @@ // @Filename: /tsconfig.json ////{ "files": ["a.ts", "b.ts"] } -const range = test.ranges(); verify.pasteEdits({ args: { - pastedText: [ `log(sauce);`,`const apple = 1 + juice`, + pastedText: [ + `log(sauce);`,`const apple = 1 + juice`, `const kiwi = 1;`, `function k() { const cherry = 3 + tomato + cucumber; }` ], - pasteLocations: [range[0], range[1], range[2], range[3]], + pasteLocations: test.ranges(), }, newFileContents: { "/a.ts": diff --git a/tests/cases/fourslash/server/pasteEdits_multiplePastesGrowingInSize.ts b/tests/cases/fourslash/server/pasteEdits_multiplePastesGrowingInSize.ts index 3f97d1da3bfdc..c191fee63114c 100644 --- a/tests/cases/fourslash/server/pasteEdits_multiplePastesGrowingInSize.ts +++ b/tests/cases/fourslash/server/pasteEdits_multiplePastesGrowingInSize.ts @@ -35,16 +35,16 @@ // @Filename: /tsconfig.json ////{ "files": ["a.ts", "b.ts", "c.ts"] } -const range = test.ranges(); verify.pasteEdits({ args: { - pastedText: [ `const t = figs;`,`apples : number`, + pastedText: [ + `const t = figs;`,`apples : number`, ` console.log(sauce + tomato); `, -`//function k(i:string) { + `//function k(i:string) { const cherry = 3 + juices + cucumber; // }` ], - pasteLocations: [range[0], range[1], range[2], range[3]], + pasteLocations: test.ranges(), }, newFileContents: { "/a.ts": diff --git a/tests/cases/fourslash/server/pasteEdits_multiplePastesShrinkingInSize.ts b/tests/cases/fourslash/server/pasteEdits_multiplePastesShrinkingInSize.ts index 1030c0c23317a..363bafb62b3a5 100644 --- a/tests/cases/fourslash/server/pasteEdits_multiplePastesShrinkingInSize.ts +++ b/tests/cases/fourslash/server/pasteEdits_multiplePastesShrinkingInSize.ts @@ -35,16 +35,16 @@ // @Filename: /tsconfig.json ////{ "files": ["a.ts", "b.ts", "c.ts"] } -const range = test.ranges(); verify.pasteEdits({ args: { - pastedText: [ `console.log("Good ");`,`const k = figs + juices;`, + pastedText: [ + `console.log("Good ");`,`const k = figs + juices;`, ` console.log(tomato);`, -`(kiwi: string) { + `(kiwi: string) { const cherry=tomato; }` ], - pasteLocations: [range[0], range[1], range[2], range[3]], + pasteLocations: test.ranges(), }, newFileContents: { "/a.ts": From aebaae1fd4407695cda39c7cbaafcb6aee785b80 Mon Sep 17 00:00:00 2001 From: navya9singh Date: Wed, 14 Aug 2024 14:05:22 -0700 Subject: [PATCH 14/19] adressing pr comments --- src/services/pasteEdits.ts | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/src/services/pasteEdits.ts b/src/services/pasteEdits.ts index da8fedbd65ca0..a47aae68990b3 100644 --- a/src/services/pasteEdits.ts +++ b/src/services/pasteEdits.ts @@ -113,24 +113,36 @@ function pasteEdits( // // We iterate over each updated range to get the node that wholly encloses the updated range. For each child of that node, it is checked if the // identifier lies within the updated range and if it is not resolved, we try resolving it. - const updatedRanges: TextRange[] = []; let offset = 0; pasteLocations.forEach((location, i) => { const oldTextLength = location.end - location.pos; const textToBePasted = actualPastedText ? actualPastedText[0] : pastedText[i]; const startPos = location.pos + offset; const endPos = startPos + textToBePasted.length; - updatedRanges.push({ pos: startPos, end: endPos }); + const range = { pos: startPos, end: endPos } satisfies TextRange; offset += textToBePasted.length - oldTextLength; - }); - - updatedRanges.forEach(range => { - const enclosingNode = findAncestor(getTokenAtPosition(context.sourceFile, range.pos), ancestorNode => rangeContainsRange(ancestorNode, range)); + const enclosingNode = findAncestor( + getTokenAtPosition(context.sourceFile, range.pos), + ancestorNode => rangeContainsRange(ancestorNode, range), + ); if (!enclosingNode) return; forEachChild(enclosingNode, function importUnresolvedIdentifiers(node) { - if (isIdentifier(node) && rangeContainsPosition(range, node.getStart(updatedFile)) && !originalProgram?.getTypeChecker().resolveName(node.text, node, SymbolFlags.All, /*excludeGlobals*/ false)) { - importAdder.addImportForUnresolvedIdentifier(context, node, /*useAutoImportProvider*/ true); - return; + if ( + isIdentifier(node) && rangeContainsPosition( + range, + node.getStart(updatedFile), + ) && !originalProgram?.getTypeChecker().resolveName( + node.text, + node, + SymbolFlags.All, + /*excludeGlobals*/ false, + ) + ) { + return importAdder.addImportForUnresolvedIdentifier( + context, + node, + /*useAutoImportProvider*/ true, + ); } node.forEachChild(importUnresolvedIdentifiers); }); From 5044795c4b3512d71b56c080977cdda197a9c81a Mon Sep 17 00:00:00 2001 From: navya9singh Date: Thu, 15 Aug 2024 11:06:37 -0700 Subject: [PATCH 15/19] fixing formatting --- src/services/pasteEdits.ts | 22 ++++++++++--------- ..._multiplePastesConsistentlyLargerInSize.ts | 2 +- ...multiplePastesConsistentlySmallerInSize.ts | 2 +- .../pasteEdits_multiplePastesEqualInSize.ts | 2 +- ...multiplePastesGrowingAndShrinkingInSize.ts | 2 +- .../pasteEdits_multiplePastesGrowingInSize.ts | 2 +- ...asteEdits_multiplePastesShrinkingInSize.ts | 2 +- 7 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/services/pasteEdits.ts b/src/services/pasteEdits.ts index a47aae68990b3..315b871260d9c 100644 --- a/src/services/pasteEdits.ts +++ b/src/services/pasteEdits.ts @@ -111,33 +111,35 @@ function pasteEdits( // `updatedRanges` represent the new ranges that account for the offset changes caused by pasting new text and // `offset` represents by how much the starting position of `pasteLocations` needs to be changed. // - // We iterate over each updated range to get the node that wholly encloses the updated range. For each child of that node, it is checked if the - // identifier lies within the updated range and if it is not resolved, we try resolving it. + // We iterate over each updated range to get the node that wholly encloses the updated range. + // For each child of that node, we checked for unresolved identifiers + // within the updated range and try importing it. let offset = 0; pasteLocations.forEach((location, i) => { const oldTextLength = location.end - location.pos; const textToBePasted = actualPastedText ? actualPastedText[0] : pastedText[i]; const startPos = location.pos + offset; const endPos = startPos + textToBePasted.length; - const range = { pos: startPos, end: endPos } satisfies TextRange; + const range: TextRange = { pos: startPos, end: endPos }; offset += textToBePasted.length - oldTextLength; + const enclosingNode = findAncestor( getTokenAtPosition(context.sourceFile, range.pos), ancestorNode => rangeContainsRange(ancestorNode, range), ); if (!enclosingNode) return; + forEachChild(enclosingNode, function importUnresolvedIdentifiers(node) { - if ( - isIdentifier(node) && rangeContainsPosition( - range, - node.getStart(updatedFile), - ) && !originalProgram?.getTypeChecker().resolveName( + const isImportCandidate = + isIdentifier(node) && + rangeContainsPosition(range, node.getStart(updatedFile)) && + !originalProgram?.getTypeChecker().resolveName( node.text, node, SymbolFlags.All, /*excludeGlobals*/ false, - ) - ) { + ); + if (isImportCandidate) { return importAdder.addImportForUnresolvedIdentifier( context, node, diff --git a/tests/cases/fourslash/server/pasteEdits_multiplePastesConsistentlyLargerInSize.ts b/tests/cases/fourslash/server/pasteEdits_multiplePastesConsistentlyLargerInSize.ts index 8ee905672665f..5d0a825ddeb2c 100644 --- a/tests/cases/fourslash/server/pasteEdits_multiplePastesConsistentlyLargerInSize.ts +++ b/tests/cases/fourslash/server/pasteEdits_multiplePastesConsistentlyLargerInSize.ts @@ -43,7 +43,7 @@ verify.pasteEdits({ `function k() { const cherry = 3 + tomato + cucumber; }` - ], + ], pasteLocations: test.ranges(), }, newFileContents: { diff --git a/tests/cases/fourslash/server/pasteEdits_multiplePastesConsistentlySmallerInSize.ts b/tests/cases/fourslash/server/pasteEdits_multiplePastesConsistentlySmallerInSize.ts index 403a9e52544a8..caa45d0d1dd49 100644 --- a/tests/cases/fourslash/server/pasteEdits_multiplePastesConsistentlySmallerInSize.ts +++ b/tests/cases/fourslash/server/pasteEdits_multiplePastesConsistentlySmallerInSize.ts @@ -50,7 +50,7 @@ verify.pasteEdits({ `function k() { const cherry =tomato + kiwi; }` -], + ], pasteLocations: test.ranges(), }, newFileContents: { diff --git a/tests/cases/fourslash/server/pasteEdits_multiplePastesEqualInSize.ts b/tests/cases/fourslash/server/pasteEdits_multiplePastesEqualInSize.ts index 7294d619e3be5..3e32e541e0d47 100644 --- a/tests/cases/fourslash/server/pasteEdits_multiplePastesEqualInSize.ts +++ b/tests/cases/fourslash/server/pasteEdits_multiplePastesEqualInSize.ts @@ -42,7 +42,7 @@ verify.pasteEdits({ `function k() { const cherry = 3 + tomato + cucumber; }` -], + ], pasteLocations: test.ranges(), }, newFileContents: { diff --git a/tests/cases/fourslash/server/pasteEdits_multiplePastesGrowingAndShrinkingInSize.ts b/tests/cases/fourslash/server/pasteEdits_multiplePastesGrowingAndShrinkingInSize.ts index 65c84d10d3536..27259b80edb82 100644 --- a/tests/cases/fourslash/server/pasteEdits_multiplePastesGrowingAndShrinkingInSize.ts +++ b/tests/cases/fourslash/server/pasteEdits_multiplePastesGrowingAndShrinkingInSize.ts @@ -39,7 +39,7 @@ verify.pasteEdits({ `function k() { const cherry = 3 + tomato + cucumber; }` -], + ], pasteLocations: test.ranges(), }, newFileContents: { diff --git a/tests/cases/fourslash/server/pasteEdits_multiplePastesGrowingInSize.ts b/tests/cases/fourslash/server/pasteEdits_multiplePastesGrowingInSize.ts index c191fee63114c..9fb4fc26fdee7 100644 --- a/tests/cases/fourslash/server/pasteEdits_multiplePastesGrowingInSize.ts +++ b/tests/cases/fourslash/server/pasteEdits_multiplePastesGrowingInSize.ts @@ -43,7 +43,7 @@ verify.pasteEdits({ `//function k(i:string) { const cherry = 3 + juices + cucumber; // }` -], + ], pasteLocations: test.ranges(), }, newFileContents: { diff --git a/tests/cases/fourslash/server/pasteEdits_multiplePastesShrinkingInSize.ts b/tests/cases/fourslash/server/pasteEdits_multiplePastesShrinkingInSize.ts index 363bafb62b3a5..4a9ad20b2a8a9 100644 --- a/tests/cases/fourslash/server/pasteEdits_multiplePastesShrinkingInSize.ts +++ b/tests/cases/fourslash/server/pasteEdits_multiplePastesShrinkingInSize.ts @@ -43,7 +43,7 @@ verify.pasteEdits({ `(kiwi: string) { const cherry=tomato; }` -], + ], pasteLocations: test.ranges(), }, newFileContents: { From d7083b86f103e6cf913371700a9d08ea0a4c6c2e Mon Sep 17 00:00:00 2001 From: navya9singh Date: Thu, 15 Aug 2024 11:22:11 -0700 Subject: [PATCH 16/19] formatting fix --- src/services/pasteEdits.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/services/pasteEdits.ts b/src/services/pasteEdits.ts index 315b871260d9c..13a073cc91cdb 100644 --- a/src/services/pasteEdits.ts +++ b/src/services/pasteEdits.ts @@ -130,8 +130,7 @@ function pasteEdits( if (!enclosingNode) return; forEachChild(enclosingNode, function importUnresolvedIdentifiers(node) { - const isImportCandidate = - isIdentifier(node) && + const isImportCandidate = isIdentifier(node) && rangeContainsPosition(range, node.getStart(updatedFile)) && !originalProgram?.getTypeChecker().resolveName( node.text, From a29d5a8a8e8d05a0fa3d065c0acb9c70ebe05ccc Mon Sep 17 00:00:00 2001 From: navya9singh Date: Thu, 15 Aug 2024 13:12:39 -0700 Subject: [PATCH 17/19] changing originalProgram to updatedProgram --- src/services/pasteEdits.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/pasteEdits.ts b/src/services/pasteEdits.ts index 13a073cc91cdb..b3e0cedb50eeb 100644 --- a/src/services/pasteEdits.ts +++ b/src/services/pasteEdits.ts @@ -132,7 +132,7 @@ function pasteEdits( forEachChild(enclosingNode, function importUnresolvedIdentifiers(node) { const isImportCandidate = isIdentifier(node) && rangeContainsPosition(range, node.getStart(updatedFile)) && - !originalProgram?.getTypeChecker().resolveName( + !updatedProgram?.getTypeChecker().resolveName( node.text, node, SymbolFlags.All, From f80483c329462041facc4fbacf1a809cf3ce8ae5 Mon Sep 17 00:00:00 2001 From: navya9singh Date: Fri, 16 Aug 2024 10:16:17 -0700 Subject: [PATCH 18/19] adding test for `updatedProgram` change --- src/services/pasteEdits.ts | 12 +- ...steEdits_noImportNeededInUpdatedProgram.js | 276 ++++++++++++++++++ ...steEdits_noImportNeededInUpdatedProgram.ts | 21 ++ 3 files changed, 303 insertions(+), 6 deletions(-) create mode 100644 tests/baselines/reference/tsserver/fourslashServer/pasteEdits_noImportNeededInUpdatedProgram.js create mode 100644 tests/cases/fourslash/server/pasteEdits_noImportNeededInUpdatedProgram.ts diff --git a/src/services/pasteEdits.ts b/src/services/pasteEdits.ts index b3e0cedb50eeb..d3c84b118aa8e 100644 --- a/src/services/pasteEdits.ts +++ b/src/services/pasteEdits.ts @@ -7,6 +7,7 @@ import { findIndex, forEachChild, formatting, + getNewLineOrDefaultFromHost, getQuotePreference, getTokenAtPosition, isIdentifier, @@ -60,16 +61,16 @@ function pasteEdits( cancellationToken: CancellationToken, changes: textChanges.ChangeTracker, ) { - let actualPastedText: string[] | undefined; + let actualPastedText: string | undefined; if (pastedText.length !== pasteLocations.length) { - actualPastedText = pastedText.length === 1 ? pastedText : [pastedText.join("\n")]; + actualPastedText = pastedText.length === 1 ? pastedText[0] : pastedText.join(getNewLineOrDefaultFromHost(formatContext.host, formatContext.options)); } const statements: Statement[] = []; let newText = targetFile.text; for (let i = pasteLocations.length - 1; i >= 0; i--) { const { pos, end } = pasteLocations[i]; - newText = actualPastedText ? newText.slice(0, pos) + actualPastedText[0] + newText.slice(end) : newText.slice(0, pos) + pastedText[i] + newText.slice(end); + newText = actualPastedText ? newText.slice(0, pos) + actualPastedText + newText.slice(end) : newText.slice(0, pos) + pastedText[i] + newText.slice(end); } let importAdder: codefix.ImportAdder; @@ -117,7 +118,7 @@ function pasteEdits( let offset = 0; pasteLocations.forEach((location, i) => { const oldTextLength = location.end - location.pos; - const textToBePasted = actualPastedText ? actualPastedText[0] : pastedText[i]; + const textToBePasted = actualPastedText ?? pastedText[i]; const startPos = location.pos + offset; const endPos = startPos + textToBePasted.length; const range: TextRange = { pos: startPos, end: endPos }; @@ -162,8 +163,7 @@ function pasteEdits( changes.replaceRangeWithText( targetFile, { pos: paste.pos, end: paste.end }, - actualPastedText ? - actualPastedText[0] : pastedText[i], + actualPastedText ?? pastedText[i], ); }); } diff --git a/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_noImportNeededInUpdatedProgram.js b/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_noImportNeededInUpdatedProgram.js new file mode 100644 index 0000000000000..8737891440e7c --- /dev/null +++ b/tests/baselines/reference/tsserver/fourslashServer/pasteEdits_noImportNeededInUpdatedProgram.js @@ -0,0 +1,276 @@ +currentDirectory:: / useCaseSensitiveFileNames: false +Info seq [hh:mm:ss:mss] Provided types map file "/typesMap.json" doesn't exist +//// [/a.ts] + + +//// [/b.ts] +export const b = 10; + +//// [/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": "/a.ts" + }, + "command": "open" + } +Info seq [hh:mm:ss:mss] getConfigFileNameForFile:: File: /a.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 /a.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: /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 (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 SVC-1-0 "" + /b.ts Text-1 "export const b = 10;" + + + 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": "/a.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: /a.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:: +/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 (Open) *new* + version: SVC-1-0 + containingProjects: 1 + /tsconfig.json *default* +/b.ts *new* + version: Text-1 + containingProjects: 1 + /tsconfig.json +/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": "/a.ts", + "pastedText": [ + "const b = 1;\nconsole.log(b);" + ], + "pasteLocations": [ + { + "start": { + "line": 1, + "offset": 1 + }, + "end": { + "line": 1, + "offset": 1 + } + } + ] + }, + "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 SVC-1-1 "const b = 1;\nconsole.log(b);" + /b.ts Text-1 "export const b = 10;" + +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": [], + "fixId": "providePostPasteEdits" + } + } +After Request +Projects:: +/tsconfig.json (Configured) *changed* + projectStateVersion: 3 *changed* + projectProgramVersion: 1 + dirty: true *changed* + +ScriptInfos:: +/a.ts (Open) *changed* + version: SVC-1-2 *changed* + containingProjects: 1 + /tsconfig.json *default* +/b.ts + version: Text-1 + containingProjects: 1 + /tsconfig.json +/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_noImportNeededInUpdatedProgram.ts b/tests/cases/fourslash/server/pasteEdits_noImportNeededInUpdatedProgram.ts new file mode 100644 index 0000000000000..e9928a6c3489e --- /dev/null +++ b/tests/cases/fourslash/server/pasteEdits_noImportNeededInUpdatedProgram.ts @@ -0,0 +1,21 @@ +/// + +// @Filename: /a.ts +//// [||] + +// @Filename: /b.ts +//// export const b = 10; + +// @Filename: /tsconfig.json +////{ "files": ["a.ts", "b.ts"] } + +const range = test.ranges(); +verify.pasteEdits({ + args: { + pastedText: [ + `const b = 1; +console.log(b);`], + pasteLocations: [range[0]], + }, + newFileContents: {} +}); From 65490bf89d0aa5abf96b82ea4131fd5c08a82357 Mon Sep 17 00:00:00 2001 From: navya9singh Date: Fri, 16 Aug 2024 14:37:27 -0700 Subject: [PATCH 19/19] fixing small errors --- tests/cases/fourslash/server/pasteEdits_addInNextLine.ts | 6 +++--- tests/cases/fourslash/server/pasteEdits_blankTargetFile.ts | 6 +++--- .../cases/fourslash/server/pasteEdits_existingImports1.ts | 3 +-- .../cases/fourslash/server/pasteEdits_existingImports2.ts | 6 +++--- tests/cases/fourslash/server/pasteEdits_knownSourceFile.ts | 7 +++---- tests/cases/fourslash/server/pasteEdits_multiplePastes1.ts | 4 ++-- tests/cases/fourslash/server/pasteEdits_multiplePastes2.ts | 6 +++--- tests/cases/fourslash/server/pasteEdits_multiplePastes3.ts | 6 +++--- tests/cases/fourslash/server/pasteEdits_multiplePastes4.ts | 4 ++-- tests/cases/fourslash/server/pasteEdits_noImportNeeded.ts | 6 +++--- .../server/pasteEdits_noImportNeededInUpdatedProgram.ts | 3 +-- tests/cases/fourslash/server/pasteEdits_pasteComments.ts | 3 +-- .../cases/fourslash/server/pasteEdits_pasteIntoSameFile.ts | 6 +++--- .../cases/fourslash/server/pasteEdits_revertUpdatedFile.ts | 3 +-- .../cases/fourslash/server/pasteEdits_unknownSourceFile.ts | 3 +-- 15 files changed, 33 insertions(+), 39 deletions(-) diff --git a/tests/cases/fourslash/server/pasteEdits_addInNextLine.ts b/tests/cases/fourslash/server/pasteEdits_addInNextLine.ts index ce3919b85c3f3..293840d052d10 100644 --- a/tests/cases/fourslash/server/pasteEdits_addInNextLine.ts +++ b/tests/cases/fourslash/server/pasteEdits_addInNextLine.ts @@ -18,12 +18,12 @@ // @Filename: /tsconfig.json ////{ "files": ["a.ts", "b.ts"] } -const range = test.ranges(); +const ranges = test.ranges(); verify.pasteEdits({ args: { pastedText: [`export const foo: Foo = {};`], - pasteLocations: [range[0]], - copiedFrom: { file: "b.ts", range: [range[1]] }, + pasteLocations: [ranges[0]], + copiedFrom: { file: "b.ts", range: [ranges[1]] }, }, newFileContents: { "/a.ts": diff --git a/tests/cases/fourslash/server/pasteEdits_blankTargetFile.ts b/tests/cases/fourslash/server/pasteEdits_blankTargetFile.ts index d4fd49c285960..f9361a4163d10 100644 --- a/tests/cases/fourslash/server/pasteEdits_blankTargetFile.ts +++ b/tests/cases/fourslash/server/pasteEdits_blankTargetFile.ts @@ -17,12 +17,12 @@ // @Filename: /tsconfig.json ////{ "files": ["c.ts", "a.ts", "b.ts"] } -const range = test.ranges(); +const ranges = test.ranges(); verify.pasteEdits({ args: { pastedText: [`console.log(abc);`], - pasteLocations: [range[0]], - copiedFrom: { file: "b.ts", range: [range[1]] }, + pasteLocations: [ranges[0]], + copiedFrom: { file: "b.ts", range: [ranges[1]] }, }, newFileContents: { "/c.ts": diff --git a/tests/cases/fourslash/server/pasteEdits_existingImports1.ts b/tests/cases/fourslash/server/pasteEdits_existingImports1.ts index 204d6bb0c8186..8141d9230d68d 100644 --- a/tests/cases/fourslash/server/pasteEdits_existingImports1.ts +++ b/tests/cases/fourslash/server/pasteEdits_existingImports1.ts @@ -19,11 +19,10 @@ // @Filename: /tsconfig.json ////{ "files": ["target.ts", "other.ts", "other2.ts", "other3.ts"] } -const range = test.ranges(); verify.pasteEdits({ args: { pastedText: [ `const m = t3 + t2 + 1;`], - pasteLocations: [range[0]], + pasteLocations: test.ranges(), }, newFileContents: { "/target.ts": diff --git a/tests/cases/fourslash/server/pasteEdits_existingImports2.ts b/tests/cases/fourslash/server/pasteEdits_existingImports2.ts index e12fe6350dbc0..d27ffb415609c 100644 --- a/tests/cases/fourslash/server/pasteEdits_existingImports2.ts +++ b/tests/cases/fourslash/server/pasteEdits_existingImports2.ts @@ -25,12 +25,12 @@ // @Filename: /tsconfig.json ////{ "files": ["target.ts", "originalFile.ts", "other.ts", "other2.ts", "other3.ts"] } -const range = test.ranges(); +const ranges = test.ranges(); verify.pasteEdits({ args: { pastedText: [ `const m = t3 + t2 + n;` ], - pasteLocations: [range[0]], - copiedFrom: { file: "originalFile.ts", range: [range[1]] }, + pasteLocations: [ranges[0]], + copiedFrom: { file: "originalFile.ts", range: [ranges[1]] }, }, newFileContents: { "/target.ts": diff --git a/tests/cases/fourslash/server/pasteEdits_knownSourceFile.ts b/tests/cases/fourslash/server/pasteEdits_knownSourceFile.ts index fe9023647fb0a..eb66aad510909 100644 --- a/tests/cases/fourslash/server/pasteEdits_knownSourceFile.ts +++ b/tests/cases/fourslash/server/pasteEdits_knownSourceFile.ts @@ -17,14 +17,13 @@ // @Filename: /tsconfig.json ////{ "files": ["file1.ts", "file2.ts", "target.ts"] } -const range = test.ranges(); -const t = range[0]; +const ranges = test.ranges(); verify.pasteEdits({ args: { pastedText: [ `const c = a + b; const t = 9;`], - pasteLocations: [range[0]], - copiedFrom: { file: "file2.ts", range: [range[1]] }, + pasteLocations: [ranges[0]], + copiedFrom: { file: "file2.ts", range: [ranges[1]] }, }, newFileContents: { "/file2.ts": diff --git a/tests/cases/fourslash/server/pasteEdits_multiplePastes1.ts b/tests/cases/fourslash/server/pasteEdits_multiplePastes1.ts index 5b0e9f5bfbfdb..4751a721a412c 100644 --- a/tests/cases/fourslash/server/pasteEdits_multiplePastes1.ts +++ b/tests/cases/fourslash/server/pasteEdits_multiplePastes1.ts @@ -19,13 +19,13 @@ // @Filename: /tsconfig.json ////{ "files": ["file1.ts", "target.ts", "file3.ts"] } -const range = test.ranges(); +const ranges = test.ranges(); verify.pasteEdits({ args: { pastedText: [ `const g = p + q; function e(); const f = r + s;`], - pasteLocations: [range[0], range[1]], + pasteLocations: [ranges[0], ranges[1]], }, newFileContents: { "/target.ts": diff --git a/tests/cases/fourslash/server/pasteEdits_multiplePastes2.ts b/tests/cases/fourslash/server/pasteEdits_multiplePastes2.ts index 71de5ac278f4e..4c46fc7413323 100644 --- a/tests/cases/fourslash/server/pasteEdits_multiplePastes2.ts +++ b/tests/cases/fourslash/server/pasteEdits_multiplePastes2.ts @@ -21,13 +21,13 @@ // @Filename: /tsconfig.json ////{ "files": ["file1.ts", "target.ts", "other.ts"] } -const range = test.ranges(); +const ranges = test.ranges(); verify.pasteEdits({ args: { pastedText: [ `export const t = aa + bb + r + s; const u = 1;`,], - pasteLocations: [range[0], range[1]], - copiedFrom: { file: "file1.ts", range: [range[2]] }, + pasteLocations: [ranges[0], ranges[1]], + copiedFrom: { file: "file1.ts", range: [ranges[2]] }, }, newFileContents: { "/target.ts": diff --git a/tests/cases/fourslash/server/pasteEdits_multiplePastes3.ts b/tests/cases/fourslash/server/pasteEdits_multiplePastes3.ts index 99b5451eb319f..f5233e9396576 100644 --- a/tests/cases/fourslash/server/pasteEdits_multiplePastes3.ts +++ b/tests/cases/fourslash/server/pasteEdits_multiplePastes3.ts @@ -24,13 +24,13 @@ // @Filename: /tsconfig.json ////{ "files": ["file1.ts", "target.ts", "other.ts"] } -const range = test.ranges(); +const ranges = test.ranges(); verify.pasteEdits({ args: { pastedText: [ `export const t = aa + bb + r + s; const u = 1;`, `export const k = r + m;`], - pasteLocations: [range[0], range[1]], - copiedFrom: { file: "file1.ts", range: [range[2], range[3]] }, + pasteLocations: [ranges[0], ranges[1]], + copiedFrom: { file: "file1.ts", range: [ranges[2], ranges[3]] }, }, newFileContents: { "/file1.ts":`import { aa, bb } from "./other"; diff --git a/tests/cases/fourslash/server/pasteEdits_multiplePastes4.ts b/tests/cases/fourslash/server/pasteEdits_multiplePastes4.ts index 61d25803abd3d..84ed288aa4840 100644 --- a/tests/cases/fourslash/server/pasteEdits_multiplePastes4.ts +++ b/tests/cases/fourslash/server/pasteEdits_multiplePastes4.ts @@ -19,11 +19,11 @@ // @Filename: /tsconfig.json ////{ "files": ["file1.ts", "target.ts", "file3.ts"] } -const range = test.ranges(); +const ranges = test.ranges(); verify.pasteEdits({ args: { pastedText: [ "const g = p + q;", "const f = r + s;"], - pasteLocations: [range[0], range[1], range[2]], + pasteLocations: [ranges[0], ranges[1], ranges[2]], }, newFileContents: { "/target.ts": diff --git a/tests/cases/fourslash/server/pasteEdits_noImportNeeded.ts b/tests/cases/fourslash/server/pasteEdits_noImportNeeded.ts index 156386a86ac7a..01f18bb50ceab 100644 --- a/tests/cases/fourslash/server/pasteEdits_noImportNeeded.ts +++ b/tests/cases/fourslash/server/pasteEdits_noImportNeeded.ts @@ -11,12 +11,12 @@ // @Filename: /tsconfig.json ////{ "files": ["a.ts", "b.ts"] } -const range = test.ranges(); +const ranges = test.ranges(); verify.pasteEdits({ args: { pastedText: [`export`], - pasteLocations: [range[0]], - copiedFrom: { file: "a.ts", range: [range[1]] }, + pasteLocations: [ranges[0]], + copiedFrom: { file: "a.ts", range: [ranges[1]] }, }, newFileContents: {} }); diff --git a/tests/cases/fourslash/server/pasteEdits_noImportNeededInUpdatedProgram.ts b/tests/cases/fourslash/server/pasteEdits_noImportNeededInUpdatedProgram.ts index e9928a6c3489e..529780843d504 100644 --- a/tests/cases/fourslash/server/pasteEdits_noImportNeededInUpdatedProgram.ts +++ b/tests/cases/fourslash/server/pasteEdits_noImportNeededInUpdatedProgram.ts @@ -9,13 +9,12 @@ // @Filename: /tsconfig.json ////{ "files": ["a.ts", "b.ts"] } -const range = test.ranges(); verify.pasteEdits({ args: { pastedText: [ `const b = 1; console.log(b);`], - pasteLocations: [range[0]], + pasteLocations: test.ranges(), }, newFileContents: {} }); diff --git a/tests/cases/fourslash/server/pasteEdits_pasteComments.ts b/tests/cases/fourslash/server/pasteEdits_pasteComments.ts index aa2d9ba943f26..eba7aca24666b 100644 --- a/tests/cases/fourslash/server/pasteEdits_pasteComments.ts +++ b/tests/cases/fourslash/server/pasteEdits_pasteComments.ts @@ -8,7 +8,6 @@ // @Filename: /tsconfig.json ////{ "files": ["target.ts"] } -const range = test.ranges(); verify.pasteEdits({ args: { pastedText: [ `/** @@ -17,7 +16,7 @@ verify.pasteEdits({ * line 3 * line 4 */`], - pasteLocations: [range[0]], + pasteLocations: test.ranges(), }, 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 06bedadcd1724..466c0b1ddbe2c 100644 --- a/tests/cases/fourslash/server/pasteEdits_pasteIntoSameFile.ts +++ b/tests/cases/fourslash/server/pasteEdits_pasteIntoSameFile.ts @@ -10,12 +10,12 @@ // @Filename: /tsconfig.json ////{ "files": ["target.ts"] } -const range = test.ranges(); +const ranges = test.ranges(); verify.pasteEdits({ args: { pastedText: [ `console.log(k);`], - pasteLocations: [range[1]], - copiedFrom: { file: "target.ts", range: [range[0]] }, + pasteLocations: [ranges[1]], + copiedFrom: { file: "target.ts", range: [ranges[0]] }, }, newFileContents: {} }); diff --git a/tests/cases/fourslash/server/pasteEdits_revertUpdatedFile.ts b/tests/cases/fourslash/server/pasteEdits_revertUpdatedFile.ts index fbe0e77ef2f99..8bb485b699540 100644 --- a/tests/cases/fourslash/server/pasteEdits_revertUpdatedFile.ts +++ b/tests/cases/fourslash/server/pasteEdits_revertUpdatedFile.ts @@ -17,11 +17,10 @@ // @Filename: /tsconfig.json ////{ "files": ["target.ts", "other.ts", "other2.ts"] } -const range = test.ranges(); verify.pasteEdits({ args: { pastedText: [ `const m = t2 + 1;`], - pasteLocations: [range[0]], + pasteLocations: test.ranges(), }, newFileContents: { "/target.ts": diff --git a/tests/cases/fourslash/server/pasteEdits_unknownSourceFile.ts b/tests/cases/fourslash/server/pasteEdits_unknownSourceFile.ts index afd370f875a74..ac77ec6527c44 100644 --- a/tests/cases/fourslash/server/pasteEdits_unknownSourceFile.ts +++ b/tests/cases/fourslash/server/pasteEdits_unknownSourceFile.ts @@ -14,7 +14,6 @@ // @Filename: /tsconfig.json ////{ "files": ["file1.ts", "file2.ts"] } -const range = test.ranges(); verify.pasteEdits({ args: { pastedText: [ `interface Testing { @@ -23,7 +22,7 @@ verify.pasteEdits({ test3: Test3; test4: Test4; }`], - pasteLocations: [range[0]], + pasteLocations: test.ranges(), }, newFileContents: { "/file2.ts":