mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
All tsserver unittests use session and typing installer (#56337)
This commit is contained in:
@@ -6,7 +6,7 @@ import * as Utils from "./_namespaces/Utils";
|
||||
import * as vfs from "./_namespaces/vfs";
|
||||
import * as vpath from "./_namespaces/vpath";
|
||||
import {
|
||||
Logger,
|
||||
LoggerWithInMemoryLogs,
|
||||
} from "./tsserverLogger";
|
||||
|
||||
import ArrayOrSingle = FourSlashInterface.ArrayOrSingle;
|
||||
@@ -259,7 +259,7 @@ export class TestState {
|
||||
|
||||
private inputFiles = new Map<string, string>(); // Map between inputFile's fileName and its content for easily looking up when resolving references
|
||||
|
||||
private logger: Logger | undefined;
|
||||
private logger: LoggerWithInMemoryLogs | undefined;
|
||||
|
||||
private static getDisplayPartsJson(displayParts: ts.SymbolDisplayPart[] | undefined) {
|
||||
let result = "";
|
||||
@@ -519,7 +519,7 @@ export class TestState {
|
||||
if (this.logger) {
|
||||
Harness.Baseline.runBaseline(
|
||||
`tsserver/fourslashServer/${ts.getBaseFileName(this.originalInputFileName).replace(".ts", ".js")}`,
|
||||
this.logger.logs!.join("\n"),
|
||||
this.logger.logs.join("\n"),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
HarnessLSCouldNotResolveModule,
|
||||
Logger,
|
||||
LoggerWithInMemoryLogs,
|
||||
} from "./tsserverLogger";
|
||||
import {
|
||||
createWatchUtils,
|
||||
@@ -130,7 +130,7 @@ export interface LanguageServiceAdapter {
|
||||
getLanguageService(): ts.LanguageService;
|
||||
getClassifier(): ts.Classifier;
|
||||
getPreProcessedFileInfo(fileName: string, fileContents: string): ts.PreProcessedFileInfo;
|
||||
getLogger(): Logger | undefined;
|
||||
getLogger(): LoggerWithInMemoryLogs | undefined;
|
||||
}
|
||||
|
||||
export abstract class LanguageServiceAdapterHost {
|
||||
@@ -611,7 +611,7 @@ export class ServerLanguageServiceAdapter implements LanguageServiceAdapter {
|
||||
private host: SessionClientHost;
|
||||
private client: ts.server.SessionClient;
|
||||
private server: FourslashSession;
|
||||
private logger: Logger;
|
||||
private logger: LoggerWithInMemoryLogs;
|
||||
constructor(cancellationToken?: ts.HostCancellationToken, options?: ts.CompilerOptions) {
|
||||
// This is the main host that tests use to direct tests
|
||||
const clientHost = new SessionClientHost(cancellationToken, options);
|
||||
|
||||
@@ -431,6 +431,7 @@ function verifyProgram(service: ts.server.ProjectService, project: ts.server.Pro
|
||||
const getDefaultLibLocation = compilerHost.getDefaultLibLocation!;
|
||||
compilerHost.getDefaultLibLocation = () => ts.getNormalizedAbsolutePath(getDefaultLibLocation(), service.host.getCurrentDirectory());
|
||||
compilerHost.getDefaultLibFileName = options => ts.combinePaths(compilerHost.getDefaultLibLocation!(), ts.getDefaultLibFileName(options));
|
||||
compilerHost.trace = ts.noop; // We dont want to update host just because of trace
|
||||
const readFile = compilerHost.readFile;
|
||||
compilerHost.readFile = fileName => {
|
||||
const path = project.toPath(fileName);
|
||||
|
||||
@@ -50,12 +50,16 @@ export function nullLogger(): Logger {
|
||||
}
|
||||
|
||||
export function createHasErrorMessageLogger(): Logger {
|
||||
return {
|
||||
...nullLogger(),
|
||||
msg: (s, type) => ts.Debug.fail(`Error: ${s}, type: ${type}`),
|
||||
};
|
||||
const logger = nullLogger();
|
||||
logger.msg = (s, type) => ts.Debug.fail(`Error: ${s}, type: ${type}`);
|
||||
return logger;
|
||||
}
|
||||
function handleLoggerGroup(logger: Logger): Logger {
|
||||
function handleLoggerGroup(logger: Logger, host: ts.server.ServerHost, logText: (s: string) => void, sanitizeLibs: true | undefined): Logger {
|
||||
logger.hasLevel = ts.returnTrue;
|
||||
logger.loggingEnabled = ts.returnTrue;
|
||||
logger.host = host;
|
||||
if (host) logText(`currentDirectory:: ${host.getCurrentDirectory()} useCaseSensitiveFileNames: ${host.useCaseSensitiveFileNames}`);
|
||||
|
||||
let inGroup = false;
|
||||
let firstInGroup = false;
|
||||
logger.startGroup = () => {
|
||||
@@ -63,11 +67,14 @@ function handleLoggerGroup(logger: Logger): Logger {
|
||||
firstInGroup = true;
|
||||
};
|
||||
logger.endGroup = () => inGroup = false;
|
||||
const originalInfo = logger.info;
|
||||
logger.info = s => msg(s, ts.server.Msg.Info, s => originalInfo.call(logger, s));
|
||||
logger.log = s => originalInfo.call(logger, s);
|
||||
logger.info = s => msg(s, ts.server.Msg.Info, log);
|
||||
logger.log = log;
|
||||
return logger;
|
||||
|
||||
function log(s: string) {
|
||||
logText((sanitizeLibs ? sanitizeLibFileText : ts.identity)(sanitizeLog(s)));
|
||||
}
|
||||
|
||||
function msg(s: string, type = ts.server.Msg.Err, write: (s: string) => void) {
|
||||
s = `[${nowString(logger)}] ${s}`;
|
||||
if (!inGroup || firstInGroup) s = padStringRight(type + " seq", " ") + s;
|
||||
@@ -86,16 +93,19 @@ export function nowString(logger: Logger) {
|
||||
return `hh:mm:ss:mss`;
|
||||
}
|
||||
|
||||
export function createLoggerWritingToConsole(host: ts.server.ServerHost) {
|
||||
return handleLoggerGroup({
|
||||
...nullLogger(),
|
||||
hasLevel: ts.returnTrue,
|
||||
loggingEnabled: ts.returnTrue,
|
||||
perftrc: s => console.log(s),
|
||||
info: s => console.log(s),
|
||||
msg: (s, type) => console.log(`${type}:: ${s}`),
|
||||
export function createLoggerWritingToConsole(host: ts.server.ServerHost, sanitizeLibs?: true) {
|
||||
const logger = createHasErrorMessageLogger();
|
||||
logger.logs = [];
|
||||
logger.logs.push = (...args) => {
|
||||
args.forEach(s => console.log(s));
|
||||
return 0;
|
||||
};
|
||||
return handleLoggerGroup(
|
||||
logger,
|
||||
host,
|
||||
});
|
||||
s => console.log(s),
|
||||
sanitizeLibs,
|
||||
) as LoggerWithInMemoryLogs;
|
||||
}
|
||||
|
||||
export function sanitizeLog(s: string): string {
|
||||
@@ -117,6 +127,7 @@ export function sanitizeLog(s: string): string {
|
||||
s = s.replace(/"exportMapKey":\s*"\d+ \d+ /g, match => match.replace(/ \d+ /, ` * `));
|
||||
s = s.replace(/getIndentationAtPosition: getCurrentSourceFile: \d+(?:\.\d+)?/, `getIndentationAtPosition: getCurrentSourceFile: *`);
|
||||
s = s.replace(/getIndentationAtPosition: computeIndentation\s*: \d+(?:\.\d+)?/, `getIndentationAtPosition: computeIndentation: *`);
|
||||
s = replaceAll(s, `@ts${ts.versionMajorMinor}`, `@tsFakeMajor.Minor`);
|
||||
s = sanitizeHarnessLSException(s);
|
||||
return s;
|
||||
}
|
||||
@@ -135,16 +146,12 @@ export function sanitizeLibFileText(s: string): string {
|
||||
return s;
|
||||
}
|
||||
|
||||
export function createLoggerWithInMemoryLogs(host: ts.server.ServerHost, sanitizeLibs?: true): Logger {
|
||||
const logger = createHasErrorMessageLogger();
|
||||
const logs: string[] = [];
|
||||
if (host) logs.push(`currentDirectory:: ${host.getCurrentDirectory()} useCaseSensitiveFileNames: ${host.useCaseSensitiveFileNames}`);
|
||||
return handleLoggerGroup({
|
||||
...logger,
|
||||
logs,
|
||||
hasLevel: ts.returnTrue,
|
||||
loggingEnabled: ts.returnTrue,
|
||||
info: s => logs.push((sanitizeLibs ? sanitizeLibFileText : ts.identity)(sanitizeLog(s))),
|
||||
host,
|
||||
});
|
||||
export interface LoggerWithInMemoryLogs extends Logger {
|
||||
logs: string[];
|
||||
}
|
||||
|
||||
export function createLoggerWithInMemoryLogs(host: ts.server.ServerHost, sanitizeLibs?: true): LoggerWithInMemoryLogs {
|
||||
const logger = createHasErrorMessageLogger();
|
||||
logger.logs = [];
|
||||
return handleLoggerGroup(logger, host, s => logger.logs!.push(s), sanitizeLibs) as LoggerWithInMemoryLogs;
|
||||
}
|
||||
|
||||
@@ -1131,9 +1131,10 @@ export class Session<TMessage = string> implements EventSender {
|
||||
}
|
||||
|
||||
private projectsUpdatedInBackgroundEvent(openFiles: string[]): void {
|
||||
this.projectService.logger.info(`got projects updated in background, updating diagnostics for ${openFiles}`);
|
||||
this.projectService.logger.info(`got projects updated in background ${openFiles}`);
|
||||
if (openFiles.length) {
|
||||
if (!this.suppressDiagnosticEvents && !this.noGetErrOnBackgroundUpdate) {
|
||||
this.projectService.logger.info(`Queueing diagnostics update for ${openFiles}`);
|
||||
// For now only queue error checking for open files. We can change this to include non open files as well
|
||||
this.errorCheck.startNew(next => this.updateErrorCheck(next, openFiles, 100, /*requireOpen*/ true));
|
||||
}
|
||||
@@ -1193,7 +1194,7 @@ export class Session<TMessage = string> implements EventSender {
|
||||
public send(msg: protocol.Message) {
|
||||
if (msg.type === "event" && !this.canUseEvents) {
|
||||
if (this.logger.hasLevel(LogLevel.verbose)) {
|
||||
this.logger.info(`Session does not support events: ignored event: ${JSON.stringify(msg)}`);
|
||||
this.logger.info(`Session does not support events: ignored event: ${stringifyIndented(msg)}`);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ import {
|
||||
import {
|
||||
changeToHostTrackingWrittenFiles,
|
||||
File,
|
||||
SerializeOutputOrder,
|
||||
StateLogger,
|
||||
TestServerHost,
|
||||
TestServerHostTrackingWrittenFiles,
|
||||
} from "./virtualFileSystemWithWatch";
|
||||
@@ -63,13 +65,12 @@ export interface TscWatchCompile extends TscWatchCompileBase {
|
||||
export const noopChange: TscWatchCompileChange = {
|
||||
caption: "No change",
|
||||
edit: ts.noop,
|
||||
timeouts: sys => sys.logTimeoutQueueLength(),
|
||||
timeouts: ts.noop,
|
||||
};
|
||||
|
||||
export type SystemSnap = ReturnType<TestServerHost["snap"]>;
|
||||
function tscWatchCompile(input: TscWatchCompile) {
|
||||
it("tsc-watch:: Generates files matching the baseline", () => {
|
||||
const { sys, baseline, oldSnap } = createBaseline(input.sys());
|
||||
const { sys, baseline } = createBaseline(input.sys());
|
||||
const {
|
||||
scenario,
|
||||
subScenario,
|
||||
@@ -92,7 +93,6 @@ function tscWatchCompile(input: TscWatchCompile) {
|
||||
commandLineArgs,
|
||||
sys,
|
||||
baseline,
|
||||
oldSnap,
|
||||
getPrograms,
|
||||
baselineSourceMap,
|
||||
baselineDependencies,
|
||||
@@ -102,44 +102,21 @@ function tscWatchCompile(input: TscWatchCompile) {
|
||||
});
|
||||
}
|
||||
|
||||
export interface TestServerHostWithTimeoutLogging {
|
||||
logTimeoutQueueLength(): void;
|
||||
}
|
||||
export type TscWatchSystem = TestServerHostTrackingWrittenFiles;
|
||||
|
||||
export type TscWatchSystem = TestServerHostTrackingWrittenFiles & TestServerHostWithTimeoutLogging;
|
||||
|
||||
function changeToTestServerHostWithTimeoutLogging(inputHost: TestServerHostTrackingWrittenFiles, baseline: string[]): TscWatchSystem {
|
||||
const host = inputHost as TscWatchSystem;
|
||||
const originalRunQueuedTimeoutCallbacks = host.runQueuedTimeoutCallbacks;
|
||||
const originalRunQueuedImmediateCallbacks = host.runQueuedImmediateCallbacks;
|
||||
host.runQueuedTimeoutCallbacks = runQueuedTimeoutCallbacks;
|
||||
host.runQueuedImmediateCallbacks = runQueuedImmediateCallbacks;
|
||||
host.logTimeoutQueueLength = logTimeoutQueueLength;
|
||||
function changeToTestServerHostWithTimeoutLogging(host: TestServerHostTrackingWrittenFiles, baseline: string[]): TscWatchSystem {
|
||||
const logger: StateLogger = {
|
||||
log: s => baseline.push(s),
|
||||
logs: baseline,
|
||||
};
|
||||
host.timeoutCallbacks.switchToBaseliningInvoke(logger, SerializeOutputOrder.BeforeDiff);
|
||||
host.immediateCallbacks.switchToBaseliningInvoke(logger, SerializeOutputOrder.BeforeDiff);
|
||||
return host;
|
||||
|
||||
function logTimeoutQueueLength() {
|
||||
baseline.push(host.timeoutCallbacks.log());
|
||||
baseline.push(host.immediateCallbacks.log());
|
||||
}
|
||||
|
||||
function runQueuedTimeoutCallbacks(timeoutId?: number) {
|
||||
baseline.push(`Before running ${host.timeoutCallbacks.log()}`);
|
||||
if (timeoutId !== undefined) baseline.push(`Invoking ${host.timeoutCallbacks.callbackType} callback:: timeoutId:: ${timeoutId}:: ${host.timeoutCallbacks.map[timeoutId].args[0]}`);
|
||||
originalRunQueuedTimeoutCallbacks.call(host, timeoutId);
|
||||
baseline.push(`After running ${host.timeoutCallbacks.log()}`);
|
||||
}
|
||||
|
||||
function runQueuedImmediateCallbacks() {
|
||||
baseline.push(`Before running ${host.immediateCallbacks.log()}`);
|
||||
originalRunQueuedImmediateCallbacks.call(host);
|
||||
baseline.push(`After running ${host.immediateCallbacks.log()}`);
|
||||
}
|
||||
}
|
||||
|
||||
export interface BaselineBase {
|
||||
baseline: string[];
|
||||
sys: TscWatchSystem;
|
||||
oldSnap: SystemSnap;
|
||||
}
|
||||
|
||||
export interface Baseline extends BaselineBase, CommandLineCallbacks {
|
||||
@@ -153,9 +130,9 @@ export function createBaseline(system: TestServerHost, modifySystem?: (sys: Test
|
||||
const sys = changeToTestServerHostWithTimeoutLogging(changeToHostTrackingWrittenFiles(initialSys), baseline);
|
||||
baseline.push(`currentDirectory:: ${sys.getCurrentDirectory()} useCaseSensitiveFileNames: ${sys.useCaseSensitiveFileNames}`);
|
||||
baseline.push("Input::");
|
||||
sys.diff(baseline);
|
||||
sys.serializeState(baseline, SerializeOutputOrder.None);
|
||||
const { cb, getPrograms } = commandLineCallbacks(sys);
|
||||
return { sys, baseline, oldSnap: sys.snap(), cb, getPrograms };
|
||||
return { sys, baseline, cb, getPrograms };
|
||||
}
|
||||
|
||||
export function createSolutionBuilderWithWatchHostForBaseline(sys: TestServerHost, cb: ts.ExecuteCommandLineCallbacks) {
|
||||
@@ -208,13 +185,10 @@ function updateWatchHostForBaseline<T extends ts.BuilderProgram>(host: ts.WatchC
|
||||
}
|
||||
|
||||
export function applyEdit(sys: BaselineBase["sys"], baseline: BaselineBase["baseline"], edit: TscWatchCompileChange["edit"], caption?: TscWatchCompileChange["caption"]) {
|
||||
const oldSnap = sys.snap();
|
||||
baseline.push(`Change::${caption ? " " + caption : ""}`, "");
|
||||
edit(sys);
|
||||
baseline.push("Input::");
|
||||
sys.diff(baseline, oldSnap);
|
||||
sys.serializeWatches(baseline);
|
||||
return sys.snap();
|
||||
sys.serializeState(baseline, SerializeOutputOrder.AfterDiff);
|
||||
}
|
||||
|
||||
export interface RunWatchBaseline<T extends ts.BuilderProgram> extends BaselineBase, TscWatchCompileBase<T> {
|
||||
@@ -230,7 +204,6 @@ export function runWatchBaseline<T extends ts.BuilderProgram = ts.EmitAndSemanti
|
||||
getPrograms,
|
||||
sys,
|
||||
baseline,
|
||||
oldSnap,
|
||||
baselineSourceMap,
|
||||
baselineDependencies,
|
||||
edits,
|
||||
@@ -243,21 +216,19 @@ export function runWatchBaseline<T extends ts.BuilderProgram = ts.EmitAndSemanti
|
||||
getPrograms,
|
||||
oldPrograms: ts.emptyArray,
|
||||
sys,
|
||||
oldSnap,
|
||||
baselineSourceMap,
|
||||
baselineDependencies,
|
||||
});
|
||||
|
||||
if (edits) {
|
||||
for (const { caption, edit, timeouts, symlinksNotReflected, skipStructureCheck } of edits) {
|
||||
oldSnap = applyEdit(sys, baseline, edit, caption);
|
||||
applyEdit(sys, baseline, edit, caption);
|
||||
timeouts(sys, programs, watchOrSolution);
|
||||
programs = watchBaseline({
|
||||
baseline,
|
||||
getPrograms,
|
||||
oldPrograms: programs,
|
||||
sys,
|
||||
oldSnap,
|
||||
baselineSourceMap,
|
||||
baselineDependencies,
|
||||
caption,
|
||||
@@ -291,7 +262,6 @@ export function watchBaseline({
|
||||
getPrograms,
|
||||
oldPrograms,
|
||||
sys,
|
||||
oldSnap,
|
||||
baselineSourceMap,
|
||||
baselineDependencies,
|
||||
caption,
|
||||
@@ -300,21 +270,18 @@ export function watchBaseline({
|
||||
symlinksNotReflected,
|
||||
}: WatchBaseline) {
|
||||
if (baselineSourceMap) generateSourceMapBaselineFiles(sys);
|
||||
sys.serializeOutput(baseline);
|
||||
const programs = getPrograms();
|
||||
baselinePrograms(baseline, programs, oldPrograms, baselineDependencies);
|
||||
sys.serializeWatches(baseline);
|
||||
baseline.push(`exitCode:: ExitStatus.${ts.ExitStatus[sys.exitCode as ts.ExitStatus]}`, "");
|
||||
sys.diff(baseline, oldSnap);
|
||||
sys.writtenFiles.forEach((value, key) => {
|
||||
assert.equal(value, 1, `Expected to write file ${key} only once`);
|
||||
});
|
||||
sys.serializeState(baseline, SerializeOutputOrder.BeforeDiff);
|
||||
baselinePrograms(baseline, programs, oldPrograms, baselineDependencies);
|
||||
baseline.push(`exitCode:: ExitStatus.${ts.ExitStatus[sys.exitCode as ts.ExitStatus]}`, "");
|
||||
// Verify program structure and resolution cache when incremental edit with tsc --watch (without build mode)
|
||||
if (resolutionCache && programs.length) {
|
||||
ts.Debug.assert(programs.length === 1);
|
||||
verifyProgramStructureAndResolutionCache(caption!, sys, programs[0][0], resolutionCache, useSourceOfProjectReferenceRedirect, symlinksNotReflected);
|
||||
}
|
||||
sys.writtenFiles.clear();
|
||||
return programs;
|
||||
}
|
||||
function verifyProgramStructureAndResolutionCache(
|
||||
|
||||
@@ -2,9 +2,8 @@ import {
|
||||
incrementalVerifier,
|
||||
} from "../../../harness/incrementalUtils";
|
||||
import {
|
||||
createHasErrorMessageLogger,
|
||||
createLoggerWithInMemoryLogs,
|
||||
Logger,
|
||||
LoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as Harness from "../../_namespaces/Harness";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
@@ -22,12 +21,13 @@ import {
|
||||
File,
|
||||
FileOrFolderOrSymLink,
|
||||
libFile,
|
||||
SerializeOutputOrder,
|
||||
StateLogger,
|
||||
TestServerHost,
|
||||
TestServerHostTrackingWrittenFiles,
|
||||
} from "./virtualFileSystemWithWatch";
|
||||
|
||||
export function baselineTsserverLogs(scenario: string, subScenario: string, sessionOrService: { logger: Logger; }) {
|
||||
ts.Debug.assert(sessionOrService.logger.logs?.length); // Ensure caller used in memory logger
|
||||
export function baselineTsserverLogs(scenario: string, subScenario: string, sessionOrService: { logger: LoggerWithInMemoryLogs; }) {
|
||||
Harness.Baseline.runBaseline(`tsserver/${scenario}/${subScenario.split(" ").join("-")}.js`, sessionOrService.logger.logs.join("\r\n"));
|
||||
}
|
||||
|
||||
@@ -49,29 +49,24 @@ export function toExternalFiles(fileNames: string[]) {
|
||||
export type TestSessionAndServiceHost = TestServerHostTrackingWrittenFiles & {
|
||||
patched: boolean;
|
||||
baselineHost(title: string): void;
|
||||
logTimeoutQueueLength(): void;
|
||||
};
|
||||
export function patchHostTimeouts(
|
||||
inputHost: TestServerHostTrackingWrittenFiles,
|
||||
logger: Logger,
|
||||
logger: LoggerWithInMemoryLogs,
|
||||
) {
|
||||
const host = inputHost as TestSessionAndServiceHost;
|
||||
if (host.patched) return host;
|
||||
host.patched = true;
|
||||
if (!logger.hasLevel(ts.server.LogLevel.verbose)) {
|
||||
host.logTimeoutQueueLength = ts.notImplemented;
|
||||
host.baselineHost = ts.notImplemented;
|
||||
return host;
|
||||
}
|
||||
|
||||
const originalRunQueuedTimeoutCallbacks = host.runQueuedTimeoutCallbacks;
|
||||
const originalRunQueuedImmediateCallbacks = host.runQueuedImmediateCallbacks;
|
||||
const originalSetTime = host.setTime;
|
||||
let hostDiff: ReturnType<TestServerHost["snap"]> | undefined;
|
||||
|
||||
host.runQueuedTimeoutCallbacks = runQueuedTimeoutCallbacks;
|
||||
host.runQueuedImmediateCallbacks = runQueuedImmediateCallbacks;
|
||||
host.logTimeoutQueueLength = logTimeoutQueueLength;
|
||||
host.timeoutCallbacks.switchToBaseliningInvoke(logger, SerializeOutputOrder.None);
|
||||
host.immediateCallbacks.switchToBaseliningInvoke(logger as StateLogger, SerializeOutputOrder.None);
|
||||
host.pendingInstalls.switchToBaseliningInvoke(logger, SerializeOutputOrder.None);
|
||||
host.setTime = setTime;
|
||||
host.baselineHost = baselineHost;
|
||||
host.patched = true;
|
||||
@@ -82,52 +77,63 @@ export function patchHostTimeouts(
|
||||
return originalSetTime.call(host, time);
|
||||
}
|
||||
|
||||
function logTimeoutQueueLength() {
|
||||
logger.log(host.timeoutCallbacks.log());
|
||||
host.baselineHost(host.immediateCallbacks.log());
|
||||
}
|
||||
|
||||
function runQueuedTimeoutCallbacks(timeoutId?: number) {
|
||||
host.baselineHost(`Before running ${host.timeoutCallbacks.log()}`);
|
||||
if (timeoutId !== undefined) logger.log(`Invoking ${host.timeoutCallbacks.callbackType} callback:: timeoutId:: ${timeoutId}:: ${host.timeoutCallbacks.map[timeoutId].args[0]}`);
|
||||
originalRunQueuedTimeoutCallbacks.call(host, timeoutId);
|
||||
host.baselineHost(`After running ${host.timeoutCallbacks.log()}`);
|
||||
}
|
||||
|
||||
function runQueuedImmediateCallbacks() {
|
||||
host.baselineHost(`Before running ${host.immediateCallbacks.log()}`);
|
||||
originalRunQueuedImmediateCallbacks.call(host);
|
||||
host.baselineHost(`After running ${host.immediateCallbacks.log()}`);
|
||||
}
|
||||
|
||||
function baselineHost(title: string) {
|
||||
logger.log(title);
|
||||
ts.Debug.assertIsDefined(logger.logs);
|
||||
host.diff(logger.logs, hostDiff);
|
||||
host.serializeWatches(logger.logs);
|
||||
hostDiff = host.snap();
|
||||
host.writtenFiles.clear();
|
||||
host.serializeState(logger.logs, SerializeOutputOrder.None);
|
||||
}
|
||||
}
|
||||
|
||||
export interface TestSessionOptions extends ts.server.SessionOptions, TestTypingsInstallerOptions {
|
||||
logger: Logger;
|
||||
allowNonBaseliningLogger?: boolean;
|
||||
host: TestServerHost;
|
||||
logger: LoggerWithInMemoryLogs;
|
||||
disableAutomaticTypingAcquisition?: boolean;
|
||||
useCancellationToken?: boolean | number;
|
||||
}
|
||||
|
||||
export type TestSessionPartialOptionsAndHost = Partial<Omit<TestSessionOptions, "typingsInstaller" | "cancellationToken">> & Pick<TestSessionOptions, "host">;
|
||||
export type TestSessionConstructorOptions = TestServerHost | TestSessionPartialOptionsAndHost;
|
||||
export type TestSessionRequest<T extends ts.server.protocol.Request> = Pick<T, "command" | "arguments">;
|
||||
|
||||
function getTestSessionPartialOptionsAndHost(optsOrHost: TestSessionConstructorOptions): TestSessionPartialOptionsAndHost {
|
||||
// eslint-disable-next-line local/no-in-operator
|
||||
return "host" in optsOrHost ?
|
||||
optsOrHost :
|
||||
{ host: optsOrHost };
|
||||
}
|
||||
export class TestSession extends ts.server.Session {
|
||||
private seq = 0;
|
||||
public testhost: TestSessionAndServiceHost;
|
||||
public override logger: Logger;
|
||||
public override host!: TestSessionAndServiceHost;
|
||||
public override logger!: LoggerWithInMemoryLogs;
|
||||
public override readonly typingsInstaller!: TestTypingsInstaller;
|
||||
public serverCancellationToken: TestServerCancellationToken;
|
||||
|
||||
constructor(opts: TestSessionOptions) {
|
||||
super(opts);
|
||||
this.logger = opts.logger;
|
||||
ts.Debug.assert(opts.allowNonBaseliningLogger || this.logger.hasLevel(ts.server.LogLevel.verbose), "Use Baselining logger and baseline tsserver log or create using allowNonBaseliningLogger");
|
||||
this.testhost = patchHostTimeouts(
|
||||
changeToHostTrackingWrittenFiles(this.host as TestServerHost),
|
||||
constructor(optsOrHost: TestSessionConstructorOptions) {
|
||||
const opts = getTestSessionPartialOptionsAndHost(optsOrHost);
|
||||
opts.logger = opts.logger || createLoggerWithInMemoryLogs(opts.host);
|
||||
const typingsInstaller = !opts.disableAutomaticTypingAcquisition ? new TestTypingsInstaller(opts) : undefined;
|
||||
const cancellationToken = opts.useCancellationToken ?
|
||||
new TestServerCancellationToken(
|
||||
opts.logger,
|
||||
ts.isNumber(opts.useCancellationToken) ? opts.useCancellationToken : undefined,
|
||||
) :
|
||||
ts.server.nullCancellationToken;
|
||||
super({
|
||||
cancellationToken,
|
||||
useSingleInferredProject: false,
|
||||
useInferredProjectPerProjectRoot: false,
|
||||
noGetErrOnBackgroundUpdate: true,
|
||||
byteLength: Buffer.byteLength,
|
||||
hrtime: process.hrtime,
|
||||
logger: opts.logger,
|
||||
canUseEvents: true,
|
||||
incrementalVerifier,
|
||||
typesMapLocation: customTypesMap.path,
|
||||
typingsInstaller,
|
||||
...opts,
|
||||
});
|
||||
if (typingsInstaller) typingsInstaller.session = this;
|
||||
this.serverCancellationToken = cancellationToken as TestServerCancellationToken;
|
||||
patchHostTimeouts(
|
||||
changeToHostTrackingWrittenFiles(this.host),
|
||||
this.logger,
|
||||
);
|
||||
}
|
||||
@@ -146,13 +152,13 @@ export class TestSession extends ts.server.Session {
|
||||
|
||||
public override executeCommand(request: ts.server.protocol.Request) {
|
||||
if (this.logger.hasLevel(ts.server.LogLevel.verbose)) {
|
||||
this.testhost.baselineHost("Before request");
|
||||
this.host.baselineHost("Before request");
|
||||
this.logger.info(`request:${ts.server.stringifyIndented(request)}`);
|
||||
}
|
||||
const response = super.executeCommand(request);
|
||||
if (this.logger.hasLevel(ts.server.LogLevel.verbose)) {
|
||||
this.logger.info(`response:${ts.server.stringifyIndented(response.response === ts.getSupportedCodeFixes() ? { ...response, response: "ts.getSupportedCodeFixes()" } : response)}`);
|
||||
this.testhost.baselineHost("After request");
|
||||
this.host.baselineHost("After request");
|
||||
}
|
||||
return response;
|
||||
}
|
||||
@@ -166,37 +172,13 @@ export class TestSession extends ts.server.Session {
|
||||
}
|
||||
}
|
||||
|
||||
export function createSession(host: TestServerHost, opts: Partial<TestSessionOptions> = {}) {
|
||||
const logger = opts.logger || createHasErrorMessageLogger();
|
||||
if (!opts.disableAutomaticTypingAcquisition && opts.typingsInstaller === undefined) {
|
||||
opts.typingsInstaller = new TestTypingsInstaller(
|
||||
host,
|
||||
logger,
|
||||
opts,
|
||||
);
|
||||
}
|
||||
|
||||
if (opts.eventHandler !== undefined) {
|
||||
opts.canUseEvents = true;
|
||||
}
|
||||
|
||||
const sessionOptions: TestSessionOptions = {
|
||||
host,
|
||||
cancellationToken: ts.server.nullCancellationToken,
|
||||
useSingleInferredProject: false,
|
||||
useInferredProjectPerProjectRoot: false,
|
||||
byteLength: Buffer.byteLength,
|
||||
hrtime: process.hrtime,
|
||||
logger,
|
||||
canUseEvents: false,
|
||||
incrementalVerifier,
|
||||
};
|
||||
|
||||
return new TestSession({ ...sessionOptions, ...opts });
|
||||
}
|
||||
|
||||
export function createSessionWithCustomEventHandler(host: TestServerHost, opts?: Partial<TestSessionOptions>, customAction?: (event: ts.server.ProjectServiceEvent) => void) {
|
||||
const session = createSession(host, { eventHandler, logger: createLoggerWithInMemoryLogs(host), ...opts });
|
||||
export function createSessionWithCustomEventHandler(
|
||||
optsOrHost: TestSessionConstructorOptions,
|
||||
customAction?: (event: ts.server.ProjectServiceEvent) => void,
|
||||
) {
|
||||
const opts = getTestSessionPartialOptionsAndHost(optsOrHost);
|
||||
opts.eventHandler = eventHandler;
|
||||
const session = new TestSession(opts);
|
||||
return session;
|
||||
function eventHandler(event: ts.server.ProjectServiceEvent) {
|
||||
let data = event.data as any;
|
||||
@@ -228,42 +210,6 @@ export function createSessionWithCustomEventHandler(host: TestServerHost, opts?:
|
||||
}
|
||||
}
|
||||
|
||||
export interface TestProjectServiceOptions extends ts.server.ProjectServiceOptions {
|
||||
logger: Logger;
|
||||
allowNonBaseliningLogger?: boolean;
|
||||
}
|
||||
|
||||
export class TestProjectService extends ts.server.ProjectService {
|
||||
public testhost: TestSessionAndServiceHost;
|
||||
constructor(host: TestServerHost, public override logger: Logger, cancellationToken: ts.HostCancellationToken, useSingleInferredProject: boolean, typingsInstaller: ts.server.ITypingsInstaller, opts: Partial<TestProjectServiceOptions> = {}) {
|
||||
super({
|
||||
host,
|
||||
logger,
|
||||
session: undefined,
|
||||
cancellationToken,
|
||||
useSingleInferredProject,
|
||||
useInferredProjectPerProjectRoot: false,
|
||||
typingsInstaller,
|
||||
typesMapLocation: customTypesMap.path,
|
||||
incrementalVerifier,
|
||||
...opts,
|
||||
});
|
||||
ts.Debug.assert(opts.allowNonBaseliningLogger || this.logger.hasLevel(ts.server.LogLevel.verbose), "Use Baselining logger and baseline tsserver log or create using allowNonBaseliningLogger");
|
||||
this.testhost = patchHostTimeouts(
|
||||
changeToHostTrackingWrittenFiles(this.host as TestServerHost),
|
||||
this.logger,
|
||||
);
|
||||
if (logger.hasLevel(ts.server.LogLevel.verbose)) this.testhost.baselineHost("Creating project service");
|
||||
}
|
||||
}
|
||||
|
||||
export function createProjectService(host: TestServerHost, options?: Partial<TestProjectServiceOptions>) {
|
||||
const cancellationToken = options?.cancellationToken || ts.server.nullCancellationToken;
|
||||
const logger = options?.logger || createHasErrorMessageLogger();
|
||||
const useSingleInferredProject = options?.useSingleInferredProject !== undefined ? options.useSingleInferredProject : false;
|
||||
return new TestProjectService(host, logger, cancellationToken, useSingleInferredProject, options?.typingsInstaller || ts.server.nullTypingsInstaller, options);
|
||||
}
|
||||
|
||||
export function protocolLocationFromSubstring(str: string, substring: string, options?: SpanFromSubstringOptions): ts.server.protocol.Location {
|
||||
const start = nthIndexOf(str, substring, options ? options.index : 0);
|
||||
ts.Debug.assert(start !== -1);
|
||||
@@ -318,11 +264,12 @@ export class TestServerCancellationToken implements ts.server.ServerCancellation
|
||||
private requestToCancel = -1;
|
||||
private isCancellationRequestedCount = 0;
|
||||
|
||||
constructor(private logger: Logger, private cancelAfterRequest = 0) {
|
||||
constructor(private logger: LoggerWithInMemoryLogs, private cancelAfterRequest = 0) {
|
||||
}
|
||||
|
||||
setRequest(requestId: number) {
|
||||
this.currentId = requestId;
|
||||
this.logger.log(`TestServerCancellationToken:: Cancellation Request id:: ${requestId}`);
|
||||
}
|
||||
|
||||
setRequestToCancel(requestId: number) {
|
||||
@@ -415,7 +362,7 @@ export function setCompilerOptionsForInferredProjectsRequestForSession(
|
||||
});
|
||||
}
|
||||
|
||||
export function logDiagnostics(sessionOrService: TestSession | TestProjectService, diagnosticsType: string, project: ts.server.Project, diagnostics: readonly ts.Diagnostic[]) {
|
||||
export function logDiagnostics(sessionOrService: TestSession, diagnosticsType: string, project: ts.server.Project, diagnostics: readonly ts.Diagnostic[]) {
|
||||
sessionOrService.logger.info(`${diagnosticsType}:: ${diagnostics.length}`);
|
||||
diagnostics.forEach(d => sessionOrService.logger.info(ts.formatDiagnostic(d, project)));
|
||||
}
|
||||
@@ -445,11 +392,10 @@ export interface CheckAllErrors extends VerifyGetErrRequestBase {
|
||||
skip?: readonly (SkipErrors | undefined)[];
|
||||
}
|
||||
function checkAllErrors({ session, existingTimeouts, files, skip }: CheckAllErrors) {
|
||||
ts.Debug.assert(session.logger.logs?.length);
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
session.testhost.runQueuedTimeoutCallbacks(existingTimeouts ? session.testhost.getNextTimeoutId() - 1 : undefined);
|
||||
if (!skip?.[i]?.semantic) session.testhost.runQueuedImmediateCallbacks();
|
||||
if (!skip?.[i]?.suggestion) session.testhost.runQueuedImmediateCallbacks();
|
||||
session.host.runQueuedTimeoutCallbacks(existingTimeouts ? session.host.getNextTimeoutId() - 1 : undefined);
|
||||
if (!skip?.[i]?.semantic) session.host.runQueuedImmediateCallbacks();
|
||||
if (!skip?.[i]?.suggestion) session.host.runQueuedImmediateCallbacks();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -460,7 +406,7 @@ function filePath(file: string | File) {
|
||||
function verifyErrorsUsingGeterr({ scenario, subScenario, allFiles, openFiles, getErrRequest }: VerifyGetErrScenario) {
|
||||
it("verifies the errors in open file", () => {
|
||||
const host = createServerHost([...allFiles(), libFile]);
|
||||
const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession(openFiles(), session);
|
||||
|
||||
verifyGetErrRequest({ session, files: getErrRequest() });
|
||||
@@ -471,7 +417,7 @@ function verifyErrorsUsingGeterr({ scenario, subScenario, allFiles, openFiles, g
|
||||
function verifyErrorsUsingGeterrForProject({ scenario, subScenario, allFiles, openFiles, getErrForProjectRequest }: VerifyGetErrScenario) {
|
||||
it("verifies the errors in projects", () => {
|
||||
const host = createServerHost([...allFiles(), libFile]);
|
||||
const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession(openFiles(), session);
|
||||
|
||||
for (const expected of getErrForProjectRequest()) {
|
||||
@@ -488,7 +434,7 @@ function verifyErrorsUsingGeterrForProject({ scenario, subScenario, allFiles, op
|
||||
function verifyErrorsUsingSyncMethods({ scenario, subScenario, allFiles, openFiles, syncDiagnostics }: VerifyGetErrScenario) {
|
||||
it("verifies the errors using sync commands", () => {
|
||||
const host = createServerHost([...allFiles(), libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession(openFiles(), session);
|
||||
for (const { file, project } of syncDiagnostics()) {
|
||||
const reqArgs = { file: filePath(file), projectFileName: project && filePath(project) };
|
||||
@@ -533,8 +479,8 @@ export function verifyGetErrScenario(scenario: VerifyGetErrScenario) {
|
||||
verifyErrorsUsingSyncMethods(scenario);
|
||||
}
|
||||
|
||||
export function verifyDynamic(service: ts.server.ProjectService, path: string) {
|
||||
(service.logger as Logger).log(`${path} isDynamic:: ${service.filenameToScriptInfo.get(path)!.isDynamic}`);
|
||||
export function verifyDynamic(session: TestSession, path: string) {
|
||||
session.logger.log(`${path} isDynamic:: ${session.getProjectService().filenameToScriptInfo.get(path)!.isDynamic}`);
|
||||
}
|
||||
|
||||
export function createHostWithSolutionBuild(files: readonly FileOrFolderOrSymLink[], rootNames: readonly string[]) {
|
||||
@@ -544,10 +490,10 @@ export function createHostWithSolutionBuild(files: readonly FileOrFolderOrSymLin
|
||||
return host;
|
||||
}
|
||||
|
||||
export function logInferredProjectsOrphanStatus(projectService: ts.server.ProjectService) {
|
||||
projectService.inferredProjects.forEach(inferredProject => (projectService.logger as Logger).log(`Inferred project: ${inferredProject.projectName} isOrphan:: ${inferredProject.isOrphan()} isClosed: ${inferredProject.isClosed()}`));
|
||||
export function logInferredProjectsOrphanStatus(session: TestSession) {
|
||||
session.getProjectService().inferredProjects.forEach(inferredProject => session.logger.log(`Inferred project: ${inferredProject.projectName} isOrphan:: ${inferredProject.isOrphan()} isClosed: ${inferredProject.isClosed()}`));
|
||||
}
|
||||
|
||||
export function logConfiguredProjectsHasOpenRefStatus(projectService: ts.server.ProjectService) {
|
||||
projectService.configuredProjects.forEach(configuredProject => (projectService.logger as Logger).log(`Configured project: ${configuredProject.projectName} hasOpenRef:: ${configuredProject.hasOpenRef()} isClosed: ${configuredProject.isClosed()}`));
|
||||
export function logConfiguredProjectsHasOpenRefStatus(session: TestSession) {
|
||||
session.getProjectService().configuredProjects.forEach(configuredProject => session.logger.log(`Configured project: ${configuredProject.projectName} hasOpenRef:: ${configuredProject.hasOpenRef()} isClosed: ${configuredProject.isClosed()}`));
|
||||
}
|
||||
|
||||
@@ -1,23 +1,24 @@
|
||||
import {
|
||||
Logger,
|
||||
LoggerWithInMemoryLogs,
|
||||
nowString,
|
||||
replaceAll,
|
||||
sanitizeLog,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
ActionInvalidate,
|
||||
ActionPackageInstalled,
|
||||
ActionSet,
|
||||
ActionWatchTypingLocations,
|
||||
EventBeginInstallTypes,
|
||||
EventEndInstallTypes,
|
||||
stringifyIndented,
|
||||
} from "../../_namespaces/ts.server";
|
||||
import {
|
||||
jsonToReadableText,
|
||||
} from "../helpers";
|
||||
import {
|
||||
patchHostTimeouts,
|
||||
TestSessionAndServiceHost,
|
||||
TestSession,
|
||||
} from "./tsserver";
|
||||
import {
|
||||
changeToHostTrackingWrittenFiles,
|
||||
File,
|
||||
TestServerHost,
|
||||
} from "./virtualFileSystemWithWatch";
|
||||
@@ -46,38 +47,19 @@ export const customTypesMap = {
|
||||
}`,
|
||||
};
|
||||
|
||||
export interface PostExecAction {
|
||||
readonly success: boolean;
|
||||
requestId: number;
|
||||
readonly packageNames: readonly string[];
|
||||
readonly callback: ts.server.typingsInstaller.RequestCompletedAction;
|
||||
}
|
||||
export function loggerToTypingsInstallerLog(logger: Logger): ts.server.typingsInstaller.Log | undefined {
|
||||
return logger?.loggingEnabled() ? {
|
||||
export function loggerToTypingsInstallerLog(logger: LoggerWithInMemoryLogs): ts.server.typingsInstaller.Log {
|
||||
ts.Debug.assert(logger.loggingEnabled());
|
||||
return {
|
||||
isEnabled: ts.returnTrue,
|
||||
writeLine: s => {
|
||||
// This is a VERY VERY NAIVE sanitization strategy.
|
||||
// If a substring containing the exact TypeScript version is found,
|
||||
// even if it's unrelated to TypeScript itself, then it will be replaced,
|
||||
// leaving us with two options:
|
||||
//
|
||||
// 1. Deal with flip-flopping baselines.
|
||||
// 2. Change the TypeScript version until no matching substring is found.
|
||||
//
|
||||
const initialLog = sanitizeLog(s);
|
||||
const pseudoSanitizedLog = replaceAll(initialLog, `@ts${ts.versionMajorMinor}`, `@tsFakeMajor.Minor`);
|
||||
return logger.log(`TI:: [${nowString(logger)}] ${pseudoSanitizedLog}`);
|
||||
},
|
||||
} : undefined;
|
||||
writeLine: s => logger.log(`TI:: [${nowString(logger)}] ${s}`),
|
||||
};
|
||||
}
|
||||
interface TypesRegistryFile {
|
||||
entries: ts.MapLike<ts.MapLike<string>>;
|
||||
}
|
||||
function loadTypesRegistryFile(typesRegistryFilePath: string, host: TestServerHost, log: ts.server.typingsInstaller.Log): Map<string, ts.MapLike<string>> {
|
||||
if (!host.fileExists(typesRegistryFilePath)) {
|
||||
if (log.isEnabled()) {
|
||||
log.writeLine(`Types registry file '${typesRegistryFilePath}' does not exist`);
|
||||
}
|
||||
log.writeLine(`Types registry file '${typesRegistryFilePath}' does not exist`);
|
||||
return new Map<string, ts.MapLike<string>>();
|
||||
}
|
||||
try {
|
||||
@@ -85,9 +67,7 @@ function loadTypesRegistryFile(typesRegistryFilePath: string, host: TestServerHo
|
||||
return new Map(Object.entries(content.entries));
|
||||
}
|
||||
catch (e) {
|
||||
if (log.isEnabled()) {
|
||||
log.writeLine(`Error when loading types registry file '${typesRegistryFilePath}': ${(e as Error).message}, ${(e as Error).stack}`);
|
||||
}
|
||||
log.writeLine(`Error when loading types registry file '${typesRegistryFilePath}': ${(e as Error).message}, ${(e as Error).stack}`);
|
||||
return new Map<string, ts.MapLike<string>>();
|
||||
}
|
||||
}
|
||||
@@ -97,161 +77,121 @@ function getTypesRegistryFileLocation(globalTypingsCacheLocation: string): strin
|
||||
}
|
||||
|
||||
export interface FileWithPackageName extends File {
|
||||
package: string;
|
||||
package?: string;
|
||||
}
|
||||
export type InstallActionThrowingError = string;
|
||||
export type InstallActionWithTypingFiles = [installedTypings: string[] | string, typingFiles: File[]];
|
||||
export type InstallActionWithFilteredTypings = [typingFiles: FileWithPackageName[]];
|
||||
export type InstallAction = InstallActionThrowingError | InstallActionWithTypingFiles | InstallActionWithFilteredTypings;
|
||||
export type InstallActionWithSuccess = boolean;
|
||||
export type InstallActionWithTypingFiles = readonly FileWithPackageName[];
|
||||
export type InstallAction = InstallActionThrowingError | InstallActionWithSuccess | InstallActionWithTypingFiles;
|
||||
export type PendingInstallCallback = (
|
||||
pendingInstallInfo: string,
|
||||
installedTypingsOrSuccess: string[] | string | boolean,
|
||||
typingFiles: readonly File[],
|
||||
onRequestCompleted: ts.server.typingsInstaller.RequestCompletedAction,
|
||||
) => void;
|
||||
export class TestTypingsInstallerWorker extends ts.server.typingsInstaller.TypingsInstaller {
|
||||
readonly typesRegistry: Map<string, ts.MapLike<string>>;
|
||||
protected projectService!: ts.server.ProjectService;
|
||||
constructor(
|
||||
readonly globalTypingsCacheLocation: string,
|
||||
throttleLimit: number,
|
||||
installTypingHost: TestServerHost,
|
||||
logger: Logger,
|
||||
typesRegistry: string | readonly string[] | undefined,
|
||||
private installAction: InstallAction | undefined,
|
||||
) {
|
||||
const log = loggerToTypingsInstallerLog(logger);
|
||||
if (log?.isEnabled()) {
|
||||
patchHostTimeouts(
|
||||
changeToHostTrackingWrittenFiles(installTypingHost),
|
||||
logger,
|
||||
);
|
||||
(installTypingHost as TestSessionAndServiceHost).baselineHost("TI:: Creating typing installer");
|
||||
}
|
||||
constructor(readonly testTypingInstaller: TestTypingsInstaller) {
|
||||
const log = loggerToTypingsInstallerLog(testTypingInstaller.session.logger);
|
||||
ts.Debug.assert(testTypingInstaller.session.host.patched);
|
||||
testTypingInstaller.session.host.baselineHost("TI:: Creating typing installer");
|
||||
super(
|
||||
installTypingHost,
|
||||
globalTypingsCacheLocation,
|
||||
testTypingInstaller.session.host,
|
||||
testTypingInstaller.globalTypingsCacheLocation,
|
||||
"/safeList.json" as ts.Path,
|
||||
customTypesMap.path,
|
||||
throttleLimit,
|
||||
testTypingInstaller.throttleLimit,
|
||||
log,
|
||||
);
|
||||
|
||||
this.ensurePackageDirectoryExists(globalTypingsCacheLocation);
|
||||
this.ensurePackageDirectoryExists(testTypingInstaller.globalTypingsCacheLocation);
|
||||
|
||||
if (this.log.isEnabled()) {
|
||||
this.log.writeLine(`Updating ${typesRegistryPackageName} npm package...`);
|
||||
this.log.writeLine(`npm install --ignore-scripts ${typesRegistryPackageName}@${this.latestDistTag}`);
|
||||
}
|
||||
installTypingHost.ensureFileOrFolder({
|
||||
path: getTypesRegistryFileLocation(globalTypingsCacheLocation),
|
||||
this.log.writeLine(`Updating ${typesRegistryPackageName} npm package...`);
|
||||
this.log.writeLine(`npm install --ignore-scripts ${typesRegistryPackageName}@${this.latestDistTag}`);
|
||||
testTypingInstaller.session.host.ensureFileOrFolder({
|
||||
path: getTypesRegistryFileLocation(testTypingInstaller.globalTypingsCacheLocation),
|
||||
content: jsonToReadableText(createTypesRegistryFileContent(
|
||||
typesRegistry ?
|
||||
ts.isString(typesRegistry) ?
|
||||
[typesRegistry] :
|
||||
typesRegistry :
|
||||
testTypingInstaller.typesRegistry ?
|
||||
ts.isString(testTypingInstaller.typesRegistry) ?
|
||||
[testTypingInstaller.typesRegistry] :
|
||||
testTypingInstaller.typesRegistry :
|
||||
ts.emptyArray,
|
||||
)),
|
||||
});
|
||||
if (this.log.isEnabled()) {
|
||||
this.log.writeLine(`TI:: Updated ${typesRegistryPackageName} npm package`);
|
||||
}
|
||||
this.typesRegistry = loadTypesRegistryFile(getTypesRegistryFileLocation(globalTypingsCacheLocation), installTypingHost, this.log);
|
||||
if (this.log.isEnabled()) {
|
||||
(installTypingHost as TestSessionAndServiceHost).baselineHost("TI:: typing installer creation complete");
|
||||
}
|
||||
this.log.writeLine(`Updated ${typesRegistryPackageName} npm package`);
|
||||
|
||||
this.typesRegistry = loadTypesRegistryFile(
|
||||
getTypesRegistryFileLocation(testTypingInstaller.globalTypingsCacheLocation),
|
||||
testTypingInstaller.session.host,
|
||||
this.log,
|
||||
);
|
||||
testTypingInstaller.session.host.baselineHost("TI:: typing installer creation complete");
|
||||
}
|
||||
|
||||
protected postExecActions: PostExecAction[] = [];
|
||||
|
||||
executePendingCommands() {
|
||||
const actionsToRun = this.postExecActions;
|
||||
this.postExecActions = [];
|
||||
for (const action of actionsToRun) {
|
||||
if (this.log.isEnabled()) {
|
||||
this.log.writeLine(`#${action.requestId} with arguments'${jsonToReadableText(action.packageNames)}':: ${action.success}`);
|
||||
}
|
||||
action.callback(action.success);
|
||||
}
|
||||
}
|
||||
|
||||
attach(projectService: ts.server.ProjectService) {
|
||||
this.projectService = projectService;
|
||||
}
|
||||
|
||||
getInstallTypingHost() {
|
||||
return this.installTypingHost;
|
||||
}
|
||||
|
||||
installWorker(requestId: number, packageNames: string[], _cwd: string, cb: ts.server.typingsInstaller.RequestCompletedAction): void {
|
||||
if (this.log.isEnabled()) {
|
||||
this.log.writeLine(`#${requestId} with arguments'${jsonToReadableText(packageNames)}'.`);
|
||||
}
|
||||
if (!this.installAction) {
|
||||
this.addPostExecAction("success", requestId, packageNames, cb);
|
||||
}
|
||||
else if (ts.isString(this.installAction)) {
|
||||
assert(false, this.installAction);
|
||||
}
|
||||
else if (this.installAction.length === 2) {
|
||||
this.executeInstallWithTypingFiles(
|
||||
installWorker(requestId: number, packageNames: string[], cwd: string, onRequestCompleted: ts.server.typingsInstaller.RequestCompletedAction): void {
|
||||
this.log.writeLine(`#${requestId} with cwd: ${cwd} arguments: ${jsonToReadableText(packageNames)}`);
|
||||
if (typeof this.testTypingInstaller.installAction === "boolean") {
|
||||
this.scheduleInstall(
|
||||
requestId,
|
||||
packageNames,
|
||||
this.installAction[0],
|
||||
this.installAction[1],
|
||||
cb,
|
||||
this.testTypingInstaller.installAction,
|
||||
ts.emptyArray,
|
||||
onRequestCompleted,
|
||||
);
|
||||
}
|
||||
else if (ts.isString(this.testTypingInstaller.installAction)) {
|
||||
assert(false, this.testTypingInstaller.installAction);
|
||||
}
|
||||
else {
|
||||
const typingFiles = this.installAction[0].filter(f => packageNames.includes(ts.server.typingsInstaller.typingsName(f.package)));
|
||||
this.executeInstallWithTypingFiles(
|
||||
const typingFiles = this.testTypingInstaller.installAction.filter(f => !f.package || packageNames.includes(ts.server.typingsInstaller.typingsName(f.package)));
|
||||
this.scheduleInstall(
|
||||
requestId,
|
||||
packageNames,
|
||||
typingFiles.map(f => f.package),
|
||||
/*success*/ true,
|
||||
typingFiles,
|
||||
cb,
|
||||
onRequestCompleted,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
executeInstallWithTypingFiles(
|
||||
private scheduleInstall(
|
||||
requestId: number,
|
||||
packageNames: string[],
|
||||
installedTypings: string[] | string,
|
||||
typingFiles: File[],
|
||||
cb: ts.server.typingsInstaller.RequestCompletedAction,
|
||||
success: boolean,
|
||||
typingFiles: readonly File[],
|
||||
onRequestCompleted: ts.server.typingsInstaller.RequestCompletedAction,
|
||||
): void {
|
||||
this.addPostExecAction(installedTypings, requestId, packageNames, success => {
|
||||
const host = this.getInstallTypingHost() as TestSessionAndServiceHost;
|
||||
host.baselineHost("TI:: Before installWorker");
|
||||
for (const file of typingFiles) {
|
||||
host.ensureFileOrFolder(file);
|
||||
}
|
||||
host.baselineHost("TI:: After installWorker");
|
||||
cb(success);
|
||||
});
|
||||
this.testTypingInstaller.session.host.scheduleInstall(
|
||||
pendingInstallInfo => {
|
||||
for (const file of typingFiles) {
|
||||
this.testTypingInstaller.session.host.ensureFileOrFolder(file);
|
||||
}
|
||||
this.testTypingInstaller.session.host.baselineHost(`TI:: Installation ${pendingInstallInfo} complete with success::${!!success}`);
|
||||
onRequestCompleted(!!success);
|
||||
},
|
||||
`#${requestId} with arguments:: ${jsonToReadableText(packageNames)}`,
|
||||
);
|
||||
}
|
||||
|
||||
sendResponse(response: ts.server.SetTypings | ts.server.InvalidateCachedTypings | ts.server.WatchTypingLocations) {
|
||||
if (this.log.isEnabled()) {
|
||||
this.log.writeLine(`Sending response:${stringifyIndented(response)}`);
|
||||
}
|
||||
if (response.kind !== ActionWatchTypingLocations) this.projectService.updateTypingsForProject(response);
|
||||
else this.projectService.watchTypingLocations(response);
|
||||
sendResponse(response: ts.server.SetTypings | ts.server.InvalidateCachedTypings | ts.server.BeginInstallTypes | ts.server.EndInstallTypes | ts.server.WatchTypingLocations | ts.server.PackageInstalledResponse) {
|
||||
this.log.writeLine(`Sending response:${stringifyIndented(response)}`);
|
||||
this.testTypingInstaller.onResponse(response);
|
||||
}
|
||||
|
||||
enqueueInstallTypingsRequest(project: ts.server.Project, typeAcquisition: ts.TypeAcquisition, unresolvedImports: ts.SortedReadonlyArray<string>) {
|
||||
const request = ts.server.createInstallTypingsRequest(project, typeAcquisition, unresolvedImports, this.globalTypingsCacheLocation);
|
||||
const request = ts.server.createInstallTypingsRequest(
|
||||
project,
|
||||
typeAcquisition,
|
||||
unresolvedImports,
|
||||
this.testTypingInstaller.globalTypingsCacheLocation,
|
||||
);
|
||||
this.install(request);
|
||||
}
|
||||
|
||||
addPostExecAction(stdout: string | string[], requestId: number, packageNames: string[], cb: ts.server.typingsInstaller.RequestCompletedAction) {
|
||||
const out = ts.isString(stdout) ? stdout : createNpmPackageJsonString(stdout);
|
||||
const action: PostExecAction = {
|
||||
success: !!out,
|
||||
requestId,
|
||||
packageNames,
|
||||
callback: cb,
|
||||
};
|
||||
this.postExecActions.push(action);
|
||||
}
|
||||
}
|
||||
|
||||
export interface TestTypingsInstallerOptions {
|
||||
host: TestServerHost;
|
||||
logger?: LoggerWithInMemoryLogs;
|
||||
globalTypingsCacheLocation?: string;
|
||||
throttleLimit?: number;
|
||||
installAction?: InstallAction;
|
||||
@@ -261,24 +201,39 @@ export interface TestTypingsInstallerOptions {
|
||||
export class TestTypingsInstaller implements ts.server.ITypingsInstaller {
|
||||
protected projectService!: ts.server.ProjectService;
|
||||
public installer!: TestTypingsInstallerWorker;
|
||||
readonly globalTypingsCacheLocation: string;
|
||||
private readonly throttleLimit: number;
|
||||
private installAction?: InstallAction;
|
||||
private typesRegistry?: string | readonly string[];
|
||||
session!: TestSession;
|
||||
packageInstalledPromise: { resolve(value: ts.ApplyCodeActionCommandResult): void; reject(reason: unknown): void; } | undefined;
|
||||
|
||||
constructor(
|
||||
private installTypingHost: TestServerHost,
|
||||
private logger: Logger,
|
||||
options?: TestTypingsInstallerOptions,
|
||||
) {
|
||||
this.globalTypingsCacheLocation = options?.globalTypingsCacheLocation || this.installTypingHost.getHostSpecificPath("/a/data");
|
||||
this.throttleLimit = options?.throttleLimit || 5;
|
||||
this.installAction = options?.installAction;
|
||||
this.typesRegistry = options?.typesRegistry;
|
||||
// Options
|
||||
readonly globalTypingsCacheLocation: string;
|
||||
readonly throttleLimit: number;
|
||||
readonly installAction: InstallAction;
|
||||
readonly typesRegistry: string | readonly string[] | undefined;
|
||||
|
||||
constructor(options: TestTypingsInstallerOptions) {
|
||||
this.globalTypingsCacheLocation = options.globalTypingsCacheLocation || options.host.getHostSpecificPath("/a/data");
|
||||
this.throttleLimit = options.throttleLimit || 5;
|
||||
this.installAction = options.installAction !== undefined ? options.installAction : true;
|
||||
this.typesRegistry = options.typesRegistry;
|
||||
}
|
||||
|
||||
isKnownTypesPackageName = ts.notImplemented;
|
||||
installPackage = ts.notImplemented;
|
||||
isKnownTypesPackageName(name: string): boolean {
|
||||
// We want to avoid looking this up in the registry as that is expensive. So first check that it's actually an NPM package.
|
||||
const validationResult = ts.JsTyping.validatePackageName(name);
|
||||
if (validationResult !== ts.JsTyping.NameValidationResult.Ok) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.ensureInstaller().typesRegistry.has(name);
|
||||
}
|
||||
|
||||
installPackage(options: ts.server.InstallPackageOptionsWithProject): Promise<ts.ApplyCodeActionCommandResult> {
|
||||
this.ensureInstaller().installPackage({ kind: "installPackage", ...options });
|
||||
ts.Debug.assert(this.packageInstalledPromise === undefined);
|
||||
return new Promise<ts.ApplyCodeActionCommandResult>((resolve, reject) => {
|
||||
this.packageInstalledPromise = { resolve, reject };
|
||||
});
|
||||
}
|
||||
|
||||
attach(projectService: ts.server.ProjectService) {
|
||||
this.projectService = projectService;
|
||||
@@ -289,27 +244,66 @@ export class TestTypingsInstaller implements ts.server.ITypingsInstaller {
|
||||
}
|
||||
|
||||
enqueueInstallTypingsRequest(project: ts.server.Project, typeAcquisition: ts.TypeAcquisition, unresolvedImports: ts.SortedReadonlyArray<string>) {
|
||||
if (!this.installer) {
|
||||
this.installer = new TestTypingsInstallerWorker(
|
||||
this.globalTypingsCacheLocation,
|
||||
this.throttleLimit,
|
||||
this.installTypingHost,
|
||||
this.logger,
|
||||
this.typesRegistry,
|
||||
this.installAction,
|
||||
);
|
||||
this.installer.attach(this.projectService);
|
||||
this.ensureInstaller().enqueueInstallTypingsRequest(project, typeAcquisition, unresolvedImports);
|
||||
}
|
||||
|
||||
private ensureInstaller() {
|
||||
return this.installer ??= new TestTypingsInstallerWorker(this);
|
||||
}
|
||||
|
||||
onResponse(response: ts.server.SetTypings | ts.server.InvalidateCachedTypings | ts.server.BeginInstallTypes | ts.server.EndInstallTypes | ts.server.WatchTypingLocations | ts.server.PackageInstalledResponse) {
|
||||
switch (response.kind) {
|
||||
case ActionPackageInstalled: {
|
||||
const { success, message } = response;
|
||||
if (success) {
|
||||
this.packageInstalledPromise!.resolve({ successMessage: message });
|
||||
}
|
||||
else {
|
||||
this.packageInstalledPromise!.reject(message);
|
||||
}
|
||||
this.packageInstalledPromise = undefined;
|
||||
|
||||
this.projectService.updateTypingsForProject(response);
|
||||
// The behavior is the same as for setTypings, so send the same event.
|
||||
this.session.event(response, "setTypings");
|
||||
break;
|
||||
}
|
||||
case EventBeginInstallTypes: {
|
||||
const body: ts.server.protocol.BeginInstallTypesEventBody = {
|
||||
eventId: response.eventId,
|
||||
packages: response.packagesToInstall,
|
||||
};
|
||||
const eventName: ts.server.protocol.BeginInstallTypesEventName = "beginInstallTypes";
|
||||
this.session.event(body, eventName);
|
||||
break;
|
||||
}
|
||||
case EventEndInstallTypes: {
|
||||
const body: ts.server.protocol.EndInstallTypesEventBody = {
|
||||
eventId: response.eventId,
|
||||
packages: response.packagesToInstall,
|
||||
success: response.installSuccess,
|
||||
};
|
||||
const eventName: ts.server.protocol.EndInstallTypesEventName = "endInstallTypes";
|
||||
this.session.event(body, eventName);
|
||||
break;
|
||||
}
|
||||
case ActionInvalidate: {
|
||||
this.projectService.updateTypingsForProject(response);
|
||||
break;
|
||||
}
|
||||
case ActionSet: {
|
||||
this.projectService.updateTypingsForProject(response);
|
||||
this.session.event(response, "setTypings");
|
||||
break;
|
||||
}
|
||||
case ActionWatchTypingLocations:
|
||||
this.projectService.watchTypingLocations(response);
|
||||
break;
|
||||
default:
|
||||
ts.assertType<never>(response);
|
||||
}
|
||||
this.installer.enqueueInstallTypingsRequest(project, typeAcquisition, unresolvedImports);
|
||||
}
|
||||
}
|
||||
function createNpmPackageJsonString(installedTypings: string[]): string {
|
||||
const dependencies: ts.MapLike<any> = {};
|
||||
for (const typing of installedTypings) {
|
||||
dependencies[typing] = "1.0.0";
|
||||
}
|
||||
return jsonToReadableText({ dependencies });
|
||||
}
|
||||
function createTypesRegistryFileContent(list: readonly string[]): TypesRegistryFile {
|
||||
const versionMap = {
|
||||
"latest": "1.3.0",
|
||||
|
||||
@@ -2,6 +2,7 @@ import {
|
||||
createWatchUtils,
|
||||
} from "../../../harness/watchUtils";
|
||||
import {
|
||||
arrayFrom,
|
||||
clear,
|
||||
clone,
|
||||
combinePaths,
|
||||
@@ -42,6 +43,9 @@ import {
|
||||
sys,
|
||||
toPath,
|
||||
} from "../../_namespaces/ts";
|
||||
import {
|
||||
typingsInstaller,
|
||||
} from "../../_namespaces/ts.server";
|
||||
import {
|
||||
timeIncrements,
|
||||
} from "../../_namespaces/vfs";
|
||||
@@ -161,6 +165,12 @@ function invokeWatcherCallbacks<T>(callbacks: readonly T[] | undefined, invokeCa
|
||||
}
|
||||
}
|
||||
|
||||
export interface StateLogger {
|
||||
log(s: string): void;
|
||||
logs: string[];
|
||||
}
|
||||
|
||||
const exitMessage = "System Exit";
|
||||
interface CallbackData {
|
||||
cb: TimeOutCallback;
|
||||
args: any[];
|
||||
@@ -168,10 +178,13 @@ interface CallbackData {
|
||||
time: number;
|
||||
}
|
||||
class Callbacks {
|
||||
readonly map: CallbackData[] = [];
|
||||
readonly map = new Map<number, CallbackData>();
|
||||
private nextId = 1;
|
||||
invoke: (invokeKey?: number) => void = invokeKey => this.invokeWorker(invokeKey);
|
||||
private hasChanges = false;
|
||||
private serializedKeys = new Map<number, any>();
|
||||
|
||||
constructor(private host: TestServerHost, readonly callbackType: string) {
|
||||
constructor(private host: TestServerHost, readonly callbackType: string, private readonly swallowExitException?: boolean) {
|
||||
}
|
||||
|
||||
getNextId() {
|
||||
@@ -181,27 +194,42 @@ class Callbacks {
|
||||
register(cb: TimeOutCallback, args: any[], ms?: number) {
|
||||
const timeoutId = this.nextId;
|
||||
this.nextId++;
|
||||
this.map[timeoutId] = { cb, args, ms, time: this.host.getTime() };
|
||||
this.map.set(timeoutId, { cb, args, ms, time: this.host.getTime() });
|
||||
this.hasChanges = true;
|
||||
return timeoutId;
|
||||
}
|
||||
|
||||
unregister(id: any) {
|
||||
if (typeof id === "number") {
|
||||
delete this.map[id];
|
||||
this.hasChanges = this.map.delete(id) || this.hasChanges;
|
||||
}
|
||||
}
|
||||
|
||||
log() {
|
||||
log(logChanges?: boolean) {
|
||||
const details: string[] = [];
|
||||
for (const timeoutId in this.map) {
|
||||
const { args } = this.map[Number(timeoutId)];
|
||||
details.push(`${timeoutId}: ${args[0]}`);
|
||||
this.map.forEach(({ args }, timeoutId) => {
|
||||
details.push(`${timeoutId}: ${args[0]}${!logChanges || this.serializedKeys.has(timeoutId) ? "" : " *new*"}`);
|
||||
if (logChanges) this.serializedKeys.set(timeoutId, args[0]);
|
||||
});
|
||||
const deleted: string[] = [];
|
||||
if (logChanges && this.serializedKeys.size !== this.map.size) {
|
||||
this.serializedKeys.forEach((value, key) => {
|
||||
if (this.map.has(key)) return;
|
||||
deleted.push(`${key}: ${value} *deleted*`);
|
||||
this.serializedKeys.delete(key);
|
||||
});
|
||||
}
|
||||
return `${this.callbackType} callback:: count: ${details.length}` + (details.length ? "\r\n" + details.join("\r\n") : "");
|
||||
return `${this.callbackType} callback:: count: ${this.map.size}` +
|
||||
(deleted.length ? "\r\n" + deleted.join("\r\n") : "") +
|
||||
(details.length ? "\r\n" + details.join("\r\n") : "");
|
||||
}
|
||||
|
||||
private invokeCallback(timeoutId: number) {
|
||||
const { cb, args, ms, time } = this.map[timeoutId];
|
||||
const data = this.map.get(timeoutId);
|
||||
if (!data) return;
|
||||
const { cb, args, ms, time } = data;
|
||||
this.map.delete(timeoutId);
|
||||
this.serializedKeys.delete(timeoutId);
|
||||
if (ms !== undefined) {
|
||||
const newTime = ms + time;
|
||||
if (this.host.getTime() < newTime) {
|
||||
@@ -209,17 +237,43 @@ class Callbacks {
|
||||
}
|
||||
}
|
||||
cb(...args);
|
||||
delete this.map[timeoutId];
|
||||
}
|
||||
|
||||
invoke(invokeKey?: number) {
|
||||
if (invokeKey) return this.invokeCallback(invokeKey);
|
||||
invokeWorker(invokeKey?: number) {
|
||||
try {
|
||||
if (invokeKey) return this.invokeCallback(invokeKey);
|
||||
|
||||
// Note: invoking a callback may result in new callbacks been queued,
|
||||
// so do not clear the entire callback list regardless. Only remove the
|
||||
// ones we have invoked.
|
||||
for (const key in this.map) {
|
||||
this.invokeCallback(Number(key));
|
||||
// Note: invoking a callback may result in new callbacks been queued,
|
||||
// so do not clear the entire callback list regardless. Only remove the
|
||||
// ones we have invoked.
|
||||
const keys = arrayFrom(this.map.keys());
|
||||
for (const key of keys) {
|
||||
this.invokeCallback(key);
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
if (this.swallowExitException && e.message === exitMessage) {
|
||||
return;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
switchToBaseliningInvoke(logger: StateLogger, serializeOutputOrder: SerializeOutputOrder) {
|
||||
this.invoke = invokeKey => {
|
||||
logger.log(`Before running ${this.log()}`);
|
||||
this.host.serializeState(logger.logs, serializeOutputOrder);
|
||||
if (invokeKey !== undefined) logger.log(`Invoking ${this.callbackType} callback:: timeoutId:: ${invokeKey}:: ${this.map.get(invokeKey)!.args[0]}`);
|
||||
this.invokeWorker(invokeKey);
|
||||
logger.log(`After running ${this.callbackType} callback:: count: ${this.map.size}`);
|
||||
this.host.serializeState(logger.logs, serializeOutputOrder);
|
||||
};
|
||||
}
|
||||
|
||||
serialize(baseline: string[]) {
|
||||
if (this.hasChanges) {
|
||||
baseline.push(this.log(/*logChanges*/ true), "");
|
||||
this.hasChanges = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -270,6 +324,18 @@ export interface TestServerHostOptions {
|
||||
environmentVariables?: Map<string, string>;
|
||||
}
|
||||
|
||||
export type PendingInstallCallback = (
|
||||
pendingInstallInfo: string,
|
||||
installedTypingsOrSuccess: string[] | string | boolean,
|
||||
typingFiles: readonly File[],
|
||||
onRequestCompleted: typingsInstaller.RequestCompletedAction,
|
||||
) => void;
|
||||
|
||||
export enum SerializeOutputOrder {
|
||||
None,
|
||||
BeforeDiff,
|
||||
AfterDiff,
|
||||
}
|
||||
export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, ModuleResolutionHost {
|
||||
args: string[] = [];
|
||||
|
||||
@@ -279,8 +345,9 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost,
|
||||
private time = timeIncrements;
|
||||
getCanonicalFileName: (s: string) => string;
|
||||
toPath: (f: string) => Path;
|
||||
readonly timeoutCallbacks = new Callbacks(this, "Timeout");
|
||||
readonly timeoutCallbacks = new Callbacks(this, "Timeout", /*swallowExitException*/ true);
|
||||
readonly immediateCallbacks = new Callbacks(this, "Immedidate");
|
||||
readonly pendingInstalls = new Callbacks(this, "PendingInstalls");
|
||||
readonly screenClears: number[] = [];
|
||||
|
||||
readonly watchUtils = createWatchUtils<TestFileWatcher, TestFsWatcher, Path>("PolledWatches", "FsWatches");
|
||||
@@ -861,15 +928,7 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost,
|
||||
}
|
||||
|
||||
runQueuedTimeoutCallbacks(timeoutId?: number) {
|
||||
try {
|
||||
this.timeoutCallbacks.invoke(timeoutId);
|
||||
}
|
||||
catch (e) {
|
||||
if (e.message === this.exitMessage) {
|
||||
return;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
this.timeoutCallbacks.invoke(timeoutId);
|
||||
}
|
||||
|
||||
runQueuedImmediateCallbacks() {
|
||||
@@ -884,6 +943,14 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost,
|
||||
this.immediateCallbacks.unregister(timeoutId);
|
||||
}
|
||||
|
||||
scheduleInstall(cb: TimeOutCallback, ...args: any[]) {
|
||||
this.pendingInstalls.register(cb, args);
|
||||
}
|
||||
|
||||
runPendingInstalls() {
|
||||
this.pendingInstalls.invoke();
|
||||
}
|
||||
|
||||
createDirectory(directoryName: string): void {
|
||||
const folder = this.toFsFolder(directoryName);
|
||||
|
||||
@@ -945,6 +1012,7 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost,
|
||||
|
||||
serializeOutput(baseline: string[]) {
|
||||
const output = this.getOutput();
|
||||
if (!this.output.length && !this.screenClears.length) return;
|
||||
let start = 0;
|
||||
baseline.push("Output::");
|
||||
for (const screenClear of this.screenClears) {
|
||||
@@ -957,31 +1025,42 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost,
|
||||
this.clearOutput();
|
||||
}
|
||||
|
||||
snap(): Map<Path, FSEntry> {
|
||||
const result = new Map<Path, FSEntry>();
|
||||
private snap() {
|
||||
this.serializedDiff = new Map<Path, FSEntry>();
|
||||
this.fs.forEach((value, key) => {
|
||||
const cloneValue = clone(value);
|
||||
if (isFsFolder(cloneValue)) {
|
||||
cloneValue.entries = cloneValue.entries.map(clone) as SortedArray<FSEntry>;
|
||||
}
|
||||
result.set(key, cloneValue);
|
||||
this.serializedDiff.set(key, cloneValue);
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
serializeState(baseline: string[], serializeOutput: SerializeOutputOrder) {
|
||||
if (serializeOutput === SerializeOutputOrder.BeforeDiff) this.serializeOutput(baseline);
|
||||
this.diff(baseline);
|
||||
if (serializeOutput === SerializeOutputOrder.AfterDiff) this.serializeOutput(baseline);
|
||||
this.serializeWatches(baseline);
|
||||
this.timeoutCallbacks.serialize(baseline);
|
||||
this.immediateCallbacks.serialize(baseline);
|
||||
this.pendingInstalls.serialize(baseline);
|
||||
}
|
||||
|
||||
writtenFiles?: Map<Path, number>;
|
||||
diff(baseline: string[], base = new Map<Path, FSEntry>()) {
|
||||
private serializedDiff = new Map<Path, FSEntry>();
|
||||
diff(baseline: string[]) {
|
||||
this.fs.forEach((newFsEntry, path) => {
|
||||
diffFsEntry(baseline, base.get(path), newFsEntry, this.inodes?.get(path), this.writtenFiles);
|
||||
diffFsEntry(baseline, this.serializedDiff.get(path), newFsEntry, this.inodes?.get(path), this.writtenFiles);
|
||||
});
|
||||
base.forEach((oldFsEntry, path) => {
|
||||
this.serializedDiff.forEach((oldFsEntry, path) => {
|
||||
const newFsEntry = this.fs.get(path);
|
||||
if (!newFsEntry) {
|
||||
diffFsEntry(baseline, oldFsEntry, newFsEntry, this.inodes?.get(path), this.writtenFiles);
|
||||
}
|
||||
});
|
||||
baseline.push("");
|
||||
this.snap();
|
||||
this.writtenFiles?.clear();
|
||||
}
|
||||
|
||||
serializeWatches(baseline?: string[]) {
|
||||
@@ -1006,14 +1085,13 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost,
|
||||
return fsEntry?.fullPath || realFullPath;
|
||||
}
|
||||
|
||||
readonly exitMessage = "System Exit";
|
||||
exitCode: number | undefined;
|
||||
readonly resolvePath = (s: string) => s;
|
||||
readonly getExecutingFilePath = () => this.executingFilePath;
|
||||
readonly getCurrentDirectory = () => this.currentDirectory;
|
||||
exit(exitCode?: number) {
|
||||
this.exitCode = exitCode;
|
||||
throw new Error(this.exitMessage);
|
||||
throw new Error(exitMessage);
|
||||
}
|
||||
getEnvironmentVariable(name: string) {
|
||||
return this.environmentVariables && this.environmentVariables.get(name) || "";
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import * as Harness from "../../_namespaces/Harness";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
createProjectService,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
createServerHost,
|
||||
File,
|
||||
@@ -11,6 +8,7 @@ import {
|
||||
extractTest,
|
||||
newLineCharacter,
|
||||
notImplementedHost,
|
||||
TestProjectService,
|
||||
} from "./extract/helpers";
|
||||
|
||||
const libFile: File = {
|
||||
@@ -415,7 +413,7 @@ function testConvertToAsyncFunction(it: Mocha.PendingTestFunction, caption: stri
|
||||
files.push(moduleFile);
|
||||
}
|
||||
const host = createServerHost(files);
|
||||
const projectService = createProjectService(host, { allowNonBaseliningLogger: true });
|
||||
const projectService = new TestProjectService(host);
|
||||
projectService.openClientFile(file.path);
|
||||
return ts.first(projectService.inferredProjects).getLanguageService();
|
||||
}
|
||||
|
||||
@@ -1,13 +1,44 @@
|
||||
import {
|
||||
incrementalVerifier,
|
||||
} from "../../../../harness/incrementalUtils";
|
||||
import {
|
||||
createHasErrorMessageLogger,
|
||||
} from "../../../../harness/tsserverLogger";
|
||||
import * as Harness from "../../../_namespaces/Harness";
|
||||
import * as ts from "../../../_namespaces/ts";
|
||||
import {
|
||||
createProjectService,
|
||||
} from "../../helpers/tsserver";
|
||||
customTypesMap,
|
||||
} from "../../helpers/typingsInstaller";
|
||||
import {
|
||||
createServerHost,
|
||||
libFile,
|
||||
TestServerHost,
|
||||
} from "../../helpers/virtualFileSystemWithWatch";
|
||||
|
||||
export interface TestProjectServiceOptions extends ts.server.ProjectServiceOptions {
|
||||
host: TestServerHost;
|
||||
}
|
||||
export type TestProjectServicePartialOptionsAndHost = Partial<Omit<TestProjectServiceOptions, "typingsInstaller" | "logger" | "host">> & Pick<TestProjectServiceOptions, "host">;
|
||||
|
||||
export class TestProjectService extends ts.server.ProjectService {
|
||||
constructor(optsOrHost: TestServerHost | TestProjectServicePartialOptionsAndHost) {
|
||||
// eslint-disable-next-line local/no-in-operator
|
||||
const opts = "host" in optsOrHost ?
|
||||
optsOrHost :
|
||||
{ host: optsOrHost };
|
||||
super({
|
||||
logger: createHasErrorMessageLogger(),
|
||||
session: undefined,
|
||||
cancellationToken: ts.server.nullCancellationToken,
|
||||
useSingleInferredProject: false,
|
||||
useInferredProjectPerProjectRoot: false,
|
||||
typesMapLocation: customTypesMap.path,
|
||||
incrementalVerifier,
|
||||
...opts,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
interface Range {
|
||||
pos: number;
|
||||
end: number;
|
||||
@@ -141,7 +172,7 @@ export function testExtractSymbol(caption: string, text: string, baselineFolder:
|
||||
|
||||
function makeProgram(f: { path: string; content: string; }, includeLib?: boolean) {
|
||||
const host = createServerHost(includeLib ? [f, libFile] : [f]); // libFile is expensive to parse repeatedly - only test when required
|
||||
const projectService = createProjectService(host, { allowNonBaseliningLogger: true });
|
||||
const projectService = new TestProjectService(host);
|
||||
projectService.openClientFile(f.path);
|
||||
const program = projectService.inferredProjects[0].getLanguageService().getProgram()!;
|
||||
const autoImportProvider = projectService.inferredProjects[0].getLanguageService().getAutoImportProvider();
|
||||
@@ -166,7 +197,7 @@ export function testExtractSymbolFailed(caption: string, text: string, descripti
|
||||
content: t.source,
|
||||
};
|
||||
const host = createServerHost([f, libFile]);
|
||||
const projectService = createProjectService(host, { allowNonBaseliningLogger: true });
|
||||
const projectService = new TestProjectService(host);
|
||||
projectService.openClientFile(f.path);
|
||||
const program = projectService.inferredProjects[0].getLanguageService().getProgram()!;
|
||||
const sourceFile = program.getSourceFile(f.path)!;
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
import * as Harness from "../../_namespaces/Harness";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
createProjectService,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
createServerHost,
|
||||
File,
|
||||
} from "../helpers/virtualFileSystemWithWatch";
|
||||
import {
|
||||
newLineCharacter,
|
||||
TestProjectService,
|
||||
} from "./extract/helpers";
|
||||
|
||||
describe("unittests:: services:: organizeImports", () => {
|
||||
@@ -985,7 +983,7 @@ export * from "lib";
|
||||
|
||||
function makeLanguageService(...files: File[]) {
|
||||
const host = createServerHost(files);
|
||||
const projectService = createProjectService(host, { useSingleInferredProject: true, allowNonBaseliningLogger: true });
|
||||
const projectService = new TestProjectService({ host, useSingleInferredProject: true });
|
||||
projectService.setCompilerOptionsForInferredProjects({ jsx: files.some(f => f.path.endsWith("x")) ? ts.JsxEmit.React : ts.JsxEmit.None });
|
||||
files.forEach(f => projectService.openClientFile(f.path));
|
||||
return projectService.inferredProjects[0].getLanguageService();
|
||||
|
||||
@@ -34,7 +34,7 @@ import {
|
||||
import {
|
||||
changeToHostTrackingWrittenFiles,
|
||||
libFile,
|
||||
TestServerHost,
|
||||
SerializeOutputOrder,
|
||||
} from "../helpers/virtualFileSystemWithWatch";
|
||||
|
||||
describe("unittests:: tsbuild:: on 'sample1' project", () => {
|
||||
@@ -317,7 +317,6 @@ describe("unittests:: tsbuild:: on 'sample1' project", () => {
|
||||
|
||||
it("building using getNextInvalidatedProject", () => {
|
||||
const baseline: string[] = [];
|
||||
let oldSnap: ReturnType<TestServerHost["snap"]> | undefined;
|
||||
const system = changeToHostTrackingWrittenFiles(
|
||||
fakes.patchHostForBuildInfoReadWrite(
|
||||
getSysForSampleProjectReferences(),
|
||||
@@ -327,7 +326,7 @@ describe("unittests:: tsbuild:: on 'sample1' project", () => {
|
||||
const host = createSolutionBuilderHostForBaseline(system);
|
||||
const builder = ts.createSolutionBuilder(host, ["tests"], {});
|
||||
baseline.push("Input::");
|
||||
baselineState();
|
||||
system.serializeState(baseline, SerializeOutputOrder.BeforeDiff);
|
||||
verifyBuildNextResult(); // core
|
||||
verifyBuildNextResult(); // logic
|
||||
verifyBuildNextResult(); // tests
|
||||
@@ -338,14 +337,7 @@ describe("unittests:: tsbuild:: on 'sample1' project", () => {
|
||||
const project = builder.getNextInvalidatedProject();
|
||||
const result = project && project.done();
|
||||
baseline.push(`Project Result:: ${jsonToReadableText({ project: project?.project, result })}`);
|
||||
baselineState();
|
||||
}
|
||||
|
||||
function baselineState() {
|
||||
system.serializeOutput(baseline);
|
||||
system.diff(baseline, oldSnap);
|
||||
system.writtenFiles.clear();
|
||||
oldSnap = system.snap();
|
||||
system.serializeState(baseline, SerializeOutputOrder.BeforeDiff);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -376,7 +368,6 @@ describe("unittests:: tsbuild:: on 'sample1' project", () => {
|
||||
describe("project invalidation", () => {
|
||||
it("invalidates projects correctly", () => {
|
||||
const baseline: string[] = [];
|
||||
let oldSnap: ReturnType<TestServerHost["snap"]> | undefined;
|
||||
const system = changeToHostTrackingWrittenFiles(
|
||||
fakes.patchHostForBuildInfoReadWrite(
|
||||
getSysForSampleProjectReferences(),
|
||||
@@ -414,10 +405,7 @@ describe("unittests:: tsbuild:: on 'sample1' project", () => {
|
||||
|
||||
function baselineState(heading: string) {
|
||||
baseline.push(heading);
|
||||
system.serializeOutput(baseline);
|
||||
system.diff(baseline, oldSnap);
|
||||
system.writtenFiles.clear();
|
||||
oldSnap = system.snap();
|
||||
system.serializeState(baseline, SerializeOutputOrder.BeforeDiff);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -35,7 +35,7 @@ describe("unittests:: tsbuildWatch:: watchMode:: program updates", () => {
|
||||
});
|
||||
|
||||
it("verify building references watches only those projects", () => {
|
||||
const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(getSysForSampleProjectReferences());
|
||||
const { sys, baseline, cb, getPrograms } = createBaseline(getSysForSampleProjectReferences());
|
||||
const host = createSolutionBuilderWithWatchHostForBaseline(sys, cb);
|
||||
const solutionBuilder = ts.createSolutionBuilderWithWatch(host, ["tests"], { watch: true });
|
||||
solutionBuilder.buildReferences("tests");
|
||||
@@ -45,7 +45,6 @@ describe("unittests:: tsbuildWatch:: watchMode:: program updates", () => {
|
||||
commandLineArgs: ["--b", "--w"],
|
||||
sys,
|
||||
baseline,
|
||||
oldSnap,
|
||||
getPrograms,
|
||||
watchOrSolution: solutionBuilder,
|
||||
});
|
||||
|
||||
@@ -54,7 +54,7 @@ export enum e2 { }
|
||||
export function f22() { } // trailing`,
|
||||
};
|
||||
const commandLineArgs = ["--b", "--w"];
|
||||
const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem([libFile, solution, sharedConfig, sharedIndex, webpackConfig, webpackIndex], { currentDirectory: "/user/username/projects/myproject" }));
|
||||
const { sys, baseline, cb, getPrograms } = createBaseline(createWatchedSystem([libFile, solution, sharedConfig, sharedIndex, webpackConfig, webpackIndex], { currentDirectory: "/user/username/projects/myproject" }));
|
||||
const buildHost = createSolutionBuilderWithWatchHostForBaseline(sys, cb);
|
||||
buildHost.getCustomTransformers = getCustomTransformers;
|
||||
const builder = ts.createSolutionBuilderWithWatch(buildHost, [solution.path], { verbose: true });
|
||||
@@ -65,7 +65,6 @@ export function f22() { } // trailing`,
|
||||
commandLineArgs,
|
||||
sys,
|
||||
baseline,
|
||||
oldSnap,
|
||||
getPrograms,
|
||||
edits: [
|
||||
{
|
||||
|
||||
@@ -27,7 +27,7 @@ describe("unittests:: tsbuildWatch:: watchEnvironment:: tsbuild:: watchMode:: wi
|
||||
const allPkgFiles = pkgs(pkgFiles);
|
||||
const system = createWatchedSystem([libFile, typing, ...flatArray(allPkgFiles)], { currentDirectory: project });
|
||||
writePkgReferences(system);
|
||||
const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(system);
|
||||
const { sys, baseline, cb, getPrograms } = createBaseline(system);
|
||||
const host = createSolutionBuilderWithWatchHostForBaseline(sys, cb);
|
||||
const solutionBuilder = ts.createSolutionBuilderWithWatch(host, ["tsconfig.json"], { watch: true, verbose: true });
|
||||
solutionBuilder.build();
|
||||
@@ -37,7 +37,6 @@ describe("unittests:: tsbuildWatch:: watchEnvironment:: tsbuild:: watchMode:: wi
|
||||
commandLineArgs: ["--b", "--w"],
|
||||
sys,
|
||||
baseline,
|
||||
oldSnap,
|
||||
getPrograms,
|
||||
edits: [
|
||||
{
|
||||
@@ -77,7 +76,7 @@ describe("unittests:: tsbuildWatch:: watchEnvironment:: tsbuild:: watchMode:: wi
|
||||
{
|
||||
caption: "modify typing file",
|
||||
edit: sys => sys.writeFile(typing.path, `${typing.content}export const typing1 = 10;`),
|
||||
timeouts: sys => sys.logTimeoutQueueLength(),
|
||||
timeouts: ts.noop,
|
||||
},
|
||||
],
|
||||
watchOrSolution: solutionBuilder,
|
||||
|
||||
@@ -55,7 +55,7 @@ describe("unittests:: tsc:: builder cancellationToken", () => {
|
||||
path: `/user/username/projects/myproject/tsconfig.json`,
|
||||
content: jsonToReadableText({ compilerOptions: { incremental: true, declaration: true } }),
|
||||
};
|
||||
const { sys, baseline, oldSnap: originalSnap } = createBaseline(createWatchedSystem(
|
||||
const { sys, baseline } = createBaseline(createWatchedSystem(
|
||||
[aFile, bFile, cFile, dFile, config, libFile],
|
||||
{ currentDirectory: "/user/username/projects/myproject" },
|
||||
));
|
||||
@@ -73,7 +73,6 @@ describe("unittests:: tsc:: builder cancellationToken", () => {
|
||||
let programs: CommandLineProgram[] = ts.emptyArray;
|
||||
let oldPrograms: CommandLineProgram[] = ts.emptyArray;
|
||||
let builderProgram: ts.EmitAndSemanticDiagnosticsBuilderProgram = undefined!;
|
||||
let oldSnap = originalSnap;
|
||||
let cancel = false;
|
||||
const cancellationToken: ts.CancellationToken = {
|
||||
isCancellationRequested: () => cancel,
|
||||
@@ -90,7 +89,7 @@ describe("unittests:: tsc:: builder cancellationToken", () => {
|
||||
|
||||
// Cancel on first semantic operation
|
||||
// Change
|
||||
oldSnap = applyEdit(
|
||||
applyEdit(
|
||||
sys,
|
||||
baseline,
|
||||
sys => sys.appendFile(cFile.path, "export function foo() {}"),
|
||||
@@ -114,7 +113,6 @@ describe("unittests:: tsc:: builder cancellationToken", () => {
|
||||
getPrograms: () => programs,
|
||||
oldPrograms,
|
||||
sys,
|
||||
oldSnap,
|
||||
});
|
||||
|
||||
// Normal emit again
|
||||
@@ -128,7 +126,7 @@ describe("unittests:: tsc:: builder cancellationToken", () => {
|
||||
Harness.Baseline.runBaseline(`tsc/cancellationToken/${scenario.split(" ").join("-")}.js`, baseline.join("\r\n"));
|
||||
|
||||
function noChange(caption: string) {
|
||||
oldSnap = applyEdit(sys, baseline, ts.noop, caption);
|
||||
applyEdit(sys, baseline, ts.noop, caption);
|
||||
}
|
||||
|
||||
function updatePrograms() {
|
||||
@@ -162,7 +160,6 @@ describe("unittests:: tsc:: builder cancellationToken", () => {
|
||||
getPrograms: () => programs,
|
||||
oldPrograms,
|
||||
sys,
|
||||
oldSnap,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ import {
|
||||
import {
|
||||
applyEdit,
|
||||
createBaseline,
|
||||
SystemSnap,
|
||||
verifyTscWatch,
|
||||
watchBaseline,
|
||||
} from "../helpers/tscWatch";
|
||||
@@ -52,21 +51,21 @@ describe("unittests:: tsc-watch:: emit file --incremental", () => {
|
||||
{ subScenario, files, optionsToExtend, modifyFs }: VerifyIncrementalWatchEmitInput,
|
||||
incremental: boolean,
|
||||
) {
|
||||
const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem(files(), { currentDirectory: project }));
|
||||
const { sys, baseline, cb, getPrograms } = createBaseline(createWatchedSystem(files(), { currentDirectory: project }));
|
||||
if (incremental) sys.exit = exitCode => sys.exitCode = exitCode;
|
||||
const argsToPass = [incremental ? "-i" : "-w", ...(optionsToExtend || ts.emptyArray)];
|
||||
baseline.push(`${sys.getExecutingFilePath()} ${argsToPass.join(" ")}`);
|
||||
let oldPrograms: readonly CommandLineProgram[] = ts.emptyArray;
|
||||
build(oldSnap);
|
||||
build();
|
||||
|
||||
if (modifyFs) {
|
||||
const oldSnap = applyEdit(sys, baseline, modifyFs);
|
||||
build(oldSnap);
|
||||
applyEdit(sys, baseline, modifyFs);
|
||||
build();
|
||||
}
|
||||
|
||||
Harness.Baseline.runBaseline(`${ts.isBuild(argsToPass) ? "tsbuild/watchMode" : "tscWatch"}/incremental/${subScenario.split(" ").join("-")}-${incremental ? "incremental" : "watch"}.js`, baseline.join("\r\n"));
|
||||
|
||||
function build(oldSnap: SystemSnap) {
|
||||
function build() {
|
||||
const closer = ts.executeCommandLine(
|
||||
sys,
|
||||
cb,
|
||||
@@ -77,7 +76,6 @@ describe("unittests:: tsc-watch:: emit file --incremental", () => {
|
||||
getPrograms,
|
||||
oldPrograms,
|
||||
sys,
|
||||
oldSnap,
|
||||
});
|
||||
if (closer) closer.close();
|
||||
}
|
||||
|
||||
@@ -625,7 +625,7 @@ export class A {
|
||||
path: "/a/d/f3.ts",
|
||||
content: "export let y = 1;",
|
||||
};
|
||||
const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem([libFile, file1, file2, file3]));
|
||||
const { sys, baseline, cb, getPrograms } = createBaseline(createWatchedSystem([libFile, file1, file2, file3]));
|
||||
const host = createWatchCompilerHostOfFilesAndCompilerOptionsForBaseline({
|
||||
rootFiles: [file2.path, file3.path],
|
||||
system: sys,
|
||||
@@ -640,11 +640,9 @@ export class A {
|
||||
getPrograms,
|
||||
oldPrograms: ts.emptyArray,
|
||||
sys,
|
||||
oldSnap,
|
||||
});
|
||||
|
||||
const { cb: cb2, getPrograms: getPrograms2 } = commandLineCallbacks(sys);
|
||||
const oldSnap2 = sys.snap();
|
||||
baseline.push("createing separate watcher");
|
||||
ts.createWatchProgram(createWatchCompilerHostOfFilesAndCompilerOptionsForBaseline({
|
||||
rootFiles: [file1.path],
|
||||
@@ -658,10 +656,8 @@ export class A {
|
||||
getPrograms: getPrograms2,
|
||||
oldPrograms: ts.emptyArray,
|
||||
sys,
|
||||
oldSnap: oldSnap2,
|
||||
});
|
||||
|
||||
sys.logTimeoutQueueLength();
|
||||
baseline.push(`First program is not updated:: ${getPrograms() === ts.emptyArray}`);
|
||||
baseline.push(`Second program is not updated:: ${getPrograms2() === ts.emptyArray}`);
|
||||
Harness.Baseline.runBaseline(`tscWatch/${scenario}/two-watch-programs-are-not-affected-by-each-other.js`, baseline.join("\r\n"));
|
||||
@@ -1205,7 +1201,7 @@ declare const eval: any`,
|
||||
path: "/a/compile",
|
||||
content: "let x = 1",
|
||||
};
|
||||
const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem([f, libFile]));
|
||||
const { sys, baseline, cb, getPrograms } = createBaseline(createWatchedSystem([f, libFile]));
|
||||
const watch = ts.createWatchProgram(createWatchCompilerHostOfFilesAndCompilerOptionsForBaseline({
|
||||
rootFiles: [f.path],
|
||||
system: sys,
|
||||
@@ -1219,7 +1215,6 @@ declare const eval: any`,
|
||||
commandLineArgs: ["--w", f.path],
|
||||
sys,
|
||||
baseline,
|
||||
oldSnap,
|
||||
getPrograms,
|
||||
watchOrSolution: watch,
|
||||
});
|
||||
@@ -2087,7 +2082,7 @@ import { x } from "../b";`,
|
||||
{
|
||||
caption: "Add excluded file to project1",
|
||||
edit: sys => sys.ensureFileOrFolder({ path: `/user/username/projects/myproject/projects/project1/temp/file.d.ts`, content: `declare class file {}` }),
|
||||
timeouts: sys => sys.logTimeoutQueueLength(),
|
||||
timeouts: ts.noop,
|
||||
},
|
||||
{
|
||||
caption: "Delete output of class3",
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
import {
|
||||
noop,
|
||||
} from "../../_namespaces/ts";
|
||||
import {
|
||||
jsonToReadableText,
|
||||
} from "../helpers";
|
||||
@@ -43,7 +46,7 @@ describe("unittests:: tsc-watch:: projects with references: invoking when refere
|
||||
},
|
||||
// not ideal, but currently because of d.ts but no new file is written
|
||||
// There will be timeout queued even though file contents are same
|
||||
timeouts: sys => sys.logTimeoutQueueLength(),
|
||||
timeouts: noop,
|
||||
},
|
||||
{
|
||||
caption: "non local edit in logic ts, and build logic",
|
||||
|
||||
@@ -31,7 +31,7 @@ describe("unittests:: tsc-watch:: resolutionCache:: tsc-watch module resolution
|
||||
content: `foo()`,
|
||||
};
|
||||
|
||||
const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem([root, imported, libFile]));
|
||||
const { sys, baseline, cb, getPrograms } = createBaseline(createWatchedSystem([root, imported, libFile]));
|
||||
const host = createWatchCompilerHostOfFilesAndCompilerOptionsForBaseline({
|
||||
rootFiles: [root.path],
|
||||
system: sys,
|
||||
@@ -48,7 +48,6 @@ describe("unittests:: tsc-watch:: resolutionCache:: tsc-watch module resolution
|
||||
commandLineArgs: ["--w", root.path],
|
||||
sys,
|
||||
baseline,
|
||||
oldSnap,
|
||||
getPrograms,
|
||||
edits: [
|
||||
{
|
||||
@@ -117,7 +116,7 @@ describe("unittests:: tsc-watch:: resolutionCache:: tsc-watch module resolution
|
||||
content: `export const y = 1;`,
|
||||
};
|
||||
|
||||
const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem([root, libFile]));
|
||||
const { sys, baseline, cb, getPrograms } = createBaseline(createWatchedSystem([root, libFile]));
|
||||
const host = createWatchCompilerHostOfFilesAndCompilerOptionsForBaseline({
|
||||
rootFiles: [root.path],
|
||||
system: sys,
|
||||
@@ -146,7 +145,6 @@ describe("unittests:: tsc-watch:: resolutionCache:: tsc-watch module resolution
|
||||
commandLineArgs: ["--w", root.path],
|
||||
sys,
|
||||
baseline,
|
||||
oldSnap,
|
||||
getPrograms,
|
||||
edits: [{
|
||||
caption: "write imported file",
|
||||
@@ -175,7 +173,7 @@ describe("unittests:: tsc-watch:: resolutionCache:: tsc-watch module resolution
|
||||
content: `export const y = 1;export const x = 10;`,
|
||||
};
|
||||
|
||||
const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem([root, imported, libFile]));
|
||||
const { sys, baseline, cb, getPrograms } = createBaseline(createWatchedSystem([root, imported, libFile]));
|
||||
const host = createWatchCompilerHostOfFilesAndCompilerOptionsForBaseline({
|
||||
rootFiles: [root.path],
|
||||
system: sys,
|
||||
@@ -202,7 +200,6 @@ describe("unittests:: tsc-watch:: resolutionCache:: tsc-watch module resolution
|
||||
commandLineArgs: ["--w", root.path],
|
||||
sys,
|
||||
baseline,
|
||||
oldSnap,
|
||||
getPrograms,
|
||||
edits: [
|
||||
{
|
||||
@@ -411,7 +408,7 @@ declare module "fs" {
|
||||
path: `/user/username/projects/myproject/node_modules/.cache/babel-loader/89c02171edab901b9926470ba6d5677e.ts`,
|
||||
content: jsonToReadableText({ something: 10 }),
|
||||
}),
|
||||
timeouts: sys => sys.logTimeoutQueueLength(),
|
||||
timeouts: ts.noop,
|
||||
},
|
||||
],
|
||||
});
|
||||
@@ -467,8 +464,7 @@ declare namespace myapp {
|
||||
{
|
||||
caption: "No change, just check program",
|
||||
edit: ts.noop,
|
||||
timeouts: (sys, [[oldProgram, oldBuilderProgram]], watchorSolution) => {
|
||||
sys.logTimeoutQueueLength();
|
||||
timeouts: (_sys, [[oldProgram, oldBuilderProgram]], watchorSolution) => {
|
||||
const newProgram = (watchorSolution as ts.WatchOfConfigFile<ts.EmitAndSemanticDiagnosticsBuilderProgram>).getProgram();
|
||||
assert.strictEqual(newProgram, oldBuilderProgram, "No change so builder program should be same");
|
||||
assert.strictEqual(newProgram.getProgram(), oldProgram, "No change so program should be same");
|
||||
|
||||
@@ -32,7 +32,7 @@ describe("unittests:: tsc-watch:: watchAPI:: with sourceOfProjectReferenceRedire
|
||||
}
|
||||
|
||||
function verifyWatch({ files, config, subScenario }: VerifyWatchInput, alreadyBuilt: boolean) {
|
||||
const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(
|
||||
const { sys, baseline, cb, getPrograms } = createBaseline(
|
||||
createWatchedSystem(files),
|
||||
alreadyBuilt ? (sys, originalRead) => {
|
||||
solutionBuildWithBaseline(sys, [config], originalRead);
|
||||
@@ -52,7 +52,6 @@ describe("unittests:: tsc-watch:: watchAPI:: with sourceOfProjectReferenceRedire
|
||||
commandLineArgs: ["--w", "--p", config],
|
||||
sys,
|
||||
baseline,
|
||||
oldSnap,
|
||||
getPrograms,
|
||||
watchOrSolution: watch,
|
||||
useSourceOfProjectReferenceRedirect: ts.returnTrue,
|
||||
|
||||
@@ -45,7 +45,7 @@ describe("unittests:: tsc-watch:: watchAPI:: tsc-watch with custom module resolu
|
||||
path: `/user/username/projects/myproject/settings.json`,
|
||||
content: jsonToReadableText({ content: "Print this" }),
|
||||
};
|
||||
const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem(
|
||||
const { sys, baseline, cb, getPrograms } = createBaseline(createWatchedSystem(
|
||||
[libFile, mainFile, config, settingsJson],
|
||||
{ currentDirectory: "/user/username/projects/myproject" },
|
||||
));
|
||||
@@ -72,7 +72,6 @@ describe("unittests:: tsc-watch:: watchAPI:: tsc-watch with custom module resolu
|
||||
commandLineArgs: ["--w", "--p", config.path],
|
||||
sys,
|
||||
baseline,
|
||||
oldSnap,
|
||||
getPrograms,
|
||||
watchOrSolution: watch,
|
||||
});
|
||||
@@ -81,7 +80,7 @@ describe("unittests:: tsc-watch:: watchAPI:: tsc-watch with custom module resolu
|
||||
describe("hasInvalidatedResolutions", () => {
|
||||
function verifyWatch(subScenario: string, implementHasInvalidatedResolution: boolean) {
|
||||
it(subScenario, () => {
|
||||
const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem({
|
||||
const { sys, baseline, cb, getPrograms } = createBaseline(createWatchedSystem({
|
||||
[`/user/username/projects/myproject/tsconfig.json`]: jsonToReadableText({
|
||||
compilerOptions: { traceResolution: true, extendedDiagnostics: true },
|
||||
files: ["main.ts"],
|
||||
@@ -105,7 +104,6 @@ describe("unittests:: tsc-watch:: watchAPI:: tsc-watch with custom module resolu
|
||||
commandLineArgs: ["--w"],
|
||||
sys,
|
||||
baseline,
|
||||
oldSnap,
|
||||
getPrograms,
|
||||
edits: [
|
||||
{
|
||||
@@ -149,7 +147,7 @@ describe("unittests:: tsc-watch:: watchAPI:: tsc-watch expose error count to wat
|
||||
path: `/user/username/projects/myproject/index.ts`,
|
||||
content: "let compiler = new Compiler(); for (let i = 0; j < 5; i++) {}",
|
||||
};
|
||||
const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem(
|
||||
const { sys, baseline, cb, getPrograms } = createBaseline(createWatchedSystem(
|
||||
[libFile, mainFile, config],
|
||||
{ currentDirectory: "/user/username/projects/myproject" },
|
||||
));
|
||||
@@ -172,7 +170,6 @@ describe("unittests:: tsc-watch:: watchAPI:: tsc-watch expose error count to wat
|
||||
commandLineArgs: ["--w", "--p", config.path],
|
||||
sys,
|
||||
baseline,
|
||||
oldSnap,
|
||||
getPrograms,
|
||||
watchOrSolution: watch,
|
||||
});
|
||||
@@ -189,7 +186,7 @@ describe("unittests:: tsc-watch:: watchAPI:: when watchHost does not implement s
|
||||
path: `/user/username/projects/myproject/main.ts`,
|
||||
content: "const x = 10;",
|
||||
};
|
||||
const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(createWatchedSystem([config, mainFile, libFile]));
|
||||
const { sys, baseline, cb, getPrograms } = createBaseline(createWatchedSystem([config, mainFile, libFile]));
|
||||
const host = createWatchCompilerHostOfConfigFileForBaseline({
|
||||
configFileName: config.path,
|
||||
system: sys,
|
||||
@@ -204,13 +201,11 @@ describe("unittests:: tsc-watch:: watchAPI:: when watchHost does not implement s
|
||||
commandLineArgs: ["--w", "--p", config.path],
|
||||
sys,
|
||||
baseline,
|
||||
oldSnap,
|
||||
getPrograms,
|
||||
edits: [{
|
||||
caption: "Write a file",
|
||||
edit: sys => sys.writeFile(`/user/username/projects/myproject/bar.ts`, "const y =10;"),
|
||||
timeouts: sys => {
|
||||
sys.logTimeoutQueueLength();
|
||||
timeouts: () => {
|
||||
watch.getProgram();
|
||||
},
|
||||
}],
|
||||
@@ -233,7 +228,7 @@ describe("unittests:: tsc-watch:: watchAPI:: when watchHost can add extraFileExt
|
||||
path: `/user/username/projects/myproject/other.vue`,
|
||||
content: "",
|
||||
};
|
||||
const { sys, baseline, oldSnap, cb, getPrograms } = createBaseline(
|
||||
const { sys, baseline, cb, getPrograms } = createBaseline(
|
||||
createWatchedSystem([config, mainFile, otherFile, libFile]),
|
||||
);
|
||||
const host = createWatchCompilerHostOfConfigFileForBaseline({
|
||||
@@ -250,7 +245,6 @@ describe("unittests:: tsc-watch:: watchAPI:: when watchHost can add extraFileExt
|
||||
commandLineArgs: ["--w", "--p", config.path],
|
||||
sys,
|
||||
baseline,
|
||||
oldSnap,
|
||||
getPrograms,
|
||||
edits: [{
|
||||
caption: "Write a file",
|
||||
@@ -293,7 +287,6 @@ describe("unittests:: tsc-watch:: watchAPI:: when watchHost uses createSemanticD
|
||||
) {
|
||||
const { cb, getPrograms } = commandLineCallbacks(sys);
|
||||
baseline.push(`tsc --w${optionsToExtend?.noEmit ? " --noEmit" : ""}`);
|
||||
const oldSnap = sys.snap();
|
||||
const host = createWatchCompilerHostOfConfigFileForBaseline<T>({
|
||||
configFileName: config.path,
|
||||
optionsToExtend,
|
||||
@@ -307,7 +300,6 @@ describe("unittests:: tsc-watch:: watchAPI:: when watchHost uses createSemanticD
|
||||
getPrograms,
|
||||
oldPrograms: ts.emptyArray,
|
||||
sys,
|
||||
oldSnap,
|
||||
});
|
||||
watch.close();
|
||||
}
|
||||
@@ -354,7 +346,7 @@ describe("unittests:: tsc-watch:: watchAPI:: when watchHost uses createSemanticD
|
||||
}
|
||||
|
||||
it("verifies that noEmit is handled on createSemanticDiagnosticsBuilderProgram and typechecking happens only on affected files", () => {
|
||||
const { sys, baseline, oldSnap, cb, getPrograms, config, mainFile } = createSystem("{}", "export const x = 10;");
|
||||
const { sys, baseline, cb, getPrograms, config, mainFile } = createSystem("{}", "export const x = 10;");
|
||||
const host = createWatchCompilerHostOfConfigFileForBaseline({
|
||||
configFileName: config.path,
|
||||
optionsToExtend: { noEmit: true },
|
||||
@@ -369,7 +361,6 @@ describe("unittests:: tsc-watch:: watchAPI:: when watchHost uses createSemanticD
|
||||
commandLineArgs: ["--w", "--p", config.path],
|
||||
sys,
|
||||
baseline,
|
||||
oldSnap,
|
||||
getPrograms,
|
||||
edits: [{
|
||||
caption: "Modify a file",
|
||||
@@ -469,7 +460,6 @@ describe("unittests:: tsc-watch:: watchAPI:: when watchHost uses createSemanticD
|
||||
applyEdit(sys, baseline, sys => sys.writeFile(mainFile.path, "export const x = 10;"), "Fix error");
|
||||
|
||||
const { cb, getPrograms } = commandLineCallbacks(sys);
|
||||
const oldSnap = sys.snap();
|
||||
const reportDiagnostic = ts.createDiagnosticReporter(sys, /*pretty*/ true);
|
||||
const reportWatchStatus = ts.createWatchStatusReporter(sys, /*pretty*/ true);
|
||||
const host = ts.createWatchCompilerHostOfConfigFile({
|
||||
@@ -498,7 +488,6 @@ describe("unittests:: tsc-watch:: watchAPI:: when watchHost uses createSemanticD
|
||||
getPrograms,
|
||||
oldPrograms: ts.emptyArray,
|
||||
sys,
|
||||
oldSnap,
|
||||
});
|
||||
Harness.Baseline.runBaseline(`tscWatch/watchApi/semantic-builder-emitOnlyDts.js`, baseline.join("\r\n"));
|
||||
});
|
||||
@@ -585,12 +574,12 @@ describe("unittests:: tsc-watch:: watchAPI:: when getParsedCommandLine is implem
|
||||
{
|
||||
caption: "Add excluded file to project1",
|
||||
edit: sys => sys.ensureFileOrFolder({ path: `/user/username/projects/myproject/projects/project1/temp/file.d.ts`, content: `declare class file {}` }),
|
||||
timeouts: sys => sys.logTimeoutQueueLength(),
|
||||
timeouts: ts.noop,
|
||||
},
|
||||
{
|
||||
caption: "Add output of class3",
|
||||
edit: sys => sys.writeFile(`/user/username/projects/myproject/projects/project1/class3.d.ts`, `declare class class3 {}`),
|
||||
timeouts: sys => sys.logTimeoutQueueLength(),
|
||||
timeouts: ts.noop,
|
||||
},
|
||||
],
|
||||
watchOrSolution: watch,
|
||||
@@ -622,7 +611,7 @@ describe("unittests:: tsc-watch:: watchAPI:: when getParsedCommandLine is implem
|
||||
{
|
||||
caption: "Add excluded file to project1",
|
||||
edit: sys => sys.ensureFileOrFolder({ path: `/user/username/projects/myproject/projects/project1/temp/file.d.ts`, content: `declare class file {}` }),
|
||||
timeouts: sys => sys.logTimeoutQueueLength(),
|
||||
timeouts: ts.noop,
|
||||
},
|
||||
{
|
||||
caption: "Delete output of class3",
|
||||
@@ -684,7 +673,7 @@ describe("unittests:: tsc-watch:: watchAPI:: when builder emit occurs with emitO
|
||||
program.emit(/*targetSourceFile*/ undefined, /*writeFile*/ undefined, /*cancellationToken*/ undefined, /*emitOnlyDtsFiles*/ true);
|
||||
baseline.cb(program);
|
||||
},
|
||||
timeouts: sys => sys.logTimeoutQueueLength(),
|
||||
timeouts: ts.noop,
|
||||
},
|
||||
{
|
||||
caption: "Emit all files",
|
||||
@@ -693,7 +682,7 @@ describe("unittests:: tsc-watch:: watchAPI:: when builder emit occurs with emitO
|
||||
program.emit();
|
||||
baseline.cb(program);
|
||||
},
|
||||
timeouts: sys => sys.logTimeoutQueueLength(),
|
||||
timeouts: ts.noop,
|
||||
},
|
||||
{
|
||||
caption: "Emit with emitOnlyDts shouldnt emit anything",
|
||||
@@ -702,7 +691,7 @@ describe("unittests:: tsc-watch:: watchAPI:: when builder emit occurs with emitO
|
||||
program.emit(/*targetSourceFile*/ undefined, /*writeFile*/ undefined, /*cancellationToken*/ undefined, /*emitOnlyDtsFiles*/ true);
|
||||
baseline.cb(program);
|
||||
},
|
||||
timeouts: sys => sys.logTimeoutQueueLength(),
|
||||
timeouts: ts.noop,
|
||||
},
|
||||
{
|
||||
caption: "Emit full should not emit anything",
|
||||
@@ -711,7 +700,7 @@ describe("unittests:: tsc-watch:: watchAPI:: when builder emit occurs with emitO
|
||||
program.emit();
|
||||
baseline.cb(program);
|
||||
},
|
||||
timeouts: sys => sys.logTimeoutQueueLength(),
|
||||
timeouts: ts.noop,
|
||||
},
|
||||
],
|
||||
watchOrSolution: watch,
|
||||
|
||||
@@ -282,17 +282,17 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po
|
||||
caption: "Start npm install",
|
||||
// npm install
|
||||
edit: sys => sys.createDirectory(`/user/username/projects/myproject/node_modules`),
|
||||
timeouts: sys => sys.logTimeoutQueueLength(), // To update folder structure
|
||||
timeouts: ts.noop, // To update folder structure
|
||||
},
|
||||
{
|
||||
caption: "npm install folder creation of file2",
|
||||
edit: sys => sys.createDirectory(`/user/username/projects/myproject/node_modules/file2`),
|
||||
timeouts: sys => sys.logTimeoutQueueLength(), // To update folder structure
|
||||
timeouts: ts.noop, // To update folder structure
|
||||
},
|
||||
{
|
||||
caption: "npm install index file in file2",
|
||||
edit: sys => sys.writeFile(`/user/username/projects/myproject/node_modules/file2/index.d.ts`, `export const x = 10;`),
|
||||
timeouts: sys => sys.logTimeoutQueueLength(), // To update folder structure
|
||||
timeouts: ts.noop, // To update folder structure
|
||||
},
|
||||
{
|
||||
caption: "Updates the program",
|
||||
@@ -503,7 +503,7 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po
|
||||
{
|
||||
caption: "Change foo",
|
||||
edit: sys => sys.replaceFileText(`/user/username/projects/myproject/node_modules/bar/foo.d.ts`, "foo", "fooBar"),
|
||||
timeouts: sys => sys.logTimeoutQueueLength(),
|
||||
timeouts: ts.noop,
|
||||
},
|
||||
],
|
||||
});
|
||||
@@ -517,7 +517,7 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po
|
||||
{
|
||||
caption: "delete fooBar",
|
||||
edit: sys => sys.deleteFile(`/user/username/projects/myproject/node_modules/bar/fooBar.d.ts`),
|
||||
timeouts: sys => sys.logTimeoutQueueLength(),
|
||||
timeouts: ts.noop,
|
||||
},
|
||||
],
|
||||
});
|
||||
@@ -536,7 +536,7 @@ describe("unittests:: tsc-watch:: watchEnvironment:: tsc-watch with different po
|
||||
{
|
||||
caption: "add new folder to temp",
|
||||
edit: sys => sys.ensureFileOrFolder({ path: `/user/username/projects/myproject/node_modules/bar/temp/fooBar/index.d.ts`, content: "export function temp(): string;" }),
|
||||
timeouts: sys => sys.logTimeoutQueueLength(),
|
||||
timeouts: ts.noop,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
commonFile1,
|
||||
@@ -8,7 +5,7 @@ import {
|
||||
} from "../helpers/tscWatch";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createSession,
|
||||
TestSession,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
createServerHost,
|
||||
@@ -36,7 +33,7 @@ ${file.content}`;
|
||||
content: "let z = 1;",
|
||||
};
|
||||
const host = createServerHost([app, file3, commonFile1, commonFile2, libFile, configFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
session.executeCommandSeq<ts.server.protocol.OpenRequest>({
|
||||
command: ts.server.protocol.CommandTypes.Open,
|
||||
arguments: { file: app.path },
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
jsonToReadableText,
|
||||
} from "../helpers";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createSession,
|
||||
openFilesForSession,
|
||||
TestSession,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
createServerHost,
|
||||
@@ -374,7 +371,7 @@ describe("unittests:: tsserver:: autoImportProvider - monorepo", () => {
|
||||
|
||||
function setup(files: File[]) {
|
||||
const host = createServerHost(files);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
const projectService = session.getProjectService();
|
||||
return {
|
||||
host,
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
dedent,
|
||||
@@ -10,9 +7,9 @@ import {
|
||||
} from "../helpers";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createSession,
|
||||
openFilesForSession,
|
||||
protocolFileLocationFromSubstring,
|
||||
TestSession,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
createServerHost,
|
||||
@@ -35,12 +32,11 @@ describe("unittests:: tsserver:: auxiliaryProject::", () => {
|
||||
content: `export class B {}`,
|
||||
};
|
||||
const host = createServerHost([aTs, bDts, bJs]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const projectService = session.getProjectService();
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([aTs], session);
|
||||
|
||||
// Open file is in inferred project
|
||||
const inferredProject = projectService.inferredProjects[0];
|
||||
const inferredProject = session.getProjectService().inferredProjects[0];
|
||||
|
||||
// getNoDtsResolutionProject will create an AuxiliaryProject with a.ts and b.js
|
||||
session.executeCommandSeq<ts.server.protocol.FindSourceDefinitionRequest>({
|
||||
@@ -53,7 +49,7 @@ describe("unittests:: tsserver:: auxiliaryProject::", () => {
|
||||
// The AuxiliaryProject should never be the default project for anything, so
|
||||
// the ScriptInfo should still report being an orphan, and getting its default
|
||||
// project should throw.
|
||||
const bJsScriptInfo = ts.Debug.checkDefined(projectService.getScriptInfo(bJs.path));
|
||||
const bJsScriptInfo = ts.Debug.checkDefined(session.getProjectService().getScriptInfo(bJs.path));
|
||||
assert(bJsScriptInfo.isOrphan());
|
||||
assert(bJsScriptInfo.isContainedByBackgroundProject());
|
||||
assert.deepEqual(bJsScriptInfo.containingProjects, [auxProject]);
|
||||
@@ -106,7 +102,7 @@ describe("unittests:: tsserver:: auxiliaryProject::", () => {
|
||||
[indexFile.path]: indexFile.content,
|
||||
[libFile.path]: libFile.content,
|
||||
});
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([indexFile], session);
|
||||
session.executeCommandSeq<ts.server.protocol.FindSourceDefinitionRequest>({
|
||||
command: ts.server.protocol.CommandTypes.FindSourceDefinition,
|
||||
@@ -165,7 +161,7 @@ describe("unittests:: tsserver:: auxiliaryProject::", () => {
|
||||
[indexFile.path]: indexFile.content,
|
||||
[libFile.path]: libFile.content,
|
||||
});
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([indexFile], session);
|
||||
session.executeCommandSeq<ts.server.protocol.FindSourceDefinitionRequest>({
|
||||
command: ts.server.protocol.CommandTypes.FindSourceDefinition,
|
||||
|
||||
@@ -2,8 +2,7 @@ import {
|
||||
IncrementalVerifierCallbacks,
|
||||
} from "../../../harness/incrementalUtils";
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
Logger,
|
||||
LoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
@@ -11,11 +10,10 @@ import {
|
||||
} from "../helpers";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createProjectService,
|
||||
createSession,
|
||||
logDiagnostics,
|
||||
openFilesForSession,
|
||||
TestProjectService,
|
||||
setCompilerOptionsForInferredProjectsRequestForSession,
|
||||
TestSession,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
createServerHost,
|
||||
@@ -79,13 +77,13 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS
|
||||
return calledMap;
|
||||
}
|
||||
|
||||
function logCacheEntry(logger: Logger, callback: CalledMaps) {
|
||||
function logCacheEntry(logger: LoggerWithInMemoryLogs, callback: CalledMaps) {
|
||||
const result = Array.from<[string, (true | CalledWithFiveArgs)[]], { key: string; count: number; }>(calledMaps[callback].entries(), ([key, arr]) => ({ key, count: arr.length }));
|
||||
logger.info(`${callback}:: ${jsonToReadableText(result)}`);
|
||||
calledMaps[callback].clear();
|
||||
}
|
||||
|
||||
function logCacheAndClear(logger: Logger) {
|
||||
function logCacheAndClear(logger: LoggerWithInMemoryLogs) {
|
||||
forEachHostProperty(prop => logCacheEntry(logger, prop));
|
||||
}
|
||||
|
||||
@@ -98,9 +96,9 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS
|
||||
}
|
||||
}
|
||||
|
||||
function logSemanticDiagnostics(projectService: TestProjectService, project: ts.server.Project, file: File) {
|
||||
function logSemanticDiagnostics(session: TestSession, project: ts.server.Project, file: File) {
|
||||
logDiagnostics(
|
||||
projectService,
|
||||
session,
|
||||
`getSemanticDiagnostics:: ${file.path}`,
|
||||
project,
|
||||
project.getLanguageService().getSemanticDiagnostics(file.path),
|
||||
@@ -120,15 +118,18 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS
|
||||
};
|
||||
|
||||
const host = createServerHost([root, imported]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
projectService.setCompilerOptionsForInferredProjects({ module: ts.ModuleKind.AMD, noLib: true });
|
||||
projectService.openClientFile(root.path);
|
||||
const project = projectService.inferredProjects[0];
|
||||
const session = new TestSession(host);
|
||||
setCompilerOptionsForInferredProjectsRequestForSession({
|
||||
module: ts.server.protocol.ModuleKind.AMD,
|
||||
noLib: true,
|
||||
}, session);
|
||||
openFilesForSession([root], session);
|
||||
const project = session.getProjectService().inferredProjects[0];
|
||||
const rootScriptInfo = project.getRootScriptInfos()[0];
|
||||
assert.equal(rootScriptInfo.fileName, root.path);
|
||||
|
||||
// ensure that imported file was found
|
||||
logSemanticDiagnostics(projectService, project, imported);
|
||||
logSemanticDiagnostics(session, project, imported);
|
||||
|
||||
const logCacheAndClear = createLoggerTrackingHostCalls(host);
|
||||
|
||||
@@ -136,29 +137,33 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS
|
||||
// ensure file has correct number of errors after edit
|
||||
editContent(`import {x} from "f1";
|
||||
var x: string = 1;`);
|
||||
logSemanticDiagnostics(projectService, project, imported);
|
||||
logCacheAndClear(projectService.logger);
|
||||
logSemanticDiagnostics(session, project, imported);
|
||||
logCacheAndClear(session.logger);
|
||||
|
||||
// trigger synchronization to make sure that the host will try to find 'f2' module on disk
|
||||
editContent(`import {x} from "f2"`);
|
||||
try {
|
||||
// trigger synchronization to make sure that the host will try to find 'f2' module on disk
|
||||
logSemanticDiagnostics(projectService, project, imported);
|
||||
logSemanticDiagnostics(session, project, imported);
|
||||
}
|
||||
catch (e) {
|
||||
projectService.logger.info(e.message);
|
||||
session.logger.info(e.message);
|
||||
}
|
||||
logCacheAndClear(projectService.logger);
|
||||
logCacheAndClear(session.logger);
|
||||
|
||||
editContent(`import {x} from "f1"`);
|
||||
logSemanticDiagnostics(projectService, project, imported);
|
||||
logCacheAndClear(projectService.logger);
|
||||
logSemanticDiagnostics(session, project, imported);
|
||||
logCacheAndClear(session.logger);
|
||||
|
||||
// setting compiler options discards module resolution cache
|
||||
projectService.setCompilerOptionsForInferredProjects({ module: ts.ModuleKind.AMD, noLib: true, target: ts.ScriptTarget.ES5 });
|
||||
logSemanticDiagnostics(projectService, project, imported);
|
||||
logCacheAndClear(projectService.logger);
|
||||
baselineTsserverLogs("cachingFileSystemInformation", "works using legacy resolution logic", projectService);
|
||||
setCompilerOptionsForInferredProjectsRequestForSession({
|
||||
module: ts.server.protocol.ModuleKind.AMD,
|
||||
noLib: true,
|
||||
target: ts.server.protocol.ScriptTarget.ES5,
|
||||
}, session);
|
||||
logSemanticDiagnostics(session, project, imported);
|
||||
logCacheAndClear(session.logger);
|
||||
baselineTsserverLogs("cachingFileSystemInformation", "works using legacy resolution logic", session);
|
||||
|
||||
function editContent(newContent: string) {
|
||||
rootScriptInfo.editContent(0, rootContent.length, newContent);
|
||||
@@ -178,22 +183,25 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS
|
||||
};
|
||||
|
||||
const host = createServerHost([root]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
projectService.setCompilerOptionsForInferredProjects({ module: ts.ModuleKind.AMD, noLib: true });
|
||||
const session = new TestSession(host);
|
||||
setCompilerOptionsForInferredProjectsRequestForSession({
|
||||
module: ts.server.protocol.ModuleKind.AMD,
|
||||
noLib: true,
|
||||
}, session);
|
||||
const logCacheAndClear = createLoggerTrackingHostCalls(host);
|
||||
projectService.openClientFile(root.path);
|
||||
const project = projectService.inferredProjects[0];
|
||||
openFilesForSession([root], session);
|
||||
const project = session.getProjectService().inferredProjects[0];
|
||||
const rootScriptInfo = project.getRootScriptInfos()[0];
|
||||
assert.equal(rootScriptInfo.fileName, root.path);
|
||||
|
||||
logSemanticDiagnostics(projectService, project, root);
|
||||
logCacheAndClear(projectService.logger);
|
||||
logSemanticDiagnostics(session, project, root);
|
||||
logCacheAndClear(session.logger);
|
||||
|
||||
host.writeFile(imported.path, imported.content);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
logSemanticDiagnostics(projectService, project, root);
|
||||
logCacheAndClear(projectService.logger);
|
||||
baselineTsserverLogs("cachingFileSystemInformation", "loads missing files from disk", projectService);
|
||||
logSemanticDiagnostics(session, project, root);
|
||||
logCacheAndClear(session.logger);
|
||||
baselineTsserverLogs("cachingFileSystemInformation", "loads missing files from disk", session);
|
||||
});
|
||||
|
||||
it("when calling goto definition of module", () => {
|
||||
@@ -239,7 +247,7 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS
|
||||
};
|
||||
const projectFiles = [clientFile, anotherModuleFile, moduleFile, tsconfigFile];
|
||||
const host = createServerHost(projectFiles);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([clientFile], session);
|
||||
const logCacheAndClear = createLoggerTrackingHostCalls(host);
|
||||
|
||||
@@ -319,19 +327,19 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS
|
||||
};
|
||||
const projectFiles = [file1, file2, es2016LibFile, tsconfigFile];
|
||||
const host = createServerHost(projectFiles, { useCaseSensitiveFileNames });
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
projectService.openClientFile(file1.path);
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file1], session);
|
||||
|
||||
const logCacheAndClear = createLoggerTrackingHostCalls(host);
|
||||
|
||||
// Create file cookie.ts
|
||||
host.writeFile(file3.path, file3.content);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
logCacheAndClear(projectService.logger);
|
||||
logCacheAndClear(session.logger);
|
||||
|
||||
projectService.openClientFile(file3.path);
|
||||
logCacheAndClear(projectService.logger);
|
||||
baselineTsserverLogs("cachingFileSystemInformation", `watchDirectories for config file with case ${useCaseSensitiveFileNames ? "" : "in"}sensitive file system`, projectService);
|
||||
openFilesForSession([file3], session);
|
||||
logCacheAndClear(session.logger);
|
||||
baselineTsserverLogs("cachingFileSystemInformation", `watchDirectories for config file with case ${useCaseSensitiveFileNames ? "" : "in"}sensitive file system`, session);
|
||||
});
|
||||
}
|
||||
verifyWatchDirectoriesCaseSensitivity(/*useCaseSensitiveFileNames*/ false);
|
||||
@@ -359,12 +367,12 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS
|
||||
|
||||
const files = [file1, file2, tsconfig, libFile];
|
||||
const host = createServerHost(files);
|
||||
const service = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
service.openClientFile(file1.path);
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file1], session);
|
||||
|
||||
const project = service.configuredProjects.get(tsconfig.path)!;
|
||||
logSemanticDiagnostics(service, project, file1);
|
||||
logSemanticDiagnostics(service, project, file2);
|
||||
const project = session.getProjectService().configuredProjects.get(tsconfig.path)!;
|
||||
logSemanticDiagnostics(session, project, file1);
|
||||
logSemanticDiagnostics(session, project, file2);
|
||||
|
||||
const debugTypesFile: File = {
|
||||
path: `${projectLocation}/node_modules/debug/index.d.ts`,
|
||||
@@ -374,9 +382,9 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS
|
||||
host.runQueuedTimeoutCallbacks(); // Scheduled invalidation of resolutions
|
||||
host.runQueuedTimeoutCallbacks(); // Actual update
|
||||
|
||||
logSemanticDiagnostics(service, project, file1);
|
||||
logSemanticDiagnostics(service, project, file2);
|
||||
baselineTsserverLogs("cachingFileSystemInformation", `includes the parent folder FLLs in ${resolution} module resolution mode`, service);
|
||||
logSemanticDiagnostics(session, project, file1);
|
||||
logSemanticDiagnostics(session, project, file2);
|
||||
baselineTsserverLogs("cachingFileSystemInformation", `includes the parent folder FLLs in ${resolution} module resolution mode`, session);
|
||||
}
|
||||
|
||||
it("Includes the parent folder FLLs in node module resolution mode", () => {
|
||||
@@ -428,9 +436,12 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS
|
||||
`,
|
||||
});
|
||||
const host = createServerHost([app, libFile, tsconfigJson, packageJson]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
projectService.setHostConfiguration({ preferences: { includePackageJsonAutoImports: "off" } });
|
||||
projectService.openClientFile(app.path);
|
||||
const session = new TestSession(host);
|
||||
session.executeCommandSeq<ts.server.protocol.ConfigureRequest>({
|
||||
command: ts.server.protocol.CommandTypes.Configure,
|
||||
arguments: { preferences: { includePackageJsonAutoImports: "off" } },
|
||||
});
|
||||
openFilesForSession([app], session);
|
||||
|
||||
let npmInstallComplete = false;
|
||||
|
||||
@@ -532,7 +543,7 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS
|
||||
baselineTsserverLogs(
|
||||
"cachingFileSystemInformation",
|
||||
`npm install works when ${timeoutDuringPartialInstallation ? "timeout occurs inbetween installation" : "timeout occurs after installation"}`,
|
||||
projectService,
|
||||
session,
|
||||
);
|
||||
|
||||
function verifyAfterPartialOrCompleteNpmInstall() {
|
||||
@@ -542,7 +553,7 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS
|
||||
host.runQueuedTimeoutCallbacks(); // Actual update
|
||||
}
|
||||
else {
|
||||
projectService.testhost.logTimeoutQueueLength();
|
||||
session.host.baselineHost("After partial npm install");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -568,11 +579,11 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS
|
||||
|
||||
const files = [app, tsconfig, libFile];
|
||||
const host = createServerHost(files);
|
||||
const service = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
service.openClientFile(app.path);
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([app], session);
|
||||
|
||||
const project = service.configuredProjects.get(tsconfig.path)!;
|
||||
logSemanticDiagnostics(service, project, app);
|
||||
const project = session.getProjectService().configuredProjects.get(tsconfig.path)!;
|
||||
logSemanticDiagnostics(session, project, app);
|
||||
|
||||
const debugTypesFile: File = {
|
||||
path: `${projectLocation}/node_modules/@types/debug/index.d.ts`,
|
||||
@@ -587,8 +598,8 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS
|
||||
};
|
||||
host.writeFile(debugTypesFile.path, debugTypesFile.content);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
logSemanticDiagnostics(service, project, app);
|
||||
baselineTsserverLogs("cachingFileSystemInformation", "when node_modules dont receive event for the @types file addition", service);
|
||||
logSemanticDiagnostics(session, project, app);
|
||||
baselineTsserverLogs("cachingFileSystemInformation", "when node_modules dont receive event for the @types file addition", session);
|
||||
});
|
||||
|
||||
it("when creating new file in symlinked folder", () => {
|
||||
@@ -615,10 +626,10 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS
|
||||
}),
|
||||
};
|
||||
const host = createServerHost([module1, module2, symlink, config, libFile]);
|
||||
const service = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
service.openClientFile(`${symlink.path}/module2.ts`);
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([`${symlink.path}/module2.ts`], session);
|
||||
host.writeFile(`${symlink.path}/module3.ts`, `import * as M from "folder1/module1";`);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
baselineTsserverLogs("cachingFileSystemInformation", "when creating new file in symlinked folder", service);
|
||||
baselineTsserverLogs("cachingFileSystemInformation", "when creating new file in symlinked folder", session);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
jsonToReadableText,
|
||||
} from "../helpers";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createSession,
|
||||
TestServerCancellationToken,
|
||||
TestSession,
|
||||
TestSessionRequest,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
@@ -33,13 +29,7 @@ describe("unittests:: tsserver:: cancellationToken", () => {
|
||||
content: "let xyz = 1;",
|
||||
};
|
||||
const host = createServerHost([f1]);
|
||||
const cancellationToken: ts.server.ServerCancellationToken = {
|
||||
isCancellationRequested: () => false,
|
||||
setRequest: requestId => session.logger.log(`ServerCancellationToken:: Cancellation Request id:: ${requestId}`),
|
||||
resetRequest: ts.noop,
|
||||
};
|
||||
|
||||
const session = createSession(host, { cancellationToken, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession({ host, useCancellationToken: true });
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.OpenRequest>({
|
||||
command: ts.server.protocol.CommandTypes.Open,
|
||||
@@ -75,13 +65,9 @@ describe("unittests:: tsserver:: cancellationToken", () => {
|
||||
};
|
||||
|
||||
const host = createServerHost([f1, config]);
|
||||
const logger = createLoggerWithInMemoryLogs(host);
|
||||
const cancellationToken = new TestServerCancellationToken(logger);
|
||||
const session = createSession(host, {
|
||||
canUseEvents: true,
|
||||
eventHandler: ts.noop,
|
||||
cancellationToken,
|
||||
logger,
|
||||
const session = new TestSession({
|
||||
host,
|
||||
useCancellationToken: true,
|
||||
});
|
||||
{
|
||||
session.executeCommandSeq<ts.server.protocol.OpenRequest>({
|
||||
@@ -112,9 +98,9 @@ describe("unittests:: tsserver:: cancellationToken", () => {
|
||||
});
|
||||
|
||||
// cancel previously issued Geterr
|
||||
cancellationToken.setRequestToCancel(getErrId);
|
||||
session.serverCancellationToken.setRequestToCancel(getErrId);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
cancellationToken.resetToken();
|
||||
session.serverCancellationToken.resetToken();
|
||||
}
|
||||
{
|
||||
const getErrId = session.getNextSeq();
|
||||
@@ -126,10 +112,10 @@ describe("unittests:: tsserver:: cancellationToken", () => {
|
||||
// run first step
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
|
||||
cancellationToken.setRequestToCancel(getErrId);
|
||||
session.serverCancellationToken.setRequestToCancel(getErrId);
|
||||
host.runQueuedImmediateCallbacks();
|
||||
|
||||
cancellationToken.resetToken();
|
||||
session.serverCancellationToken.resetToken();
|
||||
}
|
||||
{
|
||||
session.executeCommandSeq<ts.server.protocol.GeterrRequest>({
|
||||
@@ -141,7 +127,7 @@ describe("unittests:: tsserver:: cancellationToken", () => {
|
||||
// the semanticDiag message
|
||||
host.runQueuedImmediateCallbacks();
|
||||
host.runQueuedImmediateCallbacks();
|
||||
cancellationToken.resetToken();
|
||||
session.serverCancellationToken.resetToken();
|
||||
}
|
||||
{
|
||||
session.executeCommandSeq<ts.server.protocol.GeterrRequest>({
|
||||
@@ -171,14 +157,10 @@ describe("unittests:: tsserver:: cancellationToken", () => {
|
||||
}),
|
||||
};
|
||||
const host = createServerHost([f1, config]);
|
||||
const logger = createLoggerWithInMemoryLogs(host);
|
||||
const cancellationToken = new TestServerCancellationToken(logger, /*cancelAfterRequest*/ 3);
|
||||
const session = createSession(host, {
|
||||
canUseEvents: true,
|
||||
eventHandler: ts.noop,
|
||||
cancellationToken,
|
||||
const session = new TestSession({
|
||||
host,
|
||||
throttleWaitMilliseconds: 0,
|
||||
logger,
|
||||
useCancellationToken: 3,
|
||||
});
|
||||
{
|
||||
session.executeCommandSeq<ts.server.protocol.OpenRequest>({
|
||||
@@ -216,7 +198,7 @@ describe("unittests:: tsserver:: cancellationToken", () => {
|
||||
// Set the next request to be cancellable
|
||||
// The cancellation token will cancel the request the third time
|
||||
// isCancellationRequested() is called.
|
||||
cancellationToken.setRequestToCancel(session.getNextSeq());
|
||||
session.serverCancellationToken.setRequestToCancel(session.getNextSeq());
|
||||
let operationCanceledExceptionThrown = false;
|
||||
|
||||
try {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
Logger,
|
||||
LoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
@@ -8,7 +8,6 @@ import {
|
||||
} from "../helpers";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createSession,
|
||||
openExternalProjectForSession,
|
||||
openFilesForSession,
|
||||
protocolTextSpanFromSubstring,
|
||||
@@ -61,7 +60,7 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => {
|
||||
it("should contains only itself if a module file's shape didn't change, and all files referencing it if its shape changed", () => {
|
||||
const { moduleFile1, file1Consumer1, file1Consumer2, moduleFile2, globalFile3, configFile } = files();
|
||||
const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
|
||||
openFilesForSession([moduleFile1, file1Consumer1], session);
|
||||
|
||||
@@ -108,7 +107,7 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => {
|
||||
it("should be up-to-date with the reference map changes", () => {
|
||||
const { moduleFile1, file1Consumer1, file1Consumer2, moduleFile2, globalFile3, configFile } = files();
|
||||
const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
|
||||
openFilesForSession([moduleFile1, file1Consumer1], session);
|
||||
|
||||
@@ -181,7 +180,7 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => {
|
||||
it("should be up-to-date with changes made in non-open files", () => {
|
||||
const { moduleFile1, file1Consumer1, file1Consumer2, moduleFile2, globalFile3, configFile } = files();
|
||||
const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
|
||||
openFilesForSession([moduleFile1], session);
|
||||
|
||||
@@ -214,7 +213,7 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => {
|
||||
it("should be up-to-date with deleted files", () => {
|
||||
const { moduleFile1, file1Consumer1, file1Consumer2, moduleFile2, globalFile3, configFile } = files();
|
||||
const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
|
||||
openFilesForSession([moduleFile1], session);
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -245,7 +244,7 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => {
|
||||
it("should be up-to-date with newly created files", () => {
|
||||
const { moduleFile1, file1Consumer1, file1Consumer2, moduleFile2, globalFile3, configFile } = files();
|
||||
const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
|
||||
openFilesForSession([moduleFile1], session);
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -297,7 +296,7 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => {
|
||||
};
|
||||
|
||||
const host = createServerHost([moduleFile1, file1Consumer1, configFile, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
|
||||
openFilesForSession([moduleFile1, file1Consumer1], session);
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -344,7 +343,7 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => {
|
||||
it("should return all files if a global file changed shape", () => {
|
||||
const { moduleFile1, file1Consumer1, file1Consumer2, moduleFile2, globalFile3, configFile } = files();
|
||||
const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
|
||||
openFilesForSession([globalFile3], session);
|
||||
|
||||
@@ -375,7 +374,7 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => {
|
||||
};
|
||||
|
||||
const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, configFile, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([moduleFile1], session);
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
command: ts.server.protocol.CommandTypes.CompileOnSaveAffectedFileList,
|
||||
@@ -397,7 +396,7 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => {
|
||||
};
|
||||
|
||||
const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, configFile, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([moduleFile1], session);
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
command: ts.server.protocol.CommandTypes.CompileOnSaveAffectedFileList,
|
||||
@@ -423,7 +422,7 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => {
|
||||
};
|
||||
|
||||
const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, configFile2, configFile, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
|
||||
openFilesForSession([moduleFile1, file1Consumer1], session);
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -446,7 +445,7 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => {
|
||||
};
|
||||
|
||||
const host = createServerHost([moduleFile1, file1Consumer1, configFile, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([moduleFile1], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.ChangeRequest>({
|
||||
@@ -481,7 +480,7 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => {
|
||||
};
|
||||
|
||||
const host = createServerHost([moduleFile1, file1Consumer1, configFile, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([moduleFile1], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.ChangeRequest>({
|
||||
@@ -509,7 +508,7 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => {
|
||||
content: `import {y} from "./file1Consumer1";`,
|
||||
};
|
||||
const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer1Consumer1, globalFile3, configFile, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
|
||||
openFilesForSession([moduleFile1, file1Consumer1], session);
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -561,7 +560,7 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => {
|
||||
export var t2 = 10;`,
|
||||
};
|
||||
const host = createServerHost([file1, file2, configFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
|
||||
openFilesForSession([file1, file2], session);
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -579,7 +578,7 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => {
|
||||
const configFile2: File = { path: "/a/c/tsconfig.json", content: `{ "compileOnSave": true }` };
|
||||
|
||||
const host = createServerHost([file1, file2, file3, configFile1, configFile2]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
|
||||
openFilesForSession([file1, file2, file3], session);
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -598,7 +597,7 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => {
|
||||
export var x = Foo();`,
|
||||
};
|
||||
const host = createServerHost([moduleFile1, referenceFile1, configFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
|
||||
openFilesForSession([referenceFile1], session);
|
||||
host.deleteFile(moduleFile1.path);
|
||||
@@ -623,7 +622,7 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => {
|
||||
export var x = Foo();`,
|
||||
};
|
||||
const host = createServerHost([referenceFile1, configFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
|
||||
openFilesForSession([referenceFile1], session);
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -653,7 +652,7 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => {
|
||||
}),
|
||||
};
|
||||
const host = createServerHost([dtsFile, f2, config]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([dtsFile], session);
|
||||
openFilesForSession([f2], session);
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -723,7 +722,7 @@ describe("unittests:: tsserver:: compileOnSave:: affected list", () => {
|
||||
}),
|
||||
};
|
||||
const host = createServerHost([f1, f2, config]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([f1], session);
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
command: ts.server.protocol.CommandTypes.CompileOnSaveAffectedFileList,
|
||||
@@ -745,7 +744,7 @@ describe("unittests:: tsserver:: compileOnSave:: EmitFile test", () => {
|
||||
test("\r\n", logger);
|
||||
baselineTsserverLogs("compileOnSave", "line endings", { logger });
|
||||
|
||||
function test(newLine: string, logger: Logger) {
|
||||
function test(newLine: string, logger: LoggerWithInMemoryLogs) {
|
||||
const lines = ["var x = 1;", "var y = 2;"];
|
||||
const path = "/a/app";
|
||||
const f = {
|
||||
@@ -755,7 +754,7 @@ describe("unittests:: tsserver:: compileOnSave:: EmitFile test", () => {
|
||||
const host = createServerHost([f], { newLine });
|
||||
logger.host = host;
|
||||
logger.log(`currentDirectory:: ${host.getCurrentDirectory()} useCaseSensitiveFileNames: ${host.useCaseSensitiveFileNames} newLine: ${host.newLine}`);
|
||||
const session = createSession(host, { logger });
|
||||
const session = new TestSession({ host, logger });
|
||||
openFilesForSession([f], session);
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveEmitFileRequest>({
|
||||
command: ts.server.protocol.CommandTypes.CompileOnSaveEmitFile,
|
||||
@@ -779,7 +778,7 @@ describe("unittests:: tsserver:: compileOnSave:: EmitFile test", () => {
|
||||
content: `{}`,
|
||||
};
|
||||
const host = createServerHost([file1, file2, configFile, libFile], { newLine: "\r\n" });
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
|
||||
openFilesForSession([file1, file2], session);
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveEmitFileRequest>({
|
||||
@@ -804,9 +803,9 @@ describe("unittests:: tsserver:: compileOnSave:: EmitFile test", () => {
|
||||
path: "/a/b/file3.js",
|
||||
content: "console.log('file3');",
|
||||
};
|
||||
const externalProjectName = "/a/b/externalproject";
|
||||
const projectFileName = "/a/b/externalproject";
|
||||
const host = createServerHost([file1, file2, file3, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openExternalProjectForSession({
|
||||
rootFiles: toExternalFiles([file1.path, file2.path]),
|
||||
options: {
|
||||
@@ -814,7 +813,7 @@ describe("unittests:: tsserver:: compileOnSave:: EmitFile test", () => {
|
||||
outFile: "dist.js",
|
||||
compileOnSave: true,
|
||||
},
|
||||
projectFileName: externalProjectName,
|
||||
projectFileName,
|
||||
}, session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveEmitFileRequest>({
|
||||
@@ -831,9 +830,9 @@ describe("unittests:: tsserver:: compileOnSave:: EmitFile test", () => {
|
||||
path: `/root/TypeScriptProject3/TypeScriptProject3/${inputFileName}`,
|
||||
content: "consonle.log('file1');",
|
||||
};
|
||||
const externalProjectName = "/root/TypeScriptProject3/TypeScriptProject3/TypeScriptProject3.csproj";
|
||||
const projectFileName = "/root/TypeScriptProject3/TypeScriptProject3/TypeScriptProject3.csproj";
|
||||
const host = createServerHost([file1, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openExternalProjectForSession({
|
||||
rootFiles: toExternalFiles([file1.path]),
|
||||
options: {
|
||||
@@ -841,7 +840,7 @@ describe("unittests:: tsserver:: compileOnSave:: EmitFile test", () => {
|
||||
sourceMap: true,
|
||||
compileOnSave: true,
|
||||
},
|
||||
projectFileName: externalProjectName,
|
||||
projectFileName,
|
||||
}, session);
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveEmitFileRequest>({
|
||||
command: ts.server.protocol.CommandTypes.CompileOnSaveEmitFile,
|
||||
@@ -883,7 +882,7 @@ describe("unittests:: tsserver:: compileOnSave:: EmitFile test", () => {
|
||||
content: "const y = 2;",
|
||||
};
|
||||
const host = createServerHost([file1, file2, config, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file1], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -954,7 +953,7 @@ function bar() {
|
||||
};
|
||||
const files = [file1, file2, file3, ...(hasModule ? [module] : ts.emptyArray)];
|
||||
const host = createServerHost([...files, config, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file1, file2], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -1060,7 +1059,7 @@ describe("unittests:: tsserver:: compileOnSave:: CompileOnSaveAffectedFileListRe
|
||||
};
|
||||
const files = [libFile, core, app1, app2, app1Config, app2Config];
|
||||
const host = createServerHost(files);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([app1, app2, core], session);
|
||||
insertString(session, app1);
|
||||
insertString(session, app2);
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
jsonToReadableText,
|
||||
} from "../helpers";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createSession,
|
||||
openFilesForSession,
|
||||
TestSession,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
createServerHost,
|
||||
@@ -32,7 +29,7 @@ describe("unittests:: tsserver:: completions", () => {
|
||||
};
|
||||
|
||||
const host = createServerHost([aTs, bTs, tsconfig]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([aTs, bTs], session);
|
||||
|
||||
const requestLocation: ts.server.protocol.FileLocationRequestArgs = {
|
||||
@@ -182,11 +179,7 @@ export interface BrowserRouterProps {
|
||||
];
|
||||
|
||||
const host = createServerHost(files, { windowsStyleRoot: "c:/" });
|
||||
const logger = createLoggerWithInMemoryLogs(host);
|
||||
const session = createSession(host, {
|
||||
globalTypingsCacheLocation,
|
||||
logger,
|
||||
});
|
||||
const session = new TestSession({ host, globalTypingsCacheLocation });
|
||||
openFilesForSession([appFile], session);
|
||||
session.executeCommandSeq<ts.server.protocol.CompletionsRequest>({
|
||||
command: ts.server.protocol.CommandTypes.CompletionInfo,
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createSession,
|
||||
openFilesForSession,
|
||||
TestSession,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
createServerHost,
|
||||
@@ -170,7 +167,7 @@ describe("unittests:: tsserver:: completionsIncomplete", () => {
|
||||
|
||||
function setup(files: File[]) {
|
||||
const host = createServerHost(files);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
const projectService = session.getProjectService();
|
||||
session.executeCommandSeq<ts.server.protocol.ConfigureRequest>({
|
||||
command: ts.server.protocol.CommandTypes.Configure,
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createProjectService,
|
||||
closeFilesForSession,
|
||||
openFilesForSession,
|
||||
TestSession,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
createServerHost,
|
||||
@@ -22,17 +21,17 @@ describe("unittests:: tsserver:: configFileSearch:: searching for config file",
|
||||
content: "{}",
|
||||
};
|
||||
const host = createServerHost([f1, configFile]);
|
||||
const service = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
service.openClientFile(f1.path, /*fileContent*/ undefined, /*scriptKind*/ undefined, "/a");
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([{ file: f1, projectRootPath: "/a" }], session);
|
||||
|
||||
service.closeClientFile(f1.path);
|
||||
service.openClientFile(f1.path);
|
||||
baselineTsserverLogs("configFileSerach", "should stop at projectRootPath if given", service);
|
||||
closeFilesForSession([f1], session);
|
||||
openFilesForSession([f1], session);
|
||||
baselineTsserverLogs("configFileSearch", "should stop at projectRootPath if given", session);
|
||||
});
|
||||
|
||||
it("should use projectRootPath when searching for inferred project again", () => {
|
||||
const projectDir = "/a/b/projects/project";
|
||||
const configFileLocation = `${projectDir}/src`;
|
||||
const projectRootPath = "/a/b/projects/project";
|
||||
const configFileLocation = `${projectRootPath}/src`;
|
||||
const f1 = {
|
||||
path: `${configFileLocation}/file1.ts`,
|
||||
content: "",
|
||||
@@ -46,18 +45,18 @@ describe("unittests:: tsserver:: configFileSearch:: searching for config file",
|
||||
content: "{}",
|
||||
};
|
||||
const host = createServerHost([f1, libFile, configFile, configFile2]);
|
||||
const service = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
service.openClientFile(f1.path, /*fileContent*/ undefined, /*scriptKind*/ undefined, projectDir);
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([{ file: f1, projectRootPath }], session);
|
||||
|
||||
// Delete config file - should create inferred project and not configured project
|
||||
host.deleteFile(configFile.path);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
baselineTsserverLogs("configFileSearch", "should use projectRootPath when searching for inferred project again", service);
|
||||
baselineTsserverLogs("configFileSearch", "should use projectRootPath when searching for inferred project again", session);
|
||||
});
|
||||
|
||||
it("should use projectRootPath when searching for inferred project again 2", () => {
|
||||
const projectDir = "/a/b/projects/project";
|
||||
const configFileLocation = `${projectDir}/src`;
|
||||
const projectRootPath = "/a/b/projects/project";
|
||||
const configFileLocation = `${projectRootPath}/src`;
|
||||
const f1 = {
|
||||
path: `${configFileLocation}/file1.ts`,
|
||||
content: "",
|
||||
@@ -71,17 +70,17 @@ describe("unittests:: tsserver:: configFileSearch:: searching for config file",
|
||||
content: "{}",
|
||||
};
|
||||
const host = createServerHost([f1, libFile, configFile, configFile2]);
|
||||
const service = createProjectService(host, {
|
||||
const session = new TestSession({
|
||||
host,
|
||||
useSingleInferredProject: true,
|
||||
useInferredProjectPerProjectRoot: true,
|
||||
logger: createLoggerWithInMemoryLogs(host),
|
||||
});
|
||||
service.openClientFile(f1.path, /*fileContent*/ undefined, /*scriptKind*/ undefined, projectDir);
|
||||
openFilesForSession([{ file: f1, projectRootPath }], session);
|
||||
|
||||
// Delete config file - should create inferred project with project root path set
|
||||
host.deleteFile(configFile.path);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
baselineTsserverLogs("configFileSearch", "should use projectRootPath when searching for inferred project again 2", service);
|
||||
baselineTsserverLogs("configFileSearch", "should use projectRootPath when searching for inferred project again 2", session);
|
||||
});
|
||||
|
||||
describe("when the opened file is not from project root", () => {
|
||||
@@ -96,13 +95,13 @@ describe("unittests:: tsserver:: configFileSearch:: searching for config file",
|
||||
};
|
||||
function openClientFile(files: File[]) {
|
||||
const host = createServerHost(files);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
projectService.openClientFile(file.path, /*fileContent*/ undefined, /*scriptKind*/ undefined, "/a/b/projects/proj");
|
||||
return { host, projectService };
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([{ file, projectRootPath: "/a/b/projects/proj" }], session);
|
||||
return { host, session };
|
||||
}
|
||||
|
||||
it("tsconfig for the file exists", () => {
|
||||
const { host, projectService } = openClientFile([file, libFile, tsconfig]);
|
||||
const { host, session } = openClientFile([file, libFile, tsconfig]);
|
||||
|
||||
host.deleteFile(tsconfig.path);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
@@ -110,11 +109,11 @@ describe("unittests:: tsserver:: configFileSearch:: searching for config file",
|
||||
host.writeFile(tsconfig.path, tsconfig.content);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
|
||||
baselineTsserverLogs("configFileSearch", "tsconfig for the file exists", projectService);
|
||||
baselineTsserverLogs("configFileSearch", "tsconfig for the file exists", session);
|
||||
});
|
||||
|
||||
it("tsconfig for the file does not exist", () => {
|
||||
const { host, projectService } = openClientFile([file, libFile]);
|
||||
const { host, session } = openClientFile([file, libFile]);
|
||||
|
||||
host.writeFile(tsconfig.path, tsconfig.content);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
@@ -122,7 +121,7 @@ describe("unittests:: tsserver:: configFileSearch:: searching for config file",
|
||||
host.deleteFile(tsconfig.path);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
|
||||
baselineTsserverLogs("configFileSearch", "tsconfig for the file does not exist", projectService);
|
||||
baselineTsserverLogs("configFileSearch", "tsconfig for the file does not exist", session);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -131,9 +130,9 @@ describe("unittests:: tsserver:: configFileSearch:: searching for config file",
|
||||
it(scenario, () => {
|
||||
const path = `/root/teams/VSCode68/Shared Documents/General/jt-ts-test-workspace/x.js`;
|
||||
const host = createServerHost([libFile, { path, content: "const x = 10" }], { useCaseSensitiveFileNames: true });
|
||||
const service = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
service.openClientFile(path, /*fileContent*/ undefined, /*scriptKind*/ undefined, projectRootPath);
|
||||
baselineTsserverLogs("configFileSearch", scenario, service);
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([{ file: path, projectRootPath }], session);
|
||||
baselineTsserverLogs("configFileSearch", scenario, session);
|
||||
});
|
||||
}
|
||||
verifyConfigFileWatch("when projectRootPath is not present", /*projectRootPath*/ undefined);
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
jsonToReadableText,
|
||||
@@ -14,11 +11,11 @@ import {
|
||||
} from "../helpers/tscWatch";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createProjectService,
|
||||
createSession,
|
||||
closeFilesForSession,
|
||||
logConfiguredProjectsHasOpenRefStatus,
|
||||
logInferredProjectsOrphanStatus,
|
||||
openFilesForSession,
|
||||
TestSession,
|
||||
verifyGetErrRequest,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
@@ -54,13 +51,9 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => {
|
||||
};
|
||||
|
||||
const host = createServerHost([configFile, libFile, file1, file2, file3]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const { configFileName, configFileErrors } = projectService.openClientFile(file1.path);
|
||||
|
||||
assert(configFileName, "should find config file");
|
||||
assert.isTrue(!configFileErrors || configFileErrors.length === 0, `expect no errors in config file, got ${jsonToReadableText(configFileErrors)}`);
|
||||
|
||||
baselineTsserverLogs("configuredProjects", "create configured project without file list", projectService);
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file1], session);
|
||||
baselineTsserverLogs("configuredProjects", "create configured project without file list", session);
|
||||
});
|
||||
|
||||
it("create configured project with the file list", () => {
|
||||
@@ -86,13 +79,9 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => {
|
||||
};
|
||||
|
||||
const host = createServerHost([configFile, libFile, file1, file2, file3]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const { configFileName, configFileErrors } = projectService.openClientFile(file1.path);
|
||||
|
||||
assert(configFileName, "should find config file");
|
||||
assert.isTrue(!configFileErrors || configFileErrors.length === 0, `expect no errors in config file, got ${jsonToReadableText(configFileErrors)}`);
|
||||
|
||||
baselineTsserverLogs("configuredProjects", "create configured project with the file list", projectService);
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file1], session);
|
||||
baselineTsserverLogs("configuredProjects", "create configured project with the file list", session);
|
||||
});
|
||||
|
||||
it("add and then remove a config file in a folder with loose files", () => {
|
||||
@@ -113,9 +102,8 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => {
|
||||
|
||||
const host = createServerHost([libFile, commonFile1, commonFile2]);
|
||||
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
projectService.openClientFile(commonFile1.path);
|
||||
projectService.openClientFile(commonFile2.path);
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([commonFile1, commonFile2], session);
|
||||
|
||||
// Add a tsconfig file
|
||||
host.writeFile(configFile.path, configFile.content);
|
||||
@@ -125,7 +113,7 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => {
|
||||
host.deleteFile(configFile.path);
|
||||
host.runQueuedTimeoutCallbacks(); // Refresh inferred projects
|
||||
|
||||
baselineTsserverLogs("configuredProjects", "add and then remove a config file in a folder with loose files", projectService);
|
||||
baselineTsserverLogs("configuredProjects", "add and then remove a config file in a folder with loose files", session);
|
||||
});
|
||||
|
||||
it("add new files to a configured project without file list", () => {
|
||||
@@ -134,13 +122,13 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => {
|
||||
content: `{}`,
|
||||
};
|
||||
const host = createServerHost([commonFile1, libFile, configFile]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
projectService.openClientFile(commonFile1.path);
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([commonFile1], session);
|
||||
|
||||
// add a new ts file
|
||||
host.writeFile(commonFile2.path, commonFile2.content);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
baselineTsserverLogs("configuredProjects", "add new files to a configured project without file list", projectService);
|
||||
baselineTsserverLogs("configuredProjects", "add new files to a configured project without file list", session);
|
||||
});
|
||||
|
||||
it("should ignore non-existing files specified in the config file", () => {
|
||||
@@ -155,10 +143,9 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => {
|
||||
}`,
|
||||
};
|
||||
const host = createServerHost([commonFile1, commonFile2, configFile]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
projectService.openClientFile(commonFile1.path);
|
||||
projectService.openClientFile(commonFile2.path);
|
||||
baselineTsserverLogs("configuredProjects", "should ignore non-existing files specified in the config file", projectService);
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([commonFile1, commonFile2], session);
|
||||
baselineTsserverLogs("configuredProjects", "should ignore non-existing files specified in the config file", session);
|
||||
});
|
||||
|
||||
it("handle recreated files correctly", () => {
|
||||
@@ -167,8 +154,8 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => {
|
||||
content: `{}`,
|
||||
};
|
||||
const host = createServerHost([commonFile1, commonFile2, configFile]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
projectService.openClientFile(commonFile1.path);
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([commonFile1], session);
|
||||
|
||||
// delete commonFile2
|
||||
host.deleteFile(commonFile2.path);
|
||||
@@ -177,7 +164,7 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => {
|
||||
// re-add commonFile2
|
||||
host.writeFile(commonFile2.path, commonFile2.content);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
baselineTsserverLogs("configuredProjects", "handle recreated files correctly", projectService);
|
||||
baselineTsserverLogs("configuredProjects", "handle recreated files correctly", session);
|
||||
});
|
||||
|
||||
it("files explicitly excluded in config file", () => {
|
||||
@@ -194,11 +181,10 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => {
|
||||
};
|
||||
|
||||
const host = createServerHost([commonFile1, commonFile2, excludedFile1, configFile]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([commonFile1, excludedFile1], session);
|
||||
|
||||
projectService.openClientFile(commonFile1.path);
|
||||
projectService.openClientFile(excludedFile1.path);
|
||||
baselineTsserverLogs("configuredProjects", "files explicitly excluded in config file", projectService);
|
||||
baselineTsserverLogs("configuredProjects", "files explicitly excluded in config file", session);
|
||||
});
|
||||
|
||||
it("should properly handle module resolution changes in config file", () => {
|
||||
@@ -229,10 +215,8 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => {
|
||||
};
|
||||
const files = [file1, nodeModuleFile, classicModuleFile, configFile, randomFile];
|
||||
const host = createServerHost(files);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
projectService.openClientFile(file1.path);
|
||||
projectService.openClientFile(nodeModuleFile.path);
|
||||
projectService.openClientFile(classicModuleFile.path);
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file1, nodeModuleFile, classicModuleFile], session);
|
||||
|
||||
host.writeFile(
|
||||
configFile.path,
|
||||
@@ -246,11 +230,11 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => {
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
|
||||
// will not remove project 1
|
||||
logInferredProjectsOrphanStatus(projectService);
|
||||
logInferredProjectsOrphanStatus(session);
|
||||
|
||||
// Open random file and it will reuse first inferred project
|
||||
projectService.openClientFile(randomFile.path);
|
||||
baselineTsserverLogs("configuredProjects", "should properly handle module resolution changes in config file", projectService);
|
||||
openFilesForSession([randomFile], session);
|
||||
baselineTsserverLogs("configuredProjects", "should properly handle module resolution changes in config file", session);
|
||||
});
|
||||
|
||||
it("should keep the configured project when the opened file is referenced by the project but not its root", () => {
|
||||
@@ -272,11 +256,11 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => {
|
||||
}`,
|
||||
};
|
||||
const host = createServerHost([file1, file2, configFile]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
projectService.openClientFile(file1.path);
|
||||
projectService.closeClientFile(file1.path);
|
||||
projectService.openClientFile(file2.path);
|
||||
baselineTsserverLogs("configuredProjects", "should keep the configured project when the opened file is referenced by the project but not its root", projectService);
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file1], session);
|
||||
closeFilesForSession([file1], session);
|
||||
openFilesForSession([file2], session);
|
||||
baselineTsserverLogs("configuredProjects", "should keep the configured project when the opened file is referenced by the project but not its root", session);
|
||||
});
|
||||
|
||||
it("should tolerate config file errors and still try to build a project", () => {
|
||||
@@ -291,9 +275,9 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => {
|
||||
}`,
|
||||
};
|
||||
const host = createServerHost([commonFile1, commonFile2, libFile, configFile]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
projectService.openClientFile(commonFile1.path);
|
||||
baselineTsserverLogs("configuredProjects", "should tolerate config file errors and still try to build a project", projectService);
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([commonFile1], session);
|
||||
baselineTsserverLogs("configuredProjects", "should tolerate config file errors and still try to build a project", session);
|
||||
});
|
||||
|
||||
it("should reuse same project if file is opened from the configured project that has no open files", () => {
|
||||
@@ -315,16 +299,16 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => {
|
||||
}`,
|
||||
};
|
||||
const host = createServerHost([file1, file2, configFile, libFile]);
|
||||
const projectService = createProjectService(host, { useSingleInferredProject: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
projectService.openClientFile(file1.path);
|
||||
logConfiguredProjectsHasOpenRefStatus(projectService); // file1
|
||||
const session = new TestSession({ host, useSingleInferredProject: true });
|
||||
openFilesForSession([file1], session);
|
||||
logConfiguredProjectsHasOpenRefStatus(session); // file1
|
||||
|
||||
projectService.closeClientFile(file1.path);
|
||||
logConfiguredProjectsHasOpenRefStatus(projectService); // No open files
|
||||
closeFilesForSession([file1], session);
|
||||
logConfiguredProjectsHasOpenRefStatus(session); // No open files
|
||||
|
||||
projectService.openClientFile(file2.path);
|
||||
logConfiguredProjectsHasOpenRefStatus(projectService); // file2
|
||||
baselineTsserverLogs("configuredProjects", "should reuse same project if file is opened from the configured project that has no open files", projectService);
|
||||
openFilesForSession([file2], session);
|
||||
logConfiguredProjectsHasOpenRefStatus(session); // file2
|
||||
baselineTsserverLogs("configuredProjects", "should reuse same project if file is opened from the configured project that has no open files", session);
|
||||
});
|
||||
|
||||
it("should not close configured project after closing last open file, but should be closed on next file open if its not the file from same project", () => {
|
||||
@@ -342,16 +326,16 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => {
|
||||
}`,
|
||||
};
|
||||
const host = createServerHost([file1, configFile, libFile]);
|
||||
const projectService = createProjectService(host, { useSingleInferredProject: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
projectService.openClientFile(file1.path);
|
||||
logConfiguredProjectsHasOpenRefStatus(projectService); // file1
|
||||
const session = new TestSession({ host, useSingleInferredProject: true });
|
||||
openFilesForSession([file1], session);
|
||||
logConfiguredProjectsHasOpenRefStatus(session); // file1
|
||||
|
||||
projectService.closeClientFile(file1.path);
|
||||
logConfiguredProjectsHasOpenRefStatus(projectService); // No files
|
||||
closeFilesForSession([file1], session);
|
||||
logConfiguredProjectsHasOpenRefStatus(session); // No files
|
||||
|
||||
projectService.openClientFile(libFile.path);
|
||||
logConfiguredProjectsHasOpenRefStatus(projectService); // No files + project closed
|
||||
baselineTsserverLogs("configuredProjects", "should not close configured project after closing last open file, but should be closed on next file open if its not the file from same project", projectService);
|
||||
openFilesForSession([libFile], session);
|
||||
logConfiguredProjectsHasOpenRefStatus(session); // No files + project closed
|
||||
baselineTsserverLogs("configuredProjects", "should not close configured project after closing last open file, but should be closed on next file open if its not the file from same project", session);
|
||||
});
|
||||
|
||||
it("open file become a part of configured project if it is referenced from root file", () => {
|
||||
@@ -373,16 +357,13 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => {
|
||||
};
|
||||
|
||||
const host = createServerHost([file1, file2, file3]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
|
||||
projectService.openClientFile(file1.path);
|
||||
|
||||
projectService.openClientFile(file3.path);
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file1, file3], session);
|
||||
|
||||
host.writeFile(configFile.path, configFile.content);
|
||||
host.runQueuedTimeoutCallbacks(); // load configured project from disk + ensureProjectsForOpenFiles
|
||||
logInferredProjectsOrphanStatus(projectService);
|
||||
baselineTsserverLogs("configuredProjects", "open file become a part of configured project if it is referenced from root file", projectService);
|
||||
logInferredProjectsOrphanStatus(session);
|
||||
baselineTsserverLogs("configuredProjects", "open file become a part of configured project if it is referenced from root file", session);
|
||||
});
|
||||
|
||||
it("can correctly update configured project when set of root files has changed (new file on disk)", () => {
|
||||
@@ -400,15 +381,14 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => {
|
||||
};
|
||||
|
||||
const host = createServerHost([file1, configFile]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
|
||||
projectService.openClientFile(file1.path);
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file1], session);
|
||||
|
||||
host.writeFile(file2.path, file2.content);
|
||||
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
|
||||
baselineTsserverLogs("configuredProjects", "can correctly update configured project when set of root files has changed (new file on disk)", projectService);
|
||||
baselineTsserverLogs("configuredProjects", "can correctly update configured project when set of root files has changed (new file on disk)", session);
|
||||
});
|
||||
|
||||
it("can correctly update configured project when set of root files has changed (new file in list of files)", () => {
|
||||
@@ -426,14 +406,13 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => {
|
||||
};
|
||||
|
||||
const host = createServerHost([file1, file2, configFile]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
|
||||
projectService.openClientFile(file1.path);
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file1], session);
|
||||
|
||||
host.writeFile(configFile.path, jsonToReadableText({ compilerOptions: {}, files: ["f1.ts", "f2.ts"] }));
|
||||
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
baselineTsserverLogs("configuredProjects", "can correctly update configured project when set of root files has changed (new file in list of files)", projectService);
|
||||
baselineTsserverLogs("configuredProjects", "can correctly update configured project when set of root files has changed (new file in list of files)", session);
|
||||
});
|
||||
|
||||
it("can update configured project when set of root files was not changed", () => {
|
||||
@@ -451,14 +430,13 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => {
|
||||
};
|
||||
|
||||
const host = createServerHost([file1, file2, configFile]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
|
||||
projectService.openClientFile(file1.path);
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file1], session);
|
||||
|
||||
host.writeFile(configFile.path, jsonToReadableText({ compilerOptions: { outFile: "out.js" }, files: ["f1.ts", "f2.ts"] }));
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
|
||||
baselineTsserverLogs("configuredProjects", "can update configured project when set of root files was not changed", projectService);
|
||||
baselineTsserverLogs("configuredProjects", "can update configured project when set of root files was not changed", session);
|
||||
});
|
||||
|
||||
it("Open ref of configured project when open file gets added to the project as part of configured file update", () => {
|
||||
@@ -485,43 +463,37 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => {
|
||||
|
||||
const files = [file1, file2, file3, file4];
|
||||
const host = createServerHost(files.concat(configFile));
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file1, file2, file3, file4], session);
|
||||
|
||||
projectService.openClientFile(file1.path);
|
||||
projectService.openClientFile(file2.path);
|
||||
projectService.openClientFile(file3.path);
|
||||
projectService.openClientFile(file4.path);
|
||||
|
||||
logConfiguredProjectsHasOpenRefStatus(projectService); // file1 and file3
|
||||
logConfiguredProjectsHasOpenRefStatus(session); // file1 and file3
|
||||
|
||||
host.writeFile(configFile.path, "{}");
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
|
||||
logConfiguredProjectsHasOpenRefStatus(projectService); // file1, file2, file3
|
||||
logInferredProjectsOrphanStatus(projectService);
|
||||
logConfiguredProjectsHasOpenRefStatus(session); // file1, file2, file3
|
||||
logInferredProjectsOrphanStatus(session);
|
||||
|
||||
projectService.closeClientFile(file1.path);
|
||||
projectService.closeClientFile(file2.path);
|
||||
projectService.closeClientFile(file4.path);
|
||||
closeFilesForSession([file1, file2, file4], session);
|
||||
|
||||
logConfiguredProjectsHasOpenRefStatus(projectService); // file3
|
||||
logInferredProjectsOrphanStatus(projectService);
|
||||
logConfiguredProjectsHasOpenRefStatus(session); // file3
|
||||
logInferredProjectsOrphanStatus(session);
|
||||
|
||||
projectService.openClientFile(file4.path);
|
||||
logConfiguredProjectsHasOpenRefStatus(projectService); // file3
|
||||
openFilesForSession([file4], session);
|
||||
logConfiguredProjectsHasOpenRefStatus(session); // file3
|
||||
|
||||
projectService.closeClientFile(file3.path);
|
||||
logConfiguredProjectsHasOpenRefStatus(projectService); // No files
|
||||
closeFilesForSession([file3], session);
|
||||
logConfiguredProjectsHasOpenRefStatus(session); // No files
|
||||
|
||||
const file5: File = {
|
||||
path: "/file5.ts",
|
||||
content: "let zz = 1;",
|
||||
};
|
||||
host.writeFile(file5.path, file5.content);
|
||||
projectService.testhost.baselineHost("File5 written");
|
||||
projectService.openClientFile(file5.path);
|
||||
session.host.baselineHost("File5 written");
|
||||
openFilesForSession([file5], session);
|
||||
|
||||
baselineTsserverLogs("configuredProjects", "Open ref of configured project when open file gets added to the project as part of configured file update", projectService);
|
||||
baselineTsserverLogs("configuredProjects", "Open ref of configured project when open file gets added to the project as part of configured file update", session);
|
||||
});
|
||||
|
||||
it("Open ref of configured project when open file gets added to the project as part of configured file update buts its open file references are all closed when the update happens", () => {
|
||||
@@ -549,30 +521,26 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => {
|
||||
const files = [file1, file2, file3];
|
||||
const hostFiles = files.concat(file4, configFile);
|
||||
const host = createServerHost(hostFiles);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file1, file2, file3], session);
|
||||
|
||||
projectService.openClientFile(file1.path);
|
||||
projectService.openClientFile(file2.path);
|
||||
projectService.openClientFile(file3.path);
|
||||
logConfiguredProjectsHasOpenRefStatus(session); // file1 and file3
|
||||
|
||||
logConfiguredProjectsHasOpenRefStatus(projectService); // file1 and file3
|
||||
|
||||
projectService.closeClientFile(file1.path);
|
||||
projectService.closeClientFile(file3.path);
|
||||
logConfiguredProjectsHasOpenRefStatus(projectService); // No files
|
||||
closeFilesForSession([file1, file3], session);
|
||||
logConfiguredProjectsHasOpenRefStatus(session); // No files
|
||||
|
||||
host.writeFile(configFile.path, "{}");
|
||||
projectService.testhost.baselineHost("configFile updated");
|
||||
session.host.baselineHost("configFile updated");
|
||||
// Time out is not yet run so there is project update pending
|
||||
logConfiguredProjectsHasOpenRefStatus(projectService); // Pending update and file2 might get into the project
|
||||
logConfiguredProjectsHasOpenRefStatus(session); // Pending update and file2 might get into the project
|
||||
|
||||
projectService.openClientFile(file4.path);
|
||||
logConfiguredProjectsHasOpenRefStatus(projectService); // Pending update and F2 might get into the project
|
||||
openFilesForSession([file4], session);
|
||||
logConfiguredProjectsHasOpenRefStatus(session); // Pending update and F2 might get into the project
|
||||
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
logConfiguredProjectsHasOpenRefStatus(projectService); // file2
|
||||
logInferredProjectsOrphanStatus(projectService);
|
||||
baselineTsserverLogs("configuredProjects", "Open ref of configured project when open file gets added to the project as part of configured file update buts its open file references are all closed when the update happens", projectService);
|
||||
logConfiguredProjectsHasOpenRefStatus(session); // file2
|
||||
logInferredProjectsOrphanStatus(session);
|
||||
baselineTsserverLogs("configuredProjects", "Open ref of configured project when open file gets added to the project as part of configured file update buts its open file references are all closed when the update happens", session);
|
||||
});
|
||||
|
||||
it("files are properly detached when language service is disabled", () => {
|
||||
@@ -596,17 +564,17 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => {
|
||||
const originalGetFileSize = host.getFileSize;
|
||||
host.getFileSize = (filePath: string) => filePath === f2.path ? ts.server.maxProgramSizeForNonTsFiles + 1 : originalGetFileSize.call(host, filePath);
|
||||
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
projectService.openClientFile(f1.path);
|
||||
logConfiguredProjectsHasOpenRefStatus(projectService); // f1
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([f1], session);
|
||||
logConfiguredProjectsHasOpenRefStatus(session); // f1
|
||||
|
||||
projectService.closeClientFile(f1.path);
|
||||
logConfiguredProjectsHasOpenRefStatus(projectService); // No files
|
||||
closeFilesForSession([f1], session);
|
||||
logConfiguredProjectsHasOpenRefStatus(session); // No files
|
||||
|
||||
for (const f of [f1, f2, f3]) {
|
||||
// All the script infos should be present and contain the project since it is still alive.
|
||||
const scriptInfo = projectService.getScriptInfoForNormalizedPath(ts.server.toNormalizedPath(f.path))!;
|
||||
projectService.logger.log(`Containing projects for ${f.path}:: ${scriptInfo.containingProjects.map(p => p.projectName).join(",")}`);
|
||||
const scriptInfo = session.getProjectService().getScriptInfoForNormalizedPath(ts.server.toNormalizedPath(f.path))!;
|
||||
session.logger.log(`Containing projects for ${f.path}:: ${scriptInfo.containingProjects.map(p => p.projectName).join(",")}`);
|
||||
}
|
||||
|
||||
const f4 = {
|
||||
@@ -614,14 +582,14 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => {
|
||||
content: "var x = 1",
|
||||
};
|
||||
host.writeFile(f4.path, f4.content);
|
||||
projectService.openClientFile(f4.path);
|
||||
logConfiguredProjectsHasOpenRefStatus(projectService); // No files
|
||||
openFilesForSession([f4], session);
|
||||
logConfiguredProjectsHasOpenRefStatus(session); // No files
|
||||
|
||||
for (const f of [f1, f2, f3]) {
|
||||
// All the script infos should not be present since the project is closed and orphan script infos are collected
|
||||
assert.isUndefined(projectService.getScriptInfoForNormalizedPath(ts.server.toNormalizedPath(f.path)));
|
||||
assert.isUndefined(session.getProjectService().getScriptInfoForNormalizedPath(ts.server.toNormalizedPath(f.path)));
|
||||
}
|
||||
baselineTsserverLogs("configuredProjects", "files are properly detached when language service is disabled", projectService);
|
||||
baselineTsserverLogs("configuredProjects", "files are properly detached when language service is disabled", session);
|
||||
});
|
||||
|
||||
it("syntactic features work even if language service is disabled", () => {
|
||||
@@ -640,7 +608,7 @@ describe("unittests:: tsserver:: ConfiguredProjects", () => {
|
||||
const host = createServerHost([f1, f2, config]);
|
||||
const originalGetFileSize = host.getFileSize;
|
||||
host.getFileSize = (filePath: string) => filePath === f2.path ? ts.server.maxProgramSizeForNonTsFiles + 1 : originalGetFileSize.call(host, filePath);
|
||||
const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([f1], session);
|
||||
session.logger.log(`Language languageServiceEnabled:: ${session.getProjectService().configuredProjects.get(config.path)!.languageServiceEnabled}`);
|
||||
|
||||
@@ -702,7 +670,7 @@ declare var console: {
|
||||
};`,
|
||||
};
|
||||
const host = createServerHost([barConfig, barIndex, fooConfig, fooIndex, barSymLink, lib2017, libDom]);
|
||||
const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([fooIndex, barIndex], session);
|
||||
verifyGetErrRequest({ session, files: [barIndex, fooIndex] });
|
||||
baselineTsserverLogs("configuredProjects", "when multiple projects are open detects correct default project", session);
|
||||
@@ -722,9 +690,9 @@ declare var console: {
|
||||
content: "{}",
|
||||
};
|
||||
const host = createServerHost([file, app, tsconfig, libFile]);
|
||||
const service = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
service.openClientFile(file.path);
|
||||
baselineTsserverLogs("configuredProjects", "when file name starts with caret", service);
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file], session);
|
||||
baselineTsserverLogs("configuredProjects", "when file name starts with caret", session);
|
||||
});
|
||||
|
||||
describe("when creating new file", () => {
|
||||
@@ -762,10 +730,7 @@ declare var console: {
|
||||
} :
|
||||
config,
|
||||
]);
|
||||
const session = createSession(host, {
|
||||
canUseEvents: true,
|
||||
logger: createLoggerWithInMemoryLogs(host),
|
||||
});
|
||||
const session = new TestSession(host);
|
||||
session.executeCommandSeq<ts.server.protocol.OpenRequest>({
|
||||
command: ts.server.protocol.CommandTypes.Open,
|
||||
arguments: {
|
||||
@@ -870,8 +835,7 @@ foo();`,
|
||||
const host = createServerHost([barConfig, barIndex, fooBarConfig, fooBarIndex, fooConfig, fooIndex, libFile]);
|
||||
ensureErrorFreeBuild(host, [fooConfig.path]);
|
||||
const fooDts = `/user/username/projects/myproject/foo/lib/index.d.ts`;
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const service = session.getProjectService();
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([barIndex, fooBarIndex, fooIndex, fooDts], session);
|
||||
session.executeCommandSeq<ts.server.protocol.GetApplicableRefactorsRequest>({
|
||||
command: ts.server.protocol.CommandTypes.GetApplicableRefactors,
|
||||
@@ -883,7 +847,7 @@ foo();`,
|
||||
endOffset: 1,
|
||||
},
|
||||
});
|
||||
session.logger.log(`Default project for file: ${fooDts}: ${service.tryGetDefaultProjectForFile(ts.server.toNormalizedPath(fooDts))?.projectName}`);
|
||||
session.logger.log(`Default project for file: ${fooDts}: ${session.getProjectService().tryGetDefaultProjectForFile(ts.server.toNormalizedPath(fooDts))?.projectName}`);
|
||||
baselineTsserverLogs("configuredProjects", "when default configured project does not contain the file", session);
|
||||
});
|
||||
|
||||
@@ -923,15 +887,14 @@ foo();`,
|
||||
};
|
||||
|
||||
const host = createServerHost([alphaExtendedConfig, aConfig, aFile, bravoExtendedConfig, bConfig, bFile, ...(additionalFiles || ts.emptyArray)]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
return { host, projectService, aFile, bFile, aConfig, bConfig, alphaExtendedConfig, bravoExtendedConfig };
|
||||
const session = new TestSession(host);
|
||||
return { host, session, aFile, bFile, aConfig, bConfig, alphaExtendedConfig, bravoExtendedConfig };
|
||||
}
|
||||
|
||||
it("should watch the extended configs of multiple projects", () => {
|
||||
const { host, projectService, aFile, bFile, bConfig, alphaExtendedConfig, bravoExtendedConfig } = getService();
|
||||
const { host, session, aFile, bFile, bConfig, alphaExtendedConfig, bravoExtendedConfig } = getService();
|
||||
|
||||
projectService.openClientFile(aFile.path);
|
||||
projectService.openClientFile(bFile.path);
|
||||
openFilesForSession([aFile, bFile], session);
|
||||
|
||||
host.writeFile(
|
||||
alphaExtendedConfig.path,
|
||||
@@ -964,7 +927,7 @@ foo();`,
|
||||
|
||||
host.writeFile(alphaExtendedConfig.path, "{}");
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
baselineTsserverLogs("configuredProjects", "should watch the extended configs of multiple projects", projectService);
|
||||
baselineTsserverLogs("configuredProjects", "should watch the extended configs of multiple projects", session);
|
||||
});
|
||||
|
||||
it("should stop watching the extended configs of closed projects", () => {
|
||||
@@ -976,20 +939,16 @@ foo();`,
|
||||
path: `/user/username/projects/myproject/dummy/tsconfig.json`,
|
||||
content: "{}",
|
||||
};
|
||||
const { projectService, aFile, bFile } = getService([dummy, dummyConfig]);
|
||||
const { session, aFile, bFile } = getService([dummy, dummyConfig]);
|
||||
|
||||
projectService.openClientFile(aFile.path);
|
||||
projectService.openClientFile(bFile.path);
|
||||
projectService.openClientFile(dummy.path);
|
||||
openFilesForSession([aFile, bFile, dummy], session);
|
||||
|
||||
projectService.closeClientFile(bFile.path);
|
||||
projectService.closeClientFile(dummy.path);
|
||||
projectService.openClientFile(dummy.path);
|
||||
closeFilesForSession([bFile, dummy], session);
|
||||
openFilesForSession([dummy], session);
|
||||
|
||||
projectService.closeClientFile(aFile.path);
|
||||
projectService.closeClientFile(dummy.path);
|
||||
projectService.openClientFile(dummy.path);
|
||||
baselineTsserverLogs("configuredProjects", "should stop watching the extended configs of closed projects", projectService);
|
||||
closeFilesForSession([aFile, dummy], session);
|
||||
openFilesForSession([dummy], session);
|
||||
baselineTsserverLogs("configuredProjects", "should stop watching the extended configs of closed projects", session);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1009,12 +968,12 @@ describe("unittests:: tsserver:: ConfiguredProjects:: non-existing directories l
|
||||
};
|
||||
|
||||
const host = createServerHost([file1, configFile]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
projectService.openClientFile(file1.path);
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file1], session);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
|
||||
// Since file1 refers to config file as the default project, it needs to be kept alive
|
||||
baselineTsserverLogs("configuredProjects", "should be tolerated without crashing the server", projectService);
|
||||
baselineTsserverLogs("configuredProjects", "should be tolerated without crashing the server", session);
|
||||
});
|
||||
|
||||
it("should be able to handle @types if input file list is empty", () => {
|
||||
@@ -1038,11 +997,11 @@ describe("unittests:: tsserver:: ConfiguredProjects:: non-existing directories l
|
||||
content: `export const x: number`,
|
||||
};
|
||||
const host = createServerHost([f, config, t1, t2], { currentDirectory: ts.getDirectoryPath(f.path) });
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([f], session);
|
||||
|
||||
projectService.openClientFile(f.path);
|
||||
// Since f refers to config file as the default project, it needs to be kept alive
|
||||
baselineTsserverLogs("configuredProjects", "should be able to handle @types if input file list is empty", projectService);
|
||||
baselineTsserverLogs("configuredProjects", "should be able to handle @types if input file list is empty", session);
|
||||
});
|
||||
|
||||
it("should tolerate invalid include files that start in subDirectory", () => {
|
||||
@@ -1063,11 +1022,11 @@ describe("unittests:: tsserver:: ConfiguredProjects:: non-existing directories l
|
||||
}),
|
||||
};
|
||||
const host = createServerHost([f, config, libFile], { useCaseSensitiveFileNames: true });
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([f], session);
|
||||
|
||||
projectService.openClientFile(f.path);
|
||||
// Since f refers to config file as the default project, it needs to be kept alive
|
||||
baselineTsserverLogs("configuredProjects", "should tolerate invalid include files that start in subDirectory", projectService);
|
||||
baselineTsserverLogs("configuredProjects", "should tolerate invalid include files that start in subDirectory", session);
|
||||
});
|
||||
|
||||
it("Changed module resolution reflected when specifying files list", () => {
|
||||
@@ -1089,16 +1048,16 @@ describe("unittests:: tsserver:: ConfiguredProjects:: non-existing directories l
|
||||
};
|
||||
const files = [file1, file2a, configFile, libFile];
|
||||
const host = createServerHost(files);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
projectService.openClientFile(file1.path);
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file1], session);
|
||||
|
||||
host.writeFile(file2.path, file2.content);
|
||||
host.runQueuedTimeoutCallbacks(); // Scheduled invalidation of resolutions
|
||||
host.runQueuedTimeoutCallbacks(); // Actual update
|
||||
|
||||
// On next file open the files file2a should be closed and not watched any more
|
||||
projectService.openClientFile(file2.path);
|
||||
baselineTsserverLogs("configuredProjects", "changed module resolution reflected when specifying files list", projectService);
|
||||
openFilesForSession([file2], session);
|
||||
baselineTsserverLogs("configuredProjects", "changed module resolution reflected when specifying files list", session);
|
||||
});
|
||||
|
||||
it("Failed lookup locations uses parent most node_modules directory", () => {
|
||||
@@ -1128,9 +1087,9 @@ describe("unittests:: tsserver:: ConfiguredProjects:: non-existing directories l
|
||||
nonLibFiles.forEach(f => f.path = root + f.path);
|
||||
const files = nonLibFiles.concat(libFile);
|
||||
const host = createServerHost(files);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
projectService.openClientFile(file1.path);
|
||||
baselineTsserverLogs("configuredProjects", "failed lookup locations uses parent most node_modules directory", projectService);
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file1], session);
|
||||
baselineTsserverLogs("configuredProjects", "failed lookup locations uses parent most node_modules directory", session);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1146,7 +1105,7 @@ describe("unittests:: tsserver:: ConfiguredProjects:: when reading tsconfig file
|
||||
};
|
||||
|
||||
const host = createServerHost([file1, libFile, configFile]);
|
||||
const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
const originalReadFile = host.readFile;
|
||||
host.readFile = f => {
|
||||
return f === configFile.path ?
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
jsonToReadableText,
|
||||
@@ -8,7 +5,6 @@ import {
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
closeFilesForSession,
|
||||
createSession,
|
||||
openFilesForSession,
|
||||
protocolFileLocationFromSubstring,
|
||||
TestSession,
|
||||
@@ -108,7 +104,7 @@ describe("unittests:: tsserver:: with declaration file maps:: project references
|
||||
|
||||
function makeSampleProjects(addUserTsConfig?: boolean, keepAllFiles?: boolean) {
|
||||
const host = createServerHost([aTs, aTsconfig, aDtsMap, aDts, bTsconfig, bTs, bDtsMap, bDts, ...(addUserTsConfig ? [userTsForConfigProject, userTsconfig] : [userTs]), dummyFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
|
||||
checkDeclarationFiles(aTs, session);
|
||||
checkDeclarationFiles(bTs, session);
|
||||
@@ -285,7 +281,7 @@ describe("unittests:: tsserver:: with declaration file maps:: project references
|
||||
};
|
||||
|
||||
const host = createServerHost([aTs, aTsconfig, bTs, bTsconfig, aDts, aDtsMap]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
checkDeclarationFiles(aTs, session);
|
||||
openFilesForSession([bTs], session);
|
||||
|
||||
@@ -387,7 +383,7 @@ describe("unittests:: tsserver:: with declaration file maps:: project references
|
||||
};
|
||||
|
||||
const host = createServerHost([aTs, aTsconfig, bTs, bTsconfig]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([aTs, bTs], session);
|
||||
session.executeCommandSeq<ts.server.protocol.GetEditsForFileRenameRequest>({
|
||||
command: ts.server.protocol.CommandTypes.GetEditsForFileRename,
|
||||
@@ -409,7 +405,7 @@ describe("unittests:: tsserver:: with declaration file maps:: project references
|
||||
content: jsonToReadableText(aDtsInlinedSources),
|
||||
};
|
||||
const host = createServerHost([aTs, aDtsMapInlinedSources, aDts, bTs, bDtsMap, bDts, userTs, dummyFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
|
||||
openFilesForSession([userTs], session);
|
||||
// If config file then userConfig project and bConfig project since it is referenced
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
import {
|
||||
reportDocumentRegistryStats,
|
||||
} from "../../../harness/incrementalUtils";
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
jsonToReadableText,
|
||||
@@ -11,10 +8,8 @@ import {
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
closeFilesForSession,
|
||||
createProjectService,
|
||||
createSession,
|
||||
openFilesForSession,
|
||||
TestProjectService,
|
||||
TestSession,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
createServerHost,
|
||||
@@ -37,88 +32,106 @@ describe("unittests:: tsserver:: documentRegistry:: document registry in project
|
||||
content: jsonToReadableText({ files: ["index.ts"] }),
|
||||
};
|
||||
|
||||
function getProject(service: TestProjectService) {
|
||||
return service.configuredProjects.get(configFile.path)!;
|
||||
function getProject(session: TestSession) {
|
||||
return session.getProjectService().configuredProjects.get(configFile.path)!;
|
||||
}
|
||||
|
||||
function checkProject(service: TestProjectService, moduleIsOrphan: boolean) {
|
||||
function checkProject(session: TestSession, moduleIsOrphan: boolean) {
|
||||
// Update the project
|
||||
const project = getProject(service);
|
||||
const project = getProject(session);
|
||||
project.getLanguageService();
|
||||
const moduleInfo = service.getScriptInfo(moduleFile.path)!;
|
||||
const moduleInfo = session.getProjectService().getScriptInfo(moduleFile.path)!;
|
||||
assert.isDefined(moduleInfo);
|
||||
assert.equal(moduleInfo.isOrphan(), moduleIsOrphan);
|
||||
service.logger.log("DocumentRegistry::");
|
||||
service.logger.log(reportDocumentRegistryStats(service.documentRegistry).join("\n"));
|
||||
session.logger.log("DocumentRegistry::");
|
||||
session.logger.log(reportDocumentRegistryStats(session.getProjectService().documentRegistry).join("\n"));
|
||||
}
|
||||
|
||||
function createServiceAndHost() {
|
||||
function createSessionAndHost() {
|
||||
const host = createServerHost([file, moduleFile, libFile, configFile]);
|
||||
const service = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
service.openClientFile(file.path);
|
||||
checkProject(service, /*moduleIsOrphan*/ false);
|
||||
return { host, service };
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file], session);
|
||||
checkProject(session, /*moduleIsOrphan*/ false);
|
||||
return { host, session };
|
||||
}
|
||||
|
||||
function changeFileToNotImportModule(service: TestProjectService) {
|
||||
const info = service.getScriptInfo(file.path)!;
|
||||
service.applyChangesToFile(info, ts.singleIterator({ span: { start: 0, length: importModuleContent.length }, newText: "" }));
|
||||
checkProject(service, /*moduleIsOrphan*/ true);
|
||||
function changeFileToNotImportModule(session: TestSession) {
|
||||
session.executeCommandSeq<ts.server.protocol.ChangeRequest>({
|
||||
command: ts.server.protocol.CommandTypes.Change,
|
||||
arguments: {
|
||||
file: file.path,
|
||||
line: 1,
|
||||
offset: 1,
|
||||
endLine: 1,
|
||||
endOffset: importModuleContent.length + 1,
|
||||
insertString: "",
|
||||
},
|
||||
});
|
||||
checkProject(session, /*moduleIsOrphan*/ true);
|
||||
}
|
||||
|
||||
function changeFileToImportModule(service: TestProjectService) {
|
||||
const info = service.getScriptInfo(file.path)!;
|
||||
service.applyChangesToFile(info, ts.singleIterator({ span: { start: 0, length: 0 }, newText: importModuleContent }));
|
||||
checkProject(service, /*moduleIsOrphan*/ false);
|
||||
function changeFileToImportModule(session: TestSession) {
|
||||
session.executeCommandSeq<ts.server.protocol.ChangeRequest>({
|
||||
command: ts.server.protocol.CommandTypes.Change,
|
||||
arguments: {
|
||||
file: file.path,
|
||||
line: 1,
|
||||
offset: 1,
|
||||
endLine: 1,
|
||||
endOffset: 1,
|
||||
insertString: importModuleContent,
|
||||
},
|
||||
});
|
||||
checkProject(session, /*moduleIsOrphan*/ false);
|
||||
}
|
||||
|
||||
it("Caches the source file if script info is orphan", () => {
|
||||
const { service } = createServiceAndHost();
|
||||
const project = getProject(service);
|
||||
const { session } = createSessionAndHost();
|
||||
const project = getProject(session);
|
||||
|
||||
const moduleInfo = service.getScriptInfo(moduleFile.path)!;
|
||||
const moduleInfo = session.getProjectService().getScriptInfo(moduleFile.path)!;
|
||||
const sourceFile = moduleInfo.cacheSourceFile!.sourceFile;
|
||||
assert.equal(project.getSourceFile(moduleInfo.path), sourceFile);
|
||||
|
||||
// edit file
|
||||
changeFileToNotImportModule(service);
|
||||
changeFileToNotImportModule(session);
|
||||
assert.equal(moduleInfo.cacheSourceFile!.sourceFile, sourceFile);
|
||||
|
||||
// write content back
|
||||
changeFileToImportModule(service);
|
||||
changeFileToImportModule(session);
|
||||
assert.equal(moduleInfo.cacheSourceFile!.sourceFile, sourceFile);
|
||||
assert.equal(project.getSourceFile(moduleInfo.path), sourceFile);
|
||||
baselineTsserverLogs("documentRegistry", "Caches the source file if script info is orphan", service);
|
||||
baselineTsserverLogs("documentRegistry", "Caches the source file if script info is orphan", session);
|
||||
});
|
||||
|
||||
it("Caches the source file if script info is orphan, and orphan script info changes", () => {
|
||||
const { host, service } = createServiceAndHost();
|
||||
const project = getProject(service);
|
||||
const { host, session } = createSessionAndHost();
|
||||
const project = getProject(session);
|
||||
|
||||
const moduleInfo = service.getScriptInfo(moduleFile.path)!;
|
||||
const moduleInfo = session.getProjectService().getScriptInfo(moduleFile.path)!;
|
||||
const sourceFile = moduleInfo.cacheSourceFile!.sourceFile;
|
||||
assert.equal(project.getSourceFile(moduleInfo.path), sourceFile);
|
||||
|
||||
// edit file
|
||||
changeFileToNotImportModule(service);
|
||||
changeFileToNotImportModule(session);
|
||||
assert.equal(moduleInfo.cacheSourceFile!.sourceFile, sourceFile);
|
||||
|
||||
const updatedModuleContent = moduleFile.content + "\nexport const b: number;";
|
||||
host.writeFile(moduleFile.path, updatedModuleContent);
|
||||
|
||||
// write content back
|
||||
changeFileToImportModule(service);
|
||||
changeFileToImportModule(session);
|
||||
assert.notEqual(moduleInfo.cacheSourceFile!.sourceFile, sourceFile);
|
||||
assert.equal(project.getSourceFile(moduleInfo.path), moduleInfo.cacheSourceFile!.sourceFile);
|
||||
assert.equal(moduleInfo.cacheSourceFile!.sourceFile.text, updatedModuleContent);
|
||||
baselineTsserverLogs("documentRegistry", "Caches the source file if script info is orphan, and orphan script info changes", service);
|
||||
baselineTsserverLogs("documentRegistry", "Caches the source file if script info is orphan, and orphan script info changes", session);
|
||||
});
|
||||
});
|
||||
|
||||
describe("unittests:: tsserver:: documentRegistry:: works when reusing orphan script info with different scriptKind", () => {
|
||||
it("works when reusing orphan script info with different scriptKind", () => {
|
||||
const host = createServerHost({});
|
||||
const session = createSession(host, { useInferredProjectPerProjectRoot: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession({ host, useInferredProjectPerProjectRoot: true });
|
||||
const newText = "exrpot const x = 10;";
|
||||
const content = `import x from 'react';\n${newText}`;
|
||||
openFilesForSession([
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
jsonToReadableText,
|
||||
} from "../helpers";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createSession,
|
||||
openFilesForSession,
|
||||
TestSession,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
createServerHost,
|
||||
@@ -34,7 +31,7 @@ describe("unittests:: tsserver:: duplicate packages", () => {
|
||||
};
|
||||
|
||||
const host = createServerHost([aFooIndex, aFooPackage, bFooIndex, bFooPackage, aUser, bUser, tsconfig]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
|
||||
openFilesForSession([aUser, bUser], session);
|
||||
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createProjectService,
|
||||
createSession,
|
||||
closeFilesForSession,
|
||||
openFilesForSession,
|
||||
protocolFileLocationFromSubstring,
|
||||
setCompilerOptionsForInferredProjectsRequestForSession,
|
||||
TestSession,
|
||||
verifyDynamic,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
@@ -26,11 +23,11 @@ function verifyPathRecognizedAsDynamic(subscenario: string, path: string) {
|
||||
var x = 10;`,
|
||||
};
|
||||
const host = createServerHost([libFile]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
projectService.openClientFile(file.path, file.content);
|
||||
verifyDynamic(projectService, projectService.toPath(file.path));
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([{ file, content: file.content }], session);
|
||||
verifyDynamic(session, session.getProjectService().toPath(file.path));
|
||||
|
||||
baselineTsserverLogs("dynamicFiles", subscenario, projectService);
|
||||
baselineTsserverLogs("dynamicFiles", subscenario, session);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -40,7 +37,7 @@ describe("unittests:: tsserver:: dynamicFiles:: Untitled files", () => {
|
||||
const aTs: File = { path: "/proj/a.ts", content: "" };
|
||||
const tsconfig: File = { path: "/proj/tsconfig.json", content: "{}" };
|
||||
const host = createServerHost([aTs, tsconfig]);
|
||||
const session = createSession(host, { useInferredProjectPerProjectRoot: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession({ host, useInferredProjectPerProjectRoot: true });
|
||||
|
||||
openFilesForSession([aTs], session);
|
||||
|
||||
@@ -53,7 +50,7 @@ describe("unittests:: tsserver:: dynamicFiles:: Untitled files", () => {
|
||||
projectRootPath: "/proj",
|
||||
},
|
||||
});
|
||||
verifyDynamic(session.getProjectService(), `/proj/untitled:^untitled-1`);
|
||||
verifyDynamic(session, `/proj/untitled:^untitled-1`);
|
||||
session.executeCommandSeq<ts.server.protocol.CodeFixRequest>({
|
||||
command: ts.server.protocol.CommandTypes.GetCodeFixes,
|
||||
arguments: {
|
||||
@@ -74,23 +71,34 @@ describe("unittests:: tsserver:: dynamicFiles:: Untitled files", () => {
|
||||
content: "{}",
|
||||
};
|
||||
const host = createServerHost([config, libFile], { useCaseSensitiveFileNames: true, currentDirectory: "/user/username/projects/myproject" });
|
||||
const service = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
service.openClientFile(untitledFile, "const x = 10;", /*scriptKind*/ undefined, "/user/username/projects/myproject");
|
||||
verifyDynamic(service, `/user/username/projects/myproject/${untitledFile}`);
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([{
|
||||
file: untitledFile,
|
||||
content: "const x = 10;",
|
||||
projectRootPath: "/user/username/projects/myproject",
|
||||
}], session);
|
||||
verifyDynamic(session, `/user/username/projects/myproject/${untitledFile}`);
|
||||
|
||||
const untitled: File = {
|
||||
path: `/user/username/projects/myproject/Untitled-1.ts`,
|
||||
content: "const x = 10;",
|
||||
};
|
||||
host.writeFile(untitled.path, untitled.content);
|
||||
service.testhost.logTimeoutQueueLength();
|
||||
service.openClientFile(untitled.path, untitled.content, /*scriptKind*/ undefined, "/user/username/projects/myproject");
|
||||
openFilesForSession([{
|
||||
file: untitled.path,
|
||||
content: untitled.content,
|
||||
projectRootPath: "/user/username/projects/myproject",
|
||||
}], session);
|
||||
|
||||
service.closeClientFile(untitledFile);
|
||||
closeFilesForSession([untitledFile], session);
|
||||
|
||||
service.openClientFile(untitledFile, "const x = 10;", /*scriptKind*/ undefined, "/user/username/projects/myproject");
|
||||
verifyDynamic(service, `/user/username/projects/myproject/${untitledFile}`);
|
||||
baselineTsserverLogs("dynamicFiles", "opening untitled files", service);
|
||||
openFilesForSession([{
|
||||
file: untitledFile,
|
||||
content: "const x = 10;",
|
||||
projectRootPath: "/user/username/projects/myproject",
|
||||
}], session);
|
||||
verifyDynamic(session, `/user/username/projects/myproject/${untitledFile}`);
|
||||
baselineTsserverLogs("dynamicFiles", "opening untitled files", session);
|
||||
});
|
||||
|
||||
it("opening and closing untitled files when projectRootPath is different from currentDirectory", () => {
|
||||
@@ -103,35 +111,49 @@ describe("unittests:: tsserver:: dynamicFiles:: Untitled files", () => {
|
||||
content: "const y = 10",
|
||||
};
|
||||
const host = createServerHost([config, file, libFile], { useCaseSensitiveFileNames: true });
|
||||
const service = createProjectService(host, { useInferredProjectPerProjectRoot: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
service.openClientFile(untitledFile, "const x = 10;", /*scriptKind*/ undefined, "/user/username/projects/myproject");
|
||||
verifyDynamic(service, `/user/username/projects/myproject/${untitledFile}`);
|
||||
const session = new TestSession({ host, useInferredProjectPerProjectRoot: true });
|
||||
openFilesForSession([{
|
||||
file: untitledFile,
|
||||
content: "const x = 10;",
|
||||
projectRootPath: "/user/username/projects/myproject",
|
||||
}], session);
|
||||
verifyDynamic(session, `/user/username/projects/myproject/${untitledFile}`);
|
||||
|
||||
// Close untitled file
|
||||
service.closeClientFile(untitledFile);
|
||||
closeFilesForSession([untitledFile], session);
|
||||
|
||||
// Open file from configured project which should collect inferredProject
|
||||
service.openClientFile(file.path);
|
||||
baselineTsserverLogs("dynamicFiles", "opening and closing untitled files when projectRootPath is different from currentDirectory", service);
|
||||
openFilesForSession([file], session);
|
||||
baselineTsserverLogs("dynamicFiles", "opening and closing untitled files when projectRootPath is different from currentDirectory", session);
|
||||
});
|
||||
|
||||
it("when changing scriptKind of the untitled files", () => {
|
||||
const host = createServerHost([libFile], { useCaseSensitiveFileNames: true });
|
||||
const service = createProjectService(host, { useInferredProjectPerProjectRoot: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
service.openClientFile(untitledFile, "const x = 10;", ts.ScriptKind.TS, "/user/username/projects/myproject");
|
||||
const program = service.inferredProjects[0].getCurrentProgram()!;
|
||||
const session = new TestSession({ host, useInferredProjectPerProjectRoot: true });
|
||||
openFilesForSession([{
|
||||
file: untitledFile,
|
||||
content: "const x = 10;",
|
||||
scriptKindName: "TS",
|
||||
projectRootPath: "/user/username/projects/myproject",
|
||||
}], session);
|
||||
const program = session.getProjectService().inferredProjects[0].getCurrentProgram()!;
|
||||
const sourceFile = program.getSourceFile(untitledFile)!;
|
||||
|
||||
// Close untitled file
|
||||
service.closeClientFile(untitledFile);
|
||||
closeFilesForSession([untitledFile], session);
|
||||
|
||||
// Open untitled file with different mode
|
||||
service.openClientFile(untitledFile, "const x = 10;", ts.ScriptKind.TSX, "/user/username/projects/myproject");
|
||||
const newProgram = service.inferredProjects[0].getCurrentProgram()!;
|
||||
openFilesForSession([{
|
||||
file: untitledFile,
|
||||
content: "const x = 10;",
|
||||
scriptKindName: "TSX",
|
||||
projectRootPath: "/user/username/projects/myproject",
|
||||
}], session);
|
||||
const newProgram = session.getProjectService().inferredProjects[0].getCurrentProgram()!;
|
||||
const newSourceFile = newProgram.getSourceFile(untitledFile)!;
|
||||
assert.notStrictEqual(newProgram, program);
|
||||
assert.notStrictEqual(newSourceFile, sourceFile);
|
||||
baselineTsserverLogs("dynamicFiles", "when changing scriptKind of the untitled files", service);
|
||||
baselineTsserverLogs("dynamicFiles", "when changing scriptKind of the untitled files", session);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -142,16 +164,16 @@ describe("unittests:: tsserver:: dynamicFiles:: ", () => {
|
||||
content: "var x = 10;",
|
||||
};
|
||||
const host = createServerHost([libFile], { useCaseSensitiveFileNames: true });
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
setCompilerOptionsForInferredProjectsRequestForSession({
|
||||
module: ts.ModuleKind.CommonJS,
|
||||
module: ts.server.protocol.ModuleKind.CommonJS,
|
||||
allowJs: true,
|
||||
allowSyntheticDefaultImports: true,
|
||||
allowNonTsExtensions: true,
|
||||
}, session);
|
||||
openFilesForSession([{ file: file.path, content: "var x = 10;" }], session);
|
||||
|
||||
verifyDynamic(session.getProjectService(), `/${file.path}`);
|
||||
verifyDynamic(session, `/${file.path}`);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.QuickInfoRequest>({
|
||||
command: ts.server.protocol.CommandTypes.Quickinfo,
|
||||
@@ -177,11 +199,10 @@ describe("unittests:: tsserver:: dynamicFiles:: ", () => {
|
||||
};
|
||||
it("with useInferredProjectPerProjectRoot", () => {
|
||||
const host = createServerHost([libFile, configFile, configProjectFile], { useCaseSensitiveFileNames: true });
|
||||
const session = createSession(host, { useInferredProjectPerProjectRoot: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession({ host, useInferredProjectPerProjectRoot: true });
|
||||
openFilesForSession([{ file: file.path, projectRootPath: "/user/username/projects/myproject" }], session);
|
||||
|
||||
const projectService = session.getProjectService();
|
||||
verifyDynamic(projectService, `/user/username/projects/myproject/${file.path}`);
|
||||
verifyDynamic(session, `/user/username/projects/myproject/${file.path}`);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.OutliningSpansRequest>({
|
||||
command: ts.server.protocol.CommandTypes.GetOutliningSpans,
|
||||
@@ -198,9 +219,13 @@ describe("unittests:: tsserver:: dynamicFiles:: ", () => {
|
||||
|
||||
it("fails when useInferredProjectPerProjectRoot is false", () => {
|
||||
const host = createServerHost([libFile, configFile, configProjectFile], { useCaseSensitiveFileNames: true });
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
try {
|
||||
projectService.openClientFile(file.path, file.content, /*scriptKind*/ undefined, "/user/username/projects/myproject");
|
||||
openFilesForSession([{
|
||||
file,
|
||||
content: file.content,
|
||||
projectRootPath: "/user/username/projects/myproject",
|
||||
}], session);
|
||||
}
|
||||
catch (e) {
|
||||
assert.strictEqual(
|
||||
@@ -209,8 +234,8 @@ describe("unittests:: tsserver:: dynamicFiles:: ", () => {
|
||||
);
|
||||
}
|
||||
const file2Path = file.path.replace("#1", "#2");
|
||||
projectService.openClientFile(file2Path, file.content);
|
||||
baselineTsserverLogs("dynamicFiles", "dynamic file with projectRootPath fails when useInferredProjectPerProjectRoot is false", projectService);
|
||||
openFilesForSession([{ file: file2Path, content: file.content }], session);
|
||||
baselineTsserverLogs("dynamicFiles", "dynamic file with projectRootPath fails when useInferredProjectPerProjectRoot is false", session);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../../harness/tsserverLogger";
|
||||
import * as ts from "../../../_namespaces/ts";
|
||||
import {
|
||||
jsonToReadableText,
|
||||
} from "../../helpers";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createSession,
|
||||
openFilesForSession,
|
||||
TestSession,
|
||||
} from "../../helpers/tsserver";
|
||||
import {
|
||||
createServerHost,
|
||||
@@ -32,8 +29,7 @@ describe("unittests:: tsserver:: events:: LargeFileReferencedEvent with large fi
|
||||
};
|
||||
files.push(largeFile);
|
||||
const host = createServerHost(files);
|
||||
const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
|
||||
const session = new TestSession(host);
|
||||
return session;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../../harness/tsserverLogger";
|
||||
import * as ts from "../../../_namespaces/ts";
|
||||
import {
|
||||
jsonToReadableText,
|
||||
} from "../../helpers";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createProjectService,
|
||||
createSession,
|
||||
openFilesForSession,
|
||||
TestSession,
|
||||
} from "../../helpers/tsserver";
|
||||
import {
|
||||
createServerHost,
|
||||
@@ -39,7 +35,7 @@ describe("unittests:: tsserver:: events:: ProjectLanguageServiceStateEvent", ()
|
||||
const originalGetFileSize = host.getFileSize;
|
||||
host.getFileSize = (filePath: string) => filePath === f2.path ? ts.server.maxProgramSizeForNonTsFiles + 1 : originalGetFileSize.call(host, filePath);
|
||||
|
||||
const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([f1], session);
|
||||
session.logger.log(`Language service enabled: ${session.getProjectService().configuredProjects.get(config.path)!.languageServiceEnabled}`);
|
||||
|
||||
@@ -69,11 +65,11 @@ describe("unittests:: tsserver:: events:: ProjectLanguageServiceStateEvent", ()
|
||||
content: "{}",
|
||||
};
|
||||
const host = createServerHost([f1, f2, f3, libFile, config]);
|
||||
const service = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
service.openClientFile(f1.path);
|
||||
const project = service.configuredProjects.get(config.path)!;
|
||||
service.logger.info(`languageServiceEnabled: ${project.languageServiceEnabled}`);
|
||||
service.logger.info(`lastFileExceededProgramSize: ${project.lastFileExceededProgramSize}`);
|
||||
baselineTsserverLogs("events/projectLanguageServiceState", "large file size is determined correctly", service);
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([f1], session);
|
||||
const project = session.getProjectService().configuredProjects.get(config.path)!;
|
||||
session.logger.info(`languageServiceEnabled: ${project.languageServiceEnabled}`);
|
||||
session.logger.info(`lastFileExceededProgramSize: ${project.lastFileExceededProgramSize}`);
|
||||
baselineTsserverLogs("events/projectLanguageServiceState", "large file size is determined correctly", session);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../../harness/tsserverLogger";
|
||||
import * as ts from "../../../_namespaces/ts";
|
||||
import {
|
||||
jsonToReadableText,
|
||||
} from "../../helpers";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createSession,
|
||||
createSessionWithCustomEventHandler,
|
||||
openExternalProjectForSession,
|
||||
openFilesForSession,
|
||||
@@ -180,10 +176,6 @@ describe("unittests:: tsserver:: events:: ProjectLoadingStart and ProjectLoading
|
||||
});
|
||||
}
|
||||
|
||||
verifyProjectLoadingStartAndFinish("when using event handler", host => createSessionWithCustomEventHandler(host));
|
||||
verifyProjectLoadingStartAndFinish("when using default event handler", host =>
|
||||
createSession(
|
||||
host,
|
||||
{ canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) },
|
||||
));
|
||||
verifyProjectLoadingStartAndFinish("when using event handler", createSessionWithCustomEventHandler);
|
||||
verifyProjectLoadingStartAndFinish("when using default event handler", host => new TestSession(host));
|
||||
});
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../../harness/tsserverLogger";
|
||||
import * as ts from "../../../_namespaces/ts";
|
||||
import {
|
||||
jsonToReadableText,
|
||||
} from "../../helpers";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createSession,
|
||||
createSessionWithCustomEventHandler,
|
||||
openFilesForSession,
|
||||
TestSession,
|
||||
@@ -411,19 +407,14 @@ describe("unittests:: tsserver:: events:: ProjectsUpdatedInBackground", () => {
|
||||
describe("when event handler is not set but session is created with canUseEvents = true", () => {
|
||||
describe("without noGetErrOnBackgroundUpdate, diagnostics for open files are queued", () => {
|
||||
verifyProjectsUpdatedInBackgroundEvent("without noGetErrOnBackgroundUpdate", host =>
|
||||
createSession(host, {
|
||||
canUseEvents: true,
|
||||
logger: createLoggerWithInMemoryLogs(host),
|
||||
new TestSession({
|
||||
host,
|
||||
noGetErrOnBackgroundUpdate: false,
|
||||
}));
|
||||
});
|
||||
|
||||
describe("with noGetErrOnBackgroundUpdate, diagnostics for open file are not queued", () => {
|
||||
verifyProjectsUpdatedInBackgroundEvent("with noGetErrOnBackgroundUpdate", host =>
|
||||
createSession(host, {
|
||||
canUseEvents: true,
|
||||
logger: createLoggerWithInMemoryLogs(host),
|
||||
noGetErrOnBackgroundUpdate: true,
|
||||
}));
|
||||
verifyProjectsUpdatedInBackgroundEvent("with noGetErrOnBackgroundUpdate", host => new TestSession(host));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
Logger,
|
||||
LoggerWithInMemoryLogs,
|
||||
} from "../../../../harness/tsserverLogger";
|
||||
import {
|
||||
createWatchUtils,
|
||||
@@ -10,7 +10,6 @@ import * as ts from "../../../_namespaces/ts";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
closeFilesForSession,
|
||||
createSession,
|
||||
createSessionWithCustomEventHandler,
|
||||
openFilesForSession,
|
||||
TestSession,
|
||||
@@ -32,7 +31,7 @@ describe("unittests:: tsserver:: events:: watchEvents", () => {
|
||||
}
|
||||
|
||||
function createTestServerHostWithCustomWatch(
|
||||
logger: Logger,
|
||||
logger: LoggerWithInMemoryLogs,
|
||||
) {
|
||||
const idToClose = new Map<number, () => void>();
|
||||
const host = logger.host as TestServerHostWithCustomWatch;
|
||||
@@ -89,8 +88,8 @@ describe("unittests:: tsserver:: events:: watchEvents", () => {
|
||||
function updateFileOnHost(session: TestSession, file: string, log: string) {
|
||||
// Change b.ts
|
||||
session.logger.log(log);
|
||||
session.testhost.writeFile(file, session.testhost.readFile("/user/username/projects/myproject/a.ts")!);
|
||||
session.testhost.runQueuedTimeoutCallbacks();
|
||||
session.host.writeFile(file, session.host.readFile("/user/username/projects/myproject/a.ts")!);
|
||||
session.host.runQueuedTimeoutCallbacks();
|
||||
}
|
||||
|
||||
function addFile(session: TestSession, path: string) {
|
||||
@@ -102,7 +101,7 @@ describe("unittests:: tsserver:: events:: watchEvents", () => {
|
||||
arguments: { id: data.id, path, eventType: "create" },
|
||||
})
|
||||
);
|
||||
session.testhost.runQueuedTimeoutCallbacks();
|
||||
session.host.runQueuedTimeoutCallbacks();
|
||||
}
|
||||
|
||||
function changeFile(session: TestSession, path: string) {
|
||||
@@ -114,7 +113,7 @@ describe("unittests:: tsserver:: events:: watchEvents", () => {
|
||||
arguments: { id: data.id, path, eventType: "update" },
|
||||
})
|
||||
);
|
||||
session.testhost.runQueuedTimeoutCallbacks();
|
||||
session.host.runQueuedTimeoutCallbacks();
|
||||
}
|
||||
|
||||
function setup() {
|
||||
@@ -131,7 +130,7 @@ describe("unittests:: tsserver:: events:: watchEvents", () => {
|
||||
|
||||
it("canUseWatchEvents", () => {
|
||||
const { host, logger } = setup();
|
||||
const session = createSessionWithCustomEventHandler(host, { canUseWatchEvents: true, logger }, handleWatchEvents);
|
||||
const session = createSessionWithCustomEventHandler({ host, canUseWatchEvents: true, logger }, handleWatchEvents);
|
||||
openFilesForSession(["/user/username/projects/myproject/a.ts"], session);
|
||||
|
||||
// Directory watcher
|
||||
@@ -166,7 +165,7 @@ describe("unittests:: tsserver:: events:: watchEvents", () => {
|
||||
|
||||
it("canUseWatchEvents without canUseEvents", () => {
|
||||
const { host, logger } = setup();
|
||||
const session = createSession(host, { canUseEvents: false, logger });
|
||||
const session = new TestSession({ host, canUseEvents: false, canUseWatchEvents: true, logger });
|
||||
openFilesForSession(["/user/username/projects/myproject/a.ts"], session);
|
||||
|
||||
// Directory watcher
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
jsonToReadableText,
|
||||
} from "../helpers";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createSession,
|
||||
closeFilesForSession,
|
||||
openFilesForSession,
|
||||
TestSession,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
createServerHost,
|
||||
@@ -69,8 +67,8 @@ describe("unittests:: tsserver:: exportMapCache", () => {
|
||||
});
|
||||
|
||||
it("invalidates the cache when files are deleted", () => {
|
||||
const { host, projectService, exportMapCache, session } = setup();
|
||||
projectService.closeClientFile(aTs.path);
|
||||
const { host, exportMapCache, session } = setup();
|
||||
closeFilesForSession([aTs], session);
|
||||
host.deleteFile(aTs.path);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
assert.ok(!exportMapCache.isUsableByFile(bTs.path as ts.Path));
|
||||
@@ -162,8 +160,7 @@ describe("unittests:: tsserver:: exportMapCache", () => {
|
||||
}`,
|
||||
};
|
||||
const host = createServerHost([utilsTs, classesTs, tsconfig]);
|
||||
const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const projectService = session.getProjectService();
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([classesTs], session);
|
||||
session.executeCommandSeq<ts.server.protocol.ConfigureRequest>({
|
||||
command: ts.server.protocol.CommandTypes.Configure,
|
||||
@@ -187,7 +184,7 @@ describe("unittests:: tsserver:: exportMapCache", () => {
|
||||
},
|
||||
});
|
||||
|
||||
const project = projectService.configuredProjects.get(tsconfig.path)!;
|
||||
const project = session.getProjectService().configuredProjects.get(tsconfig.path)!;
|
||||
const exportMapCache = project.getCachedExportInfoMap();
|
||||
assert.ok(exportMapCache.isUsableByFile(classesTs.path as ts.Path));
|
||||
assert.ok(!exportMapCache.isEmpty());
|
||||
@@ -233,13 +230,12 @@ describe("unittests:: tsserver:: exportMapCache", () => {
|
||||
|
||||
function setup() {
|
||||
const host = createServerHost([aTs, bTs, ambientDeclaration, tsconfig, packageJson, mobxPackageJson, mobxDts, exportEqualsMappedType]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([aTs, bTs], session);
|
||||
const projectService = session.getProjectService();
|
||||
const project = projectService.configuredProjects.get(tsconfig.path)!;
|
||||
const project = session.getProjectService().configuredProjects.get(tsconfig.path)!;
|
||||
triggerCompletions();
|
||||
const checker = project.getLanguageService().getProgram()!.getTypeChecker();
|
||||
return { host, project, projectService, session, exportMapCache: project.getCachedExportInfoMap(), checker, triggerCompletions };
|
||||
return { host, project, session, exportMapCache: project.getCachedExportInfoMap(), checker, triggerCompletions };
|
||||
|
||||
function triggerCompletions() {
|
||||
const requestLocation: ts.server.protocol.FileLocationRequestArgs = {
|
||||
|
||||
@@ -1,19 +1,16 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import {
|
||||
getSymlinkedExtendsSys,
|
||||
} from "../helpers/extends";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createSession,
|
||||
openFilesForSession,
|
||||
TestSession,
|
||||
} from "../helpers/tsserver";
|
||||
|
||||
describe("unittests:: tsserver:: extends::", () => {
|
||||
it("resolves the symlink path", () => {
|
||||
const host = getSymlinkedExtendsSys(/*forTsserver*/ true);
|
||||
const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession(["/users/user/projects/myproject/src/index.ts"], session);
|
||||
baselineTsserverLogs("tsserver", "resolves the symlink path", session);
|
||||
});
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as Harness from "../../_namespaces/Harness";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
@@ -8,13 +5,13 @@ import {
|
||||
} from "../helpers";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createProjectService,
|
||||
createSession,
|
||||
closeFilesForSession,
|
||||
logConfiguredProjectsHasOpenRefStatus,
|
||||
logInferredProjectsOrphanStatus,
|
||||
openExternalProjectForSession,
|
||||
openExternalProjectsForSession,
|
||||
openFilesForSession,
|
||||
TestSession,
|
||||
toExternalFile,
|
||||
toExternalFiles,
|
||||
verifyDynamic,
|
||||
@@ -40,7 +37,7 @@ describe("unittests:: tsserver:: externalProjects", () => {
|
||||
};
|
||||
|
||||
const host = createServerHost([f1, config], { useCaseSensitiveFileNames: false });
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
session.executeCommandSeq<ts.server.protocol.ConfigureRequest>({
|
||||
command: ts.server.protocol.CommandTypes.Configure,
|
||||
arguments: {
|
||||
@@ -100,7 +97,7 @@ describe("unittests:: tsserver:: externalProjects", () => {
|
||||
error: undefined,
|
||||
};
|
||||
};
|
||||
const session = createSession(host, { globalPlugins: ["myplugin"], logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession({ host, globalPlugins: ["myplugin"] });
|
||||
|
||||
openExternalProjectsForSession([p1], session);
|
||||
session.executeCommandSeq<ts.server.protocol.SemanticDiagnosticsSyncRequest>({
|
||||
@@ -132,7 +129,7 @@ describe("unittests:: tsserver:: externalProjects", () => {
|
||||
const p3 = makeProject(f3);
|
||||
|
||||
const host = createServerHost([f1, f2, f3]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openExternalProjectsForSession([p1, p2], session);
|
||||
openExternalProjectsForSession([p1, p3], session);
|
||||
openExternalProjectsForSession([], session);
|
||||
@@ -149,38 +146,46 @@ describe("unittests:: tsserver:: externalProjects", () => {
|
||||
path: "/a/b/f2.ts",
|
||||
content: "let y =1;",
|
||||
};
|
||||
const externalProjectName = "externalproject";
|
||||
const projectFileName = "externalproject";
|
||||
const host = createServerHost([file1, file2]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
projectService.openExternalProject({
|
||||
const session = new TestSession(host);
|
||||
openExternalProjectForSession({
|
||||
rootFiles: toExternalFiles([file1.path, file2.path]),
|
||||
options: {},
|
||||
projectFileName: externalProjectName,
|
||||
});
|
||||
projectFileName,
|
||||
}, session);
|
||||
// open client file - should not lead to creation of inferred project
|
||||
projectService.openClientFile(file1.path, file1.content);
|
||||
openFilesForSession([file1], session);
|
||||
// close client file - external project should still exists
|
||||
projectService.closeClientFile(file1.path);
|
||||
projectService.closeExternalProject(externalProjectName);
|
||||
baselineTsserverLogs("externalProjects", "should not close external project with no open files", projectService);
|
||||
closeFilesForSession([file1], session);
|
||||
session.executeCommandSeq<ts.server.protocol.CloseExternalProjectRequest>({
|
||||
command: ts.server.protocol.CommandTypes.CloseExternalProject,
|
||||
arguments: { projectFileName },
|
||||
});
|
||||
baselineTsserverLogs("externalProjects", "should not close external project with no open files", session);
|
||||
});
|
||||
|
||||
it("external project for dynamic file", () => {
|
||||
const externalProjectName = "^ScriptDocument1 file1.ts";
|
||||
const projectFileName = "^ScriptDocument1 file1.ts";
|
||||
const externalFiles = toExternalFiles(["^ScriptDocument1 file1.ts"]);
|
||||
const host = createServerHost([]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
projectService.openExternalProject({
|
||||
const session = new TestSession(host);
|
||||
openExternalProjectForSession({
|
||||
rootFiles: externalFiles,
|
||||
options: {},
|
||||
projectFileName: externalProjectName,
|
||||
});
|
||||
projectFileName,
|
||||
}, session);
|
||||
|
||||
verifyDynamic(projectService, "/^scriptdocument1 file1.ts");
|
||||
verifyDynamic(session, "/^scriptdocument1 file1.ts");
|
||||
|
||||
externalFiles[0].content = "let x =1;";
|
||||
projectService.applyChangesInOpenFiles(externalFiles);
|
||||
baselineTsserverLogs("externalProjects", "external project for dynamic file", projectService);
|
||||
session.executeCommandSeq<ts.server.protocol.ApplyChangedToOpenFilesRequest>({
|
||||
command: ts.server.protocol.CommandTypes.ApplyChangedToOpenFiles,
|
||||
arguments: {
|
||||
openFiles: externalFiles,
|
||||
},
|
||||
});
|
||||
baselineTsserverLogs("externalProjects", "external project for dynamic file", session);
|
||||
});
|
||||
|
||||
it("when file name starts with ^", () => {
|
||||
@@ -193,16 +198,16 @@ describe("unittests:: tsserver:: externalProjects", () => {
|
||||
content: "const y = 10;",
|
||||
};
|
||||
const host = createServerHost([file, app, libFile]);
|
||||
const service = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
service.openExternalProjects([{
|
||||
const session = new TestSession(host);
|
||||
openExternalProjectsForSession([{
|
||||
projectFileName: `/user/username/projects/myproject/myproject.njsproj`,
|
||||
rootFiles: [
|
||||
toExternalFile(file.path),
|
||||
toExternalFile(app.path),
|
||||
],
|
||||
options: {},
|
||||
}]);
|
||||
baselineTsserverLogs("externalProjects", "when file name starts with caret", service);
|
||||
}], session);
|
||||
baselineTsserverLogs("externalProjects", "when file name starts with caret", session);
|
||||
});
|
||||
|
||||
it("external project that included config files", () => {
|
||||
@@ -236,34 +241,37 @@ describe("unittests:: tsserver:: externalProjects", () => {
|
||||
path: "/a/d/f3.ts",
|
||||
content: "let z =1;",
|
||||
};
|
||||
const externalProjectName = "externalproject";
|
||||
const projectFileName = "externalproject";
|
||||
const host = createServerHost([file1, file2, file3, config1, config2]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
projectService.openExternalProject({
|
||||
const session = new TestSession(host);
|
||||
openExternalProjectForSession({
|
||||
rootFiles: toExternalFiles([config1.path, config2.path, file3.path]),
|
||||
options: {},
|
||||
projectFileName: externalProjectName,
|
||||
});
|
||||
projectFileName,
|
||||
}, session);
|
||||
|
||||
// open client file - should not lead to creation of inferred project
|
||||
projectService.openClientFile(file1.path, file1.content);
|
||||
logInferredProjectsOrphanStatus(projectService);
|
||||
openFilesForSession([file1], session);
|
||||
logInferredProjectsOrphanStatus(session);
|
||||
|
||||
projectService.openClientFile(file3.path, file3.content);
|
||||
logInferredProjectsOrphanStatus(projectService);
|
||||
openFilesForSession([file3], session);
|
||||
logInferredProjectsOrphanStatus(session);
|
||||
|
||||
projectService.closeExternalProject(externalProjectName);
|
||||
logInferredProjectsOrphanStatus(projectService);
|
||||
session.executeCommandSeq<ts.server.protocol.CloseExternalProjectRequest>({
|
||||
command: ts.server.protocol.CommandTypes.CloseExternalProject,
|
||||
arguments: { projectFileName },
|
||||
});
|
||||
logInferredProjectsOrphanStatus(session);
|
||||
// open file 'file1' from configured project keeps project alive
|
||||
|
||||
projectService.closeClientFile(file3.path);
|
||||
logInferredProjectsOrphanStatus(projectService);
|
||||
closeFilesForSession([file3], session);
|
||||
logInferredProjectsOrphanStatus(session);
|
||||
|
||||
projectService.closeClientFile(file1.path);
|
||||
logInferredProjectsOrphanStatus(projectService);
|
||||
closeFilesForSession([file1], session);
|
||||
logInferredProjectsOrphanStatus(session);
|
||||
|
||||
projectService.openClientFile(file2.path, file2.content);
|
||||
baselineTsserverLogs("externalProjects", "external project that included config files", projectService);
|
||||
openFilesForSession([file2], session);
|
||||
baselineTsserverLogs("externalProjects", "external project that included config files", session);
|
||||
});
|
||||
|
||||
it("external project with included config file opened after configured project", () => {
|
||||
@@ -275,23 +283,26 @@ describe("unittests:: tsserver:: externalProjects", () => {
|
||||
path: "/a/b/tsconfig.json",
|
||||
content: jsonToReadableText({ compilerOptions: {} }),
|
||||
};
|
||||
const externalProjectName = "externalproject";
|
||||
const projectFileName = "externalproject";
|
||||
const host = createServerHost([file1, configFile]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
|
||||
projectService.openClientFile(file1.path);
|
||||
openFilesForSession([file1], session);
|
||||
|
||||
projectService.openExternalProject({
|
||||
openExternalProjectForSession({
|
||||
rootFiles: toExternalFiles([configFile.path]),
|
||||
options: {},
|
||||
projectFileName: externalProjectName,
|
||||
});
|
||||
projectFileName,
|
||||
}, session);
|
||||
|
||||
projectService.closeClientFile(file1.path);
|
||||
closeFilesForSession([file1], session);
|
||||
// configured project is alive since it is opened as part of external project
|
||||
|
||||
projectService.closeExternalProject(externalProjectName);
|
||||
baselineTsserverLogs("externalProjects", "external project with included config file opened after configured project", projectService);
|
||||
session.executeCommandSeq<ts.server.protocol.CloseExternalProjectRequest>({
|
||||
command: ts.server.protocol.CommandTypes.CloseExternalProject,
|
||||
arguments: { projectFileName },
|
||||
});
|
||||
baselineTsserverLogs("externalProjects", "external project with included config file opened after configured project", session);
|
||||
});
|
||||
|
||||
it("external project with included config file opened after configured project and then closed", () => {
|
||||
@@ -307,25 +318,28 @@ describe("unittests:: tsserver:: externalProjects", () => {
|
||||
path: "/a/b/tsconfig.json",
|
||||
content: jsonToReadableText({ compilerOptions: {} }),
|
||||
};
|
||||
const externalProjectName = "externalproject";
|
||||
const projectFileName = "externalproject";
|
||||
const host = createServerHost([file1, file2, libFile, configFile]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
|
||||
projectService.openClientFile(file1.path);
|
||||
openFilesForSession([file1], session);
|
||||
|
||||
projectService.openExternalProject({
|
||||
openExternalProjectForSession({
|
||||
rootFiles: toExternalFiles([configFile.path]),
|
||||
options: {},
|
||||
projectFileName: externalProjectName,
|
||||
});
|
||||
projectFileName,
|
||||
}, session);
|
||||
|
||||
projectService.closeExternalProject(externalProjectName);
|
||||
session.executeCommandSeq<ts.server.protocol.CloseExternalProjectRequest>({
|
||||
command: ts.server.protocol.CommandTypes.CloseExternalProject,
|
||||
arguments: { projectFileName },
|
||||
});
|
||||
// configured project is alive since file is still open
|
||||
|
||||
projectService.closeClientFile(file1.path);
|
||||
closeFilesForSession([file1], session);
|
||||
|
||||
projectService.openClientFile(file2.path);
|
||||
baselineTsserverLogs("externalProjects", "external project with included config file opened after configured project and then closed", projectService);
|
||||
openFilesForSession([file2], session);
|
||||
baselineTsserverLogs("externalProjects", "external project with included config file opened after configured project and then closed", session);
|
||||
});
|
||||
|
||||
it("can correctly update external project when set of root files has changed", () => {
|
||||
@@ -338,12 +352,20 @@ describe("unittests:: tsserver:: externalProjects", () => {
|
||||
content: "let y = 1",
|
||||
};
|
||||
const host = createServerHost([file1, file2]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
|
||||
projectService.openExternalProject({ projectFileName: "project", options: {}, rootFiles: toExternalFiles([file1.path]) });
|
||||
openExternalProjectForSession({
|
||||
projectFileName: "project",
|
||||
options: {},
|
||||
rootFiles: toExternalFiles([file1.path]),
|
||||
}, session);
|
||||
|
||||
projectService.openExternalProject({ projectFileName: "project", options: {}, rootFiles: toExternalFiles([file1.path, file2.path]) });
|
||||
baselineTsserverLogs("externalProjects", "can correctly update external project when set of root files has changed", projectService);
|
||||
openExternalProjectForSession({
|
||||
projectFileName: "project",
|
||||
options: {},
|
||||
rootFiles: toExternalFiles([file1.path, file2.path]),
|
||||
}, session);
|
||||
baselineTsserverLogs("externalProjects", "can correctly update external project when set of root files has changed", session);
|
||||
});
|
||||
|
||||
it("can update external project when set of root files was not changed", () => {
|
||||
@@ -361,12 +383,20 @@ describe("unittests:: tsserver:: externalProjects", () => {
|
||||
};
|
||||
|
||||
const host = createServerHost([file1, file2, file3]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
|
||||
projectService.openExternalProject({ projectFileName: "project", options: { moduleResolution: ts.ModuleResolutionKind.Node10 }, rootFiles: toExternalFiles([file1.path, file2.path]) });
|
||||
openExternalProjectForSession({
|
||||
projectFileName: "project",
|
||||
options: { moduleResolution: ts.ModuleResolutionKind.Node10 },
|
||||
rootFiles: toExternalFiles([file1.path, file2.path]),
|
||||
}, session);
|
||||
|
||||
projectService.openExternalProject({ projectFileName: "project", options: { moduleResolution: ts.ModuleResolutionKind.Classic }, rootFiles: toExternalFiles([file1.path, file2.path]) });
|
||||
baselineTsserverLogs("externalProjects", "can update external project when set of root files was not changed", projectService);
|
||||
openExternalProjectForSession({
|
||||
projectFileName: "project",
|
||||
options: { moduleResolution: ts.ModuleResolutionKind.Classic },
|
||||
rootFiles: toExternalFiles([file1.path, file2.path]),
|
||||
}, session);
|
||||
baselineTsserverLogs("externalProjects", "can update external project when set of root files was not changed", session);
|
||||
});
|
||||
|
||||
it("language service disabled state is updated in external projects", () => {
|
||||
@@ -382,30 +412,30 @@ describe("unittests:: tsserver:: externalProjects", () => {
|
||||
const originalGetFileSize = host.getFileSize;
|
||||
host.getFileSize = (filePath: string) => filePath === f2.path ? ts.server.maxProgramSizeForNonTsFiles + 1 : originalGetFileSize.call(host, filePath);
|
||||
|
||||
const service = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
const projectFileName = "/a/proj.csproj";
|
||||
|
||||
service.openExternalProject({
|
||||
openExternalProjectForSession({
|
||||
projectFileName,
|
||||
rootFiles: toExternalFiles([f1.path, f2.path]),
|
||||
options: {},
|
||||
});
|
||||
assert.isFalse(service.externalProjects[0].languageServiceEnabled, "language service should be disabled - 1");
|
||||
}, session);
|
||||
assert.isFalse(session.getProjectService().externalProjects[0].languageServiceEnabled, "language service should be disabled - 1");
|
||||
|
||||
service.openExternalProject({
|
||||
openExternalProjectForSession({
|
||||
projectFileName,
|
||||
rootFiles: toExternalFiles([f1.path]),
|
||||
options: {},
|
||||
});
|
||||
assert.isTrue(service.externalProjects[0].languageServiceEnabled, "language service should be enabled");
|
||||
}, session);
|
||||
assert.isTrue(session.getProjectService().externalProjects[0].languageServiceEnabled, "language service should be enabled");
|
||||
|
||||
service.openExternalProject({
|
||||
openExternalProjectForSession({
|
||||
projectFileName,
|
||||
rootFiles: toExternalFiles([f1.path, f2.path]),
|
||||
options: {},
|
||||
});
|
||||
assert.isFalse(service.externalProjects[0].languageServiceEnabled, "language service should be disabled - 2");
|
||||
baselineTsserverLogs("externalProjects", "language service disabled state is updated in external projects", service);
|
||||
}, session);
|
||||
assert.isFalse(session.getProjectService().externalProjects[0].languageServiceEnabled, "language service should be disabled - 2");
|
||||
baselineTsserverLogs("externalProjects", "language service disabled state is updated in external projects", session);
|
||||
});
|
||||
|
||||
describe("deleting config file opened from the external project works", () => {
|
||||
@@ -420,8 +450,11 @@ describe("unittests:: tsserver:: externalProjects", () => {
|
||||
};
|
||||
const projectFileName = "/user/someuser/project/WebApplication6.csproj";
|
||||
const host = createServerHost([libFile, site, configFile]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
projectService.setHostConfiguration({ preferences: { lazyConfiguredProjectsFromExternalProject } });
|
||||
const session = new TestSession(host);
|
||||
session.executeCommandSeq<ts.server.protocol.ConfigureRequest>({
|
||||
command: ts.server.protocol.CommandTypes.Configure,
|
||||
arguments: { preferences: { lazyConfiguredProjectsFromExternalProject } },
|
||||
});
|
||||
|
||||
const externalProject: ts.server.protocol.ExternalProject = {
|
||||
projectFileName,
|
||||
@@ -430,18 +463,28 @@ describe("unittests:: tsserver:: externalProjects", () => {
|
||||
typeAcquisition: { include: [] },
|
||||
};
|
||||
|
||||
projectService.openExternalProjects([externalProject]);
|
||||
openExternalProjectsForSession([externalProject], session);
|
||||
|
||||
const knownProjects = projectService.synchronizeProjectList([]);
|
||||
const knownProjects = session.executeCommandSeq<ts.server.protocol.SynchronizeProjectListRequest>({
|
||||
command: ts.server.protocol.CommandTypes.SynchronizeProjectList,
|
||||
arguments: {
|
||||
knownProjects: [],
|
||||
},
|
||||
}).response as ts.server.protocol.ProjectFilesWithDiagnostics[];
|
||||
|
||||
host.deleteFile(configFile.path);
|
||||
|
||||
projectService.synchronizeProjectList(ts.map(knownProjects, proj => proj.info!)); // TODO: GH#18217 GH#20039
|
||||
session.executeCommandSeq<ts.server.protocol.SynchronizeProjectListRequest>({
|
||||
command: ts.server.protocol.CommandTypes.SynchronizeProjectList,
|
||||
arguments: {
|
||||
knownProjects: knownProjects.map(p => p.info!),
|
||||
},
|
||||
}).response as ts.server.protocol.ProjectFilesWithDiagnostics[];
|
||||
|
||||
externalProject.rootFiles.length = 1;
|
||||
projectService.openExternalProjects([externalProject]);
|
||||
openExternalProjectsForSession([externalProject], session);
|
||||
|
||||
baselineTsserverLogs("externalProjects", `deleting config file opened from the external project works${lazyConfiguredProjectsFromExternalProject ? " with lazyConfiguredProjectsFromExternalProject" : ""}`, projectService);
|
||||
baselineTsserverLogs("externalProjects", `deleting config file opened from the external project works${lazyConfiguredProjectsFromExternalProject ? " with lazyConfiguredProjectsFromExternalProject" : ""}`, session);
|
||||
}
|
||||
it("when lazyConfiguredProjectsFromExternalProject not set", () => {
|
||||
verifyDeletingConfigFile(/*lazyConfiguredProjectsFromExternalProject*/ false);
|
||||
@@ -466,37 +509,40 @@ describe("unittests:: tsserver:: externalProjects", () => {
|
||||
content: "",
|
||||
};
|
||||
const host = createServerHost([f1, f2]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
projectService.setHostConfiguration({ preferences: { lazyConfiguredProjectsFromExternalProject } });
|
||||
const session = new TestSession(host);
|
||||
session.executeCommandSeq<ts.server.protocol.ConfigureRequest>({
|
||||
command: ts.server.protocol.CommandTypes.Configure,
|
||||
arguments: { preferences: { lazyConfiguredProjectsFromExternalProject } },
|
||||
});
|
||||
|
||||
// open external project
|
||||
const projectName = "/a/b/proj1";
|
||||
projectService.openExternalProject({
|
||||
projectFileName: projectName,
|
||||
const projectFileName = "/a/b/proj1";
|
||||
openExternalProjectForSession({
|
||||
projectFileName,
|
||||
rootFiles: toExternalFiles([f1.path, f2.path]),
|
||||
options: {},
|
||||
});
|
||||
projectService.openClientFile(f1.path);
|
||||
}, session);
|
||||
openFilesForSession([f1], session);
|
||||
|
||||
// rename lib.ts to tsconfig.json
|
||||
host.renameFile(f2.path, tsconfig.path);
|
||||
projectService.openExternalProject({
|
||||
projectFileName: projectName,
|
||||
openExternalProjectForSession({
|
||||
projectFileName,
|
||||
rootFiles: toExternalFiles([f1.path, tsconfig.path]),
|
||||
options: {},
|
||||
});
|
||||
}, session);
|
||||
if (lazyConfiguredProjectsFromExternalProject) {
|
||||
projectService.ensureInferredProjectsUpToDate_TestOnly();
|
||||
session.getProjectService().ensureInferredProjectsUpToDate_TestOnly();
|
||||
}
|
||||
|
||||
// rename tsconfig.json back to lib.ts
|
||||
host.renameFile(tsconfig.path, f2.path);
|
||||
projectService.openExternalProject({
|
||||
projectFileName: projectName,
|
||||
openExternalProjectForSession({
|
||||
projectFileName,
|
||||
rootFiles: toExternalFiles([f1.path, f2.path]),
|
||||
options: {},
|
||||
});
|
||||
baselineTsserverLogs("externalProjects", `correctly handling add or remove tsconfig - 1${lazyConfiguredProjectsFromExternalProject ? " with lazyConfiguredProjectsFromExternalProject" : ""}`, projectService);
|
||||
}, session);
|
||||
baselineTsserverLogs("externalProjects", `correctly handling add or remove tsconfig - 1${lazyConfiguredProjectsFromExternalProject ? " with lazyConfiguredProjectsFromExternalProject" : ""}`, session);
|
||||
}
|
||||
it("when lazyConfiguredProjectsFromExternalProject not set", () => {
|
||||
verifyAddRemoveConfig(/*lazyConfiguredProjectsFromExternalProject*/ false);
|
||||
@@ -529,55 +575,61 @@ describe("unittests:: tsserver:: externalProjects", () => {
|
||||
content: "{}",
|
||||
};
|
||||
const host = createServerHost([f1, cLib, cTsconfig, dLib, dTsconfig]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
projectService.setHostConfiguration({ preferences: { lazyConfiguredProjectsFromExternalProject } });
|
||||
const session = new TestSession(host);
|
||||
session.executeCommandSeq<ts.server.protocol.ConfigureRequest>({
|
||||
command: ts.server.protocol.CommandTypes.Configure,
|
||||
arguments: { preferences: { lazyConfiguredProjectsFromExternalProject } },
|
||||
});
|
||||
|
||||
// open external project
|
||||
const projectName = "/a/b/proj1";
|
||||
projectService.openExternalProject({
|
||||
projectFileName: projectName,
|
||||
const projectFileName = "/a/b/proj1";
|
||||
openExternalProjectForSession({
|
||||
projectFileName,
|
||||
rootFiles: toExternalFiles([f1.path]),
|
||||
options: {},
|
||||
});
|
||||
}, session);
|
||||
|
||||
// add two config file as root files
|
||||
projectService.openExternalProject({
|
||||
projectFileName: projectName,
|
||||
openExternalProjectForSession({
|
||||
projectFileName,
|
||||
rootFiles: toExternalFiles([f1.path, cTsconfig.path, dTsconfig.path]),
|
||||
options: {},
|
||||
});
|
||||
}, session);
|
||||
if (lazyConfiguredProjectsFromExternalProject) {
|
||||
projectService.ensureInferredProjectsUpToDate_TestOnly();
|
||||
session.getProjectService().ensureInferredProjectsUpToDate_TestOnly();
|
||||
}
|
||||
|
||||
// remove one config file
|
||||
projectService.openExternalProject({
|
||||
projectFileName: projectName,
|
||||
openExternalProjectForSession({
|
||||
projectFileName,
|
||||
rootFiles: toExternalFiles([f1.path, dTsconfig.path]),
|
||||
options: {},
|
||||
});
|
||||
}, session);
|
||||
|
||||
// remove second config file
|
||||
projectService.openExternalProject({
|
||||
projectFileName: projectName,
|
||||
openExternalProjectForSession({
|
||||
projectFileName,
|
||||
rootFiles: toExternalFiles([f1.path]),
|
||||
options: {},
|
||||
});
|
||||
}, session);
|
||||
|
||||
// open two config files
|
||||
// add two config file as root files
|
||||
projectService.openExternalProject({
|
||||
projectFileName: projectName,
|
||||
openExternalProjectForSession({
|
||||
projectFileName,
|
||||
rootFiles: toExternalFiles([f1.path, cTsconfig.path, dTsconfig.path]),
|
||||
options: {},
|
||||
});
|
||||
}, session);
|
||||
if (lazyConfiguredProjectsFromExternalProject) {
|
||||
projectService.ensureInferredProjectsUpToDate_TestOnly();
|
||||
session.getProjectService().ensureInferredProjectsUpToDate_TestOnly();
|
||||
}
|
||||
|
||||
// close all projects - no projects should be opened
|
||||
projectService.closeExternalProject(projectName);
|
||||
baselineTsserverLogs("externalProjects", `correctly handling add or remove tsconfig - 2${lazyConfiguredProjectsFromExternalProject ? " with lazyConfiguredProjectsFromExternalProject" : ""}`, projectService);
|
||||
session.executeCommandSeq<ts.server.protocol.CloseExternalProjectRequest>({
|
||||
command: ts.server.protocol.CommandTypes.CloseExternalProject,
|
||||
arguments: { projectFileName },
|
||||
});
|
||||
baselineTsserverLogs("externalProjects", `correctly handling add or remove tsconfig - 2${lazyConfiguredProjectsFromExternalProject ? " with lazyConfiguredProjectsFromExternalProject" : ""}`, session);
|
||||
}
|
||||
|
||||
it("when lazyConfiguredProjectsFromExternalProject not set", () => {
|
||||
@@ -635,13 +687,13 @@ describe("unittests:: tsserver:: externalProjects", () => {
|
||||
),
|
||||
};
|
||||
const host = createServerHost([libES5, libES2015Promise, app, config1], { executingFilePath: "/compiler/tsc.js" });
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
projectService.openClientFile(app.path);
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([app], session);
|
||||
|
||||
host.writeFile(config2.path, config2.content);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
|
||||
baselineTsserverLogs("externalProjects", "correctly handles changes in lib section of config file", projectService);
|
||||
baselineTsserverLogs("externalProjects", "correctly handles changes in lib section of config file", session);
|
||||
});
|
||||
|
||||
it("should handle non-existing directories in config file", () => {
|
||||
@@ -660,15 +712,15 @@ describe("unittests:: tsserver:: externalProjects", () => {
|
||||
}),
|
||||
};
|
||||
const host = createServerHost([f, config]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
projectService.openClientFile(f.path);
|
||||
logConfiguredProjectsHasOpenRefStatus(projectService);
|
||||
projectService.closeClientFile(f.path);
|
||||
logConfiguredProjectsHasOpenRefStatus(projectService);
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([f], session);
|
||||
logConfiguredProjectsHasOpenRefStatus(session);
|
||||
closeFilesForSession([f], session);
|
||||
logConfiguredProjectsHasOpenRefStatus(session);
|
||||
|
||||
projectService.openClientFile(f.path);
|
||||
logConfiguredProjectsHasOpenRefStatus(projectService);
|
||||
baselineTsserverLogs("externalProjects", "should handle non-existing directories in config file", projectService);
|
||||
openFilesForSession([f], session);
|
||||
logConfiguredProjectsHasOpenRefStatus(session);
|
||||
baselineTsserverLogs("externalProjects", "should handle non-existing directories in config file", session);
|
||||
});
|
||||
|
||||
it("handles loads existing configured projects of external projects when lazyConfiguredProjectsFromExternalProject is disabled", () => {
|
||||
@@ -682,29 +734,38 @@ describe("unittests:: tsserver:: externalProjects", () => {
|
||||
};
|
||||
const projectFileName = "/a/b/project.csproj";
|
||||
const host = createServerHost([f1, config]);
|
||||
const service = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
service.setHostConfiguration({ preferences: { lazyConfiguredProjectsFromExternalProject: true } });
|
||||
service.openExternalProject({
|
||||
const session = new TestSession(host);
|
||||
session.executeCommandSeq<ts.server.protocol.ConfigureRequest>({
|
||||
command: ts.server.protocol.CommandTypes.Configure,
|
||||
arguments: { preferences: { lazyConfiguredProjectsFromExternalProject: true } },
|
||||
});
|
||||
openExternalProjectForSession({
|
||||
projectFileName,
|
||||
rootFiles: toExternalFiles([f1.path, config.path]),
|
||||
options: {},
|
||||
} as ts.server.protocol.ExternalProject);
|
||||
const project = service.configuredProjects.get(config.path)!;
|
||||
}, session);
|
||||
const project = session.getProjectService().configuredProjects.get(config.path)!;
|
||||
assert.equal(project.pendingUpdateLevel, ts.ProgramUpdateLevel.Full); // External project referenced configured project pending to be reloaded
|
||||
|
||||
service.setHostConfiguration({ preferences: { lazyConfiguredProjectsFromExternalProject: false } });
|
||||
session.executeCommandSeq<ts.server.protocol.ConfigureRequest>({
|
||||
command: ts.server.protocol.CommandTypes.Configure,
|
||||
arguments: { preferences: { lazyConfiguredProjectsFromExternalProject: false } },
|
||||
});
|
||||
assert.equal(project.pendingUpdateLevel, ts.ProgramUpdateLevel.Update); // External project referenced configured project loaded
|
||||
|
||||
service.closeExternalProject(projectFileName);
|
||||
session.executeCommandSeq<ts.server.protocol.CloseExternalProjectRequest>({
|
||||
command: ts.server.protocol.CommandTypes.CloseExternalProject,
|
||||
arguments: { projectFileName },
|
||||
});
|
||||
|
||||
service.openExternalProject({
|
||||
openExternalProjectForSession({
|
||||
projectFileName,
|
||||
rootFiles: toExternalFiles([f1.path, config.path]),
|
||||
options: {},
|
||||
} as ts.server.protocol.ExternalProject);
|
||||
const project2 = service.configuredProjects.get(config.path)!;
|
||||
}, session);
|
||||
const project2 = session.getProjectService().configuredProjects.get(config.path)!;
|
||||
assert.equal(project2.pendingUpdateLevel, ts.ProgramUpdateLevel.Update); // External project referenced configured project loaded
|
||||
baselineTsserverLogs("externalProjects", "handles loads existing configured projects of external projects when lazyConfiguredProjectsFromExternalProject is disabled", service);
|
||||
baselineTsserverLogs("externalProjects", "handles loads existing configured projects of external projects when lazyConfiguredProjectsFromExternalProject is disabled", session);
|
||||
});
|
||||
|
||||
it("handles creation of external project with jsconfig before jsconfig creation watcher is invoked", () => {
|
||||
@@ -715,24 +776,29 @@ describe("unittests:: tsserver:: externalProjects", () => {
|
||||
};
|
||||
const files = [libFile, tsconfig];
|
||||
const host = createServerHost(files);
|
||||
const service = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
|
||||
// Create external project
|
||||
service.openExternalProjects([{
|
||||
openExternalProjectsForSession([{
|
||||
projectFileName,
|
||||
rootFiles: [{ fileName: tsconfig.path }],
|
||||
options: { allowJs: false },
|
||||
}]);
|
||||
}], session);
|
||||
|
||||
// write js file, open external project and open it for edit
|
||||
const jsFilePath = `/user/username/projects/myproject/javascript.js`;
|
||||
host.writeFile(jsFilePath, "");
|
||||
service.openExternalProjects([{
|
||||
openExternalProjectsForSession([{
|
||||
projectFileName,
|
||||
rootFiles: [{ fileName: tsconfig.path }, { fileName: jsFilePath }],
|
||||
options: { allowJs: false },
|
||||
}]);
|
||||
service.applyChangesInOpenFiles(ts.singleIterator({ fileName: jsFilePath, scriptKind: ts.ScriptKind.JS, content: "" }));
|
||||
}], session);
|
||||
session.executeCommandSeq<ts.server.protocol.ApplyChangedToOpenFilesRequest>({
|
||||
command: ts.server.protocol.CommandTypes.ApplyChangedToOpenFiles,
|
||||
arguments: {
|
||||
openFiles: [{ fileName: jsFilePath, scriptKind: "JS", content: "" }],
|
||||
},
|
||||
});
|
||||
|
||||
// write jsconfig file
|
||||
const jsConfig: File = {
|
||||
@@ -743,13 +809,13 @@ describe("unittests:: tsserver:: externalProjects", () => {
|
||||
host.ensureFileOrFolder(jsConfig, /*ignoreWatchInvokedWithTriggerAsFileCreate*/ true);
|
||||
|
||||
// Open external project
|
||||
service.openExternalProjects([{
|
||||
openExternalProjectsForSession([{
|
||||
projectFileName,
|
||||
rootFiles: [{ fileName: jsConfig.path }, { fileName: tsconfig.path }, { fileName: jsFilePath }],
|
||||
options: { allowJs: false },
|
||||
}]);
|
||||
logInferredProjectsOrphanStatus(service);
|
||||
baselineTsserverLogs("externalProjects", "handles creation of external project with jsconfig before jsconfig creation watcher is invoked", service);
|
||||
}], session);
|
||||
logInferredProjectsOrphanStatus(session);
|
||||
baselineTsserverLogs("externalProjects", "handles creation of external project with jsconfig before jsconfig creation watcher is invoked", session);
|
||||
});
|
||||
|
||||
it("does not crash if external file does not exist", () => {
|
||||
@@ -778,10 +844,7 @@ describe("unittests:: tsserver:: externalProjects", () => {
|
||||
error: undefined,
|
||||
};
|
||||
};
|
||||
const session = createSession(host, {
|
||||
globalPlugins: ["myplugin"],
|
||||
logger: createLoggerWithInMemoryLogs(host),
|
||||
});
|
||||
const session = new TestSession({ host, globalPlugins: ["myplugin"] });
|
||||
// When the external project is opened, the graph will be updated,
|
||||
// and in the process getExternalFiles() above will be called.
|
||||
// Since the external file does not exist, there will not be a script
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import {
|
||||
protocol,
|
||||
} from "../../_namespaces/ts.server";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createSession,
|
||||
TestSession,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
createServerHost,
|
||||
@@ -80,7 +77,7 @@ const bar: Bar = {
|
||||
},
|
||||
];
|
||||
const host = createServerHost(files);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
// Open files in the two configured projects
|
||||
session.executeCommandSeq<protocol.UpdateOpenRequest>({
|
||||
command: protocol.CommandTypes.UpdateOpen,
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
jsonToReadableText,
|
||||
@@ -8,9 +5,9 @@ import {
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
closeFilesForSession,
|
||||
createSession,
|
||||
openFilesForSession,
|
||||
protocolTextSpanFromSubstring,
|
||||
TestSession,
|
||||
verifyGetErrRequest,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
@@ -51,7 +48,7 @@ describe("unittests:: tsserver:: forceConsistentCasingInFileNames", () => {
|
||||
};
|
||||
|
||||
const host = createServerHost([file1, file2, file2Dts, libFile, tsconfig, tsconfigAll], { useCaseSensitiveFileNames: false });
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
|
||||
openFilesForSession([file1], session);
|
||||
session.executeCommandSeq<ts.server.protocol.CompilerOptionsDiagnosticsRequest>({
|
||||
@@ -80,7 +77,7 @@ describe("unittests:: tsserver:: forceConsistentCasingInFileNames", () => {
|
||||
};
|
||||
|
||||
const host = createServerHost([loggerFile, anotherFile, tsconfig, libFile, tsconfig]);
|
||||
const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([{ file: loggerFile, projectRootPath: "/user/username/projects/myproject" }], session);
|
||||
verifyGetErrRequest({ session, files: [loggerFile] });
|
||||
|
||||
@@ -129,7 +126,7 @@ describe("unittests:: tsserver:: forceConsistentCasingInFileNames", () => {
|
||||
};
|
||||
|
||||
const host = createServerHost([loggerFile, anotherFile, tsconfig, libFile, tsconfig]);
|
||||
const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([{ file: anotherFile, projectRootPath: "/user/username/projects/myproject" }], session);
|
||||
verifyGetErrRequest({ session, files: [anotherFile] });
|
||||
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
jsonToReadableText,
|
||||
} from "../helpers";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createSession,
|
||||
openFilesForSession,
|
||||
TestSession,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
createServerHost,
|
||||
@@ -21,7 +18,7 @@ describe("unittests:: tsserver:: formatSettings", () => {
|
||||
content: "let x;",
|
||||
};
|
||||
const host = createServerHost([f1]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([f1], session);
|
||||
|
||||
const defaultSettings = session.getProjectService().getFormatCodeOptions(f1.path as ts.server.NormalizedPath);
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createSession,
|
||||
openFilesForSession,
|
||||
TestSession,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
createServerHost,
|
||||
@@ -16,7 +13,7 @@ describe("unittests:: tsserver:: getApplicableRefactors", () => {
|
||||
it("works when taking position", () => {
|
||||
const aTs: File = { path: "/a.ts", content: "" };
|
||||
const host = createServerHost([aTs]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([aTs], session);
|
||||
session.executeCommandSeq<ts.server.protocol.GetApplicableRefactorsRequest>({
|
||||
command: ts.server.protocol.CommandTypes.GetApplicableRefactors,
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
jsonToReadableText,
|
||||
} from "../helpers";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createSession,
|
||||
openFilesForSession,
|
||||
TestSession,
|
||||
textSpanFromSubstring,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
@@ -83,7 +80,7 @@ describe("unittests:: tsserver:: getEditsForFileRename", () => {
|
||||
};
|
||||
|
||||
const host = createServerHost([aUserTs, aOldTs, aTsconfig, bUserTs, bTsconfig]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([aUserTs, bUserTs], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.GetEditsForFileRenameRequest>({
|
||||
@@ -102,7 +99,7 @@ describe("unittests:: tsserver:: getEditsForFileRename", () => {
|
||||
const tsconfig: File = { path: "/tsconfig.json", content: jsonToReadableText({ files: ["./a.ts", "./b.ts"] }) };
|
||||
|
||||
const host = createServerHost([aTs, cTs, tsconfig]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([aTs, cTs], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.GetEditsForFileRenameRequest>({
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createSession,
|
||||
openFilesForSession,
|
||||
protocolFileLocationFromSubstring,
|
||||
TestSession,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
createServerHost,
|
||||
@@ -32,7 +29,7 @@ export const { nest: [valueE, { valueF }] } = { nest: [0, { valueF: 1 }] };
|
||||
content: "{}",
|
||||
};
|
||||
const host = createServerHost([mainTs, modTs, tsconfig]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([mainTs, modTs], session);
|
||||
return { session, modTs };
|
||||
}
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createSession,
|
||||
openFilesForSession,
|
||||
TestSession,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
createServerHost,
|
||||
@@ -41,7 +38,7 @@ describe("unittests:: tsserver:: getFileReferences", () => {
|
||||
|
||||
function makeSampleSession() {
|
||||
const host = createServerHost([aTs, bTs, cTs, dTs, tsconfig]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([aTs, bTs, cTs, dTs], session);
|
||||
return session;
|
||||
}
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
jsonToReadableText,
|
||||
} from "../helpers";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createSession,
|
||||
openFilesForSession,
|
||||
TestSession,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
createServerHost,
|
||||
@@ -44,7 +41,7 @@ import { value1 } from "../node_modules/.cache/someFile.d.ts";`,
|
||||
content: "{}",
|
||||
};
|
||||
const host = createServerHost([file1, file2, file3, file3, file4, nodeModulesFile1, nodeModulesFile2, tsconfig]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file1], session);
|
||||
session.executeCommandSeq<ts.server.protocol.GetMoveToRefactoringFileSuggestionsRequest>({
|
||||
command: ts.server.protocol.CommandTypes.GetMoveToRefactoringFileSuggestions,
|
||||
@@ -69,7 +66,7 @@ import { value1 } from "../node_modules/.cache/someFile.d.ts";`,
|
||||
const tsconfig: File = { path: "/tsconfig.json", content: jsonToReadableText({ files: ["./file1.ts", "./file2.tsx", "./file3.mts", "./file4.cts", "./file5.js", "./file6.d.ts", "./file7.ts"] }) };
|
||||
|
||||
const host = createServerHost([file1, file2, file3, file4, file5, file6, file7, tsconfig]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file1], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.GetMoveToRefactoringFileSuggestionsRequest>({
|
||||
@@ -90,7 +87,7 @@ import { value1 } from "../node_modules/.cache/someFile.d.ts";`,
|
||||
const tsconfig: File = { path: "/tsconfig.json", content: jsonToReadableText({ files: ["./file1.js", "./file2.js", "./file3.mts", "./file4.ts", "./file5.js"] }) };
|
||||
|
||||
const host = createServerHost([file1, file2, file3, file4, file5, tsconfig]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file1], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.GetMoveToRefactoringFileSuggestionsRequest>({
|
||||
@@ -110,7 +107,7 @@ import { value1 } from "../node_modules/.cache/someFile.d.ts";`,
|
||||
const tsconfig: File = { path: "/tsconfig.json", content: jsonToReadableText({ files: ["./file1.d.ts", "./a/lib.d.ts", "./a/file3.d.ts", "/a/lib.es6.d.ts"] }) };
|
||||
|
||||
const host = createServerHost([file1, file2, file3, file4, tsconfig]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file1], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.GetMoveToRefactoringFileSuggestionsRequest>({
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import {
|
||||
protocol,
|
||||
} from "../../_namespaces/ts.server";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createSession,
|
||||
TestSession,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
createServerHost,
|
||||
@@ -45,7 +42,7 @@ declare class Stuff {
|
||||
},
|
||||
];
|
||||
const host = createServerHost(files);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
// Open files in the two configured projects
|
||||
session.executeCommandSeq<protocol.UpdateOpenRequest>({
|
||||
command: protocol.CommandTypes.UpdateOpen,
|
||||
@@ -112,7 +109,7 @@ declare class Stuff {
|
||||
},
|
||||
];
|
||||
const host = createServerHost(files);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
// Open files in the two configured projects
|
||||
session.executeCommandSeq<protocol.UpdateOpenRequest>({
|
||||
command: protocol.CommandTypes.UpdateOpen,
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createSession,
|
||||
openExternalProjectForSession,
|
||||
TestSession,
|
||||
toExternalFile,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
@@ -22,8 +19,12 @@ describe("unittests:: tsserver:: importHelpers", () => {
|
||||
content: "",
|
||||
};
|
||||
const host = createServerHost([f1, tslib]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
openExternalProjectForSession({ projectFileName: "p", rootFiles: [toExternalFile(f1.path)], options: { importHelpers: true } }, session);
|
||||
const session = new TestSession(host);
|
||||
openExternalProjectForSession({
|
||||
projectFileName: "p",
|
||||
rootFiles: [toExternalFile(f1.path)],
|
||||
options: { importHelpers: true },
|
||||
}, session);
|
||||
baselineTsserverLogs("importHelpers", "should not crash in tsserver", session);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createSession,
|
||||
TestSession,
|
||||
verifyGetErrRequest,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
@@ -13,7 +10,7 @@ import {
|
||||
describe("unittests:: tsserver:: inconsistentErrorInEditor", () => {
|
||||
it("should not error", () => {
|
||||
const host = createServerHost([]);
|
||||
const session = createSession(host, { canUseEvents: true, noGetErrOnBackgroundUpdate: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
session.executeCommandSeq<ts.server.protocol.UpdateOpenRequest>({
|
||||
command: ts.server.protocol.CommandTypes.UpdateOpen,
|
||||
arguments: {
|
||||
@@ -45,7 +42,7 @@ describe("unittests:: tsserver:: inconsistentErrorInEditor", () => {
|
||||
describe("unittests:: tsserver:: inconsistentErrorInEditor2", () => {
|
||||
it("should not error", () => {
|
||||
const host = createServerHost([]);
|
||||
const session = createSession(host, { canUseEvents: true, noGetErrOnBackgroundUpdate: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
session.executeCommandSeq<ts.server.protocol.UpdateOpenRequest>({
|
||||
command: ts.server.protocol.CommandTypes.UpdateOpen,
|
||||
arguments: {
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
dedent,
|
||||
@@ -14,11 +11,10 @@ import {
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
closeFilesForSession,
|
||||
createProjectService,
|
||||
createSession,
|
||||
logInferredProjectsOrphanStatus,
|
||||
openFilesForSession,
|
||||
setCompilerOptionsForInferredProjectsRequestForSession,
|
||||
TestSession,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
createServerHost,
|
||||
@@ -41,9 +37,9 @@ describe("unittests:: tsserver:: inferredProjects", () => {
|
||||
content: `export let x: number`,
|
||||
};
|
||||
const host = createServerHost([appFile, moduleFile, libFile]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
projectService.openClientFile(appFile.path);
|
||||
baselineTsserverLogs("inferredProjects", "create inferred project", projectService);
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([appFile], session);
|
||||
baselineTsserverLogs("inferredProjects", "create inferred project", session);
|
||||
});
|
||||
|
||||
it("should use only one inferred project if 'useOneInferredProject' is set", () => {
|
||||
@@ -71,14 +67,12 @@ describe("unittests:: tsserver:: inferredProjects", () => {
|
||||
};
|
||||
|
||||
const host = createServerHost([file1, file2, file3, libFile]);
|
||||
const projectService = createProjectService(host, { useSingleInferredProject: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
projectService.openClientFile(file1.path);
|
||||
projectService.openClientFile(file2.path);
|
||||
projectService.openClientFile(file3.path);
|
||||
const session = new TestSession({ host, useSingleInferredProject: true });
|
||||
openFilesForSession([file1, file2, file3], session);
|
||||
|
||||
host.writeFile(configFile.path, configFile.content);
|
||||
host.runQueuedTimeoutCallbacks(); // load configured project from disk + ensureProjectsForOpenFiles
|
||||
baselineTsserverLogs("inferredProjects", "should use only one inferred project if useOneInferredProject is set", projectService);
|
||||
baselineTsserverLogs("inferredProjects", "should use only one inferred project if useOneInferredProject is set", session);
|
||||
});
|
||||
|
||||
it("disable inferred project", () => {
|
||||
@@ -88,12 +82,12 @@ describe("unittests:: tsserver:: inferredProjects", () => {
|
||||
};
|
||||
|
||||
const host = createServerHost([file1]);
|
||||
const projectService = createProjectService(host, { useSingleInferredProject: true, serverMode: ts.LanguageServiceMode.Syntactic, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession({ host, useSingleInferredProject: true, serverMode: ts.LanguageServiceMode.Syntactic });
|
||||
|
||||
projectService.openClientFile(file1.path, file1.content);
|
||||
openFilesForSession([file1], session);
|
||||
|
||||
projectService.logger.log(`LanguageServiceEnabled:: ${projectService.inferredProjects[0].languageServiceEnabled}`);
|
||||
baselineTsserverLogs("inferredProjects", "disable inferred project", projectService);
|
||||
session.logger.log(`LanguageServiceEnabled:: ${session.getProjectService().inferredProjects[0].languageServiceEnabled}`);
|
||||
baselineTsserverLogs("inferredProjects", "disable inferred project", session);
|
||||
});
|
||||
|
||||
it("project settings for inferred projects", () => {
|
||||
@@ -106,14 +100,15 @@ describe("unittests:: tsserver:: inferredProjects", () => {
|
||||
content: "export let x: number",
|
||||
};
|
||||
const host = createServerHost([file1, modFile]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
|
||||
projectService.openClientFile(file1.path);
|
||||
projectService.openClientFile(modFile.path);
|
||||
projectService.setCompilerOptionsForInferredProjects({ moduleResolution: ts.ModuleResolutionKind.Classic });
|
||||
openFilesForSession([file1, modFile], session);
|
||||
setCompilerOptionsForInferredProjectsRequestForSession({
|
||||
moduleResolution: ts.server.protocol.ModuleResolutionKind.Classic,
|
||||
}, session);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
logInferredProjectsOrphanStatus(projectService);
|
||||
baselineTsserverLogs("inferredProjects", "project settings for inferred projects", projectService);
|
||||
logInferredProjectsOrphanStatus(session);
|
||||
baselineTsserverLogs("inferredProjects", "project settings for inferred projects", session);
|
||||
});
|
||||
|
||||
it("should support files without extensions", () => {
|
||||
@@ -122,7 +117,7 @@ describe("unittests:: tsserver:: inferredProjects", () => {
|
||||
content: "let x = 1",
|
||||
};
|
||||
const host = createServerHost([f]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
setCompilerOptionsForInferredProjectsRequestForSession({ allowJs: true }, session);
|
||||
openFilesForSession([{ file: f.path, content: f.content, scriptKindName: "JS" }], session);
|
||||
baselineTsserverLogs("inferredProjects", "should support files without extensions", session);
|
||||
@@ -134,19 +129,19 @@ describe("unittests:: tsserver:: inferredProjects", () => {
|
||||
const file3 = { path: "/b/file2.ts", content: "let x = 3;", projectRootPath: "/b" };
|
||||
const file4 = { path: "/c/file3.ts", content: "let z = 4;" };
|
||||
const host = createServerHost([file1, file2, file3, file4]);
|
||||
const session = createSession(host, {
|
||||
const session = new TestSession({
|
||||
host,
|
||||
useSingleInferredProject: true,
|
||||
useInferredProjectPerProjectRoot: true,
|
||||
logger: createLoggerWithInMemoryLogs(host),
|
||||
});
|
||||
setCompilerOptionsForInferredProjectsRequestForSession({
|
||||
allowJs: true,
|
||||
target: ts.ScriptTarget.ESNext,
|
||||
target: ts.server.protocol.ScriptTarget.ESNext,
|
||||
}, session);
|
||||
setCompilerOptionsForInferredProjectsRequestForSession({
|
||||
options: {
|
||||
allowJs: true,
|
||||
target: ts.ScriptTarget.ES2015,
|
||||
target: ts.server.protocol.ScriptTarget.ES2015,
|
||||
},
|
||||
projectRootPath: "/b",
|
||||
}, session);
|
||||
@@ -190,15 +185,15 @@ describe("unittests:: tsserver:: inferredProjects", () => {
|
||||
{ path: "/c/file3.ts", content: "let z = 4;" },
|
||||
];
|
||||
const host = createServerHost(files, { useCaseSensitiveFileNames });
|
||||
const session = createSession(host, { useSingleInferredProject: true, useInferredProjectPerProjectRoot: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession({ host, useSingleInferredProject: true, useInferredProjectPerProjectRoot: true });
|
||||
setCompilerOptionsForInferredProjectsRequestForSession({
|
||||
allowJs: true,
|
||||
target: ts.ScriptTarget.ESNext,
|
||||
target: ts.server.protocol.ScriptTarget.ESNext,
|
||||
}, session);
|
||||
setCompilerOptionsForInferredProjectsRequestForSession({
|
||||
options: {
|
||||
allowJs: true,
|
||||
target: ts.ScriptTarget.ES2015,
|
||||
target: ts.server.protocol.ScriptTarget.ES2015,
|
||||
},
|
||||
projectRootPath: "/a",
|
||||
}, session);
|
||||
@@ -212,7 +207,7 @@ describe("unittests:: tsserver:: inferredProjects", () => {
|
||||
setCompilerOptionsForInferredProjectsRequestForSession({
|
||||
options: {
|
||||
allowJs: true,
|
||||
target: ts.ScriptTarget.ES2017,
|
||||
target: ts.server.protocol.ScriptTarget.ES2017,
|
||||
},
|
||||
projectRootPath: "/A",
|
||||
}, session);
|
||||
@@ -255,7 +250,7 @@ describe("unittests:: tsserver:: inferredProjects", () => {
|
||||
content: `const jsFile2 = 10;`,
|
||||
};
|
||||
const host = createServerHost([appFile, libFile, config, jsFile1, jsFile2]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
|
||||
// Do not remove config project when opening jsFile that is not present as part of config project
|
||||
openFilesForSession([jsFile1], session);
|
||||
@@ -276,25 +271,24 @@ describe("unittests:: tsserver:: inferredProjects", () => {
|
||||
const file1 = { path: "/a/file1.js", content: "" };
|
||||
const host = createServerHost([file1]);
|
||||
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
|
||||
projectService.openClientFile(file1.path);
|
||||
openFilesForSession([file1], session);
|
||||
|
||||
const inferredProject = projectService.inferredProjects[0];
|
||||
projectService.logger.log(`typeAcquisition : setting to undefined`);
|
||||
const inferredProject = session.getProjectService().inferredProjects[0];
|
||||
session.logger.log(`typeAcquisition : setting to undefined`);
|
||||
inferredProject.setTypeAcquisition(undefined);
|
||||
projectService.logger.log(`typeAcquisition should be inferred for inferred projects: ${jsonToReadableText(inferredProject.getTypeAcquisition())}`);
|
||||
baselineTsserverLogs("inferredProjects", "regression test - should infer typeAcquisition for inferred projects when set undefined", projectService);
|
||||
session.logger.log(`typeAcquisition should be inferred for inferred projects: ${jsonToReadableText(inferredProject.getTypeAcquisition())}`);
|
||||
baselineTsserverLogs("inferredProjects", "regression test - should infer typeAcquisition for inferred projects when set undefined", session);
|
||||
});
|
||||
|
||||
it("Setting compiler options for inferred projects when there are no open files should not schedule any refresh", () => {
|
||||
const host = createServerHost([commonFile1, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
setCompilerOptionsForInferredProjectsRequestForSession({
|
||||
allowJs: true,
|
||||
target: ts.ScriptTarget.ES2015,
|
||||
target: ts.server.protocol.ScriptTarget.ES2015,
|
||||
}, session);
|
||||
session.testhost.logTimeoutQueueLength();
|
||||
baselineTsserverLogs("inferredProjects", "Setting compiler options for inferred projects when there are no open files should not schedule any refresh", session);
|
||||
});
|
||||
|
||||
@@ -322,7 +316,7 @@ describe("unittests:: tsserver:: inferredProjects", () => {
|
||||
`,
|
||||
[libFile.path]: libFile.content,
|
||||
});
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([{
|
||||
file: "/user/username/projects/myproject/app.ts",
|
||||
projectRootPath: "/user/username/projects/myproject",
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
commonFile1,
|
||||
@@ -8,7 +5,6 @@ import {
|
||||
} from "../helpers/tscWatch";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createSession,
|
||||
TestSession,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
@@ -29,7 +25,7 @@ describe("unittests:: tsserver:: inlayHints", () => {
|
||||
|
||||
it("with updateOpen request does not corrupt documents", () => {
|
||||
const host = createServerHost([app, commonFile1, commonFile2, libFile, configFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
session.executeCommandSeq<ts.server.protocol.OpenRequest>({
|
||||
command: ts.server.protocol.CommandTypes.Open,
|
||||
arguments: { file: app.path },
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createSession,
|
||||
openFilesForSession,
|
||||
TestSession,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
createServerHost,
|
||||
@@ -31,7 +28,7 @@ describe("unittests:: tsserver:: jsdocTag:: jsdoc @link ", () => {
|
||||
it(subScenario, () => {
|
||||
const { command, displayPartsForJSDoc } = options;
|
||||
const host = createServerHost([file, config]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
session.executeCommandSeq<ts.server.protocol.ConfigureRequest>({
|
||||
command: ts.server.protocol.CommandTypes.Configure,
|
||||
arguments: { preferences: { displayPartsForJSDoc } },
|
||||
@@ -118,7 +115,7 @@ x(1)`,
|
||||
|
||||
const { command, displayPartsForJSDoc } = options;
|
||||
const host = createServerHost([linkInParamTag, config]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
session.executeCommandSeq<ts.server.protocol.ConfigureRequest>({
|
||||
command: ts.server.protocol.CommandTypes.Configure,
|
||||
arguments: { preferences: { displayPartsForJSDoc } },
|
||||
@@ -171,7 +168,7 @@ foo`,
|
||||
};
|
||||
const { command, displayPartsForJSDoc } = options;
|
||||
const host = createServerHost([linkInParamJSDoc, config]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
session.executeCommandSeq<ts.server.protocol.ConfigureRequest>({
|
||||
command: ts.server.protocol.CommandTypes.Configure,
|
||||
arguments: { preferences: { displayPartsForJSDoc } },
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as Utils from "../../_namespaces/Utils";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createProjectService,
|
||||
logDiagnostics,
|
||||
openFilesForSession,
|
||||
TestSession,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
createServerHost,
|
||||
@@ -22,10 +20,9 @@ describe("unittests:: tsserver:: languageService", () => {
|
||||
content: "let x = 1;",
|
||||
};
|
||||
const host = createServerHost([lib, f], { executingFilePath: "/a/Lib/tsc.js", useCaseSensitiveFileNames: true });
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
projectService.openClientFile(f.path);
|
||||
projectService.inferredProjects[0].getLanguageService().getProgram();
|
||||
baselineTsserverLogs("languageService", "should work correctly on case-sensitive file systems", projectService);
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([f], session);
|
||||
baselineTsserverLogs("languageService", "should work correctly on case-sensitive file systems", session);
|
||||
});
|
||||
|
||||
it("should support multiple projects with the same file under differing `paths` settings", () => {
|
||||
@@ -67,21 +64,20 @@ describe("unittests:: tsserver:: languageService", () => {
|
||||
];
|
||||
|
||||
const host = createServerHost(files, { executingFilePath: "/project/tsc.js", useCaseSensitiveFileNames: true });
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
projectService.openClientFile(files[3].path);
|
||||
projectService.openClientFile(files[6].path);
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([files[3], files[6].path], session);
|
||||
logDiagnostics(
|
||||
projectService,
|
||||
session,
|
||||
`getSemanticDiagnostics:: ${files[1].path}`,
|
||||
projectService.configuredProjects.get(files[1].path)!,
|
||||
projectService.configuredProjects.get(files[1].path)!.getLanguageService().getProgram()!.getSemanticDiagnostics(),
|
||||
session.getProjectService().configuredProjects.get(files[1].path)!,
|
||||
session.getProjectService().configuredProjects.get(files[1].path)!.getLanguageService().getProgram()!.getSemanticDiagnostics(),
|
||||
);
|
||||
logDiagnostics(
|
||||
projectService,
|
||||
session,
|
||||
`getSemanticDiagnostics:: ${files[4].path}`,
|
||||
projectService.configuredProjects.get(files[4].path)!,
|
||||
projectService.configuredProjects.get(files[4].path)!.getLanguageService().getProgram()!.getSemanticDiagnostics(),
|
||||
session.getProjectService().configuredProjects.get(files[4].path)!,
|
||||
session.getProjectService().configuredProjects.get(files[4].path)!.getLanguageService().getProgram()!.getSemanticDiagnostics(),
|
||||
);
|
||||
baselineTsserverLogs("languageService", "should support multiple projects with the same file under differing paths settings", projectService);
|
||||
baselineTsserverLogs("languageService", "should support multiple projects with the same file under differing paths settings", session);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import {
|
||||
jsonToReadableText,
|
||||
} from "../helpers";
|
||||
@@ -9,14 +6,14 @@ import {
|
||||
} from "../helpers/libraryResolution";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createSession,
|
||||
openFilesForSession,
|
||||
TestSession,
|
||||
} from "../helpers/tsserver";
|
||||
|
||||
describe("unittests:: tsserver:: libraryResolution", () => {
|
||||
it("with config", () => {
|
||||
const host = getServerHostForLibResolution();
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession(["/home/src/projects/project1/index.ts"], session);
|
||||
host.ensureFileOrFolder({ path: "/home/src/projects/node_modules/@typescript/lib-dom/index.d.ts", content: "interface DOMInterface { }" });
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
@@ -61,7 +58,7 @@ describe("unittests:: tsserver:: libraryResolution", () => {
|
||||
});
|
||||
it("with config with redirection", () => {
|
||||
const host = getServerHostForLibResolution(/*libRedirection*/ true);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession(["/home/src/projects/project1/index.ts"], session);
|
||||
host.deleteFile("/home/src/projects/node_modules/@typescript/lib-dom/index.d.ts");
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
dedent,
|
||||
@@ -8,9 +5,9 @@ import {
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
closeFilesForSession,
|
||||
createSession,
|
||||
openFilesForSession,
|
||||
setCompilerOptionsForInferredProjectsRequestForSession,
|
||||
TestSession,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
createServerHost,
|
||||
@@ -30,13 +27,13 @@ describe("unittests:: tsserver:: maxNodeModuleJsDepth for inferred projects", ()
|
||||
};
|
||||
|
||||
const host = createServerHost([file1, moduleFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file1], session);
|
||||
|
||||
session.logger.log(`maxNodeModuleJsDepth: ${session.getProjectService().inferredProjects[0].getCompilationSettings().maxNodeModuleJsDepth}`);
|
||||
|
||||
// Assert the option sticks
|
||||
setCompilerOptionsForInferredProjectsRequestForSession({ target: ts.ScriptTarget.ES2016 }, session);
|
||||
setCompilerOptionsForInferredProjectsRequestForSession({ target: ts.server.protocol.ScriptTarget.ES2016 }, session);
|
||||
session.logger.log(`maxNodeModuleJsDepth: ${session.getProjectService().inferredProjects[0].getCompilationSettings().maxNodeModuleJsDepth}`);
|
||||
baselineTsserverLogs("maxNodeModuleJsDepth", "should be set to 2 if the project has js root files", session);
|
||||
});
|
||||
@@ -52,7 +49,7 @@ describe("unittests:: tsserver:: maxNodeModuleJsDepth for inferred projects", ()
|
||||
};
|
||||
|
||||
const host = createServerHost([file1, file2, libFile]);
|
||||
const session = createSession(host, { useSingleInferredProject: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession({ host, useSingleInferredProject: true });
|
||||
|
||||
openFilesForSession([file1], session);
|
||||
session.logger.log(`maxNodeModuleJsDepth: ${session.getProjectService().inferredProjects[0].getCompilationSettings().maxNodeModuleJsDepth}`);
|
||||
@@ -84,7 +81,7 @@ describe("unittests:: tsserver:: maxNodeModuleJsDepth for inferred projects", ()
|
||||
`,
|
||||
[libFile.path]: libFile.content,
|
||||
});
|
||||
const session = createSession(host, { useSingleInferredProject: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession({ host, useSingleInferredProject: true });
|
||||
|
||||
openFilesForSession(["/user/username/projects/project1/src/file1.js"], session);
|
||||
baselineTsserverLogs("maxNodeModuleJsDepth", "handles resolutions when currentNodeModulesDepth changes when referencing file from another file", session);
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as Harness from "../../_namespaces/Harness";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
@@ -8,8 +5,8 @@ import {
|
||||
} from "../helpers";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createSession,
|
||||
openFilesForSession,
|
||||
TestSession,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
createServerHost,
|
||||
@@ -58,7 +55,7 @@ describe("unittests:: tsserver:: with metadataInResponse::", () => {
|
||||
|
||||
it("can pass through metadata when the command returns array", () => {
|
||||
const host = createHostWithPlugin([aTs, tsconfig]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([aTs], session);
|
||||
session.executeCommandSeq<ts.server.protocol.CompletionsRequest>({
|
||||
command: ts.server.protocol.CommandTypes.Completions,
|
||||
@@ -69,7 +66,7 @@ describe("unittests:: tsserver:: with metadataInResponse::", () => {
|
||||
|
||||
it("can pass through metadata when the command returns object", () => {
|
||||
const host = createHostWithPlugin([aTs, tsconfig]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([aTs], session);
|
||||
session.executeCommandSeq<ts.server.protocol.CompletionsRequest>({
|
||||
command: ts.server.protocol.CommandTypes.CompletionInfo,
|
||||
@@ -81,7 +78,7 @@ describe("unittests:: tsserver:: with metadataInResponse::", () => {
|
||||
it("returns undefined correctly", () => {
|
||||
const aTs: File = { path: "/a.ts", content: `class c { prop = "hello"; foo() { const x = 0; } }` };
|
||||
const host = createHostWithPlugin([aTs, tsconfig]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([aTs], session);
|
||||
session.executeCommandSeq<ts.server.protocol.CompletionsRequest>({
|
||||
command: ts.server.protocol.CommandTypes.Completions,
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
dedent,
|
||||
@@ -22,9 +19,9 @@ import {
|
||||
} from "../helpers/solutionBuilder";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createSession,
|
||||
openFilesForSession,
|
||||
protocolTextSpanFromSubstring,
|
||||
TestSession,
|
||||
verifyGetErrRequest,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
@@ -66,7 +63,7 @@ describe("unittests:: tsserver:: moduleResolution", () => {
|
||||
`,
|
||||
};
|
||||
const host = createServerHost([configFile, fileA, fileB, packageFile, { ...libFile, path: "/a/lib/lib.es2016.full.d.ts" }]);
|
||||
const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([fileA], session);
|
||||
return {
|
||||
host,
|
||||
@@ -168,7 +165,7 @@ describe("unittests:: tsserver:: moduleResolution", () => {
|
||||
|
||||
it("node10Result", () => {
|
||||
const host = createServerHost(getFsContentsForNode10Result());
|
||||
const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession(["/home/src/projects/project/index.mts"], session);
|
||||
verifyGetErrRequest({
|
||||
files: ["/home/src/projects/project/index.mts"],
|
||||
@@ -239,7 +236,7 @@ describe("unittests:: tsserver:: moduleResolution", () => {
|
||||
solutionBuildWithBaseline(host, ["packages/package-b"]);
|
||||
host.clearOutput();
|
||||
}
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host), canUseEvents: true });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession(["/home/src/projects/project/packages/package-b/src/index.ts"], session);
|
||||
verifyGetErrRequest({
|
||||
session,
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
jsonToReadableText,
|
||||
} from "../helpers";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createSession,
|
||||
openFilesForSession,
|
||||
TestSession,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
createServerHost,
|
||||
@@ -144,10 +141,9 @@ describe("unittests:: tsserver:: moduleSpecifierCache", () => {
|
||||
|
||||
function setup() {
|
||||
const host = createServerHost([aTs, bTs, cTs, bSymlink, ambientDeclaration, tsconfig, packageJson, mobxPackageJson, mobxDts]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([aTs, bTs, cTs], session);
|
||||
const projectService = session.getProjectService();
|
||||
const project = projectService.configuredProjects.get(tsconfig.path)!;
|
||||
const project = session.getProjectService().configuredProjects.get(tsconfig.path)!;
|
||||
session.executeCommandSeq<ts.server.protocol.ConfigureRequest>({
|
||||
command: ts.server.protocol.CommandTypes.Configure,
|
||||
arguments: {
|
||||
@@ -161,7 +157,7 @@ function setup() {
|
||||
});
|
||||
triggerCompletions({ file: bTs.path, line: 1, offset: 3 });
|
||||
|
||||
return { host, project, projectService, session, moduleSpecifierCache: project.getModuleSpecifierCache(), triggerCompletions };
|
||||
return { host, project, session, moduleSpecifierCache: project.getModuleSpecifierCache(), triggerCompletions };
|
||||
|
||||
function triggerCompletions(requestLocation: ts.server.protocol.FileLocationRequestArgs) {
|
||||
session.executeCommandSeq<ts.server.protocol.CompletionsRequest>({
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
jsonToReadableText,
|
||||
} from "../helpers";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createSession,
|
||||
openFilesForSession,
|
||||
TestSession,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
createServerHost,
|
||||
@@ -27,7 +24,7 @@ describe("unittests:: tsserver:: navigate-to for javascript project", () => {
|
||||
content: "{}",
|
||||
};
|
||||
const host = createServerHost([file1, configFile, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file1], session);
|
||||
|
||||
// Try to find some interface type defined in lib.d.ts
|
||||
@@ -73,7 +70,7 @@ describe("unittests:: tsserver:: navigate-to for javascript project", () => {
|
||||
export const ghijkl = a.abcdef;`,
|
||||
};
|
||||
const host = createServerHost([configFile1, file1, configFile2, file2]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file1, file2], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.NavtoRequest>({
|
||||
@@ -121,7 +118,7 @@ export const ghijkl = a.abcdef;`,
|
||||
export const ghijkl = a.abcdef;`,
|
||||
};
|
||||
const host = createServerHost([configFile1, file1, configFile2, file2, solutionConfig]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file1], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.NavtoRequest>({
|
||||
@@ -141,7 +138,7 @@ export const ghijkl = a.abcdef;`,
|
||||
content: "{}",
|
||||
};
|
||||
const host = createServerHost([file1, configFile, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file1], session);
|
||||
|
||||
// Try to find some interface type defined in lib.d.ts
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createSession,
|
||||
openFilesForSession,
|
||||
TestSession,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
createServerHost,
|
||||
@@ -20,7 +17,7 @@ describe("unittests:: tsserver:: occurrence highlight on string", () => {
|
||||
};
|
||||
|
||||
const host = createServerHost([file1]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file1], session);
|
||||
session.executeCommandSeq<ts.server.protocol.DocumentHighlightsRequest>({
|
||||
command: ts.server.protocol.CommandTypes.DocumentHighlights,
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
closeFilesForSession,
|
||||
createProjectService,
|
||||
createSession,
|
||||
openExternalProjectForSession,
|
||||
openFilesForSession,
|
||||
protocolTextSpanFromSubstring,
|
||||
TestSession,
|
||||
@@ -27,21 +23,17 @@ describe("unittests:: tsserver:: Open-file", () => {
|
||||
};
|
||||
const projectFileName = "externalProject";
|
||||
const host = createServerHost([f]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
// create a project
|
||||
projectService.openExternalProject({ projectFileName, rootFiles: [toExternalFile(f.path)], options: {} });
|
||||
|
||||
const p = projectService.externalProjects[0];
|
||||
// force to load the content of the file
|
||||
p.updateGraph();
|
||||
|
||||
const scriptInfo = p.getScriptInfo(f.path)!;
|
||||
projectService.logger.log(`Snapshot size: ${scriptInfo.getSnapshot().getLength()}`);
|
||||
openExternalProjectForSession({
|
||||
projectFileName,
|
||||
rootFiles: [toExternalFile(f.path)],
|
||||
options: {},
|
||||
}, session);
|
||||
|
||||
// open project and replace its content with empty string
|
||||
projectService.openClientFile(f.path, "");
|
||||
projectService.logger.log(`Snapshot size: ${scriptInfo.getSnapshot().getLength()}`);
|
||||
baselineTsserverLogs("openfile", "realoaded with empty content", projectService);
|
||||
openFilesForSession([{ file: f, content: "" }], session);
|
||||
baselineTsserverLogs("openfile", "realoaded with empty content", session);
|
||||
});
|
||||
|
||||
function verifyOpenFileWorks(subScenario: string, useCaseSensitiveFileNames: boolean) {
|
||||
@@ -65,7 +57,7 @@ describe("unittests:: tsserver:: Open-file", () => {
|
||||
const host = createServerHost([file1, file2, configFile, configFile2], {
|
||||
useCaseSensitiveFileNames,
|
||||
});
|
||||
const service = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
|
||||
// Open file1 -> configFile
|
||||
verifyConfigFileName(file1, "/a");
|
||||
@@ -77,11 +69,10 @@ describe("unittests:: tsserver:: Open-file", () => {
|
||||
verifyConfigFileName(file2, "/a/b");
|
||||
verifyConfigFileName(file2, "/a/B");
|
||||
|
||||
baselineTsserverLogs("openfile", subScenario, service);
|
||||
function verifyConfigFileName(file: File, projectRoot: string) {
|
||||
const { configFileName } = service.openClientFile(file.path, /*fileContent*/ undefined, /*scriptKind*/ undefined, projectRoot);
|
||||
service.logger.log(`file: ${file.path} configFile: ${configFileName}`);
|
||||
service.closeClientFile(file.path);
|
||||
baselineTsserverLogs("openfile", subScenario, session);
|
||||
function verifyConfigFileName(file: File, projectRootPath: string) {
|
||||
openFilesForSession([{ file, projectRootPath }], session);
|
||||
closeFilesForSession([file], session);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -89,50 +80,45 @@ describe("unittests:: tsserver:: Open-file", () => {
|
||||
verifyOpenFileWorks("project root is used with case-insensitive system", /*useCaseSensitiveFileNames*/ false);
|
||||
|
||||
it("uses existing project even if project refresh is pending", () => {
|
||||
const projectFolder = "/user/someuser/projects/myproject";
|
||||
const projectRootPath = "/user/someuser/projects/myproject";
|
||||
const aFile: File = {
|
||||
path: `${projectFolder}/src/a.ts`,
|
||||
path: `${projectRootPath}/src/a.ts`,
|
||||
content: "export const x = 0;",
|
||||
};
|
||||
const configFile: File = {
|
||||
path: `${projectFolder}/tsconfig.json`,
|
||||
path: `${projectRootPath}/tsconfig.json`,
|
||||
content: "{}",
|
||||
};
|
||||
const files = [aFile, configFile, libFile];
|
||||
const host = createServerHost(files);
|
||||
const service = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
service.openClientFile(aFile.path, /*fileContent*/ undefined, ts.ScriptKind.TS, projectFolder);
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([{ file: aFile, projectRootPath }], session);
|
||||
|
||||
const bFile: File = {
|
||||
path: `${projectFolder}/src/b.ts`,
|
||||
path: `${projectRootPath}/src/b.ts`,
|
||||
content: `export {}; declare module "./a" { export const y: number; }`,
|
||||
};
|
||||
host.writeFile(bFile.path, bFile.content);
|
||||
service.openClientFile(bFile.path, /*fileContent*/ undefined, ts.ScriptKind.TS, projectFolder);
|
||||
baselineTsserverLogs("openfile", "uses existing project even if project refresh is pending", service);
|
||||
openFilesForSession([{ file: bFile, projectRootPath }], session);
|
||||
baselineTsserverLogs("openfile", "uses existing project even if project refresh is pending", session);
|
||||
});
|
||||
|
||||
it("can open same file again", () => {
|
||||
const projectFolder = "/user/someuser/projects/myproject";
|
||||
const projectRootPath = "/user/someuser/projects/myproject";
|
||||
const aFile: File = {
|
||||
path: `${projectFolder}/src/a.ts`,
|
||||
path: `${projectRootPath}/src/a.ts`,
|
||||
content: "export const x = 0;",
|
||||
};
|
||||
const configFile: File = {
|
||||
path: `${projectFolder}/tsconfig.json`,
|
||||
path: `${projectRootPath}/tsconfig.json`,
|
||||
content: "{}",
|
||||
};
|
||||
const files = [aFile, configFile, libFile];
|
||||
const host = createServerHost(files);
|
||||
const service = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
verifyProject(aFile.content);
|
||||
verifyProject(`${aFile.content}export const y = 10;`);
|
||||
baselineTsserverLogs("openfile", "can open same file again", service);
|
||||
|
||||
function verifyProject(aFileContent: string) {
|
||||
service.openClientFile(aFile.path, aFileContent, ts.ScriptKind.TS, projectFolder);
|
||||
service.logger.log(`aFileContent: ${service.configuredProjects.get(configFile.path)!.getCurrentProgram()?.getSourceFile(aFile.path)!.text}`);
|
||||
}
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([{ file: aFile, content: aFile.content, projectRootPath }], session);
|
||||
openFilesForSession([{ file: aFile, content: `${aFile.content}export const y = 10;`, projectRootPath }], session);
|
||||
baselineTsserverLogs("openfile", "can open same file again", session);
|
||||
});
|
||||
|
||||
it("when file makes edits to add/remove comment directives, they are handled correcrly", () => {
|
||||
@@ -153,7 +139,7 @@ foo();
|
||||
bar();`,
|
||||
};
|
||||
const host = createServerHost([file, libFile]);
|
||||
const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file], session);
|
||||
verifyGetErrRequest({ session, files: [file] });
|
||||
|
||||
@@ -198,7 +184,7 @@ bar();`,
|
||||
"/project/tsconfig.json": "{}",
|
||||
[libFile.path]: libFile.content,
|
||||
});
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
return { host, session };
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
jsonToReadableText,
|
||||
} from "../helpers";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createSession,
|
||||
openFilesForSession,
|
||||
TestSession,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
createServerHost,
|
||||
@@ -46,7 +43,7 @@ describe("unittests:: tsserver:: packageJsonInfo::", () => {
|
||||
|
||||
// Add package.json
|
||||
host.writeFile(packageJson.path, packageJson.content);
|
||||
session.testhost.baselineHost("Add package.json");
|
||||
session.host.baselineHost("Add package.json");
|
||||
let packageJsonInfo = projectService.packageJsonCache.getInDirectory("/" as ts.Path)!;
|
||||
assert.ok(packageJsonInfo);
|
||||
assert.ok(packageJsonInfo.dependencies);
|
||||
@@ -62,7 +59,7 @@ describe("unittests:: tsserver:: packageJsonInfo::", () => {
|
||||
dependencies: undefined,
|
||||
}),
|
||||
);
|
||||
session.testhost.baselineHost("Edit package.json");
|
||||
session.host.baselineHost("Edit package.json");
|
||||
packageJsonInfo = projectService.packageJsonCache.getInDirectory("/" as ts.Path)!;
|
||||
assert.isUndefined(packageJsonInfo.dependencies);
|
||||
|
||||
@@ -77,7 +74,7 @@ describe("unittests:: tsserver:: packageJsonInfo::", () => {
|
||||
|
||||
// Delete package.json
|
||||
host.deleteFile(packageJson.path);
|
||||
session.testhost.baselineHost("delete packageJson");
|
||||
session.host.baselineHost("delete packageJson");
|
||||
assert.isUndefined(projectService.packageJsonCache.getInDirectory("/" as ts.Path));
|
||||
baselineTsserverLogs("packageJsonInfo", "finds package.json on demand, watches for deletion, and removes them from cache", session);
|
||||
});
|
||||
@@ -87,7 +84,7 @@ describe("unittests:: tsserver:: packageJsonInfo::", () => {
|
||||
const { session, projectService, host } = setup();
|
||||
// Add package.json in /src
|
||||
host.writeFile("/src/package.json", packageJson.content);
|
||||
session.testhost.baselineHost("packageJson");
|
||||
session.host.baselineHost("packageJson");
|
||||
assert.lengthOf(projectService.getPackageJsonsVisibleToFile("/a.ts" as ts.Path), 1);
|
||||
assert.lengthOf(projectService.getPackageJsonsVisibleToFile("/src/b.ts" as ts.Path), 2);
|
||||
baselineTsserverLogs("packageJsonInfo", "finds multiple package.json files when present", session);
|
||||
@@ -101,7 +98,7 @@ describe("unittests:: tsserver:: packageJsonInfo::", () => {
|
||||
assert.isFalse(packageJsonInfo.parseable);
|
||||
|
||||
host.writeFile(packageJson.path, packageJson.content);
|
||||
session.testhost.baselineHost("packageJson");
|
||||
session.host.baselineHost("packageJson");
|
||||
projectService.getPackageJsonsVisibleToFile("/src/whatever/blah.ts" as ts.Path);
|
||||
const packageJsonInfo2 = projectService.packageJsonCache.getInDirectory("/" as ts.Path)!;
|
||||
assert.ok(packageJsonInfo2);
|
||||
@@ -120,7 +117,7 @@ describe("unittests:: tsserver:: packageJsonInfo::", () => {
|
||||
assert.isFalse(packageJsonInfo.parseable);
|
||||
|
||||
host.writeFile(packageJson.path, packageJson.content);
|
||||
session.testhost.baselineHost("PackageJson");
|
||||
session.host.baselineHost("PackageJson");
|
||||
projectService.getPackageJsonsVisibleToFile("/src/whatever/blah.ts" as ts.Path);
|
||||
const packageJsonInfo2 = projectService.packageJsonCache.getInDirectory("/" as ts.Path)!;
|
||||
assert.ok(packageJsonInfo2);
|
||||
@@ -134,7 +131,7 @@ describe("unittests:: tsserver:: packageJsonInfo::", () => {
|
||||
|
||||
function setup(files: readonly File[] = [tsConfig, packageJson]) {
|
||||
const host = createServerHost(files);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([files[0]], session);
|
||||
return { host, session, projectService: session.getProjectService() };
|
||||
}
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
closeFilesForSession,
|
||||
createSession,
|
||||
openFilesForSession,
|
||||
protocolFileLocationFromSubstring,
|
||||
TestSession,
|
||||
verifyGetErrRequest,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
@@ -43,10 +40,10 @@ import { something } from "something";
|
||||
content: "{}",
|
||||
};
|
||||
const host = createServerHost([file1, file2, file3, something, libFile, configFile]);
|
||||
const session = createSession(host, {
|
||||
const session = new TestSession({
|
||||
host,
|
||||
serverMode: ts.LanguageServiceMode.PartialSemantic,
|
||||
useSingleInferredProject: true,
|
||||
logger: createLoggerWithInMemoryLogs(host),
|
||||
});
|
||||
return { host, session, file1, file2, file3, something, configFile };
|
||||
}
|
||||
@@ -105,10 +102,10 @@ import { something } from "something";
|
||||
const expectedErrorMessage = "')' expected.";
|
||||
|
||||
const host = createServerHost([file1, libFile, configFile]);
|
||||
const session = createSession(host, {
|
||||
const session = new TestSession({
|
||||
host,
|
||||
serverMode: ts.LanguageServiceMode.PartialSemantic,
|
||||
useSingleInferredProject: true,
|
||||
logger: createLoggerWithInMemoryLogs(host),
|
||||
});
|
||||
|
||||
const service = session.getProjectService();
|
||||
@@ -170,10 +167,10 @@ function fooB() { }`,
|
||||
content: "{}",
|
||||
};
|
||||
const host = createServerHost([file1, file2, file3, something, libFile, configFile]);
|
||||
const session = createSession(host, {
|
||||
const session = new TestSession({
|
||||
host,
|
||||
serverMode: ts.LanguageServiceMode.PartialSemantic,
|
||||
useSingleInferredProject: true,
|
||||
logger: createLoggerWithInMemoryLogs(host),
|
||||
});
|
||||
openFilesForSession([file1], session);
|
||||
baselineTsserverLogs("partialSemanticServer", "should not include referenced files from unopened files", session);
|
||||
@@ -214,7 +211,7 @@ function fooB() { }`,
|
||||
content: "",
|
||||
};
|
||||
const host = createServerHost([angularFormsDts, angularFormsPackageJson, tsconfig, packageJson, indexTs, libFile]);
|
||||
const session = createSession(host, { serverMode: ts.LanguageServiceMode.PartialSemantic, useSingleInferredProject: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession({ host, serverMode: ts.LanguageServiceMode.PartialSemantic, useSingleInferredProject: true });
|
||||
const service = session.getProjectService();
|
||||
openFilesForSession([indexTs], session);
|
||||
const project = service.inferredProjects[0];
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as Harness from "../../_namespaces/Harness";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
@@ -8,9 +5,8 @@ import {
|
||||
} from "../helpers";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createSession,
|
||||
openFilesForSession,
|
||||
TestSessionOptions,
|
||||
TestSession,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
createServerHost,
|
||||
@@ -23,7 +19,7 @@ describe("unittests:: tsserver:: plugins:: loading", () => {
|
||||
const testProtocolCommandRequest = "testProtocolCommandRequest";
|
||||
const testProtocolCommandResponse = "testProtocolCommandResponse";
|
||||
|
||||
function createHostWithPlugin(files: readonly File[], opts?: Partial<TestSessionOptions>) {
|
||||
function createHostWithPlugin(files: readonly File[], globalPlugins?: readonly string[]) {
|
||||
const host = createServerHost(files);
|
||||
host.require = (_initialPath, moduleName) => {
|
||||
session.logger.log(`Loading plugin: ${moduleName}`);
|
||||
@@ -42,7 +38,7 @@ describe("unittests:: tsserver:: plugins:: loading", () => {
|
||||
error: undefined,
|
||||
};
|
||||
};
|
||||
const session = createSession(host, { ...opts, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession({ host, globalPlugins });
|
||||
return { host, session };
|
||||
}
|
||||
|
||||
@@ -74,7 +70,7 @@ describe("unittests:: tsserver:: plugins:: loading", () => {
|
||||
path: "/tsconfig.json",
|
||||
content: "{}",
|
||||
};
|
||||
const { session } = createHostWithPlugin([aTs, tsconfig, libFile], { globalPlugins: [...expectedToLoad, ...notToLoad] });
|
||||
const { session } = createHostWithPlugin([aTs, tsconfig, libFile], [...expectedToLoad, ...notToLoad]);
|
||||
openFilesForSession([aTs], session);
|
||||
baselineTsserverLogs("plugins", "With global plugins", session);
|
||||
});
|
||||
@@ -135,7 +131,7 @@ describe("unittests:: tsserver:: plugins:: loading", () => {
|
||||
error: undefined,
|
||||
};
|
||||
};
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([aTs], session);
|
||||
session.logger.log(`ExternalFiles:: ${jsonToReadableText(session.getProjectService().configuredProjects.get(tsconfig.path)!.getExternalFiles())}`);
|
||||
|
||||
@@ -197,7 +193,7 @@ describe("unittests:: tsserver:: plugins:: overriding getSupportedCodeFixes", ()
|
||||
error: undefined,
|
||||
};
|
||||
};
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([aTs, bTs, cTs], session);
|
||||
// Without arguments
|
||||
session.executeCommandSeq<ts.server.protocol.GetSupportedCodeFixesRequest>({
|
||||
@@ -293,7 +289,7 @@ describe("unittests:: tsserver:: plugins:: supportedExtensions::", () => {
|
||||
error: undefined,
|
||||
};
|
||||
};
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host), globalPlugins: ["myplugin"] });
|
||||
const session = new TestSession({ host, globalPlugins: ["myplugin"] });
|
||||
openFilesForSession([aTs], session);
|
||||
|
||||
host.writeFile("/user/username/projects/myproject/c.vue", "cVue file");
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
defer,
|
||||
@@ -8,8 +5,8 @@ import {
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
closeFilesForSession,
|
||||
createSession,
|
||||
openFilesForSession,
|
||||
TestSession,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
createServerHost,
|
||||
@@ -19,7 +16,7 @@ import {
|
||||
describe("unittests:: tsserver:: pluginsAsync:: async loaded plugins", () => {
|
||||
function setup(globalPlugins: string[]) {
|
||||
const host = createServerHost([libFile]);
|
||||
const session = createSession(host, { canUseEvents: true, globalPlugins, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession({ host, globalPlugins });
|
||||
return { host, session };
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
jsonToReadableText,
|
||||
@@ -9,11 +6,10 @@ import {
|
||||
appendAllScriptInfos,
|
||||
baselineTsserverLogs,
|
||||
closeFilesForSession,
|
||||
createProjectService,
|
||||
createSession,
|
||||
openExternalProjectForSession,
|
||||
openFilesForSession,
|
||||
setCompilerOptionsForInferredProjectsRequestForSession,
|
||||
TestSession,
|
||||
TestSessionRequest,
|
||||
toExternalFiles,
|
||||
verifyGetErrRequest,
|
||||
@@ -37,7 +33,7 @@ describe("unittests:: tsserver:: projectErrors::", () => {
|
||||
content: "",
|
||||
};
|
||||
const host = createServerHost([file1, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
const projectFileName = "/a/b/test.csproj";
|
||||
const compilerOptionsRequest: TestSessionRequest<ts.server.protocol.CompilerOptionsDiagnosticsRequest> = {
|
||||
command: ts.server.protocol.CommandTypes.CompilerOptionsDiagnosticsFull,
|
||||
@@ -82,7 +78,7 @@ describe("unittests:: tsserver:: projectErrors::", () => {
|
||||
content: jsonToReadableText({ files: [file1, file2].map(f => ts.getBaseFileName(f.path)) }),
|
||||
};
|
||||
const host = createServerHost([file1, config, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file1], session);
|
||||
const compilerOptionsRequest: TestSessionRequest<ts.server.protocol.CompilerOptionsDiagnosticsRequest> = {
|
||||
command: ts.server.protocol.CommandTypes.CompilerOptionsDiagnosticsFull,
|
||||
@@ -114,7 +110,7 @@ describe("unittests:: tsserver:: projectErrors::", () => {
|
||||
content: correctConfig.content.substr(1),
|
||||
};
|
||||
const host = createServerHost([file1, file2, corruptedConfig]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
|
||||
openFilesForSession([file1], session);
|
||||
{
|
||||
@@ -166,7 +162,7 @@ describe("unittests:: tsserver:: projectErrors::", () => {
|
||||
content: correctConfig.content.substr(1),
|
||||
};
|
||||
const host = createServerHost([file1, file2, correctConfig]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
|
||||
openFilesForSession([file1], session);
|
||||
{
|
||||
@@ -212,9 +208,9 @@ describe("unittests:: tsserver:: projectErrors:: are reported as appropriate", (
|
||||
content: "{",
|
||||
};
|
||||
const host = createServerHost([file1, corruptedConfig]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
projectService.openClientFile(file1.path);
|
||||
baselineTsserverLogs("projectErrors", "document is not contained in project", projectService);
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file1], session);
|
||||
baselineTsserverLogs("projectErrors", "document is not contained in project", session);
|
||||
});
|
||||
|
||||
describe("when opening new file that doesnt exist on disk yet", () => {
|
||||
@@ -229,7 +225,7 @@ describe("unittests:: tsserver:: projectErrors:: are reported as appropriate", (
|
||||
content: "class c { }",
|
||||
};
|
||||
const host = createServerHost([libFile, fileInRoot, fileInProjectRoot]);
|
||||
const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host), useInferredProjectPerProjectRoot: true });
|
||||
const session = new TestSession({ host, useInferredProjectPerProjectRoot: true });
|
||||
|
||||
const untitledFile = "untitled:Untitled-1";
|
||||
const refPathNotFound1 = "../../../../../../typings/@epic/Core.d.ts";
|
||||
@@ -276,7 +272,7 @@ describe("unittests:: tsserver:: projectErrors:: are reported as appropriate", (
|
||||
content: jsonToReadableText({ compilerOptions: { module: "none", targer: "es5" }, exclude: ["node_modules"] }),
|
||||
};
|
||||
const host = createServerHost([app, foo, configFile]);
|
||||
const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.OpenRequest>({
|
||||
command: ts.server.protocol.CommandTypes.Open,
|
||||
@@ -297,7 +293,7 @@ describe("unittests:: tsserver:: projectErrors:: are reported as appropriate", (
|
||||
content: "let x: number = false;",
|
||||
};
|
||||
const host = createServerHost([file, libFile]);
|
||||
const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
session.executeCommandSeq<ts.server.protocol.GeterrRequest>({
|
||||
command: ts.server.protocol.CommandTypes.Geterr,
|
||||
arguments: {
|
||||
@@ -325,7 +321,7 @@ describe("unittests:: tsserver:: projectErrors:: are reported as appropriate", (
|
||||
};
|
||||
const files = [libFile, app, serverUtilities, backendTest];
|
||||
const host = createServerHost(files);
|
||||
const session = createSession(host, { useInferredProjectPerProjectRoot: true, canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession({ host, useInferredProjectPerProjectRoot: true });
|
||||
openFilesForSession([{ file: app, projectRootPath: "/user/username/projects/myproject" }], session);
|
||||
openFilesForSession([{ file: backendTest, projectRootPath: "/user/username/projects/myproject" }], session);
|
||||
verifyGetErrRequest({ session, files: [backendTest.path, app.path] });
|
||||
@@ -363,7 +359,7 @@ declare module '@custom/plugin' {
|
||||
};
|
||||
const files = [libFile, aFile, config, plugin, pluginProposed];
|
||||
const host = createServerHost(files);
|
||||
const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([aFile], session);
|
||||
|
||||
verifyGetErrRequest({ session, files: [aFile] });
|
||||
@@ -421,7 +417,7 @@ describe("unittests:: tsserver:: Project Errors for Configure file diagnostics e
|
||||
}`,
|
||||
};
|
||||
const host = createServerHost([file, libFile, configFile]);
|
||||
const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file], session);
|
||||
baselineTsserverLogs("projectErrors", "configFileDiagnostic events are generated when the config file has errors", session);
|
||||
});
|
||||
@@ -438,7 +434,7 @@ describe("unittests:: tsserver:: Project Errors for Configure file diagnostics e
|
||||
}`,
|
||||
};
|
||||
const host = createServerHost([file, libFile, configFile]);
|
||||
const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file], session);
|
||||
baselineTsserverLogs("projectErrors", "configFileDiagnostic events are generated when the config file doesnt have errors", session);
|
||||
});
|
||||
@@ -456,7 +452,7 @@ describe("unittests:: tsserver:: Project Errors for Configure file diagnostics e
|
||||
};
|
||||
|
||||
const host = createServerHost([file, libFile, configFile]);
|
||||
const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file], session);
|
||||
|
||||
configFile.content = `{
|
||||
@@ -499,7 +495,7 @@ describe("unittests:: tsserver:: Project Errors for Configure file diagnostics e
|
||||
}`,
|
||||
};
|
||||
const host = createServerHost([file, libFile, configFile]);
|
||||
const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file2], session);
|
||||
openFilesForSession([file], session);
|
||||
// We generate only if project is created when opening file from the project
|
||||
@@ -522,7 +518,7 @@ describe("unittests:: tsserver:: Project Errors for Configure file diagnostics e
|
||||
}`,
|
||||
};
|
||||
const host = createServerHost([file, libFile, configFile]);
|
||||
const session = createSession(host, { canUseEvents: true, suppressDiagnosticEvents: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession({ host, suppressDiagnosticEvents: true });
|
||||
openFilesForSession([file], session);
|
||||
baselineTsserverLogs("projectErrors", "configFileDiagnostic events are not generated when the config file has errors but suppressDiagnosticEvents is true", session);
|
||||
});
|
||||
@@ -548,7 +544,7 @@ describe("unittests:: tsserver:: Project Errors for Configure file diagnostics e
|
||||
};
|
||||
|
||||
const host = createServerHost([file, file2, file3, libFile, configFile]);
|
||||
const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file2], session);
|
||||
openFilesForSession([file], session);
|
||||
// We generate only if project is created when opening file from the project
|
||||
@@ -571,7 +567,7 @@ describe("unittests:: tsserver:: Project Errors for Configure file diagnostics e
|
||||
};
|
||||
|
||||
const host = createServerHost([file, libFile, configFile]);
|
||||
const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file], session);
|
||||
baselineTsserverLogs("projectErrors", "configFileDiagnostic events contains the project reference errors", session);
|
||||
});
|
||||
@@ -584,7 +580,7 @@ describe("unittests:: tsserver:: projectErrors:: dont include overwrite emit err
|
||||
content: "function test1() { }",
|
||||
};
|
||||
const host = createServerHost([f1, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([f1], session);
|
||||
|
||||
const projectService = session.getProjectService();
|
||||
@@ -594,7 +590,7 @@ describe("unittests:: tsserver:: projectErrors:: dont include overwrite emit err
|
||||
arguments: { projectFileName },
|
||||
});
|
||||
|
||||
setCompilerOptionsForInferredProjectsRequestForSession({ module: ts.ModuleKind.CommonJS }, session);
|
||||
setCompilerOptionsForInferredProjectsRequestForSession({ module: ts.server.protocol.ModuleKind.CommonJS }, session);
|
||||
session.executeCommandSeq<ts.server.protocol.CompilerOptionsDiagnosticsRequest>({
|
||||
command: ts.server.protocol.CommandTypes.CompilerOptionsDiagnosticsFull,
|
||||
arguments: { projectFileName },
|
||||
@@ -608,7 +604,7 @@ describe("unittests:: tsserver:: projectErrors:: dont include overwrite emit err
|
||||
content: "function test1() { }",
|
||||
};
|
||||
const host = createServerHost([f1, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
const projectFileName = "/a/b/project.csproj";
|
||||
const externalFiles = toExternalFiles([f1.path]);
|
||||
openExternalProjectForSession({
|
||||
@@ -625,7 +621,7 @@ describe("unittests:: tsserver:: projectErrors:: dont include overwrite emit err
|
||||
openExternalProjectForSession({
|
||||
projectFileName,
|
||||
rootFiles: externalFiles,
|
||||
options: { module: ts.ModuleKind.CommonJS },
|
||||
options: { module: ts.server.protocol.ModuleKind.CommonJS },
|
||||
}, session);
|
||||
session.executeCommandSeq<ts.server.protocol.CompilerOptionsDiagnosticsRequest>({
|
||||
command: ts.server.protocol.CommandTypes.CompilerOptionsDiagnosticsFull,
|
||||
@@ -658,7 +654,7 @@ describe("unittests:: tsserver:: projectErrors:: reports Options Diagnostic loca
|
||||
content: configFileContentWithComment,
|
||||
};
|
||||
const host = createServerHost([file, libFile, configFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.SemanticDiagnosticsSyncRequest>({
|
||||
@@ -683,7 +679,7 @@ describe("unittests:: tsserver:: projectErrors:: with config file change", () =>
|
||||
const tsconfig: File = { path: "/tsconfig.json", content: options(/*allowUnusedLabels*/ true) };
|
||||
|
||||
const host = createServerHost([aTs, tsconfig]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([aTs], session);
|
||||
|
||||
host.modifyFile(tsconfig.path, options(/*allowUnusedLabels*/ false));
|
||||
@@ -722,7 +718,7 @@ console.log(blabla);`,
|
||||
};
|
||||
|
||||
const host = createServerHost([test, blabla, libFile, tsconfig]);
|
||||
const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([test], session);
|
||||
return { host, session, test, blabla, tsconfig };
|
||||
}
|
||||
@@ -761,7 +757,7 @@ describe("unittests:: tsserver:: projectErrors:: with npm install when", () => {
|
||||
};
|
||||
const projectFiles = [main, libFile, config];
|
||||
const host = createServerHost(projectFiles);
|
||||
const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([{ file: main, projectRootPath: "/user/username/projects/myproject" }], session);
|
||||
verifyGetErrRequest({ session, files: [main] });
|
||||
|
||||
@@ -805,9 +801,6 @@ describe("unittests:: tsserver:: projectErrors:: with npm install when", () => {
|
||||
host.runQueuedTimeoutCallbacks(); // Invalidation of failed lookups
|
||||
host.runQueuedTimeoutCallbacks(); // Actual update
|
||||
}
|
||||
else {
|
||||
session.testhost.logTimeoutQueueLength();
|
||||
}
|
||||
verifyGetErrRequest({ session, files: [main], existingTimeouts: !npmInstallComplete && !timeoutDuringPartialInstallation });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
jsonToReadableText,
|
||||
@@ -10,9 +7,9 @@ import {
|
||||
} from "../helpers/solutionBuilder";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createSession,
|
||||
openFilesForSession,
|
||||
protocolToLocation,
|
||||
TestSession,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
createServerHost,
|
||||
@@ -61,7 +58,7 @@ fn2();
|
||||
describe("Of usageTs", () => {
|
||||
it("with initial file open, without specifying project file", () => {
|
||||
const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([usageTs], session);
|
||||
|
||||
// Verify CompileOnSaveAffectedFileList
|
||||
@@ -85,7 +82,7 @@ fn2();
|
||||
});
|
||||
it("with initial file open, with specifying project file", () => {
|
||||
const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([usageTs], session);
|
||||
|
||||
// Verify CompileOnSaveAffectedFileList
|
||||
@@ -109,7 +106,7 @@ fn2();
|
||||
});
|
||||
it("with local change to dependency, without specifying project file", () => {
|
||||
const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([usageTs], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -139,7 +136,7 @@ fn2();
|
||||
});
|
||||
it("with local change to dependency, with specifying project file", () => {
|
||||
const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([usageTs], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -169,7 +166,7 @@ fn2();
|
||||
});
|
||||
it("with local change to usage, without specifying project file", () => {
|
||||
const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([usageTs], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -210,7 +207,7 @@ fn2();
|
||||
});
|
||||
it("with local change to usage, with specifying project file", () => {
|
||||
const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([usageTs], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -251,7 +248,7 @@ fn2();
|
||||
});
|
||||
it("with change to dependency, without specifying project file", () => {
|
||||
const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([usageTs], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -281,7 +278,7 @@ fn2();
|
||||
});
|
||||
it("with change to dependency, with specifying project file", () => {
|
||||
const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([usageTs], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -311,7 +308,7 @@ fn2();
|
||||
});
|
||||
it("with change to usage, without specifying project file", () => {
|
||||
const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([usageTs], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -352,7 +349,7 @@ fn2();
|
||||
});
|
||||
it("with change to usage, with specifying project file", () => {
|
||||
const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([usageTs], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -396,7 +393,7 @@ fn2();
|
||||
describe("Of dependencyTs in usage project", () => {
|
||||
it("with initial file open, without specifying project file", () => {
|
||||
const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([usageTs], session);
|
||||
|
||||
// Verify CompileOnSaveAffectedFileList
|
||||
@@ -420,7 +417,7 @@ fn2();
|
||||
});
|
||||
it("with initial file open, with specifying project file", () => {
|
||||
const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([usageTs], session);
|
||||
|
||||
// Verify CompileOnSaveAffectedFileList
|
||||
@@ -444,7 +441,7 @@ fn2();
|
||||
});
|
||||
it("with local change to dependency, without specifying project file", () => {
|
||||
const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([usageTs], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -474,7 +471,7 @@ fn2();
|
||||
});
|
||||
it("with local change to dependency, with specifying project file", () => {
|
||||
const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([usageTs], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -504,7 +501,7 @@ fn2();
|
||||
});
|
||||
it("with local change to usage, without specifying project file", () => {
|
||||
const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([usageTs], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -545,7 +542,7 @@ fn2();
|
||||
});
|
||||
it("with local change to usage, with specifying project file", () => {
|
||||
const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([usageTs], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -586,7 +583,7 @@ fn2();
|
||||
});
|
||||
it("with change to dependency, without specifying project file", () => {
|
||||
const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([usageTs], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -616,7 +613,7 @@ fn2();
|
||||
});
|
||||
it("with change to dependency, with specifying project file", () => {
|
||||
const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([usageTs], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -646,7 +643,7 @@ fn2();
|
||||
});
|
||||
it("with change to usage, without specifying project file", () => {
|
||||
const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([usageTs], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -687,7 +684,7 @@ fn2();
|
||||
});
|
||||
it("with change to usage, with specifying project file", () => {
|
||||
const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([usageTs], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -733,7 +730,7 @@ fn2();
|
||||
describe("Of usageTs", () => {
|
||||
it("with initial file open, without specifying project file", () => {
|
||||
const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([usageTs, dependencyTs], session);
|
||||
|
||||
// Verify CompileOnSaveAffectedFileList
|
||||
@@ -757,7 +754,7 @@ fn2();
|
||||
});
|
||||
it("with initial file open, with specifying project file", () => {
|
||||
const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([usageTs, dependencyTs], session);
|
||||
|
||||
// Verify CompileOnSaveAffectedFileList
|
||||
@@ -781,7 +778,7 @@ fn2();
|
||||
});
|
||||
it("with local change to dependency, without specifying project file", () => {
|
||||
const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([usageTs, dependencyTs], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -822,7 +819,7 @@ fn2();
|
||||
});
|
||||
it("with local change to dependency, with specifying project file", () => {
|
||||
const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([usageTs, dependencyTs], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -863,7 +860,7 @@ fn2();
|
||||
});
|
||||
it("with local change to usage, without specifying project file", () => {
|
||||
const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([usageTs, dependencyTs], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -904,7 +901,7 @@ fn2();
|
||||
});
|
||||
it("with local change to usage, with specifying project file", () => {
|
||||
const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([usageTs, dependencyTs], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -945,7 +942,7 @@ fn2();
|
||||
});
|
||||
it("with change to dependency, without specifying project file", () => {
|
||||
const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([usageTs, dependencyTs], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -986,7 +983,7 @@ fn2();
|
||||
});
|
||||
it("with change to dependency, with specifying project file", () => {
|
||||
const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([usageTs, dependencyTs], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -1027,7 +1024,7 @@ fn2();
|
||||
});
|
||||
it("with change to usage, without specifying project file", () => {
|
||||
const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([usageTs, dependencyTs], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -1068,7 +1065,7 @@ fn2();
|
||||
});
|
||||
it("with change to usage, with specifying project file", () => {
|
||||
const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([usageTs, dependencyTs], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -1111,7 +1108,7 @@ fn2();
|
||||
describe("Of dependencyTs in usage project", () => {
|
||||
it("with initial file open, with specifying project file", () => {
|
||||
const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([usageTs, dependencyTs], session);
|
||||
|
||||
// Verify CompileOnSaveAffectedFileList
|
||||
@@ -1135,7 +1132,7 @@ fn2();
|
||||
});
|
||||
it("with local change to dependency, with specifying project file", () => {
|
||||
const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([usageTs, dependencyTs], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -1176,7 +1173,7 @@ fn2();
|
||||
});
|
||||
it("with local change to usage, with specifying project file", () => {
|
||||
const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([usageTs, dependencyTs], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -1217,7 +1214,7 @@ fn2();
|
||||
});
|
||||
it("with change to dependency, with specifying project file", () => {
|
||||
const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([usageTs, dependencyTs], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -1258,7 +1255,7 @@ fn2();
|
||||
});
|
||||
it("with change to usage, with specifying project file", () => {
|
||||
const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([usageTs, dependencyTs], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -1302,7 +1299,7 @@ fn2();
|
||||
describe("Of dependencyTs", () => {
|
||||
it("with initial file open, without specifying project file", () => {
|
||||
const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([usageTs, dependencyTs], session);
|
||||
|
||||
// Verify CompileOnSaveAffectedFileList
|
||||
@@ -1326,7 +1323,7 @@ fn2();
|
||||
});
|
||||
it("with initial file open, with specifying project file", () => {
|
||||
const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([usageTs, dependencyTs], session);
|
||||
|
||||
// Verify CompileOnSaveAffectedFileList
|
||||
@@ -1350,7 +1347,7 @@ fn2();
|
||||
});
|
||||
it("with local change to dependency, without specifying project file", () => {
|
||||
const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([usageTs, dependencyTs], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -1391,7 +1388,7 @@ fn2();
|
||||
});
|
||||
it("with local change to dependency, with specifying project file", () => {
|
||||
const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([usageTs, dependencyTs], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -1432,7 +1429,7 @@ fn2();
|
||||
});
|
||||
it("with local change to usage, without specifying project file", () => {
|
||||
const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([usageTs, dependencyTs], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -1473,7 +1470,7 @@ fn2();
|
||||
});
|
||||
it("with local change to usage, with specifying project file", () => {
|
||||
const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([usageTs, dependencyTs], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -1514,7 +1511,7 @@ fn2();
|
||||
});
|
||||
it("with change to dependency, without specifying project file", () => {
|
||||
const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([usageTs, dependencyTs], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -1555,7 +1552,7 @@ fn2();
|
||||
});
|
||||
it("with change to dependency, with specifying project file", () => {
|
||||
const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([usageTs, dependencyTs], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -1596,7 +1593,7 @@ fn2();
|
||||
});
|
||||
it("with change to usage, without specifying project file", () => {
|
||||
const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([usageTs, dependencyTs], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -1637,7 +1634,7 @@ fn2();
|
||||
});
|
||||
it("with change to usage, with specifying project file", () => {
|
||||
const host = createServerHost([dependencyTs, dependencyConfig, usageTs, usageConfig, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([usageTs, dependencyTs], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveAffectedFileListRequest>({
|
||||
@@ -1741,7 +1738,7 @@ describe("unittests:: tsserver:: with project references and compile on save wit
|
||||
// ts build should succeed
|
||||
ensureErrorFreeBuild(host, [siblingConfig.path]);
|
||||
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([siblingSource], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.CompileOnSaveEmitFileRequest>({
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
dedent,
|
||||
@@ -14,11 +11,10 @@ import {
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createHostWithSolutionBuild,
|
||||
createProjectService,
|
||||
createSession,
|
||||
openFilesForSession,
|
||||
protocolFileLocationFromSubstring,
|
||||
protocolLocationFromSubstring,
|
||||
TestSession,
|
||||
verifyGetErrRequest,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
@@ -119,7 +115,7 @@ describe("unittests:: tsserver:: with project references and tsbuild", () => {
|
||||
const files = [libFile, containerLibConfig, containerLibIndex, containerExecConfig, containerExecIndex, containerCompositeExecConfig, containerCompositeExecIndex, containerConfig];
|
||||
if (tempFile) files.push(tempFile);
|
||||
const host = createHostWithSolutionBuild(files, [containerConfig.path]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
return { files, session, containerConfig, containerCompositeExecIndex };
|
||||
}
|
||||
|
||||
@@ -260,7 +256,7 @@ function foo() {
|
||||
[commonConfig, keyboardTs, keyboardTestTs, srcConfig, terminalTs, libFile],
|
||||
[srcConfig.path],
|
||||
);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([keyboardTs, terminalTs], session);
|
||||
|
||||
const searchStr = "evaluateKeyboardEvent";
|
||||
@@ -331,23 +327,23 @@ function foo() {
|
||||
};
|
||||
const files = [libFile, aTs, a2Ts, configA, bDts, bTs, configB, cTs, configC];
|
||||
const host = createServerHost(files);
|
||||
const service = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
service.openClientFile(aTs.path);
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([aTs], session);
|
||||
|
||||
// project A referencing b.d.ts without project reference
|
||||
const projectA = service.configuredProjects.get(configA.path)!;
|
||||
const projectA = session.getProjectService().configuredProjects.get(configA.path)!;
|
||||
assert.isDefined(projectA);
|
||||
|
||||
// reuses b.d.ts but sets the path and resolved path since projectC has project references
|
||||
// as the real resolution was to b.ts
|
||||
service.openClientFile(cTs.path);
|
||||
openFilesForSession([cTs], session);
|
||||
|
||||
// Now new project for project A tries to reuse b but there is no filesByName mapping for b's source location
|
||||
host.writeFile(a2Ts.path, `${a2Ts.content}export const y = 30;`);
|
||||
service.testhost.baselineHost("a2Ts modified");
|
||||
session.host.baselineHost("a2Ts modified");
|
||||
assert.isTrue(projectA.dirty);
|
||||
projectA.updateGraph();
|
||||
baselineTsserverLogs("projectReferences", "reusing d.ts files from composite and non composite projects", service);
|
||||
baselineTsserverLogs("projectReferences", "reusing d.ts files from composite and non composite projects", session);
|
||||
});
|
||||
|
||||
describe("when references are monorepo like with symlinks", () => {
|
||||
@@ -389,7 +385,7 @@ function foo() {
|
||||
createServerHost(files);
|
||||
|
||||
// Create symlink in node module
|
||||
const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([aTest], session);
|
||||
verifyGetErrRequest({ session, files: [aTest] });
|
||||
session.executeCommandSeq<ts.server.protocol.UpdateOpenRequest>({
|
||||
@@ -548,7 +544,7 @@ testCompositeFunction('why hello there', 42);`,
|
||||
symLink: `/user/username/projects/myproject/packages/emit-composite`,
|
||||
};
|
||||
const host = createServerHost([libFile, compositeConfig, compositePackageJson, compositeIndex, compositeTestModule, consumerConfig, consumerIndex, symlink], { useCaseSensitiveFileNames: true });
|
||||
const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([consumerIndex], session);
|
||||
verifyGetErrRequest({ session, files: [consumerIndex] });
|
||||
baselineTsserverLogs("projectReferences", `when the referenced projects have allowJs and emitDeclarationOnly`, session);
|
||||
@@ -618,7 +614,7 @@ testCompositeFunction('why hello there', 42);`,
|
||||
|
||||
const files = [libFile, solution, compilerConfig, typesFile, programFile, servicesConfig, servicesFile, libFile];
|
||||
const host = createServerHost(files);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([programFile], session);
|
||||
|
||||
// Find all references for getSourceFile
|
||||
@@ -738,7 +734,7 @@ testCompositeFunction('why hello there', 42);`,
|
||||
|
||||
const files = [libFile, solutionConfig, aConfig, aFile, bConfig, bFile, cConfig, cFile, dConfig, dFile, libFile];
|
||||
const host = createServerHost(files);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([bFile], session);
|
||||
|
||||
// The first search will trigger project loads
|
||||
@@ -812,7 +808,7 @@ ${usage}`,
|
||||
content: definition,
|
||||
};
|
||||
const host = createServerHost([libFile, solution, libFile, apiConfig, apiFile, appConfig, appFile, sharedConfig, sharedFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([apiFile], session);
|
||||
|
||||
// Find all references
|
||||
@@ -929,7 +925,7 @@ export const foo = local;`,
|
||||
|
||||
const files = [libFile, solution, compilerConfig, typesFile, programFile, servicesConfig, servicesFile, libFile];
|
||||
const host = createServerHost(files);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([programFile], session);
|
||||
|
||||
// Find all references
|
||||
@@ -1047,7 +1043,7 @@ export function bar() {}`,
|
||||
fileResolvingToMainDts,
|
||||
...additionalFiles,
|
||||
]);
|
||||
const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
const service = session.getProjectService();
|
||||
service.openClientFile(main.path);
|
||||
return { session, service, host };
|
||||
@@ -1324,7 +1320,7 @@ bar;`,
|
||||
content: `class class2 {}`,
|
||||
};
|
||||
const host = createServerHost([config1, class1, class1Dts, config2, class2, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([class2], session);
|
||||
return { host, session, class1 };
|
||||
}
|
||||
@@ -1479,7 +1475,7 @@ bar;`,
|
||||
solutionBuildWithBaseline(host, [solnConfig.path]);
|
||||
host.clearOutput();
|
||||
}
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([appIndex], session);
|
||||
session.executeCommandSeq<ts.server.protocol.CodeFixRequest>({
|
||||
command: ts.server.protocol.CommandTypes.GetCodeFixes,
|
||||
@@ -1561,7 +1557,7 @@ bar;`,
|
||||
noCoreRef2File,
|
||||
noCoreRef2Config,
|
||||
], { useCaseSensitiveFileNames: true });
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([mainFile, coreFile], session);
|
||||
|
||||
// Find all refs in coreFile
|
||||
@@ -1652,7 +1648,7 @@ const b: B = new B();`,
|
||||
};
|
||||
|
||||
const host = createServerHost([configA, indexA, configB, indexB, helperB, dtsB, ...(dtsMapPresent ? [dtsMapB] : [])]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([indexA, ...(projectAlreadyLoaded ? [helperB] : [])], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.ReferencesRequest>({
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
jsonToReadableText,
|
||||
@@ -9,7 +6,6 @@ import {
|
||||
baselineTsserverLogs,
|
||||
closeFilesForSession,
|
||||
createHostWithSolutionBuild,
|
||||
createSession,
|
||||
openFilesForSession,
|
||||
TestSession,
|
||||
TestSessionRequest,
|
||||
@@ -248,14 +244,14 @@ fn5();
|
||||
}),
|
||||
);
|
||||
onHostCreate?.(host);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
return { host, session };
|
||||
}
|
||||
|
||||
function createSessionWithProjectReferences(onHostCreate?: OnHostCreate) {
|
||||
const host = createHostWithSolutionBuild(files, [mainConfig.path]);
|
||||
onHostCreate?.(host);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
return { host, session };
|
||||
}
|
||||
|
||||
@@ -274,7 +270,7 @@ fn5();
|
||||
}),
|
||||
);
|
||||
onHostCreate?.(host);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
return { host, session };
|
||||
}
|
||||
|
||||
@@ -855,7 +851,7 @@ ${dependencyTs.content}`,
|
||||
|
||||
it("when projects are not built", () => {
|
||||
const host = createServerHost(files);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([mainTs, randomFile], session);
|
||||
verifyAllFnAction(
|
||||
session,
|
||||
@@ -1671,7 +1667,7 @@ ${dependencyTs.content}`,
|
||||
|
||||
it("when projects are not built", () => {
|
||||
const host = createServerHost(files);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([dependencyTs, randomFile], session);
|
||||
verifyAllFnAction(
|
||||
session,
|
||||
@@ -2723,7 +2719,7 @@ ${dependencyTs.content}`,
|
||||
|
||||
it("when projects are not built", () => {
|
||||
const host = createServerHost(files);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([mainTs, dependencyTs, randomFile], session);
|
||||
verifyAllFnAction(
|
||||
session,
|
||||
|
||||
@@ -12,13 +12,13 @@ import {
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
closeFilesForSession,
|
||||
createProjectService,
|
||||
createSession,
|
||||
logConfiguredProjectsHasOpenRefStatus,
|
||||
logInferredProjectsOrphanStatus,
|
||||
openExternalProjectForSession,
|
||||
openFilesForSession,
|
||||
protocolFileLocationFromSubstring,
|
||||
setCompilerOptionsForInferredProjectsRequestForSession,
|
||||
TestSession,
|
||||
TestSessionRequest,
|
||||
toExternalFile,
|
||||
toExternalFiles,
|
||||
@@ -42,7 +42,7 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
let x = y`,
|
||||
};
|
||||
const host = createServerHost([file1, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file1], session);
|
||||
|
||||
// Two errors: CommonFile2 not found and cannot find name y
|
||||
@@ -70,7 +70,7 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
};
|
||||
const files = [commonFile1, commonFile2, configFile];
|
||||
const host = createServerHost(files);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([commonFile1], session);
|
||||
|
||||
configFile.content = `{
|
||||
@@ -105,13 +105,25 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
const proj1name = "proj1", proj2name = "proj2", proj3name = "proj3";
|
||||
|
||||
const host = createServerHost([file1, file2, file3]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
|
||||
openExternalProjectForSession({ rootFiles: toExternalFiles([file1.path]), options: {}, projectFileName: proj1name }, session);
|
||||
openExternalProjectForSession({
|
||||
rootFiles: toExternalFiles([file1.path]),
|
||||
options: {},
|
||||
projectFileName: proj1name,
|
||||
}, session);
|
||||
|
||||
openExternalProjectForSession({ rootFiles: toExternalFiles([file2.path]), options: {}, projectFileName: proj2name }, session);
|
||||
openExternalProjectForSession({
|
||||
rootFiles: toExternalFiles([file2.path]),
|
||||
options: {},
|
||||
projectFileName: proj2name,
|
||||
}, session);
|
||||
|
||||
openExternalProjectForSession({ rootFiles: toExternalFiles([file3.path]), options: {}, projectFileName: proj3name }, session);
|
||||
openExternalProjectForSession({
|
||||
rootFiles: toExternalFiles([file3.path]),
|
||||
options: {},
|
||||
projectFileName: proj3name,
|
||||
}, session);
|
||||
baselineTsserverLogs("projects", "should disable features when the files are too large", session);
|
||||
});
|
||||
|
||||
@@ -127,12 +139,16 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
fileSize: 100,
|
||||
};
|
||||
|
||||
const projName = "proj1";
|
||||
const projectFileName = "proj1";
|
||||
|
||||
const host = createServerHost([file1, file2]);
|
||||
const session = createSession(host, { useSingleInferredProject: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession({ host, useSingleInferredProject: true });
|
||||
|
||||
openExternalProjectForSession({ rootFiles: toExternalFiles([file1.path, file2.path]), options: {}, projectFileName: projName }, session);
|
||||
openExternalProjectForSession({
|
||||
rootFiles: toExternalFiles([file1.path, file2.path]),
|
||||
options: {},
|
||||
projectFileName,
|
||||
}, session);
|
||||
|
||||
openFilesForSession([file2], session);
|
||||
baselineTsserverLogs("projects", "should not crash when opening a file in a project with a disabled language service", session);
|
||||
@@ -154,16 +170,24 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
),
|
||||
};
|
||||
|
||||
const externalProjectName = "externalproject";
|
||||
const projectFileName = "externalproject";
|
||||
const host = createServerHost([file1, config1]);
|
||||
const projectService = createProjectService(host, { useSingleInferredProject: true, serverMode: ts.LanguageServiceMode.Syntactic, logger: createLoggerWithInMemoryLogs(host) });
|
||||
projectService.openExternalProject({
|
||||
rootFiles: toExternalFiles([file1.path, config1.path]),
|
||||
options: {},
|
||||
projectFileName: externalProjectName,
|
||||
});
|
||||
|
||||
baselineTsserverLogs("projects", "external project including config file", projectService);
|
||||
const session = new TestSession({ host, useSingleInferredProject: true, serverMode: ts.LanguageServiceMode.Syntactic });
|
||||
const request: ts.server.protocol.OpenExternalProjectRequest = {
|
||||
command: ts.server.protocol.CommandTypes.OpenExternalProject,
|
||||
arguments: {
|
||||
rootFiles: toExternalFiles([file1.path, config1.path]),
|
||||
options: {},
|
||||
projectFileName,
|
||||
},
|
||||
seq: session.getNextSeq(),
|
||||
type: "request",
|
||||
};
|
||||
session.host.baselineHost("Before request");
|
||||
session.logger.info(`request:${ts.server.stringifyIndented(request)}`);
|
||||
session.getProjectService().openExternalProject(request.arguments);
|
||||
session.host.baselineHost("After request");
|
||||
baselineTsserverLogs("projects", "external project including config file", session);
|
||||
});
|
||||
|
||||
it("loose file included in config file (openClientFile)", () => {
|
||||
@@ -182,9 +206,9 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
};
|
||||
|
||||
const host = createServerHost([file1, config1]);
|
||||
const projectService = createProjectService(host, { useSingleInferredProject: true, serverMode: ts.LanguageServiceMode.Syntactic, logger: createLoggerWithInMemoryLogs(host) });
|
||||
projectService.openClientFile(file1.path, file1.content);
|
||||
baselineTsserverLogs("projects", "loose file included in config file (openClientFile)", projectService);
|
||||
const session = new TestSession({ host, useSingleInferredProject: true, serverMode: ts.LanguageServiceMode.Syntactic });
|
||||
openFilesForSession([{ file: file1, content: file1.content }], session);
|
||||
baselineTsserverLogs("projects", "loose file included in config file (openClientFile)", session);
|
||||
});
|
||||
|
||||
it("loose file included in config file (applyCodeChanges)", () => {
|
||||
@@ -203,10 +227,15 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
};
|
||||
|
||||
const host = createServerHost([file1, config1]);
|
||||
const projectService = createProjectService(host, { useSingleInferredProject: true, serverMode: ts.LanguageServiceMode.Syntactic, logger: createLoggerWithInMemoryLogs(host) });
|
||||
projectService.applyChangesInOpenFiles(ts.singleIterator({ fileName: file1.path, content: file1.content }));
|
||||
const session = new TestSession({ host, useSingleInferredProject: true, serverMode: ts.LanguageServiceMode.Syntactic });
|
||||
session.executeCommandSeq<ts.server.protocol.ApplyChangedToOpenFilesRequest>({
|
||||
command: ts.server.protocol.CommandTypes.ApplyChangedToOpenFiles,
|
||||
arguments: {
|
||||
openFiles: [{ fileName: file1.path, content: file1.content }],
|
||||
},
|
||||
});
|
||||
|
||||
baselineTsserverLogs("projects", "loose file included in config file (applyCodeChanges)", projectService);
|
||||
baselineTsserverLogs("projects", "loose file included in config file (applyCodeChanges)", session);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -221,8 +250,12 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
};
|
||||
|
||||
const host = createServerHost([f1, f2, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
openExternalProjectForSession({ projectFileName: "/a/b/project", rootFiles: toExternalFiles([f1.path, f2.path]), options: {} }, session);
|
||||
const session = new TestSession(host);
|
||||
openExternalProjectForSession({
|
||||
projectFileName: "/a/b/project",
|
||||
rootFiles: toExternalFiles([f1.path, f2.path]),
|
||||
options: {},
|
||||
}, session);
|
||||
|
||||
openFilesForSession([f1, { file: f2.path, content: "let x: string" }], session);
|
||||
// should contain completions for string
|
||||
@@ -251,8 +284,12 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
};
|
||||
|
||||
const host = createServerHost([f1, f2, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
openExternalProjectForSession({ projectFileName: "/a/b/project", rootFiles: [{ fileName: f1.path }, { fileName: f2.path, hasMixedContent: true }], options: {} }, session);
|
||||
const session = new TestSession(host);
|
||||
openExternalProjectForSession({
|
||||
projectFileName: "/a/b/project",
|
||||
rootFiles: [{ fileName: f1.path }, { fileName: f2.path, hasMixedContent: true }],
|
||||
options: {},
|
||||
}, session);
|
||||
openFilesForSession([f1, { file: f2.path, content: "let somelongname: string" }], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.CompletionsRequest>({
|
||||
@@ -282,16 +319,14 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
content: `export let y = 1;`,
|
||||
};
|
||||
const host = createServerHost([file1, file2, file3]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
|
||||
projectService.openClientFile(file1.path);
|
||||
|
||||
projectService.openClientFile(file3.path);
|
||||
openFilesForSession([file1, file3], session);
|
||||
|
||||
host.writeFile(file2.path, `export * from "../c/f3"`); // now inferred project should inclule file3
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
logInferredProjectsOrphanStatus(projectService);
|
||||
baselineTsserverLogs("projects", "changes in closed files are reflected in project structure", projectService);
|
||||
logInferredProjectsOrphanStatus(session);
|
||||
baselineTsserverLogs("projects", "changes in closed files are reflected in project structure", session);
|
||||
});
|
||||
|
||||
it("deleted files affect project structure", () => {
|
||||
@@ -308,14 +343,13 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
content: `export let y = 1;`,
|
||||
};
|
||||
const host = createServerHost([file1, file2, file3]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
|
||||
projectService.openClientFile(file1.path);
|
||||
projectService.openClientFile(file3.path);
|
||||
openFilesForSession([file1, file3], session);
|
||||
|
||||
host.deleteFile(file2.path);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
baselineTsserverLogs("projects", "deleted files affect project structure", projectService);
|
||||
baselineTsserverLogs("projects", "deleted files affect project structure", session);
|
||||
});
|
||||
|
||||
it("ignores files excluded by a custom safe type list", () => {
|
||||
@@ -328,15 +362,19 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
content: "whoa do @@ not parse me ok thanks!!!",
|
||||
};
|
||||
const host = createServerHost([file1, office, customTypesMap]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
try {
|
||||
projectService.openExternalProject({ projectFileName: "project", options: {}, rootFiles: toExternalFiles([file1.path, office.path]) });
|
||||
projectService.logger.log(`TypeAcquisition:: ${jsonToReadableText(projectService.externalProjects[0].getTypeAcquisition())}`);
|
||||
openExternalProjectForSession({
|
||||
projectFileName: "project",
|
||||
options: {},
|
||||
rootFiles: toExternalFiles([file1.path, office.path]),
|
||||
}, session);
|
||||
session.logger.log(`TypeAcquisition:: ${jsonToReadableText(session.getProjectService().externalProjects[0].getTypeAcquisition())}`);
|
||||
}
|
||||
finally {
|
||||
projectService.resetSafeList();
|
||||
session.getProjectService().resetSafeList();
|
||||
}
|
||||
baselineTsserverLogs("projects", "ignores files excluded by a custom safe type list", projectService);
|
||||
baselineTsserverLogs("projects", "ignores files excluded by a custom safe type list", session);
|
||||
});
|
||||
|
||||
it("file with name constructor.js doesnt cause issue with typeAcquisition when safe type list", () => {
|
||||
@@ -353,50 +391,15 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
content: "export function is() { return true; }",
|
||||
};
|
||||
const host = createServerHost([file1, libFile, constructorFile, bliss, customTypesMap]);
|
||||
let request: string | undefined;
|
||||
const cachePath = "/a/data";
|
||||
const typingsInstaller: ts.server.ITypingsInstaller = {
|
||||
isKnownTypesPackageName: ts.returnFalse,
|
||||
installPackage: ts.notImplemented,
|
||||
enqueueInstallTypingsRequest: (proj, typeAcquisition, unresolvedImports) => {
|
||||
assert.isUndefined(request);
|
||||
request = jsonToReadableText(ts.server.createInstallTypingsRequest(proj, typeAcquisition, unresolvedImports || ts.server.emptyArray, cachePath));
|
||||
},
|
||||
attach: ts.noop,
|
||||
onProjectClosed: ts.noop,
|
||||
globalTypingsCacheLocation: cachePath,
|
||||
};
|
||||
const projectFileName = "project";
|
||||
const session = new TestSession(host);
|
||||
openExternalProjectForSession({
|
||||
projectFileName,
|
||||
options: {},
|
||||
rootFiles: toExternalFiles([file1.path, constructorFile.path, bliss.path]),
|
||||
}, session);
|
||||
|
||||
const projectName = "project";
|
||||
const projectService = createProjectService(host, { typingsInstaller, logger: createLoggerWithInMemoryLogs(host) });
|
||||
projectService.openExternalProject({ projectFileName: projectName, options: {}, rootFiles: toExternalFiles([file1.path, constructorFile.path, bliss.path]) });
|
||||
assert.equal(
|
||||
request,
|
||||
jsonToReadableText({
|
||||
projectName,
|
||||
fileNames: [libFile.path, file1.path, constructorFile.path, bliss.path],
|
||||
compilerOptions: { allowNonTsExtensions: true, noEmitForJsFiles: true },
|
||||
typeAcquisition: { include: ["blissfuljs"], exclude: [], enable: true },
|
||||
unresolvedImports: ["s"],
|
||||
projectRootPath: "/",
|
||||
cachePath,
|
||||
kind: "discover",
|
||||
}),
|
||||
);
|
||||
const response = JSON.parse(request!);
|
||||
request = undefined;
|
||||
projectService.updateTypingsForProject({
|
||||
kind: "action::set",
|
||||
projectName: response.projectName,
|
||||
typeAcquisition: response.typeAcquisition,
|
||||
compilerOptions: response.compilerOptions,
|
||||
typings: ts.emptyArray,
|
||||
unresolvedImports: response.unresolvedImports,
|
||||
});
|
||||
|
||||
projectService.testhost.logTimeoutQueueLength();
|
||||
assert.isUndefined(request);
|
||||
baselineTsserverLogs("projects", "file with name constructor.js doesnt cause issue with typeAcquisition when safe type list", projectService);
|
||||
baselineTsserverLogs("projects", "file with name constructor.js doesnt cause issue with typeAcquisition when safe type list", session);
|
||||
});
|
||||
|
||||
it("ignores files excluded by the default type list", () => {
|
||||
@@ -430,15 +433,19 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
};
|
||||
const files = [file1, minFile, kendoFile1, kendoFile2, kendoFile3, officeFile1, officeFile2];
|
||||
const host = createServerHost(files);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
try {
|
||||
projectService.openExternalProject({ projectFileName: "project", options: {}, rootFiles: toExternalFiles(files.map(f => f.path)) });
|
||||
projectService.logger.log(`TypeAcquisition:: ${jsonToReadableText(projectService.externalProjects[0].getTypeAcquisition())}`);
|
||||
openExternalProjectForSession({
|
||||
projectFileName: "project",
|
||||
options: {},
|
||||
rootFiles: toExternalFiles(files.map(f => f.path)),
|
||||
}, session);
|
||||
session.logger.log(`TypeAcquisition:: ${jsonToReadableText(session.getProjectService().externalProjects[0].getTypeAcquisition())}`);
|
||||
}
|
||||
finally {
|
||||
projectService.resetSafeList();
|
||||
session.getProjectService().resetSafeList();
|
||||
}
|
||||
baselineTsserverLogs("projects", "ignores files excluded by the default type list", projectService);
|
||||
baselineTsserverLogs("projects", "ignores files excluded by the default type list", session);
|
||||
});
|
||||
|
||||
it("removes version numbers correctly", () => {
|
||||
@@ -471,14 +478,19 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
content: "let y = 5",
|
||||
};
|
||||
const host = createServerHost([file1, file2, file3, customTypesMap]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
try {
|
||||
projectService.openExternalProject({ projectFileName: "project", options: {}, rootFiles: toExternalFiles([file1.path, file2.path]), typeAcquisition: { enable: true } });
|
||||
openExternalProjectForSession({
|
||||
projectFileName: "project",
|
||||
options: {},
|
||||
rootFiles: toExternalFiles([file1.path, file2.path]),
|
||||
typeAcquisition: { enable: true },
|
||||
}, session);
|
||||
}
|
||||
finally {
|
||||
projectService.resetSafeList();
|
||||
session.getProjectService().resetSafeList();
|
||||
}
|
||||
baselineTsserverLogs("projects", "ignores files excluded by a legacy safe type list", projectService);
|
||||
baselineTsserverLogs("projects", "ignores files excluded by a legacy safe type list", session);
|
||||
});
|
||||
|
||||
it("correctly migrate files between projects", () => {
|
||||
@@ -497,49 +509,48 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
content: "export let y = 1;",
|
||||
};
|
||||
const host = createServerHost([file1, file2, file3]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
|
||||
projectService.openClientFile(file2.path);
|
||||
logInferredProjectsOrphanStatus(projectService);
|
||||
openFilesForSession([file2], session);
|
||||
logInferredProjectsOrphanStatus(session);
|
||||
|
||||
projectService.openClientFile(file3.path);
|
||||
logInferredProjectsOrphanStatus(projectService);
|
||||
openFilesForSession([file3], session);
|
||||
logInferredProjectsOrphanStatus(session);
|
||||
|
||||
projectService.openClientFile(file1.path);
|
||||
logInferredProjectsOrphanStatus(projectService);
|
||||
openFilesForSession([file1], session);
|
||||
logInferredProjectsOrphanStatus(session);
|
||||
|
||||
projectService.closeClientFile(file1.path);
|
||||
logInferredProjectsOrphanStatus(projectService);
|
||||
closeFilesForSession([file1], session);
|
||||
logInferredProjectsOrphanStatus(session);
|
||||
|
||||
projectService.closeClientFile(file3.path);
|
||||
logInferredProjectsOrphanStatus(projectService);
|
||||
closeFilesForSession([file3], session);
|
||||
logInferredProjectsOrphanStatus(session);
|
||||
|
||||
projectService.openClientFile(file3.path);
|
||||
logInferredProjectsOrphanStatus(projectService);
|
||||
baselineTsserverLogs("projects", "correctly migrate files between projects", projectService);
|
||||
openFilesForSession([file3], session);
|
||||
logInferredProjectsOrphanStatus(session);
|
||||
baselineTsserverLogs("projects", "correctly migrate files between projects", session);
|
||||
});
|
||||
|
||||
it("regression test for crash in acquireOrUpdateDocument", () => {
|
||||
const tsFile = {
|
||||
fileName: "/a/b/file1.ts",
|
||||
path: "/a/b/file1.ts",
|
||||
content: "",
|
||||
};
|
||||
const jsFile = {
|
||||
path: "/a/b/file1.js",
|
||||
content: "var x = 10;",
|
||||
fileName: "/a/b/file1.js",
|
||||
scriptKind: "JS" as const,
|
||||
};
|
||||
|
||||
const host = createServerHost([]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
projectService.applyChangesInOpenFiles(ts.singleIterator(tsFile));
|
||||
const projs = projectService.synchronizeProjectList([]);
|
||||
projectService.findProject(projs[0].info!.projectName)!.getLanguageService().getNavigationBarItems(tsFile.fileName);
|
||||
projectService.synchronizeProjectList([projs[0].info!]);
|
||||
projectService.applyChangesInOpenFiles(ts.singleIterator(jsFile));
|
||||
baselineTsserverLogs("projects", "regression test for crash in acquireOrUpdateDocument", projectService);
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession(["/a/b/file1.ts"], session);
|
||||
const projs = session.executeCommandSeq<ts.server.protocol.SynchronizeProjectListRequest>({
|
||||
command: ts.server.protocol.CommandTypes.SynchronizeProjectList,
|
||||
arguments: { knownProjects: [] },
|
||||
}).response as ts.server.protocol.ProjectFilesWithDiagnostics[];
|
||||
session.executeCommandSeq<ts.server.protocol.NavBarRequest>({
|
||||
command: ts.server.protocol.CommandTypes.NavBar,
|
||||
arguments: { file: "/a/b/file1.ts" },
|
||||
});
|
||||
session.executeCommandSeq<ts.server.protocol.SynchronizeProjectListRequest>({
|
||||
command: ts.server.protocol.CommandTypes.SynchronizeProjectList,
|
||||
arguments: {
|
||||
knownProjects: projs.map(p => p.info!),
|
||||
},
|
||||
});
|
||||
openFilesForSession([{ file: "/a/b/file1.js", content: "var x = 10;" }], session);
|
||||
baselineTsserverLogs("projects", "regression test for crash in acquireOrUpdateDocument", session);
|
||||
});
|
||||
|
||||
it("config file is deleted", () => {
|
||||
@@ -556,15 +567,13 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
content: jsonToReadableText({ compilerOptions: {} }),
|
||||
};
|
||||
const host = createServerHost([file1, file2, config]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
|
||||
projectService.openClientFile(file1.path);
|
||||
|
||||
projectService.openClientFile(file2.path);
|
||||
openFilesForSession([file1, file2], session);
|
||||
|
||||
host.deleteFile(config.path);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
baselineTsserverLogs("projects", "config file is deleted", projectService);
|
||||
baselineTsserverLogs("projects", "config file is deleted", session);
|
||||
});
|
||||
|
||||
it("loading files with correct priority", () => {
|
||||
@@ -587,23 +596,26 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
}),
|
||||
};
|
||||
const host = createServerHost([f1, f2, f3, config]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
projectService.setHostConfiguration({
|
||||
extraFileExtensions: [
|
||||
{ extension: ".js", isMixedContent: false },
|
||||
{ extension: ".html", isMixedContent: true },
|
||||
],
|
||||
const session = new TestSession(host);
|
||||
session.executeCommandSeq<ts.server.protocol.ConfigureRequest>({
|
||||
command: ts.server.protocol.CommandTypes.Configure,
|
||||
arguments: {
|
||||
extraFileExtensions: [
|
||||
{ extension: ".js", isMixedContent: false },
|
||||
{ extension: ".html", isMixedContent: true },
|
||||
],
|
||||
},
|
||||
});
|
||||
projectService.openClientFile(f1.path);
|
||||
openFilesForSession([f1], session);
|
||||
|
||||
// Since f2 refers to config file as the default project, it needs to be kept alive
|
||||
projectService.closeClientFile(f1.path);
|
||||
projectService.openClientFile(f2.path);
|
||||
closeFilesForSession([f1], session);
|
||||
openFilesForSession([f2], session);
|
||||
|
||||
// Should close configured project with next file open
|
||||
projectService.closeClientFile(f2.path);
|
||||
projectService.openClientFile(f3.path);
|
||||
baselineTsserverLogs("projects", "loading files with correct priority", projectService);
|
||||
closeFilesForSession([f2], session);
|
||||
openFilesForSession([f3], session);
|
||||
baselineTsserverLogs("projects", "loading files with correct priority", session);
|
||||
});
|
||||
|
||||
it("tsconfig script block support", () => {
|
||||
@@ -620,10 +632,9 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
content: jsonToReadableText({ compilerOptions: { allowJs: true } }),
|
||||
};
|
||||
const host = createServerHost([file1, file2, config]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
// HTML file will not be included in any projects yet
|
||||
openFilesForSession([file1], session);
|
||||
const projectService = session.getProjectService();
|
||||
|
||||
// Specify .html extension as mixed content
|
||||
const extraFileExtensions = [{ extension: ".html", scriptKind: ts.ScriptKind.JS, isMixedContent: true }];
|
||||
@@ -634,12 +645,17 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
});
|
||||
|
||||
// Open HTML file
|
||||
projectService.applyChangesInOpenFiles(ts.singleIterator({
|
||||
fileName: file2.path,
|
||||
hasMixedContent: true,
|
||||
scriptKind: ts.ScriptKind.JS,
|
||||
content: `var hello = "hello";`,
|
||||
}));
|
||||
session.executeCommandSeq<ts.server.protocol.ApplyChangedToOpenFilesRequest>({
|
||||
command: ts.server.protocol.CommandTypes.ApplyChangedToOpenFiles,
|
||||
arguments: {
|
||||
openFiles: [{
|
||||
fileName: file2.path,
|
||||
hasMixedContent: true,
|
||||
scriptKind: "JS",
|
||||
content: `var hello = "hello";`,
|
||||
}],
|
||||
},
|
||||
});
|
||||
// Now HTML file is included in the project
|
||||
|
||||
// Check identifiers defined in HTML content are available in .ts file
|
||||
@@ -654,11 +670,12 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
});
|
||||
|
||||
// Close HTML file
|
||||
projectService.applyChangesInOpenFiles(
|
||||
/*openFiles*/ undefined,
|
||||
/*changedFiles*/ undefined,
|
||||
/*closedFiles*/ [file2.path],
|
||||
);
|
||||
session.executeCommandSeq<ts.server.protocol.ApplyChangedToOpenFilesRequest>({
|
||||
command: ts.server.protocol.CommandTypes.ApplyChangedToOpenFiles,
|
||||
arguments: {
|
||||
closedFiles: [file2.path],
|
||||
},
|
||||
});
|
||||
|
||||
// HTML file is still included in project
|
||||
|
||||
@@ -731,7 +748,7 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
function verfiy(config: File, host: TestServerHost) {
|
||||
logger.host = host;
|
||||
logger.log(`currentDirectory:: ${host.getCurrentDirectory()} useCaseSensitiveFileNames: ${host.useCaseSensitiveFileNames}`);
|
||||
const session = createSession(host, { logger });
|
||||
const session = new TestSession({ host, logger });
|
||||
session.executeCommandSeq<ts.server.protocol.ConfigureRequest>({
|
||||
command: ts.server.protocol.CommandTypes.Configure,
|
||||
arguments: { extraFileExtensions },
|
||||
@@ -758,19 +775,21 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
content: "export let x = 1",
|
||||
};
|
||||
const host = createServerHost([file1, file2]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file1, file2], session);
|
||||
|
||||
projectService.openClientFile(file1.path);
|
||||
projectService.openClientFile(file2.path);
|
||||
session.executeCommandSeq<ts.server.protocol.ApplyChangedToOpenFilesRequest>({
|
||||
command: ts.server.protocol.CommandTypes.ApplyChangedToOpenFiles,
|
||||
arguments: {
|
||||
changedFiles: [{
|
||||
fileName: file1.path,
|
||||
changes: [{ span: ts.createTextSpan(0, file1.path.length), newText: "let y = 1" }],
|
||||
}],
|
||||
},
|
||||
});
|
||||
|
||||
projectService.applyChangesInOpenFiles(
|
||||
/*openFiles*/ undefined,
|
||||
/*changedFiles*/ ts.singleIterator({ fileName: file1.path, changes: ts.singleIterator({ span: ts.createTextSpan(0, file1.path.length), newText: "let y = 1" }) }),
|
||||
/*closedFiles*/ undefined,
|
||||
);
|
||||
|
||||
projectService.ensureInferredProjectsUpToDate_TestOnly();
|
||||
baselineTsserverLogs("projects", "project structure update is deferred if files are not added or removed", projectService);
|
||||
session.getProjectService().ensureInferredProjectsUpToDate_TestOnly();
|
||||
baselineTsserverLogs("projects", "project structure update is deferred if files are not added or removed", session);
|
||||
});
|
||||
|
||||
it("files with mixed content are handled correctly", () => {
|
||||
@@ -779,29 +798,37 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
content: `<html><script language="javascript">var x = 1;</></html>`,
|
||||
};
|
||||
const host = createServerHost([file1]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
const projectFileName = "projectFileName";
|
||||
projectService.openExternalProject({ projectFileName, options: {}, rootFiles: [{ fileName: file1.path, scriptKind: ts.ScriptKind.JS, hasMixedContent: true }] });
|
||||
openExternalProjectForSession({
|
||||
projectFileName,
|
||||
options: {},
|
||||
rootFiles: [{
|
||||
fileName: file1.path,
|
||||
scriptKind: "JS",
|
||||
hasMixedContent: true,
|
||||
}],
|
||||
}, session);
|
||||
|
||||
const project = projectService.externalProjects[0];
|
||||
const project = session.getProjectService().externalProjects[0];
|
||||
|
||||
const scriptInfo = project.getScriptInfo(file1.path)!;
|
||||
const snap = scriptInfo.getSnapshot();
|
||||
const actualText = ts.getSnapshotText(snap);
|
||||
projectService.logger.info(`Text of${file1.path}: ${actualText}`);
|
||||
session.logger.info(`Text of${file1.path}: ${actualText}`);
|
||||
|
||||
projectService.openClientFile(file1.path, `var x = 1;`);
|
||||
project.updateGraph();
|
||||
|
||||
const quickInfo = project.getLanguageService().getQuickInfoAtPosition(file1.path, 4)!;
|
||||
projectService.logger.info(`QuickInfo : ${quickInfo.kind}`);
|
||||
|
||||
projectService.closeClientFile(file1.path);
|
||||
file1.content = `var x = 1;`;
|
||||
openFilesForSession([{ file: file1.path, content: file1.content }], session);
|
||||
session.executeCommandSeq<ts.server.protocol.QuickInfoRequest>({
|
||||
command: ts.server.protocol.CommandTypes.Quickinfo,
|
||||
arguments: protocolFileLocationFromSubstring(file1, "x"),
|
||||
});
|
||||
closeFilesForSession([file1], session);
|
||||
|
||||
const scriptInfo2 = project.getScriptInfo(file1.path)!;
|
||||
const actualText2 = ts.getSnapshotText(scriptInfo2.getSnapshot());
|
||||
projectService.logger.info(`Text of${file1.path}: ${actualText2}`);
|
||||
baselineTsserverLogs("projects", "files with mixed content are handled correctly", projectService);
|
||||
session.logger.info(`Text of${file1.path}: ${actualText2}`);
|
||||
baselineTsserverLogs("projects", "files with mixed content are handled correctly", session);
|
||||
});
|
||||
|
||||
it("syntax tree cache handles changes in project settings", () => {
|
||||
@@ -810,15 +837,38 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
content: "{x: 1}",
|
||||
};
|
||||
const host = createServerHost([file1]);
|
||||
const projectService = createProjectService(host, { useSingleInferredProject: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
projectService.setCompilerOptionsForInferredProjects({ target: ts.ScriptTarget.ES5, allowJs: false });
|
||||
projectService.openClientFile(file1.path);
|
||||
projectService.inferredProjects[0].getLanguageService(/*ensureSynchronized*/ false).getOutliningSpans(file1.path);
|
||||
projectService.setCompilerOptionsForInferredProjects({ target: ts.ScriptTarget.ES5, allowJs: true });
|
||||
projectService.getScriptInfo(file1.path)!.editContent(0, 0, " ");
|
||||
projectService.inferredProjects[0].getLanguageService(/*ensureSynchronized*/ false).getOutliningSpans(file1.path);
|
||||
projectService.closeClientFile(file1.path);
|
||||
baselineTsserverLogs("projects", "syntax tree cache handles changes in project settings", projectService);
|
||||
const session = new TestSession({ host, useSingleInferredProject: true });
|
||||
setCompilerOptionsForInferredProjectsRequestForSession({
|
||||
target: ts.server.protocol.ScriptTarget.ES5,
|
||||
allowJs: false,
|
||||
}, session);
|
||||
openFilesForSession([file1], session);
|
||||
session.executeCommandSeq<ts.server.protocol.OutliningSpansRequest>({
|
||||
command: ts.server.protocol.CommandTypes.GetOutliningSpans,
|
||||
arguments: { file: file1.path },
|
||||
});
|
||||
setCompilerOptionsForInferredProjectsRequestForSession({
|
||||
target: ts.server.protocol.ScriptTarget.ES5,
|
||||
allowJs: true,
|
||||
}, session);
|
||||
session.executeCommandSeq<ts.server.protocol.ApplyChangedToOpenFilesRequest>({
|
||||
command: ts.server.protocol.CommandTypes.ApplyChangedToOpenFiles,
|
||||
arguments: {
|
||||
changedFiles: [{
|
||||
fileName: file1.path,
|
||||
changes: [{
|
||||
span: { start: 0, length: 0 },
|
||||
newText: " ",
|
||||
}],
|
||||
}],
|
||||
},
|
||||
});
|
||||
session.executeCommandSeq<ts.server.protocol.OutliningSpansRequest>({
|
||||
command: ts.server.protocol.CommandTypes.GetOutliningSpans,
|
||||
arguments: { file: file1.path },
|
||||
});
|
||||
closeFilesForSession([file1], session);
|
||||
baselineTsserverLogs("projects", "syntax tree cache handles changes in project settings", session);
|
||||
});
|
||||
|
||||
it("File in multiple projects at opened and closed correctly", () => {
|
||||
@@ -839,23 +889,23 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
content: "{}",
|
||||
};
|
||||
const host = createServerHost([file1, file2, tsconfig1, tsconfig2]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
|
||||
projectService.openClientFile(file2.path);
|
||||
logConfiguredProjectsHasOpenRefStatus(projectService);
|
||||
openFilesForSession([file2], session);
|
||||
logConfiguredProjectsHasOpenRefStatus(session);
|
||||
|
||||
projectService.openClientFile(file1.path);
|
||||
logConfiguredProjectsHasOpenRefStatus(projectService);
|
||||
openFilesForSession([file1], session);
|
||||
logConfiguredProjectsHasOpenRefStatus(session);
|
||||
|
||||
projectService.closeClientFile(file2.path);
|
||||
logConfiguredProjectsHasOpenRefStatus(projectService);
|
||||
closeFilesForSession([file2], session);
|
||||
logConfiguredProjectsHasOpenRefStatus(session);
|
||||
|
||||
projectService.closeClientFile(file1.path);
|
||||
logConfiguredProjectsHasOpenRefStatus(projectService);
|
||||
closeFilesForSession([file1], session);
|
||||
logConfiguredProjectsHasOpenRefStatus(session);
|
||||
|
||||
projectService.openClientFile(file2.path);
|
||||
logConfiguredProjectsHasOpenRefStatus(projectService);
|
||||
baselineTsserverLogs("projects", "File in multiple projects at opened and closed correctly", projectService);
|
||||
openFilesForSession([file2], session);
|
||||
logConfiguredProjectsHasOpenRefStatus(session);
|
||||
baselineTsserverLogs("projects", "File in multiple projects at opened and closed correctly", session);
|
||||
});
|
||||
|
||||
it("snapshot from different caches are incompatible", () => {
|
||||
@@ -865,7 +915,7 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
};
|
||||
const host = createServerHost([f1]);
|
||||
const projectFileName = "/a/b/proj.csproj";
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openExternalProjectForSession({
|
||||
projectFileName,
|
||||
rootFiles: [toExternalFile(f1.path)],
|
||||
@@ -895,7 +945,7 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
content: jsonToReadableText({ compilerOptions: {} }),
|
||||
};
|
||||
const host = createServerHost([f1, libFile, config]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
session.executeCommandSeq({
|
||||
command: ts.server.protocol.CommandTypes.Open,
|
||||
arguments: {
|
||||
@@ -934,10 +984,10 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
};
|
||||
|
||||
const host = createServerHost([file1, configFile], { windowsStyleRoot: "c:/" });
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file1], session);
|
||||
|
||||
projectService.openClientFile(file1.path);
|
||||
baselineTsserverLogs("projects", "Properly handle Windows-style outDir", projectService);
|
||||
baselineTsserverLogs("projects", "Properly handle Windows-style outDir", session);
|
||||
});
|
||||
|
||||
it("files opened and closed affecting multiple projects", () => {
|
||||
@@ -960,7 +1010,7 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
|
||||
const files = [config, file, filesFile1, filesFile2, libFile];
|
||||
const host = createServerHost(files);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
// Create configured project
|
||||
session.executeCommandSeq<ts.server.protocol.OpenRequest>({
|
||||
command: ts.server.protocol.CommandTypes.Open,
|
||||
@@ -1022,7 +1072,7 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
};
|
||||
const files = [file1, file2, libFile, config];
|
||||
const host = createServerHost(files);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
session.executeCommandSeq<ts.server.protocol.OpenRequest>({
|
||||
command: ts.server.protocol.CommandTypes.Open,
|
||||
arguments: { file: file2.path, fileContent: file2.content },
|
||||
@@ -1064,7 +1114,7 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
};
|
||||
|
||||
const host = createServerHost([file1, file2, tsconfig]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
const projectService = session.getProjectService();
|
||||
session.executeCommandSeq<ts.server.protocol.ConfigureRequest>({
|
||||
command: ts.server.protocol.CommandTypes.Configure,
|
||||
@@ -1079,9 +1129,9 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
});
|
||||
|
||||
// Open external project
|
||||
const projectName = "/proj1";
|
||||
const projectFileName = "/proj1";
|
||||
openExternalProjectForSession({
|
||||
projectFileName: projectName,
|
||||
projectFileName,
|
||||
rootFiles: toExternalFiles([file1.path, file2.path, tsconfig.path]),
|
||||
options: {},
|
||||
}, session);
|
||||
@@ -1124,8 +1174,8 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
};
|
||||
const files = [file1, file2, libFile, config];
|
||||
const host = createServerHost(files);
|
||||
const service = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
service.openClientFile(file1.path);
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file1], session);
|
||||
|
||||
const configContent2 = jsonToReadableText({
|
||||
files: ["src/file1.ts"],
|
||||
@@ -1141,11 +1191,11 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
|
||||
verifyFile2InfoIsOrphan();
|
||||
baselineTsserverLogs("projects", "Orphan source files are handled correctly on watch trigger", service);
|
||||
baselineTsserverLogs("projects", "Orphan source files are handled correctly on watch trigger", session);
|
||||
|
||||
function verifyFile2InfoIsOrphan() {
|
||||
const info = ts.Debug.checkDefined(service.getScriptInfoForPath(file2.path as ts.Path));
|
||||
service.logger.log(`Containing projects for ${file2.path}:: ${info.containingProjects.map(p => p.projectName).join(",")}`);
|
||||
const info = ts.Debug.checkDefined(session.getProjectService().getScriptInfoForPath(file2.path as ts.Path));
|
||||
session.logger.log(`Containing projects for ${file2.path}:: ${info.containingProjects.map(p => p.projectName).join(",")}`);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1161,12 +1211,12 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
};
|
||||
const files = [file1, config];
|
||||
const host = createServerHost(files);
|
||||
const service = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
service.openClientFile(file1.path);
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file1], session);
|
||||
|
||||
host.modifyFile(file1.path, file1.content, { invokeFileDeleteCreateAsPartInsteadOfChange: true });
|
||||
service.testhost.logTimeoutQueueLength();
|
||||
baselineTsserverLogs("projects", "no project structure update on directory watch invoke on open file save", service);
|
||||
session.host.baselineHost("After modifying file");
|
||||
baselineTsserverLogs("projects", "no project structure update on directory watch invoke on open file save", session);
|
||||
});
|
||||
|
||||
it("synchronizeProjectList provides redirect info when requested", () => {
|
||||
@@ -1202,7 +1252,7 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
};
|
||||
const files = [fileA, fileB, configA, configB, libFile];
|
||||
const host = createServerHost(files);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([fileA, fileB], session);
|
||||
session.executeCommandSeq<ts.server.protocol.SynchronizeProjectListRequest>({
|
||||
command: ts.server.protocol.CommandTypes.SynchronizeProjectList,
|
||||
@@ -1248,13 +1298,19 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
};
|
||||
const files = [fileA, fileB, fileB2, configA, configB, libFile];
|
||||
const host = createServerHost(files);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([fileA, fileB], session);
|
||||
session.executeCommandSeq<ts.server.protocol.SynchronizeProjectListRequest>({
|
||||
command: ts.server.protocol.CommandTypes.SynchronizeProjectList,
|
||||
arguments: { knownProjects: [], includeProjectReferenceRedirectInfo: true },
|
||||
});
|
||||
const knownProjects = session.getProjectService().synchronizeProjectList([], /*includeProjectReferenceRedirectInfo*/ true);
|
||||
const knownProjects = session.executeCommandSeq<ts.server.protocol.SynchronizeProjectListRequest>({
|
||||
command: ts.server.protocol.CommandTypes.SynchronizeProjectList,
|
||||
arguments: {
|
||||
knownProjects: [],
|
||||
includeProjectReferenceRedirectInfo: true,
|
||||
},
|
||||
}).response as ts.server.protocol.ProjectFilesWithDiagnostics[];
|
||||
|
||||
host.modifyFile(
|
||||
configA.path,
|
||||
@@ -1287,7 +1343,7 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
content: jsonToReadableText({ extends: "./tsconfig_base.json" }),
|
||||
};
|
||||
const host = createServerHost([file, config, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file], session);
|
||||
session.executeCommandSeq<ts.server.protocol.SynchronizeProjectListRequest>({
|
||||
command: ts.server.protocol.CommandTypes.SynchronizeProjectList,
|
||||
@@ -1306,7 +1362,7 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
content: jsonToReadableText({ extends: "./tsconfig_base.json" }),
|
||||
};
|
||||
const host = createServerHost([file, config, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file], session);
|
||||
session.executeCommandSeq<ts.server.protocol.SynchronizeProjectListRequest>({
|
||||
command: ts.server.protocol.CommandTypes.SynchronizeProjectList,
|
||||
@@ -1335,7 +1391,7 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
};
|
||||
const files = [fileSubA, fileB, config, libFile];
|
||||
const host = createServerHost(files);
|
||||
const session = createSession(host, { canUseEvents: true, noGetErrOnBackgroundUpdate: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFile(fileB);
|
||||
openFile(fileSubA);
|
||||
|
||||
@@ -1345,11 +1401,9 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
host.deleteFile(fileSubA.path);
|
||||
host.deleteFolder(ts.getDirectoryPath(fileSubA.path));
|
||||
host.writeFile(fileA.path, fileA.content);
|
||||
session.testhost.logTimeoutQueueLength();
|
||||
|
||||
closeFilesForSession([fileSubA], session);
|
||||
// This should cancel existing updates and schedule new ones
|
||||
session.testhost.logTimeoutQueueLength();
|
||||
|
||||
// Open the fileA (as if rename)
|
||||
// config project is updated to check if fileA is present in it
|
||||
@@ -1362,7 +1416,6 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
const originalFileExists = host.fileExists;
|
||||
host.fileExists = s => s === fileA.path ? false : originalFileExists.call(host, s);
|
||||
closeFilesForSession([fileA], session);
|
||||
session.testhost.logTimeoutQueueLength(); // Update configured project and projects for open file
|
||||
|
||||
// This should create inferred project since fileSubA not on the disk
|
||||
openFile(fileSubA);
|
||||
@@ -1373,7 +1426,6 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
// Actually trigger the file move
|
||||
host.deleteFile(fileA.path);
|
||||
host.ensureFileOrFolder(fileSubA);
|
||||
session.testhost.logTimeoutQueueLength();
|
||||
|
||||
verifyGetErrRequest({ session, files: [fileB, fileSubA], existingTimeouts: true });
|
||||
baselineTsserverLogs("projects", "handles delayed directory watch invoke on file creation", session);
|
||||
@@ -1384,20 +1436,28 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
});
|
||||
|
||||
it("assert when removing project", () => {
|
||||
const host = createServerHost([commonFile1, commonFile2, libFile]);
|
||||
const service = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
service.openClientFile(commonFile1.path);
|
||||
const randomFile: File = { path: "/random/random.ts", content: "export const y = 10;" };
|
||||
const host = createServerHost([commonFile1, commonFile2, randomFile, libFile]);
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([commonFile1], session);
|
||||
const service = session.getProjectService();
|
||||
const project = service.inferredProjects[0];
|
||||
// Intentionally create scriptinfo and attach it to project
|
||||
const info = service.getOrCreateScriptInfoForNormalizedPath(commonFile2.path as ts.server.NormalizedPath, /*openedByClient*/ false)!;
|
||||
info.attachToProject(project);
|
||||
try {
|
||||
service.applyChangesInOpenFiles(/*openFiles*/ undefined, /*changedFiles*/ undefined, [commonFile1.path]);
|
||||
session.executeCommandSeq<ts.server.protocol.ApplyChangedToOpenFilesRequest>({
|
||||
command: ts.server.protocol.CommandTypes.ApplyChangedToOpenFiles,
|
||||
arguments: {
|
||||
openFiles: [{ fileName: randomFile.path }],
|
||||
closedFiles: [commonFile1.path],
|
||||
},
|
||||
});
|
||||
}
|
||||
catch (e) {
|
||||
assert.isTrue(e.message.indexOf("Debug Failure. False expression: Found script Info still attached to project") === 0);
|
||||
}
|
||||
baselineTsserverLogs("projects", "assert when removing project", service);
|
||||
baselineTsserverLogs("projects", "assert when removing project", session);
|
||||
});
|
||||
it("does not look beyond node_modules folders for default configured projects", () => {
|
||||
const rootFilePath = ts.server.asNormalizedPath("/project/index.ts");
|
||||
@@ -1405,25 +1465,17 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
const nodeModulesFilePath1 = ts.server.asNormalizedPath("/project/node_modules/@types/a/index.d.ts");
|
||||
const nodeModulesProjectPath1 = ts.server.asNormalizedPath("/project/node_modules/@types/a/tsconfig.json");
|
||||
const nodeModulesFilePath2 = ts.server.asNormalizedPath("/project/node_modules/@types/b/index.d.ts");
|
||||
const serverHost = createServerHost([
|
||||
const host = createServerHost([
|
||||
{ path: rootFilePath, content: "import 'a'; import 'b';" },
|
||||
{ path: rootProjectPath, content: "{}" },
|
||||
{ path: nodeModulesFilePath1, content: "{}" },
|
||||
{ path: nodeModulesProjectPath1, content: "{}" },
|
||||
{ path: nodeModulesFilePath2, content: "{}" },
|
||||
]);
|
||||
const projectService = createProjectService(serverHost, { useSingleInferredProject: true, logger: createLoggerWithInMemoryLogs(serverHost) });
|
||||
const session = new TestSession({ host, useSingleInferredProject: true });
|
||||
|
||||
const openRootFileResult = projectService.openClientFile(rootFilePath);
|
||||
assert.strictEqual(openRootFileResult.configFileName?.toString(), rootProjectPath);
|
||||
|
||||
const openNodeModulesFileResult1 = projectService.openClientFile(nodeModulesFilePath1);
|
||||
assert.strictEqual(openNodeModulesFileResult1.configFileName?.toString(), nodeModulesProjectPath1);
|
||||
|
||||
const openNodeModulesFileResult2 = projectService.openClientFile(nodeModulesFilePath2);
|
||||
assert.isUndefined(openNodeModulesFileResult2.configFileName);
|
||||
|
||||
baselineTsserverLogs("projects", "does not look beyond node_modules folders for default configured projects", projectService);
|
||||
openFilesForSession([rootFilePath, nodeModulesFilePath1, nodeModulesFilePath2], session);
|
||||
baselineTsserverLogs("projects", "does not look beyond node_modules folders for default configured projects", session);
|
||||
});
|
||||
|
||||
describe("file opened is in configured project that will be removed", () => {
|
||||
@@ -1452,7 +1504,7 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
content: `export function foobar() { }`,
|
||||
};
|
||||
const host = createServerHost([testsConfig, testsFile, innerFile, innerConfig, innerSrcFile, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([testsFile], session);
|
||||
closeFilesForSession([testsFile], session);
|
||||
openFilesForSession([innerFile], session);
|
||||
@@ -1501,7 +1553,7 @@ describe("unittests:: tsserver:: projects::", () => {
|
||||
content: `function fooBar() { }`,
|
||||
};
|
||||
const host = createServerHost([rootConfig, mocksFile, innerFile, innerConfig, innerSrcFile, libFile]);
|
||||
const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([mocksFile], session);
|
||||
closeFilesForSession([mocksFile], session);
|
||||
openFilesForSession([innerFile], session);
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import {
|
||||
jsonToReadableText,
|
||||
} from "../helpers";
|
||||
@@ -9,7 +6,8 @@ import {
|
||||
} from "../helpers/sampleProjectReferences";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createProjectService,
|
||||
openFilesForSession,
|
||||
TestSession,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
createServerHost,
|
||||
@@ -20,9 +18,8 @@ import {
|
||||
describe("unittests:: tsserver:: projects with references: invoking when references are already built", () => {
|
||||
it("on sample project", () => {
|
||||
const host = createServerHost(getFsContentsForSampleProjectReferences());
|
||||
const logger = createLoggerWithInMemoryLogs(host);
|
||||
const service = createProjectService(host, { logger });
|
||||
service.openClientFile("/user/username/projects/sample1/tests/index.ts");
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession(["/user/username/projects/sample1/tests/index.ts"], session);
|
||||
|
||||
// local edit in ts file
|
||||
host.appendFile("/user/username/projects/sample1/logic/index.ts", `function foo() {}`);
|
||||
@@ -41,11 +38,11 @@ describe("unittests:: tsserver:: projects with references: invoking when referen
|
||||
}),
|
||||
);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
baselineTsserverLogs("projectsWithReferences", "sample project", service);
|
||||
baselineTsserverLogs("projectsWithReferences", "sample project", session);
|
||||
});
|
||||
|
||||
describe("on transitive references in different folders", () => {
|
||||
function createService() {
|
||||
function setup() {
|
||||
const aConfig: File = {
|
||||
path: `/user/username/projects/myproject/a/tsconfig.json`,
|
||||
content: jsonToReadableText({
|
||||
@@ -91,22 +88,22 @@ X;`,
|
||||
export class A {}`,
|
||||
};
|
||||
const host = createServerHost([libFile, aConfig, bConfig, cConfig, aTs, bTs, cTs, refsTs]);
|
||||
const service = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
service.openClientFile(cTs.path);
|
||||
return { host, service, aConfig, bConfig, cConfig, aTs, bTs, cTs, refsTs };
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([cTs], session);
|
||||
return { host, session, aConfig, bConfig, cConfig, aTs, bTs, cTs, refsTs };
|
||||
}
|
||||
|
||||
it("non local edit", () => {
|
||||
const { host, service, bTs } = createService();
|
||||
const { host, session, bTs } = setup();
|
||||
|
||||
// non local edit
|
||||
host.appendFile(bTs.path, `export function gFoo() { }`);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
baselineTsserverLogs("projectsWithReferences", "transitive references with non local edit", service);
|
||||
baselineTsserverLogs("projectsWithReferences", "transitive references with non local edit", session);
|
||||
});
|
||||
|
||||
it("edit on config file", () => {
|
||||
const { host, service, cConfig, refsTs } = createService();
|
||||
const { host, session, cConfig, refsTs } = setup();
|
||||
const nRefsTs: File = {
|
||||
path: `/user/username/projects/myproject/nrefs/a.d.ts`,
|
||||
content: refsTs.content,
|
||||
@@ -120,11 +117,11 @@ export class A {}`,
|
||||
// revert the edit on config file
|
||||
host.writeFile(cConfig.path, cConfig.content);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
baselineTsserverLogs("projectsWithReferences", "transitive references with edit on config file", service);
|
||||
baselineTsserverLogs("projectsWithReferences", "transitive references with edit on config file", session);
|
||||
});
|
||||
|
||||
it("edit in referenced config file", () => {
|
||||
const { host, service, bConfig, refsTs } = createService();
|
||||
const { host, session, bConfig, refsTs } = setup();
|
||||
const nRefsTs: File = {
|
||||
path: `/user/username/projects/myproject/nrefs/a.d.ts`,
|
||||
content: refsTs.content,
|
||||
@@ -138,34 +135,34 @@ export class A {}`,
|
||||
// revert the edit on config file
|
||||
host.writeFile(bConfig.path, bConfig.content);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
baselineTsserverLogs("projectsWithReferences", "transitive references with edit in referenced config file", service);
|
||||
baselineTsserverLogs("projectsWithReferences", "transitive references with edit in referenced config file", session);
|
||||
});
|
||||
|
||||
it("deleting referenced config file", () => {
|
||||
const { host, service, bConfig } = createService();
|
||||
const { host, session, bConfig } = setup();
|
||||
host.deleteFile(bConfig.path);
|
||||
host.runQueuedTimeoutCallbacks(); // Schedules failed lookup invalidation
|
||||
|
||||
// revert
|
||||
host.writeFile(bConfig.path, bConfig.content);
|
||||
host.runQueuedTimeoutCallbacks(); // Schedules failed lookup invalidation
|
||||
baselineTsserverLogs("projectsWithReferences", "transitive references with deleting referenced config file", service);
|
||||
baselineTsserverLogs("projectsWithReferences", "transitive references with deleting referenced config file", session);
|
||||
});
|
||||
|
||||
it("deleting transitively referenced config file", () => {
|
||||
const { host, service, aConfig } = createService();
|
||||
const { host, session, aConfig } = setup();
|
||||
host.deleteFile(aConfig.path);
|
||||
host.runQueuedTimeoutCallbacks(); // Schedules failed lookup invalidation
|
||||
|
||||
// revert
|
||||
host.writeFile(aConfig.path, aConfig.content);
|
||||
host.runQueuedTimeoutCallbacks(); // Schedules failed lookup invalidation
|
||||
baselineTsserverLogs("projectsWithReferences", "transitive references with deleting transitively referenced config file", service);
|
||||
baselineTsserverLogs("projectsWithReferences", "transitive references with deleting transitively referenced config file", session);
|
||||
});
|
||||
});
|
||||
|
||||
describe("on transitive references in different folders without files", () => {
|
||||
function createService() {
|
||||
function setup() {
|
||||
const aConfig: File = {
|
||||
path: `/user/username/projects/myproject/a/tsconfig.json`,
|
||||
content: jsonToReadableText({ compilerOptions: { composite: true } }),
|
||||
@@ -206,22 +203,22 @@ X;`,
|
||||
export class A {}`,
|
||||
};
|
||||
const host = createServerHost([libFile, aConfig, bConfig, cConfig, aTs, bTs, cTs, refsTs]);
|
||||
const service = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
service.openClientFile(cTs.path);
|
||||
return { host, service, aConfig, bConfig, cConfig, aTs, bTs, cTs, refsTs };
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([cTs], session);
|
||||
return { host, session, aConfig, bConfig, cConfig, aTs, bTs, cTs, refsTs };
|
||||
}
|
||||
|
||||
it("non local edit", () => {
|
||||
const { host, service, bTs } = createService();
|
||||
const { host, session, bTs } = setup();
|
||||
|
||||
// non local edit
|
||||
host.appendFile(bTs.path, `export function gFoo() { }`);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
baselineTsserverLogs("projectsWithReferences", "trasitive references without files with non local edit", service);
|
||||
baselineTsserverLogs("projectsWithReferences", "trasitive references without files with non local edit", session);
|
||||
});
|
||||
|
||||
it("edit on config file", () => {
|
||||
const { host, service, cConfig, refsTs } = createService();
|
||||
const { host, session, cConfig, refsTs } = setup();
|
||||
const nRefsTs: File = {
|
||||
path: `/user/username/projects/myproject/nrefs/a.d.ts`,
|
||||
content: refsTs.content,
|
||||
@@ -235,11 +232,11 @@ export class A {}`,
|
||||
// revert the edit on config file
|
||||
host.writeFile(cConfig.path, cConfig.content);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
baselineTsserverLogs("projectsWithReferences", "trasitive references without files with edit on config file", service);
|
||||
baselineTsserverLogs("projectsWithReferences", "trasitive references without files with edit on config file", session);
|
||||
});
|
||||
|
||||
it("edit in referenced config file", () => {
|
||||
const { host, service, bConfig, refsTs } = createService();
|
||||
const { host, session, bConfig, refsTs } = setup();
|
||||
const nRefsTs: File = {
|
||||
path: `/user/username/projects/myproject/nrefs/a.d.ts`,
|
||||
content: refsTs.content,
|
||||
@@ -253,29 +250,29 @@ export class A {}`,
|
||||
// revert the edit on config file
|
||||
host.writeFile(bConfig.path, bConfig.content);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
baselineTsserverLogs("projectsWithReferences", "trasitive references without files with edit in referenced config file", service);
|
||||
baselineTsserverLogs("projectsWithReferences", "trasitive references without files with edit in referenced config file", session);
|
||||
});
|
||||
|
||||
it("deleting referenced config file", () => {
|
||||
const { host, service, bConfig } = createService();
|
||||
const { host, session, bConfig } = setup();
|
||||
host.deleteFile(bConfig.path);
|
||||
host.runQueuedTimeoutCallbacks(); // Schedules failed lookup invalidation
|
||||
|
||||
// revert
|
||||
host.writeFile(bConfig.path, bConfig.content);
|
||||
host.runQueuedTimeoutCallbacks(); // Schedules failed lookup invalidation
|
||||
baselineTsserverLogs("projectsWithReferences", "trasitive references without files with deleting referenced config file", service);
|
||||
baselineTsserverLogs("projectsWithReferences", "trasitive references without files with deleting referenced config file", session);
|
||||
});
|
||||
|
||||
it("deleting transitively referenced config file", () => {
|
||||
const { host, service, aConfig } = createService();
|
||||
const { host, session, aConfig } = setup();
|
||||
host.deleteFile(aConfig.path);
|
||||
host.runQueuedTimeoutCallbacks(); // Schedules failed lookup invalidation
|
||||
|
||||
// revert
|
||||
host.writeFile(aConfig.path, aConfig.content);
|
||||
host.runQueuedTimeoutCallbacks(); // Schedules failed lookup invalidation
|
||||
baselineTsserverLogs("projectsWithReferences", "trasitive references without files with deleting transitively referenced config file", service);
|
||||
baselineTsserverLogs("projectsWithReferences", "trasitive references without files with deleting transitively referenced config file", session);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createSession,
|
||||
openFilesForSession,
|
||||
TestSession,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
createServerHost,
|
||||
@@ -19,7 +16,7 @@ describe("unittests:: tsserver:: refactors", () => {
|
||||
content: "function f() {\n 1;\n}",
|
||||
};
|
||||
const host = createServerHost([file]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.ConfigureRequest>({
|
||||
@@ -57,7 +54,7 @@ describe("unittests:: tsserver:: refactors", () => {
|
||||
};
|
||||
|
||||
const host = createServerHost([aTs, tsconfig]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([aTs], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.GetEditsForRefactorRequest>({
|
||||
@@ -79,7 +76,7 @@ describe("unittests:: tsserver:: refactors", () => {
|
||||
const aTs: File = { path: "/Foo/a.ts", content: "const x = 0;" };
|
||||
const tsconfig: File = { path: "/Foo/tsconfig.json", content: '{ "files": ["./a.ts"] }' };
|
||||
const host = createServerHost([aTs, tsconfig]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([aTs], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.GetEditsForRefactorRequest>({
|
||||
@@ -106,7 +103,7 @@ describe("unittests:: tsserver:: refactors", () => {
|
||||
};
|
||||
const tsconfig: File = { path: "/Foo/tsconfig.json", content: `{ "files": ["./a.ts", "./b.ts"] }` };
|
||||
const host = createServerHost([aTs, bTs, tsconfig]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([aTs], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.GetEditsForRefactorRequest>({
|
||||
@@ -139,7 +136,7 @@ describe("unittests:: tsserver:: refactors", () => {
|
||||
content: `{ "files": ["./a.ts"] }`,
|
||||
};
|
||||
const host = createServerHost([aTs, bTxt, tsconfig]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([aTs], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.GetEditsForRefactorRequest>({
|
||||
@@ -181,7 +178,7 @@ describe("unittests:: tsserver:: refactors", () => {
|
||||
content: `{ "files": ["./a.ts"] }`,
|
||||
};
|
||||
const host = createServerHost([fooATs, fooTsconfig, barATs, barTsconfig]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([barATs], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.GetEditsForRefactorRequest>({
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
closeFilesForSession,
|
||||
createSession,
|
||||
logInferredProjectsOrphanStatus,
|
||||
openFilesForSession,
|
||||
TestSession,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
createServerHost,
|
||||
@@ -25,7 +22,7 @@ describe("unittests:: tsserver:: reload", () => {
|
||||
content: "const y = 42",
|
||||
};
|
||||
const host = createServerHost([f1, tmp]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
|
||||
// send open request
|
||||
openFilesForSession([f1], session);
|
||||
@@ -63,13 +60,12 @@ describe("unittests:: tsserver:: reload", () => {
|
||||
content: "const y = 42",
|
||||
};
|
||||
const host = createServerHost([f1, tmp, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
const openContent = "let z = 1";
|
||||
// send open request
|
||||
openFilesForSession([{ file: f1.path, content: openContent }], session);
|
||||
|
||||
const projectService = session.getProjectService();
|
||||
const info = projectService.getScriptInfo(f1.path)!;
|
||||
const info = session.getProjectService().getScriptInfo(f1.path)!;
|
||||
assert.isDefined(info);
|
||||
checkScriptInfoContents("contents set during open request");
|
||||
|
||||
@@ -126,12 +122,12 @@ describe("unittests:: tsserver:: reload", () => {
|
||||
baselineTsserverLogs("reload", "should work when script info doesnt have any project open", session);
|
||||
|
||||
function checkInferredProjectIsOrphan() {
|
||||
logInferredProjectsOrphanStatus(projectService);
|
||||
logInferredProjectsOrphanStatus(session);
|
||||
session.logger.log(`info:: ${info.path}:: ${info.containingProjects.map(p => p.projectName).join(",")}`);
|
||||
}
|
||||
|
||||
function checkScriptInfoAndProjects(captionForContents: string) {
|
||||
assert.strictEqual(projectService.getScriptInfo(f1.path), info);
|
||||
assert.strictEqual(session.getProjectService().getScriptInfo(f1.path), info);
|
||||
checkScriptInfoContents(captionForContents);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
jsonToReadableText,
|
||||
} from "../helpers";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createSession,
|
||||
openExternalProjectForSession,
|
||||
openFilesForSession,
|
||||
setCompilerOptionsForInferredProjectsRequestForSession,
|
||||
@@ -48,14 +44,12 @@ describe("unittests:: tsserver:: reloadProjects", () => {
|
||||
const updatedText = `${file2.content}
|
||||
bar();`;
|
||||
host.writeFile(file2.path, updatedText);
|
||||
session.testhost.logTimeoutQueueLength();
|
||||
session.executeCommandSeq({
|
||||
command: ts.server.protocol.CommandTypes.ReloadProjects,
|
||||
});
|
||||
|
||||
// delete file
|
||||
host.deleteFile(file2.path);
|
||||
session.testhost.logTimeoutQueueLength();
|
||||
session.executeCommandSeq({
|
||||
command: ts.server.protocol.CommandTypes.ReloadProjects,
|
||||
});
|
||||
@@ -63,7 +57,7 @@ describe("unittests:: tsserver:: reloadProjects", () => {
|
||||
|
||||
it("configured project", () => {
|
||||
const host = createServerHost([configFile, libFile, file1, file2]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
session.executeCommandSeq<ts.server.protocol.ConfigureRequest>({
|
||||
command: ts.server.protocol.CommandTypes.Configure,
|
||||
arguments: { watchOptions: { excludeFiles: [file2.path] } },
|
||||
@@ -72,7 +66,6 @@ describe("unittests:: tsserver:: reloadProjects", () => {
|
||||
|
||||
// Install module1
|
||||
host.ensureFileOrFolder(moduleFile);
|
||||
session.testhost.logTimeoutQueueLength();
|
||||
|
||||
session.executeCommandSeq({
|
||||
command: ts.server.protocol.CommandTypes.ReloadProjects,
|
||||
@@ -84,7 +77,7 @@ describe("unittests:: tsserver:: reloadProjects", () => {
|
||||
|
||||
it("inferred project", () => {
|
||||
const host = createServerHost([libFile, file1, file2]);
|
||||
const session = createSession(host, { useInferredProjectPerProjectRoot: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession({ host, useInferredProjectPerProjectRoot: true });
|
||||
session.executeCommandSeq<ts.server.protocol.ConfigureRequest>({
|
||||
command: ts.server.protocol.CommandTypes.Configure,
|
||||
arguments: { watchOptions: { excludeFiles: [file2.path] } },
|
||||
@@ -99,7 +92,6 @@ describe("unittests:: tsserver:: reloadProjects", () => {
|
||||
|
||||
// Install module1
|
||||
host.ensureFileOrFolder(moduleFile);
|
||||
session.testhost.logTimeoutQueueLength();
|
||||
|
||||
session.executeCommandSeq({
|
||||
command: ts.server.protocol.CommandTypes.ReloadProjects,
|
||||
@@ -111,7 +103,7 @@ describe("unittests:: tsserver:: reloadProjects", () => {
|
||||
|
||||
it("external project", () => {
|
||||
const host = createServerHost([libFile, file1, file2]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
session.executeCommandSeq<ts.server.protocol.ConfigureRequest>({
|
||||
command: ts.server.protocol.CommandTypes.Configure,
|
||||
arguments: { watchOptions: { excludeFiles: [file2.path] } },
|
||||
@@ -125,7 +117,6 @@ describe("unittests:: tsserver:: reloadProjects", () => {
|
||||
|
||||
// Install module1
|
||||
host.ensureFileOrFolder(moduleFile);
|
||||
session.testhost.logTimeoutQueueLength();
|
||||
|
||||
session.executeCommandSeq({
|
||||
command: ts.server.protocol.CommandTypes.ReloadProjects,
|
||||
@@ -137,7 +128,7 @@ describe("unittests:: tsserver:: reloadProjects", () => {
|
||||
|
||||
it("external project with config file", () => {
|
||||
const host = createServerHost([libFile, file1, file2, configFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
session.executeCommandSeq<ts.server.protocol.ConfigureRequest>({
|
||||
command: ts.server.protocol.CommandTypes.Configure,
|
||||
arguments: { watchOptions: { excludeFiles: [file2.path] } },
|
||||
@@ -151,7 +142,6 @@ describe("unittests:: tsserver:: reloadProjects", () => {
|
||||
|
||||
// Install module1
|
||||
host.ensureFileOrFolder(moduleFile);
|
||||
session.testhost.logTimeoutQueueLength();
|
||||
|
||||
session.executeCommandSeq({
|
||||
command: ts.server.protocol.CommandTypes.ReloadProjects,
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createSession,
|
||||
openFilesForSession,
|
||||
protocolFileLocationFromSubstring,
|
||||
TestSession,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
createServerHost,
|
||||
@@ -19,7 +16,7 @@ describe("unittests:: tsserver:: rename", () => {
|
||||
const bTs: File = { path: "/b.ts", content: 'import { a } from "./a";' };
|
||||
|
||||
const host = createServerHost([aTs, bTs]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([bTs], session);
|
||||
|
||||
// rename fails with allowRenameOfImportPath disabled
|
||||
@@ -57,7 +54,7 @@ describe("unittests:: tsserver:: rename", () => {
|
||||
it("works with prefixText and suffixText when enabled", () => {
|
||||
const aTs: File = { path: "/a.ts", content: "const x = 0; const o = { x };" };
|
||||
const host = createServerHost([aTs]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([aTs], session);
|
||||
|
||||
// rename with prefixText and suffixText disabled
|
||||
@@ -96,7 +93,7 @@ describe("unittests:: tsserver:: rename", () => {
|
||||
const bTs: File = { path: "/b.ts", content: `import aTest from "./a"; function test() { return aTest(); }` };
|
||||
|
||||
const host = createServerHost([aTs, bTs]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([bTs], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.ConfigureRequest>({
|
||||
@@ -114,7 +111,7 @@ describe("unittests:: tsserver:: rename", () => {
|
||||
const aTs: File = { path: "/a.ts", content: "const x = 1; export { x };" };
|
||||
const bTs: File = { path: "/b.ts", content: `import { x } from "./a"; const y = x + 1;` };
|
||||
const host = createServerHost([aTs, bTs]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([aTs, bTs], session);
|
||||
|
||||
// rename from file with prefixText and suffixText enabled
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import * as Utils from "../../_namespaces/Utils";
|
||||
import {
|
||||
@@ -11,16 +8,13 @@ import {
|
||||
} from "../helpers/contents";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createProjectService,
|
||||
createSession,
|
||||
openExternalProjectForSession,
|
||||
openFilesForSession,
|
||||
setCompilerOptionsForInferredProjectsRequestForSession,
|
||||
TestSession,
|
||||
toExternalFiles,
|
||||
verifyGetErrRequest,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
TestTypingsInstaller,
|
||||
} from "../helpers/typingsInstaller";
|
||||
import {
|
||||
createServerHost,
|
||||
File,
|
||||
@@ -38,15 +32,11 @@ describe("unittests:: tsserver:: resolutionCache:: tsserverProjectSystem extra r
|
||||
content: "export let x = 1",
|
||||
};
|
||||
const host = createServerHost([file1, lib]);
|
||||
const logger = createLoggerWithInMemoryLogs(host);
|
||||
const projectService = createProjectService(host, {
|
||||
typingsInstaller: new TestTypingsInstaller(host, logger, { globalTypingsCacheLocation: "/a/cache" }),
|
||||
logger,
|
||||
});
|
||||
const session = new TestSession({ host, globalTypingsCacheLocation: "/a/cache" });
|
||||
|
||||
projectService.setCompilerOptionsForInferredProjects({ traceResolution: true, allowJs: true });
|
||||
projectService.openClientFile(file1.path);
|
||||
baselineTsserverLogs("resolutionCache", "can load typings that are proper modules", projectService);
|
||||
setCompilerOptionsForInferredProjectsRequestForSession({ traceResolution: true, allowJs: true }, session);
|
||||
openFilesForSession([file1], session);
|
||||
baselineTsserverLogs("resolutionCache", "can load typings that are proper modules", session);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -72,9 +62,9 @@ describe("unittests:: tsserver:: resolutionCache:: tsserverProjectSystem watchin
|
||||
}),
|
||||
};
|
||||
const host = createServerHost([f1, t1, tsconfig]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
|
||||
projectService.openClientFile(f1.path);
|
||||
openFilesForSession([f1], session);
|
||||
|
||||
// delete t1
|
||||
host.deleteFile(t1.path);
|
||||
@@ -86,7 +76,7 @@ describe("unittests:: tsserver:: resolutionCache:: tsserverProjectSystem watchin
|
||||
// run throttled operation
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
|
||||
baselineTsserverLogs("resolutionCache", "works correctly when typings are added or removed", projectService);
|
||||
baselineTsserverLogs("resolutionCache", "works correctly when typings are added or removed", session);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -101,7 +91,7 @@ describe("unittests:: tsserver:: resolutionCache:: tsserverProjectSystem add the
|
||||
content: "import * as T from './moduleFile'; T.bar();",
|
||||
};
|
||||
const host = createServerHost([file1]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file1], session);
|
||||
session.executeCommandSeq<ts.server.protocol.SemanticDiagnosticsSyncRequest>({
|
||||
command: ts.server.protocol.CommandTypes.SemanticDiagnosticsSync,
|
||||
@@ -132,7 +122,7 @@ describe("unittests:: tsserver:: resolutionCache:: tsserverProjectSystem add the
|
||||
content: 'import f = require("pad"); f;',
|
||||
};
|
||||
const host = createServerHost([file1, libFile]);
|
||||
const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
session.executeCommandSeq<ts.server.protocol.OpenRequest>({
|
||||
command: ts.server.protocol.CommandTypes.Open,
|
||||
arguments: {
|
||||
@@ -164,7 +154,7 @@ describe("unittests:: tsserver:: resolutionCache:: tsserverProjectSystem add the
|
||||
};
|
||||
|
||||
const host = createServerHost([file]);
|
||||
const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.OpenRequest>({
|
||||
command: ts.server.protocol.CommandTypes.Open,
|
||||
@@ -182,7 +172,7 @@ describe("unittests:: tsserver:: resolutionCache:: tsserverProjectSystem add the
|
||||
};
|
||||
|
||||
const host = createServerHost([file]);
|
||||
const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.OpenRequest>({
|
||||
command: ts.server.protocol.CommandTypes.Open,
|
||||
@@ -207,14 +197,13 @@ describe("unittests:: tsserver:: resolutionCache:: tsserverProjectSystem add the
|
||||
};
|
||||
|
||||
const host = createServerHost([file]);
|
||||
const session = createSession(host, { canUseEvents: true, suppressDiagnosticEvents: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession({ host, suppressDiagnosticEvents: true });
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.OpenRequest>({
|
||||
command: ts.server.protocol.CommandTypes.Open,
|
||||
arguments: { file: file.path, fileContent: file.content },
|
||||
});
|
||||
|
||||
session.testhost.logTimeoutQueueLength();
|
||||
session.executeCommandSeq<ts.server.protocol.GeterrRequest>({
|
||||
command: ts.server.protocol.CommandTypes.Geterr,
|
||||
arguments: {
|
||||
@@ -223,7 +212,6 @@ describe("unittests:: tsserver:: resolutionCache:: tsserverProjectSystem add the
|
||||
},
|
||||
});
|
||||
|
||||
session.testhost.logTimeoutQueueLength();
|
||||
session.executeCommandSeq<ts.server.protocol.GeterrForProjectRequest>({
|
||||
command: ts.server.protocol.CommandTypes.GeterrForProject,
|
||||
arguments: {
|
||||
@@ -232,7 +220,6 @@ describe("unittests:: tsserver:: resolutionCache:: tsserverProjectSystem add the
|
||||
},
|
||||
});
|
||||
|
||||
session.testhost.logTimeoutQueueLength();
|
||||
baselineTsserverLogs("resolutionCache", "suppressed diagnostic events", session);
|
||||
});
|
||||
});
|
||||
@@ -248,7 +235,7 @@ describe("unittests:: tsserver:: resolutionCache:: tsserverProjectSystem rename
|
||||
content: "import * as T from './moduleFile'; T.bar();",
|
||||
};
|
||||
const host = createServerHost([moduleFile, file1]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
|
||||
openFilesForSession([file1], session);
|
||||
session.executeCommandSeq<ts.server.protocol.SemanticDiagnosticsSyncRequest>({
|
||||
@@ -295,7 +282,7 @@ describe("unittests:: tsserver:: resolutionCache:: tsserverProjectSystem rename
|
||||
content: `{}`,
|
||||
};
|
||||
const host = createServerHost([moduleFile, file1, configFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
|
||||
openFilesForSession([file1], session);
|
||||
session.executeCommandSeq<ts.server.protocol.SemanticDiagnosticsSyncRequest>({
|
||||
@@ -329,15 +316,23 @@ describe("unittests:: tsserver:: resolutionCache:: tsserverProjectSystem rename
|
||||
path: "/a/b/tsconfig.json",
|
||||
content: "{}",
|
||||
};
|
||||
const projectName = "project1";
|
||||
const projectFileName = "project1";
|
||||
const host = createServerHost([f1]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
openExternalProjectForSession({ rootFiles: toExternalFiles([f1.path, config.path]), options: {}, projectFileName: projectName }, session);
|
||||
const session = new TestSession(host);
|
||||
openExternalProjectForSession({
|
||||
rootFiles: toExternalFiles([f1.path, config.path]),
|
||||
options: {},
|
||||
projectFileName,
|
||||
}, session);
|
||||
|
||||
// should have one external project since config file is missing
|
||||
|
||||
host.writeFile(config.path, config.content);
|
||||
openExternalProjectForSession({ rootFiles: toExternalFiles([f1.path, config.path]), options: {}, projectFileName: projectName }, session);
|
||||
openExternalProjectForSession({
|
||||
rootFiles: toExternalFiles([f1.path, config.path]),
|
||||
options: {},
|
||||
projectFileName,
|
||||
}, session);
|
||||
baselineTsserverLogs("resolutionCache", "should property handle missing config files", session);
|
||||
});
|
||||
|
||||
@@ -360,9 +355,9 @@ describe("unittests:: tsserver:: resolutionCache:: tsserverProjectSystem rename
|
||||
path: "/a/c",
|
||||
};
|
||||
const host = createServerHost([f1, config, node, cwd], { currentDirectory: cwd.path });
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
projectService.openClientFile(f1.path);
|
||||
baselineTsserverLogs("resolutionCache", subScenario, projectService);
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([f1], session);
|
||||
baselineTsserverLogs("resolutionCache", subScenario, session);
|
||||
});
|
||||
}
|
||||
verifyTypesLoad("types should load from config file path if config exists", /*includeTypeRoots*/ false);
|
||||
@@ -407,14 +402,13 @@ describe("unittests:: tsserver:: resolutionCache:: tsserverProjectSystem module
|
||||
const { module1, module2 } = getModules(`/user/username/projects/myproject/src/module1.ts`, `/user/username/projects/myproject/module2.ts`);
|
||||
const files = [module1, module2, file1, file2, configFile, libFile];
|
||||
const host = createServerHost(files);
|
||||
const service = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
service.openClientFile(file1.path);
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file1], session);
|
||||
|
||||
host.writeFile(file1.path, file1.content + fileContent);
|
||||
host.writeFile(file2.path, file2.content + fileContent);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
|
||||
baselineTsserverLogs("resolutionCache", "relative module name from files in same folder", service);
|
||||
baselineTsserverLogs("resolutionCache", "relative module name from files in same folder", session);
|
||||
});
|
||||
|
||||
it("non relative module name", () => {
|
||||
@@ -423,13 +417,12 @@ describe("unittests:: tsserver:: resolutionCache:: tsserverProjectSystem module
|
||||
const { module1, module2 } = getModules(`/user/username/projects/myproject/src/node_modules/module1/index.ts`, `/user/username/projects/myproject/node_modules/module2/index.ts`);
|
||||
const files = [module1, module2, file1, file2, configFile, libFile];
|
||||
const host = createServerHost(files);
|
||||
const service = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
service.openClientFile(file1.path);
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file1], session);
|
||||
|
||||
host.writeFile(file1.path, file1.content + fileContent);
|
||||
host.writeFile(file2.path, file2.content + fileContent);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
baselineTsserverLogs("resolutionCache", "non relative module name from files in same folder", service);
|
||||
baselineTsserverLogs("resolutionCache", "non relative module name from files in same folder", session);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -463,15 +456,14 @@ describe("unittests:: tsserver:: resolutionCache:: tsserverProjectSystem module
|
||||
const { module1, module2 } = getModules(`/user/username/projects/myproject/product/src/module1.ts`, `/user/username/projects/myproject/product/module2.ts`);
|
||||
const files = [module1, module2, file1, file2, file3, file4, configFile, libFile];
|
||||
const host = createServerHost(files);
|
||||
const service = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
service.openClientFile(file1.path);
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file1], session);
|
||||
|
||||
host.writeFile(file1.path, file1.content + fileContent1);
|
||||
host.writeFile(file2.path, file2.content + fileContent2);
|
||||
host.writeFile(file3.path, file3.content + fileContent3);
|
||||
host.writeFile(file4.path, file4.content + fileContent4);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
baselineTsserverLogs("resolutionCache", "relative module name from files in different folders", service);
|
||||
baselineTsserverLogs("resolutionCache", "relative module name from files in different folders", session);
|
||||
});
|
||||
|
||||
it("non relative module name", () => {
|
||||
@@ -480,15 +472,14 @@ describe("unittests:: tsserver:: resolutionCache:: tsserverProjectSystem module
|
||||
const { module1, module2 } = getModules(`/user/username/projects/myproject/product/node_modules/module1/index.ts`, `/user/username/projects/myproject/node_modules/module2/index.ts`);
|
||||
const files = [module1, module2, file1, file2, file3, file4, configFile, libFile];
|
||||
const host = createServerHost(files);
|
||||
const service = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
service.openClientFile(file1.path);
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file1], session);
|
||||
|
||||
host.writeFile(file1.path, file1.content + fileContent);
|
||||
host.writeFile(file2.path, file2.content + fileContent);
|
||||
host.writeFile(file3.path, file3.content + fileContent);
|
||||
host.writeFile(file4.path, file4.content + fileContent);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
baselineTsserverLogs("resolutionCache", "non relative module name from files in different folders", service);
|
||||
baselineTsserverLogs("resolutionCache", "non relative module name from files in different folders", session);
|
||||
});
|
||||
|
||||
it("non relative module name from inferred project", () => {
|
||||
@@ -502,15 +493,14 @@ describe("unittests:: tsserver:: resolutionCache:: tsserverProjectSystem module
|
||||
const { module1, module2 } = getModules(`/user/username/projects/myproject/product/node_modules/module1/index.ts`, `/user/username/projects/myproject/node_modules/module2/index.ts`);
|
||||
const files = [module1, module2, file1, file2, file3, file4, libFile];
|
||||
const host = createServerHost(files);
|
||||
const service = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
service.setCompilerOptionsForInferredProjects({ traceResolution: true });
|
||||
service.openClientFile(file1.path);
|
||||
host.writeFile(file1.path, file1.content + importModuleContent);
|
||||
const session = new TestSession(host);
|
||||
setCompilerOptionsForInferredProjectsRequestForSession({ traceResolution: true }, session);
|
||||
openFilesForSession([file1], session);
|
||||
host.writeFile(file2.path, file2.content + importModuleContent);
|
||||
host.writeFile(file3.path, file3.content + importModuleContent);
|
||||
host.writeFile(file4.path, file4.content + importModuleContent);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
baselineTsserverLogs("resolutionCache", "non relative module name from inferred project", service);
|
||||
baselineTsserverLogs("resolutionCache", "non relative module name from inferred project", session);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -561,7 +551,7 @@ export const x = 10;`,
|
||||
|
||||
const files = [...(useNodeFile ? [nodeFile] : []), electronFile, srcFile, moduleFile, configFile, libFile];
|
||||
const host = createServerHost(files);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([{ file: srcFile.path, content: srcFile.content, scriptKindName: "TS", projectRootPath: "/user/username/projects/myproject" }], session);
|
||||
baselineTsserverLogs("resolutionCache", scenario, session);
|
||||
});
|
||||
@@ -586,13 +576,12 @@ export const x = 10;`,
|
||||
it("when watching node_modules in inferred project for failed lookup/closed script infos", () => {
|
||||
const files = [libFile, file1, file2];
|
||||
const host = createServerHost(files);
|
||||
const service = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
service.openClientFile(file1.path);
|
||||
service.testhost.logTimeoutQueueLength();
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file1], session);
|
||||
|
||||
host.ensureFileOrFolder(npmCacheFile);
|
||||
service.testhost.logTimeoutQueueLength();
|
||||
baselineTsserverLogs("resolutionCache", "when watching node_modules in inferred project for failed lookup/closed script infos", service);
|
||||
session.host.baselineHost("After npm cache update");
|
||||
baselineTsserverLogs("resolutionCache", "when watching node_modules in inferred project for failed lookup/closed script infos", session);
|
||||
});
|
||||
it("when watching node_modules as part of wild card directories in config project", () => {
|
||||
const config: File = {
|
||||
@@ -601,13 +590,12 @@ export const x = 10;`,
|
||||
};
|
||||
const files = [libFile, file1, file2, config];
|
||||
const host = createServerHost(files);
|
||||
const service = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
service.openClientFile(file1.path);
|
||||
service.testhost.logTimeoutQueueLength();
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file1], session);
|
||||
|
||||
host.ensureFileOrFolder(npmCacheFile);
|
||||
service.testhost.logTimeoutQueueLength();
|
||||
baselineTsserverLogs("resolutionCache", "when watching node_modules as part of wild card directories in config project", service);
|
||||
session.host.baselineHost("After npm cache update");
|
||||
baselineTsserverLogs("resolutionCache", "when watching node_modules as part of wild card directories in config project", session);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -621,13 +609,13 @@ export const x = 10;`,
|
||||
const { module1, module2 } = getModules(`/user/username/projects/myproject/src/node_modules/module1/index.ts`, `/user/username/projects/myproject/node_modules/module2/index.ts`);
|
||||
const files = [module1, module2, file1, configFile, libFile];
|
||||
const host = createServerHost(files);
|
||||
const service = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
service.openClientFile(file1.path);
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file1], session);
|
||||
|
||||
// invoke callback to simulate saving
|
||||
host.modifyFile(file1.path, file1.content, { invokeFileDeleteCreateAsPartInsteadOfChange: true });
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
baselineTsserverLogs("resolutionCache", "avoid unnecessary lookup invalidation on save", service);
|
||||
baselineTsserverLogs("resolutionCache", "avoid unnecessary lookup invalidation on save", session);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -663,7 +651,7 @@ describe("unittests:: tsserver:: resolutionCache:: tsserverProjectSystem with pr
|
||||
export const y = x;
|
||||
`,
|
||||
});
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession(["/users/username/projects/app/appB.ts"], session);
|
||||
baselineTsserverLogs("resolutionCache", "sharing across references", session);
|
||||
});
|
||||
@@ -696,7 +684,7 @@ describe("unittests:: tsserver:: resolutionCache:: tsserverProjectSystem with pr
|
||||
export const y = x;
|
||||
`,
|
||||
});
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession(["/users/username/projects/app/appB.ts"], session);
|
||||
baselineTsserverLogs("resolutionCache", "not sharing across references", session);
|
||||
});
|
||||
|
||||
@@ -70,7 +70,6 @@ describe("unittests:: tsserver:: Session:: General functionality", () => {
|
||||
cancellationToken: ts.server.nullCancellationToken,
|
||||
useSingleInferredProject: false,
|
||||
useInferredProjectPerProjectRoot: false,
|
||||
typingsInstaller: undefined!, // TODO: GH#18217
|
||||
byteLength: Buffer.byteLength,
|
||||
hrtime: process.hrtime,
|
||||
logger: nullLogger(),
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
jsonToReadableText,
|
||||
} from "../helpers";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createSession,
|
||||
openExternalProjectForSession,
|
||||
openFilesForSession,
|
||||
TestSession,
|
||||
toExternalFiles,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
@@ -35,7 +32,7 @@ describe("unittests:: tsserver:: with skipLibCheck", () => {
|
||||
};`,
|
||||
};
|
||||
const host = createServerHost([file1, file2]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file1, file2], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.SemanticDiagnosticsSyncRequest>({
|
||||
@@ -77,7 +74,7 @@ describe("unittests:: tsserver:: with skipLibCheck", () => {
|
||||
};`,
|
||||
};
|
||||
const host = createServerHost([jsFile, dTsFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
|
||||
openExternalProjectForSession({
|
||||
projectFileName: "project1",
|
||||
@@ -108,7 +105,7 @@ describe("unittests:: tsserver:: with skipLibCheck", () => {
|
||||
};`,
|
||||
};
|
||||
const host = createServerHost([jsFile, dTsFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
|
||||
openExternalProjectForSession({
|
||||
projectFileName: "project1",
|
||||
@@ -143,7 +140,7 @@ describe("unittests:: tsserver:: with skipLibCheck", () => {
|
||||
declare var x: string;`,
|
||||
};
|
||||
const host = createServerHost([jsconfigFile, jsFile, dTsFile1, dTsFile2]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([jsFile], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.SemanticDiagnosticsSyncRequest>({
|
||||
@@ -168,7 +165,7 @@ describe("unittests:: tsserver:: with skipLibCheck", () => {
|
||||
};
|
||||
|
||||
const host = createServerHost([jsFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([jsFile], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.SemanticDiagnosticsSyncRequest>({
|
||||
@@ -194,7 +191,7 @@ describe("unittests:: tsserver:: with skipLibCheck", () => {
|
||||
};
|
||||
|
||||
const host = createServerHost([jsconfigFile, jsFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([jsFile], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.SemanticDiagnosticsSyncRequest>({
|
||||
@@ -221,7 +218,7 @@ describe("unittests:: tsserver:: with skipLibCheck", () => {
|
||||
};
|
||||
|
||||
const host = createServerHost([jsconfigFile, jsFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([jsFile], session);
|
||||
|
||||
session.executeCommandSeq<ts.server.protocol.SemanticDiagnosticsSyncRequest>({
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createSession,
|
||||
openFilesForSession,
|
||||
TestSession,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
createServerHost,
|
||||
@@ -29,7 +26,7 @@ class Foo {
|
||||
}`,
|
||||
};
|
||||
const host = createServerHost([file, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file], session);
|
||||
session.executeCommandSeq<ts.server.protocol.SelectionRangeRequest>({
|
||||
command: ts.server.protocol.CommandTypes.SelectionRange,
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
dedent,
|
||||
@@ -11,9 +8,9 @@ import {
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
closeFilesForSession,
|
||||
createSession,
|
||||
openFilesForSession,
|
||||
protocolLocationFromSubstring,
|
||||
TestSession,
|
||||
verifyGetErrRequest,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
@@ -64,7 +61,7 @@ describe("unittests:: tsserver:: symLinks", () => {
|
||||
|
||||
const files = [cFile, libFile, aFile, aTsconfig, aC, bFile, bTsconfig, bC];
|
||||
const host = createServerHost(files);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession(
|
||||
[
|
||||
{ file: aFile, projectRootPath: folderA },
|
||||
@@ -134,7 +131,7 @@ new C();`,
|
||||
};
|
||||
|
||||
function createSessionAndOpenFile(host: TestServerHost) {
|
||||
const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
session.executeCommandSeq<ts.server.protocol.OpenRequest>({
|
||||
command: ts.server.protocol.CommandTypes.Open,
|
||||
arguments: {
|
||||
@@ -244,7 +241,7 @@ new C();`,
|
||||
}),
|
||||
"C:/temp/replay/axios-src/node_modules/follow-redirects/index.js": "export const x = 10;",
|
||||
}, { windowsStyleRoot: "C:/" });
|
||||
const session = createSession(host, { canUseEvents: true, logger: createLoggerWithInMemoryLogs(host), disableAutomaticTypingAcquisition: true });
|
||||
const session = new TestSession({ host, disableAutomaticTypingAcquisition: true });
|
||||
openFilesForSession(["c:/temp/replay/axios-src/lib/core/AxiosHeaders.js"], session); // Creates InferredProject1 and AutoImportProvider1
|
||||
session.executeCommandSeq<ts.server.protocol.UpdateOpenRequest>({ // Different content from disk
|
||||
command: ts.server.protocol.CommandTypes.UpdateOpen,
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createSession,
|
||||
openFilesForSession,
|
||||
TestSession,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
createServerHost,
|
||||
@@ -98,7 +95,7 @@ function setup() {
|
||||
depSrcSubFolderIndexTs,
|
||||
link,
|
||||
]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
const projectService = session.getProjectService();
|
||||
return {
|
||||
host,
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
closeFilesForSession,
|
||||
createSession,
|
||||
openFilesForSession,
|
||||
protocolFileLocationFromSubstring,
|
||||
TestSession,
|
||||
@@ -44,7 +40,7 @@ import { something } from "something";
|
||||
content: "{}",
|
||||
};
|
||||
const host = createServerHost([file1, file2, file3, something, libFile, configFile]);
|
||||
const session = createSession(host, { serverMode: ts.LanguageServiceMode.Syntactic, useSingleInferredProject: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession({ host, serverMode: ts.LanguageServiceMode.Syntactic, useSingleInferredProject: true });
|
||||
return { host, session, file1, file2, file3, something, configFile };
|
||||
}
|
||||
|
||||
@@ -155,7 +151,7 @@ function fooB() { }`,
|
||||
content: "{}",
|
||||
};
|
||||
const host = createServerHost([file1, file2, file3, something, libFile, configFile]);
|
||||
const session = createSession(host, { serverMode: ts.LanguageServiceMode.Syntactic, useSingleInferredProject: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession({ host, serverMode: ts.LanguageServiceMode.Syntactic, useSingleInferredProject: true });
|
||||
const service = session.getProjectService();
|
||||
openFilesForSession([file1], session);
|
||||
const project = service.inferredProjects[0];
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createSession,
|
||||
openFilesForSession,
|
||||
TestSession,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
createServerHost,
|
||||
@@ -40,7 +37,7 @@ describe("Test Suite 1", () => {
|
||||
};
|
||||
const files = [app, libFile, tsconfig];
|
||||
const host = createServerHost(files);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([{ file: app.path, content: app.content }], session);
|
||||
|
||||
host.writeFile(unitTest1.path, unitTest1.content);
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
jsonToReadableText,
|
||||
@@ -8,9 +5,9 @@ import {
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
closeFilesForSession,
|
||||
createSession,
|
||||
openExternalProjectForSession,
|
||||
openFilesForSession,
|
||||
TestSession,
|
||||
toExternalFiles,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
@@ -22,10 +19,7 @@ describe("unittests:: tsserver:: project telemetry", () => {
|
||||
it("does nothing for inferred project", () => {
|
||||
const file = makeFile("/a.js");
|
||||
const host = createServerHost([file]);
|
||||
const session = createSession(host, {
|
||||
canUseEvents: true,
|
||||
logger: createLoggerWithInMemoryLogs(host),
|
||||
});
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file], session);
|
||||
baselineTsserverLogs("telemetry", "does nothing for inferred project", session);
|
||||
});
|
||||
@@ -36,10 +30,7 @@ describe("unittests:: tsserver:: project telemetry", () => {
|
||||
const tsconfig = makeFile("/a/tsconfig.json", {});
|
||||
|
||||
const host = createServerHost([file, file2, tsconfig]);
|
||||
const session = createSession(host, {
|
||||
canUseEvents: true,
|
||||
logger: createLoggerWithInMemoryLogs(host),
|
||||
});
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file], session);
|
||||
closeFilesForSession([file], session);
|
||||
openFilesForSession([file2], session);
|
||||
@@ -54,10 +45,7 @@ describe("unittests:: tsserver:: project telemetry", () => {
|
||||
const tsconfig = makeFile("/tsconfig.json", { compilerOptions, include: ["src"] });
|
||||
|
||||
const host = createServerHost([...files, notIncludedFile, tsconfig]);
|
||||
const session = createSession(host, {
|
||||
canUseEvents: true,
|
||||
logger: createLoggerWithInMemoryLogs(host),
|
||||
});
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([files[0]], session);
|
||||
baselineTsserverLogs("telemetry", "counts files by extension", session);
|
||||
});
|
||||
@@ -65,10 +53,7 @@ describe("unittests:: tsserver:: project telemetry", () => {
|
||||
it("works with external project", () => {
|
||||
const file1 = makeFile("/a.ts");
|
||||
const host = createServerHost([file1]);
|
||||
const session = createSession(host, {
|
||||
canUseEvents: true,
|
||||
logger: createLoggerWithInMemoryLogs(host),
|
||||
});
|
||||
const session = new TestSession(host);
|
||||
const compilerOptions: ts.server.protocol.CompilerOptions = { strict: true };
|
||||
|
||||
const projectFileName = "/hunter2/foo.csproj";
|
||||
@@ -133,10 +118,7 @@ describe("unittests:: tsserver:: project telemetry", () => {
|
||||
const tsconfig = makeFile("/tsconfig.json", { compilerOptions, files: ["/a.ts"] });
|
||||
|
||||
const host = createServerHost([file, tsconfig]);
|
||||
const session = createSession(host, {
|
||||
canUseEvents: true,
|
||||
logger: createLoggerWithInMemoryLogs(host),
|
||||
});
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file], session);
|
||||
baselineTsserverLogs("telemetry", "does not expose paths", session);
|
||||
});
|
||||
@@ -152,10 +134,7 @@ describe("unittests:: tsserver:: project telemetry", () => {
|
||||
compileOnSave: true,
|
||||
});
|
||||
const host = createServerHost([file, tsconfig]);
|
||||
const session = createSession(host, {
|
||||
canUseEvents: true,
|
||||
logger: createLoggerWithInMemoryLogs(host),
|
||||
});
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file], session);
|
||||
baselineTsserverLogs("telemetry", "sends telemetry for extends, files, include, exclude, and compileOnSave", session);
|
||||
});
|
||||
@@ -180,10 +159,7 @@ describe("unittests:: tsserver:: project telemetry", () => {
|
||||
},
|
||||
});
|
||||
const host = createServerHost([file, jsconfig]);
|
||||
const session = createSession(host, {
|
||||
canUseEvents: true,
|
||||
logger: createLoggerWithInMemoryLogs(host),
|
||||
});
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file], session);
|
||||
baselineTsserverLogs("telemetry", "sends telemetry for typeAcquisition settings", session);
|
||||
});
|
||||
@@ -195,10 +171,7 @@ describe("unittests:: tsserver:: project telemetry", () => {
|
||||
compilerOptions: autoJsCompilerOptions,
|
||||
});
|
||||
const host = createServerHost([tsconfig, tsFile, jsFile]);
|
||||
const session = createSession(host, {
|
||||
canUseEvents: true,
|
||||
logger: createLoggerWithInMemoryLogs(host),
|
||||
});
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([jsFile], session);
|
||||
baselineTsserverLogs("telemetry", "sends telemetry for file sizes", session);
|
||||
});
|
||||
@@ -207,10 +180,7 @@ describe("unittests:: tsserver:: project telemetry", () => {
|
||||
const file = makeFile("/a.js");
|
||||
const tsconfig = makeFile("/jsconfig.json", {});
|
||||
const host = createServerHost([tsconfig, file]);
|
||||
const session = createSession(host, {
|
||||
canUseEvents: true,
|
||||
logger: createLoggerWithInMemoryLogs(host),
|
||||
});
|
||||
const session = new TestSession(host);
|
||||
const fileSize = ts.server.maxProgramSizeForNonTsFiles + 1;
|
||||
host.getFileSize = () => fileSize;
|
||||
openFilesForSession([file], session);
|
||||
@@ -222,10 +192,7 @@ describe("unittests:: tsserver:: project telemetry", () => {
|
||||
const ajs = makeFile("/a.js", "// @ts-check\nconst x = 0;");
|
||||
const bjs = makeFile("/b.js");
|
||||
const host = createServerHost([ajs, bjs]);
|
||||
const session = createSession(host, {
|
||||
canUseEvents: true,
|
||||
logger: createLoggerWithInMemoryLogs(host),
|
||||
});
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([ajs, bjs], session);
|
||||
|
||||
// No repeated send for opening a file seen before.
|
||||
@@ -236,10 +203,7 @@ describe("unittests:: tsserver:: project telemetry", () => {
|
||||
it("not for '.ts' file", () => {
|
||||
const ats = makeFile("/a.ts", "");
|
||||
const host = createServerHost([ats]);
|
||||
const session = createSession(host, {
|
||||
canUseEvents: true,
|
||||
logger: createLoggerWithInMemoryLogs(host),
|
||||
});
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([ats], session);
|
||||
baselineTsserverLogs("telemetry", "not for ts file", session);
|
||||
});
|
||||
@@ -249,10 +213,7 @@ describe("unittests:: tsserver:: project telemetry", () => {
|
||||
const compilerOptions: ts.CompilerOptions = { checkJs: true };
|
||||
const jsconfig = makeFile("/jsconfig.json", { compilerOptions });
|
||||
const host = createServerHost([jsconfig, file]);
|
||||
const session = createSession(host, {
|
||||
canUseEvents: true,
|
||||
logger: createLoggerWithInMemoryLogs(host),
|
||||
});
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file], session);
|
||||
baselineTsserverLogs("telemetry", "even for project with ts-check in config", session);
|
||||
});
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createProjectService,
|
||||
openFilesForSession,
|
||||
TestSession,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
createServerHost,
|
||||
@@ -116,9 +114,9 @@ describe("unittests:: tsserver:: Text storage", () => {
|
||||
const host = createServerHost([largeFile]);
|
||||
|
||||
// The large-file handling requires a ScriptInfo with a containing project
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
projectService.openClientFile(largeFile.path);
|
||||
const scriptInfo = projectService.getScriptInfo(largeFile.path);
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([largeFile], session);
|
||||
const scriptInfo = session.getProjectService().getScriptInfo(largeFile.path);
|
||||
|
||||
const ts1 = new ts.server.TextStorage(host, scriptInfo!);
|
||||
|
||||
@@ -126,7 +124,7 @@ describe("unittests:: tsserver:: Text storage", () => {
|
||||
assert.isFalse(ts1.hasScriptVersionCache_TestOnly());
|
||||
|
||||
assert.strictEqual(largeFile.content.length, ts1.getTelemetryFileSize());
|
||||
baselineTsserverLogs("textStorage", "should be able to return the file size when a JS file is too large to load into text", projectService);
|
||||
baselineTsserverLogs("textStorage", "should be able to return the file size when a JS file is too large to load into text", session);
|
||||
});
|
||||
|
||||
it("should return the file size without reloading the file", () => {
|
||||
|
||||
@@ -1,18 +1,13 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
jsonToReadableText,
|
||||
} from "../helpers";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createProjectService,
|
||||
openExternalProjectForSession,
|
||||
openFilesForSession,
|
||||
TestSession,
|
||||
toExternalFile,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
TestTypingsInstaller,
|
||||
} from "../helpers/typingsInstaller";
|
||||
import {
|
||||
createServerHost,
|
||||
} from "../helpers/virtualFileSystemWithWatch";
|
||||
@@ -28,15 +23,15 @@ describe("unittests:: tsserver:: typeAquisition:: autoDiscovery", () => {
|
||||
content: "",
|
||||
};
|
||||
const host = createServerHost([file1, file2]);
|
||||
const projectService = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
projectService.openExternalProject({
|
||||
const session = new TestSession(host);
|
||||
openExternalProjectForSession({
|
||||
projectFileName: "/a/b/proj.csproj",
|
||||
rootFiles: [toExternalFile(file2.path), { fileName: file1.path, hasMixedContent: true, scriptKind: ts.ScriptKind.JS }],
|
||||
rootFiles: [toExternalFile(file2.path), { fileName: file1.path, hasMixedContent: true, scriptKind: "JS" }],
|
||||
options: {},
|
||||
});
|
||||
const typeAcquisition = projectService.externalProjects[0].getTypeAcquisition();
|
||||
projectService.logger.log(`Typine acquisition should be enabled: ${typeAcquisition.enable}`);
|
||||
baselineTsserverLogs("typeAquisition", "does not depend on extension", projectService);
|
||||
}, session);
|
||||
const typeAcquisition = session.getProjectService().externalProjects[0].getTypeAcquisition();
|
||||
session.logger.log(`Typine acquisition should be enabled: ${typeAcquisition.enable}`);
|
||||
baselineTsserverLogs("typeAquisition", "does not depend on extension", session);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -60,14 +55,10 @@ describe("unittests:: tsserver:: typeAquisition:: prefer typings to js", () => {
|
||||
content: jsonToReadableText({ compilerOptions: { allowJs: true }, exclude: ["node_modules"] }),
|
||||
};
|
||||
const host = createServerHost([f1, barjs, barTypings, config]);
|
||||
const logger = createLoggerWithInMemoryLogs(host);
|
||||
const projectService = createProjectService(host, {
|
||||
typingsInstaller: new TestTypingsInstaller(host, logger, { globalTypingsCacheLocation }),
|
||||
logger,
|
||||
});
|
||||
const session = new TestSession({ host, globalTypingsCacheLocation });
|
||||
|
||||
projectService.openClientFile(f1.path);
|
||||
openFilesForSession([f1], session);
|
||||
|
||||
baselineTsserverLogs("typeAquisition", "prefer typings in second pass", projectService);
|
||||
baselineTsserverLogs("typeAquisition", "prefer typings in second pass", session);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createSession,
|
||||
openFilesForSession,
|
||||
TestSession,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
createServerHost,
|
||||
@@ -165,7 +162,7 @@ describe("unittests:: tsserver:: typeOnlyImportChains", () => {
|
||||
|
||||
function assertUsageError(subScenario: string, files: readonly File[], openFile: File) {
|
||||
const host = createServerHost([...files, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([openFile], session);
|
||||
session.executeCommandSeq<ts.server.protocol.SemanticDiagnosticsSyncRequest>({
|
||||
command: ts.server.protocol.CommandTypes.SemanticDiagnosticsSync,
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import {
|
||||
jsonToReadableText,
|
||||
} from "../helpers";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createSession,
|
||||
openFilesForSession,
|
||||
TestSession,
|
||||
} from "../helpers/tsserver";
|
||||
import {
|
||||
createServerHost,
|
||||
@@ -63,7 +60,7 @@ declare class TestLib {
|
||||
|
||||
const files = [typeLib, appLib, testFile, testConfig, libFile];
|
||||
const host = createServerHost(files);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([testFile], session);
|
||||
host.writeFile(appLib.path, appLib.content.replace("test()", "test2()"));
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
@@ -92,7 +89,7 @@ declare class TestLib {
|
||||
};
|
||||
const files = [file, tsconfig, filesystem, libFile];
|
||||
const host = createServerHost(files);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file], session);
|
||||
baselineTsserverLogs("typeReferenceDirectives", "when typeReferenceDirective is relative path and in a sibling folder", session);
|
||||
});
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
import {
|
||||
createLoggerWithInMemoryLogs,
|
||||
Logger,
|
||||
LoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger";
|
||||
import * as ts from "../../_namespaces/ts";
|
||||
import {
|
||||
@@ -12,8 +12,6 @@ import {
|
||||
} from "../helpers/tscWatch";
|
||||
import {
|
||||
baselineTsserverLogs,
|
||||
createProjectService,
|
||||
createSession,
|
||||
openExternalProjectForSession,
|
||||
openFilesForSession,
|
||||
protocolFileLocationFromSubstring,
|
||||
@@ -55,7 +53,7 @@ describe("unittests:: tsserver:: watchEnvironment:: tsserverProjectSystem watchD
|
||||
const environmentVariables = new Map<string, string>();
|
||||
environmentVariables.set("TSC_WATCHDIRECTORY", tscWatchDirectory);
|
||||
const host = createServerHost(files, { environmentVariables });
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([index], session);
|
||||
session.executeCommandSeq<ts.server.protocol.CompletionsRequest>({
|
||||
command: ts.server.protocol.CommandTypes.CompletionInfo,
|
||||
@@ -109,7 +107,7 @@ describe("unittests:: tsserver:: watchEnvironment:: tsserverProjectSystem Watche
|
||||
};
|
||||
const files = [configFile, file1, file2, libFile];
|
||||
const host = createServerHost(files, { windowsStyleRoot: "c:/" });
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([file1], session);
|
||||
baselineTsserverLogs("watchEnvironment", scenario, session);
|
||||
});
|
||||
@@ -143,7 +141,7 @@ it(`unittests:: tsserver:: watchEnvironment:: tsserverProjectSystem recursive wa
|
||||
const environmentVariables = new Map<string, string>();
|
||||
environmentVariables.set("TSC_WATCHDIRECTORY", Tsc_WatchDirectory.NonRecursiveWatchDirectory);
|
||||
const host = createServerHost([index, file1, configFile, libFile, nodeModulesExistingUnusedFile], { environmentVariables });
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([index], session);
|
||||
|
||||
const nodeModulesIgnoredFileFromIgnoreDirectory: File = {
|
||||
@@ -178,7 +176,7 @@ it(`unittests:: tsserver:: watchEnvironment:: tsserverProjectSystem recursive wa
|
||||
emacsIgnoredFileFromIgnoreDirectory,
|
||||
].forEach(ignoredEntity => {
|
||||
host.ensureFileOrFolder(ignoredEntity);
|
||||
session.testhost.logTimeoutQueueLength();
|
||||
session.host.baselineHost("After writing ignored file or folder");
|
||||
});
|
||||
|
||||
baselineTsserverLogs("watchEnvironment", `recursive directory does not watch files starting with dot in node_modules`, session);
|
||||
@@ -193,7 +191,7 @@ it("unittests:: tsserver:: watchEnvironment:: tsserverProjectSystem watching fil
|
||||
verifyFilePathStyle("//vda1cs4850/c$/users/username/myprojects/project/x.js", logger);
|
||||
baselineTsserverLogs("watchEnvironment", `watching files with network style paths`, { logger });
|
||||
|
||||
function verifyFilePathStyle(path: string, logger: Logger) {
|
||||
function verifyFilePathStyle(path: string, logger: LoggerWithInMemoryLogs) {
|
||||
const windowsStyleRoot = path.substring(0, ts.getRootLength(path));
|
||||
const file: File = { path, content: "const x = 10" };
|
||||
const host = createServerHost(
|
||||
@@ -203,7 +201,7 @@ it("unittests:: tsserver:: watchEnvironment:: tsserverProjectSystem watching fil
|
||||
logger.host = host;
|
||||
logger.info(`For files of style ${path}`);
|
||||
logger.log(`currentDirectory:: ${host.getCurrentDirectory()} useCaseSensitiveFileNames: ${host.useCaseSensitiveFileNames}`);
|
||||
const session = createSession(host, { logger });
|
||||
const session = new TestSession({ host, logger });
|
||||
openFilesForSession([file], session);
|
||||
}
|
||||
});
|
||||
@@ -216,8 +214,7 @@ describe("unittests:: tsserver:: watchEnvironment:: handles watch compiler optio
|
||||
};
|
||||
const files = [libFile, commonFile2, configFile];
|
||||
const host = createServerHost(files.concat(commonFile1));
|
||||
const logger = createLoggerWithInMemoryLogs(host);
|
||||
const session = createSession(host, { logger });
|
||||
const session = new TestSession(host);
|
||||
session.executeCommandSeq<ts.server.protocol.ConfigureRequest>({
|
||||
command: ts.server.protocol.CommandTypes.Configure,
|
||||
arguments: {
|
||||
@@ -237,8 +234,7 @@ describe("unittests:: tsserver:: watchEnvironment:: handles watch compiler optio
|
||||
};
|
||||
const files = [libFile, commonFile2, configFile];
|
||||
const host = createServerHost(files.concat(commonFile1), { runWithoutRecursiveWatches: true });
|
||||
const logger = createLoggerWithInMemoryLogs(host);
|
||||
const session = createSession(host, { logger });
|
||||
const session = new TestSession(host);
|
||||
session.executeCommandSeq<ts.server.protocol.ConfigureRequest>({
|
||||
command: ts.server.protocol.CommandTypes.Configure,
|
||||
arguments: {
|
||||
@@ -258,8 +254,7 @@ describe("unittests:: tsserver:: watchEnvironment:: handles watch compiler optio
|
||||
};
|
||||
const files = [libFile, commonFile2, configFile];
|
||||
const host = createServerHost(files.concat(commonFile1), { runWithoutRecursiveWatches: true, runWithFallbackPolling: true });
|
||||
const logger = createLoggerWithInMemoryLogs(host);
|
||||
const session = createSession(host, { logger });
|
||||
const session = new TestSession(host);
|
||||
session.executeCommandSeq<ts.server.protocol.ConfigureRequest>({
|
||||
command: ts.server.protocol.CommandTypes.Configure,
|
||||
arguments: {
|
||||
@@ -283,8 +278,7 @@ describe("unittests:: tsserver:: watchEnvironment:: handles watch compiler optio
|
||||
};
|
||||
const files = [libFile, commonFile2, configFile];
|
||||
const host = createServerHost(files.concat(commonFile1));
|
||||
const logger = createLoggerWithInMemoryLogs(host);
|
||||
const session = createSession(host, { logger });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([{ file: commonFile1, projectRootPath: "/a/b" }], session);
|
||||
baselineTsserverLogs("watchEnvironment", `with watchFile option in configFile`, session);
|
||||
});
|
||||
@@ -300,8 +294,7 @@ describe("unittests:: tsserver:: watchEnvironment:: handles watch compiler optio
|
||||
};
|
||||
const files = [libFile, commonFile2, configFile];
|
||||
const host = createServerHost(files.concat(commonFile1), { runWithoutRecursiveWatches: true });
|
||||
const logger = createLoggerWithInMemoryLogs(host);
|
||||
const session = createSession(host, { logger });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([{ file: commonFile1, projectRootPath: "/a/b" }], session);
|
||||
baselineTsserverLogs("watchEnvironment", `with watchDirectory option in configFile`, session);
|
||||
});
|
||||
@@ -317,8 +310,7 @@ describe("unittests:: tsserver:: watchEnvironment:: handles watch compiler optio
|
||||
};
|
||||
const files = [libFile, commonFile2, configFile];
|
||||
const host = createServerHost(files.concat(commonFile1), { runWithoutRecursiveWatches: true, runWithFallbackPolling: true });
|
||||
const logger = createLoggerWithInMemoryLogs(host);
|
||||
const session = createSession(host, { logger });
|
||||
const session = new TestSession(host);
|
||||
session.executeCommandSeq<ts.server.protocol.ConfigureRequest>({
|
||||
command: ts.server.protocol.CommandTypes.Configure,
|
||||
arguments: {
|
||||
@@ -366,7 +358,7 @@ describe("unittests:: tsserver:: watchEnvironment:: handles watch compiler optio
|
||||
const { main, bar, foo } = setupFiles();
|
||||
const files = [libFile, main, bar, foo, configFile];
|
||||
const host = createServerHost(files, { currentDirectory: "/user/username/projects/myproject" });
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
setupConfigureHost(session, configureHost);
|
||||
openFilesForSession([main], session);
|
||||
return session;
|
||||
@@ -386,7 +378,7 @@ describe("unittests:: tsserver:: watchEnvironment:: handles watch compiler optio
|
||||
const { main, bar, foo } = setupFiles();
|
||||
const files = [libFile, main, bar, foo];
|
||||
const host = createServerHost(files, { currentDirectory: "/user/username/projects/myproject" });
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
setupConfigureHost(session, configureHost);
|
||||
openExternalProjectForSession({
|
||||
projectFileName: `/user/username/projects/myproject/project.csproj`,
|
||||
@@ -411,23 +403,23 @@ describe("unittests:: tsserver:: watchEnvironment:: handles watch compiler optio
|
||||
const { main, bar, foo } = setupFiles();
|
||||
const files = [libFile, main, bar, foo];
|
||||
const host = createServerHost(files, { currentDirectory: "/user/username/projects/myproject" });
|
||||
const service = createProjectService(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
service.openExternalProject({
|
||||
const session = new TestSession(host);
|
||||
openExternalProjectForSession({
|
||||
projectFileName: `/user/username/projects/myproject/project.csproj`,
|
||||
rootFiles: toExternalFiles([main.path, bar.path, foo.path]),
|
||||
options: { excludeDirectories: ["**/../*"] },
|
||||
} as ts.server.protocol.ExternalProject);
|
||||
service.openClientFile(main.path);
|
||||
const project = service.externalProjects[0];
|
||||
service.logger.info(jsonToReadableText(project.getAllProjectErrors()));
|
||||
baselineTsserverLogs("watchEnvironment", `external project watch options errors`, service);
|
||||
}, session);
|
||||
openFilesForSession([main], session);
|
||||
const project = session.getProjectService().externalProjects[0];
|
||||
session.logger.info(jsonToReadableText(project.getAllProjectErrors()));
|
||||
baselineTsserverLogs("watchEnvironment", `external project watch options errors`, session);
|
||||
});
|
||||
|
||||
function setupInferredProject(configureHost?: boolean) {
|
||||
const { main, bar, foo } = setupFiles();
|
||||
const files = [libFile, main, bar, foo];
|
||||
const host = createServerHost(files, { currentDirectory: "/user/username/projects/myproject" });
|
||||
const session = createSession(host, { useInferredProjectPerProjectRoot: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession({ host, useInferredProjectPerProjectRoot: true });
|
||||
setupConfigureHost(session, configureHost);
|
||||
setCompilerOptionsForInferredProjectsRequestForSession({
|
||||
options: { excludeDirectories: ["node_modules"] },
|
||||
@@ -451,12 +443,15 @@ describe("unittests:: tsserver:: watchEnvironment:: handles watch compiler optio
|
||||
const { main, bar, foo } = setupFiles();
|
||||
const files = [libFile, main, bar, foo];
|
||||
const host = createServerHost(files, { currentDirectory: "/user/username/projects/myproject" });
|
||||
const service = createProjectService(host, { useInferredProjectPerProjectRoot: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
service.setCompilerOptionsForInferredProjects({ excludeDirectories: ["**/../*"] }, "/user/username/projects/myproject");
|
||||
service.openClientFile(main.path, main.content, ts.ScriptKind.TS, "/user/username/projects/myproject");
|
||||
const project = service.inferredProjects[0];
|
||||
service.logger.info(jsonToReadableText(project.getAllProjectErrors()));
|
||||
baselineTsserverLogs("watchEnvironment", `inferred project watch options errors`, service);
|
||||
const session = new TestSession({ host, useInferredProjectPerProjectRoot: true });
|
||||
setCompilerOptionsForInferredProjectsRequestForSession({
|
||||
options: { excludeDirectories: ["**/../*"] },
|
||||
projectRootPath: "/user/username/projects/myproject",
|
||||
}, session);
|
||||
openFilesForSession([{ file: main.path, projectRootPath: "/user/username/projects/myproject" }], session);
|
||||
const project = session.getProjectService().inferredProjects[0];
|
||||
session.logger.info(jsonToReadableText(project.getAllProjectErrors()));
|
||||
baselineTsserverLogs("watchEnvironment", `inferred project watch options errors`, session);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -469,7 +464,7 @@ describe("unittests:: tsserver:: watchEnvironment:: file names on case insensiti
|
||||
content: `import { foo } from "bar"`,
|
||||
};
|
||||
const host = createServerHost([file, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([{ file, projectRootPath }], session);
|
||||
baselineTsserverLogs("watchEnvironment", scenario, session);
|
||||
});
|
||||
@@ -496,7 +491,7 @@ describe("unittests:: tsserver:: watchEnvironment:: watchFile is single watcher
|
||||
content: `import * as tsconfig from "./tsconfig.json";`,
|
||||
};
|
||||
const host = createServerHost([config, index, libFile]);
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([index], session);
|
||||
baselineTsserverLogs("watchEnvironment", "when watchFile is single watcher per file", session);
|
||||
});
|
||||
@@ -517,7 +512,7 @@ describe("unittests:: tsserver:: watchEnvironment:: watching at workspaces codes
|
||||
content: `export function randomSeed(): string;`,
|
||||
};
|
||||
const host = createServerHost([config, main, randomSeed, libFile], { inodeWatching: true, runWithoutRecursiveWatches: true });
|
||||
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host), canUseEvents: true, noGetErrOnBackgroundUpdate: true });
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession([main], session);
|
||||
verifyGetErrRequest({ session, files: [main] });
|
||||
// npm ci
|
||||
|
||||
@@ -5,7 +5,6 @@ import {
|
||||
combinePaths,
|
||||
createGetCanonicalFileName,
|
||||
Debug,
|
||||
forEachAncestorDirectory,
|
||||
getDirectoryPath,
|
||||
MapLike,
|
||||
normalizePath,
|
||||
@@ -15,7 +14,6 @@ import {
|
||||
version,
|
||||
} from "./_namespaces/ts";
|
||||
import {
|
||||
ActionPackageInstalled,
|
||||
Arguments,
|
||||
EventTypesRegistry,
|
||||
findArgument,
|
||||
@@ -23,7 +21,6 @@ import {
|
||||
InitializationFailedResponse,
|
||||
InstallTypingHost,
|
||||
nowString,
|
||||
PackageInstalledResponse,
|
||||
stringifyIndented,
|
||||
TypesRegistryResponse,
|
||||
TypingInstallerRequestUnion,
|
||||
@@ -182,19 +179,7 @@ export class NodeTypingsInstaller extends TypingsInstaller {
|
||||
break;
|
||||
}
|
||||
case "installPackage": {
|
||||
const { fileName, packageName, projectName, projectRootPath } = req;
|
||||
const cwd = getDirectoryOfPackageJson(fileName, this.installTypingHost) || projectRootPath;
|
||||
if (cwd) {
|
||||
this.installWorker(-1, [packageName], cwd, success => {
|
||||
const message = success ? `Package ${packageName} installed.` : `There was an error installing ${packageName}.`;
|
||||
const response: PackageInstalledResponse = { kind: ActionPackageInstalled, projectName, success, message };
|
||||
this.sendResponse(response);
|
||||
});
|
||||
}
|
||||
else {
|
||||
const response: PackageInstalledResponse = { kind: ActionPackageInstalled, projectName, success: false, message: "Could not determine a project root path." };
|
||||
this.sendResponse(response);
|
||||
}
|
||||
this.installPackage(req);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -214,7 +199,7 @@ export class NodeTypingsInstaller extends TypingsInstaller {
|
||||
|
||||
protected installWorker(requestId: number, packageNames: string[], cwd: string, onRequestCompleted: RequestCompletedAction): void {
|
||||
if (this.log.isEnabled()) {
|
||||
this.log.writeLine(`#${requestId} with arguments'${JSON.stringify(packageNames)}'.`);
|
||||
this.log.writeLine(`#${requestId} with cwd: ${cwd} arguments: ${JSON.stringify(packageNames)}`);
|
||||
}
|
||||
const start = Date.now();
|
||||
const hasError = installNpmPackages(this.npmPath, version, packageNames, command => this.execSyncAndLog(command, { cwd }));
|
||||
@@ -244,14 +229,6 @@ export class NodeTypingsInstaller extends TypingsInstaller {
|
||||
}
|
||||
}
|
||||
|
||||
function getDirectoryOfPackageJson(fileName: string, host: InstallTypingHost): string | undefined {
|
||||
return forEachAncestorDirectory(getDirectoryPath(fileName), directory => {
|
||||
if (host.fileExists(combinePaths(directory, "package.json"))) {
|
||||
return directory;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const logFilePath = findArgument(Arguments.LogFile);
|
||||
const globalTypingsCacheLocation = findArgument(Arguments.GlobalCacheLocation);
|
||||
const typingSafeListLocation = findArgument(Arguments.TypingSafeListLocation);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import {
|
||||
combinePaths,
|
||||
forEachAncestorDirectory,
|
||||
forEachKey,
|
||||
getBaseFileName,
|
||||
getDirectoryPath,
|
||||
@@ -18,6 +19,7 @@ import {
|
||||
versionMajorMinor,
|
||||
} from "./_namespaces/ts";
|
||||
import {
|
||||
ActionPackageInstalled,
|
||||
ActionSet,
|
||||
ActionWatchTypingLocations,
|
||||
BeginInstallTypes,
|
||||
@@ -26,8 +28,10 @@ import {
|
||||
EndInstallTypes,
|
||||
EventBeginInstallTypes,
|
||||
EventEndInstallTypes,
|
||||
InstallPackageRequest,
|
||||
InstallTypingHost,
|
||||
InvalidateCachedTypings,
|
||||
PackageInstalledResponse,
|
||||
SetTypings,
|
||||
stringifyIndented,
|
||||
WatchTypingLocations,
|
||||
@@ -196,6 +200,39 @@ export abstract class TypingsInstaller {
|
||||
}
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
installPackage(req: InstallPackageRequest) {
|
||||
const { fileName, packageName, projectName, projectRootPath } = req;
|
||||
const cwd = forEachAncestorDirectory(getDirectoryPath(fileName), directory => {
|
||||
if (this.installTypingHost.fileExists(combinePaths(directory, "package.json"))) {
|
||||
return directory;
|
||||
}
|
||||
}) || projectRootPath;
|
||||
if (cwd) {
|
||||
this.installWorker(-1, [packageName], cwd, success => {
|
||||
const message = success ?
|
||||
`Package ${packageName} installed.` :
|
||||
`There was an error installing ${packageName}.`;
|
||||
const response: PackageInstalledResponse = {
|
||||
kind: ActionPackageInstalled,
|
||||
projectName,
|
||||
success,
|
||||
message,
|
||||
};
|
||||
this.sendResponse(response);
|
||||
});
|
||||
}
|
||||
else {
|
||||
const response: PackageInstalledResponse = {
|
||||
kind: ActionPackageInstalled,
|
||||
projectName,
|
||||
success: false,
|
||||
message: "Could not determine a project root path.",
|
||||
};
|
||||
this.sendResponse(response);
|
||||
}
|
||||
}
|
||||
|
||||
private initializeSafeList() {
|
||||
// Prefer the safe list from the types map if it exists
|
||||
if (this.typesMapLocation) {
|
||||
@@ -455,7 +492,8 @@ export abstract class TypingsInstaller {
|
||||
|
||||
protected abstract installWorker(requestId: number, packageNames: string[], cwd: string, onRequestCompleted: RequestCompletedAction): void;
|
||||
protected abstract sendResponse(response: SetTypings | InvalidateCachedTypings | BeginInstallTypes | EndInstallTypes | WatchTypingLocations): void;
|
||||
|
||||
/** @internal */
|
||||
protected abstract sendResponse(response: SetTypings | InvalidateCachedTypings | BeginInstallTypes | EndInstallTypes | WatchTypingLocations | PackageInstalledResponse): void;
|
||||
protected readonly latestDistTag = "latest";
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user