mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Refactor tsserver, tsc and fourslash-server tests so that paths are always watchable (#59844)
This commit is contained in:
@@ -303,28 +303,34 @@ export function sortAndDeduplicateDiagnostics<T extends Diagnostic>(diagnostics:
|
||||
return sortAndDeduplicate<T>(diagnostics, compareDiagnostics, diagnosticsEqualityComparer);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export const targetToLibMap = new Map<ScriptTarget, string>([
|
||||
[ScriptTarget.ESNext, "lib.esnext.full.d.ts"],
|
||||
[ScriptTarget.ES2023, "lib.es2023.full.d.ts"],
|
||||
[ScriptTarget.ES2022, "lib.es2022.full.d.ts"],
|
||||
[ScriptTarget.ES2021, "lib.es2021.full.d.ts"],
|
||||
[ScriptTarget.ES2020, "lib.es2020.full.d.ts"],
|
||||
[ScriptTarget.ES2019, "lib.es2019.full.d.ts"],
|
||||
[ScriptTarget.ES2018, "lib.es2018.full.d.ts"],
|
||||
[ScriptTarget.ES2017, "lib.es2017.full.d.ts"],
|
||||
[ScriptTarget.ES2016, "lib.es2016.full.d.ts"],
|
||||
[ScriptTarget.ES2015, "lib.es6.d.ts"], // We don't use lib.es2015.full.d.ts due to breaking change.
|
||||
]);
|
||||
|
||||
export function getDefaultLibFileName(options: CompilerOptions): string {
|
||||
switch (getEmitScriptTarget(options)) {
|
||||
const target = getEmitScriptTarget(options);
|
||||
switch (target) {
|
||||
case ScriptTarget.ESNext:
|
||||
return "lib.esnext.full.d.ts";
|
||||
case ScriptTarget.ES2023:
|
||||
return "lib.es2023.full.d.ts";
|
||||
case ScriptTarget.ES2022:
|
||||
return "lib.es2022.full.d.ts";
|
||||
case ScriptTarget.ES2021:
|
||||
return "lib.es2021.full.d.ts";
|
||||
case ScriptTarget.ES2020:
|
||||
return "lib.es2020.full.d.ts";
|
||||
case ScriptTarget.ES2019:
|
||||
return "lib.es2019.full.d.ts";
|
||||
case ScriptTarget.ES2018:
|
||||
return "lib.es2018.full.d.ts";
|
||||
case ScriptTarget.ES2017:
|
||||
return "lib.es2017.full.d.ts";
|
||||
case ScriptTarget.ES2016:
|
||||
return "lib.es2016.full.d.ts";
|
||||
case ScriptTarget.ES2015:
|
||||
return "lib.es6.d.ts"; // We don't use lib.es2015.full.d.ts due to breaking change.
|
||||
return targetToLibMap.get(target)!;
|
||||
default:
|
||||
return "lib.d.ts";
|
||||
}
|
||||
|
||||
@@ -422,218 +422,3 @@ export class CompilerHost implements ts.CompilerHost {
|
||||
return parsed;
|
||||
}
|
||||
}
|
||||
|
||||
export type ExpectedDiagnosticMessage = [ts.DiagnosticMessage, ...(string | number)[]];
|
||||
export interface ExpectedDiagnosticMessageChain {
|
||||
message: ExpectedDiagnosticMessage;
|
||||
next?: ExpectedDiagnosticMessageChain[];
|
||||
}
|
||||
|
||||
export interface ExpectedDiagnosticLocation {
|
||||
file: string;
|
||||
start: number;
|
||||
length: number;
|
||||
}
|
||||
export interface ExpectedDiagnosticRelatedInformation extends ExpectedDiagnosticMessageChain {
|
||||
location?: ExpectedDiagnosticLocation;
|
||||
}
|
||||
|
||||
export enum DiagnosticKind {
|
||||
Error = "Error",
|
||||
Status = "Status",
|
||||
}
|
||||
export interface ExpectedErrorDiagnostic extends ExpectedDiagnosticRelatedInformation {
|
||||
relatedInformation?: ExpectedDiagnosticRelatedInformation[];
|
||||
}
|
||||
|
||||
export type ExpectedDiagnostic = ExpectedDiagnosticMessage | ExpectedErrorDiagnostic;
|
||||
|
||||
interface SolutionBuilderDiagnostic {
|
||||
kind: DiagnosticKind;
|
||||
diagnostic: ts.Diagnostic;
|
||||
}
|
||||
|
||||
function indentedText(indent: number, text: string) {
|
||||
if (!indent) return text;
|
||||
let indentText = "";
|
||||
for (let i = 0; i < indent; i++) {
|
||||
indentText += " ";
|
||||
}
|
||||
return `
|
||||
${indentText}${text}`;
|
||||
}
|
||||
|
||||
function expectedDiagnosticMessageToText([message, ...args]: ExpectedDiagnosticMessage) {
|
||||
let text = ts.getLocaleSpecificMessage(message);
|
||||
if (args.length) {
|
||||
text = ts.formatStringFromArgs(text, args);
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
function expectedDiagnosticMessageChainToText({ message, next }: ExpectedDiagnosticMessageChain, indent = 0) {
|
||||
let text = indentedText(indent, expectedDiagnosticMessageToText(message));
|
||||
if (next) {
|
||||
indent++;
|
||||
next.forEach(kid => text += expectedDiagnosticMessageChainToText(kid, indent));
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
function expectedDiagnosticRelatedInformationToText({ location, ...diagnosticMessage }: ExpectedDiagnosticRelatedInformation) {
|
||||
const text = expectedDiagnosticMessageChainToText(diagnosticMessage);
|
||||
if (location) {
|
||||
const { file, start, length } = location;
|
||||
return `${file}(${start}:${length}):: ${text}`;
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
function expectedErrorDiagnosticToText({ relatedInformation, ...diagnosticRelatedInformation }: ExpectedErrorDiagnostic) {
|
||||
let text = `${DiagnosticKind.Error}!: ${expectedDiagnosticRelatedInformationToText(diagnosticRelatedInformation)}`;
|
||||
if (relatedInformation) {
|
||||
for (const kid of relatedInformation) {
|
||||
text += `
|
||||
related:: ${expectedDiagnosticRelatedInformationToText(kid)}`;
|
||||
}
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
function expectedDiagnosticToText(errorOrStatus: ExpectedDiagnostic) {
|
||||
return ts.isArray(errorOrStatus) ?
|
||||
`${DiagnosticKind.Status}!: ${expectedDiagnosticMessageToText(errorOrStatus)}` :
|
||||
expectedErrorDiagnosticToText(errorOrStatus);
|
||||
}
|
||||
|
||||
function diagnosticMessageChainToText({ messageText, next }: ts.DiagnosticMessageChain, indent = 0) {
|
||||
let text = indentedText(indent, messageText);
|
||||
if (next) {
|
||||
indent++;
|
||||
next.forEach(kid => text += diagnosticMessageChainToText(kid, indent));
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
function diagnosticRelatedInformationToText({ file, start, length, messageText }: ts.DiagnosticRelatedInformation) {
|
||||
const text = typeof messageText === "string" ?
|
||||
messageText :
|
||||
diagnosticMessageChainToText(messageText);
|
||||
return file ?
|
||||
`${file.fileName}(${start}:${length}):: ${text}` :
|
||||
text;
|
||||
}
|
||||
|
||||
function diagnosticToText({ kind, diagnostic: { relatedInformation, ...diagnosticRelatedInformation } }: SolutionBuilderDiagnostic) {
|
||||
let text = `${kind}!: ${diagnosticRelatedInformationToText(diagnosticRelatedInformation)}`;
|
||||
if (relatedInformation) {
|
||||
for (const kid of relatedInformation) {
|
||||
text += `
|
||||
related:: ${diagnosticRelatedInformationToText(kid)}`;
|
||||
}
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
export const version = "FakeTSVersion";
|
||||
|
||||
export function patchHostForBuildInfoReadWrite<T extends ts.System>(sys: T) {
|
||||
const originalReadFile = sys.readFile;
|
||||
sys.readFile = (path, encoding) => {
|
||||
const value = originalReadFile.call(sys, path, encoding);
|
||||
if (!value || !ts.isBuildInfoFile(path)) return value;
|
||||
const buildInfo = ts.getBuildInfo(path, value);
|
||||
if (!buildInfo) return value;
|
||||
ts.Debug.assert(buildInfo.version === version);
|
||||
buildInfo.version = ts.version;
|
||||
return ts.getBuildInfoText(buildInfo);
|
||||
};
|
||||
return patchHostForBuildInfoWrite(sys, version);
|
||||
}
|
||||
|
||||
export function patchHostForBuildInfoWrite<T extends ts.System>(sys: T, version: string) {
|
||||
const originalWrite = sys.write;
|
||||
sys.write = msg => originalWrite.call(sys, msg.replace(ts.version, version));
|
||||
const originalWriteFile = sys.writeFile;
|
||||
sys.writeFile = (fileName: string, content: string, writeByteOrderMark: boolean) => {
|
||||
if (ts.isBuildInfoFile(fileName)) {
|
||||
const buildInfo = ts.getBuildInfo(fileName, content);
|
||||
if (buildInfo) {
|
||||
buildInfo.version = version;
|
||||
return originalWriteFile.call(sys, fileName, ts.getBuildInfoText(buildInfo), writeByteOrderMark);
|
||||
}
|
||||
}
|
||||
return originalWriteFile.call(sys, fileName, content, writeByteOrderMark);
|
||||
};
|
||||
return sys;
|
||||
}
|
||||
|
||||
export class SolutionBuilderHost extends CompilerHost implements ts.SolutionBuilderHost<ts.BuilderProgram> {
|
||||
createProgram: ts.CreateProgram<ts.BuilderProgram>;
|
||||
|
||||
private constructor(sys: System | vfs.FileSystem, options?: ts.CompilerOptions, setParentNodes?: boolean, createProgram?: ts.CreateProgram<ts.BuilderProgram>, jsDocParsingMode?: ts.JSDocParsingMode) {
|
||||
super(sys, options, setParentNodes, jsDocParsingMode);
|
||||
this.createProgram = createProgram || ts.createEmitAndSemanticDiagnosticsBuilderProgram as unknown as ts.CreateProgram<ts.BuilderProgram>;
|
||||
}
|
||||
|
||||
static create(sys: System | vfs.FileSystem, options?: ts.CompilerOptions, setParentNodes?: boolean, createProgram?: ts.CreateProgram<ts.BuilderProgram>, jsDocParsingMode?: ts.JSDocParsingMode) {
|
||||
const host = new SolutionBuilderHost(sys, options, setParentNodes, createProgram, jsDocParsingMode);
|
||||
patchHostForBuildInfoReadWrite(host.sys);
|
||||
return host;
|
||||
}
|
||||
|
||||
createHash(data: string) {
|
||||
return `${ts.generateDjb2Hash(data)}-${data}`;
|
||||
}
|
||||
|
||||
diagnostics: SolutionBuilderDiagnostic[] = [];
|
||||
|
||||
reportDiagnostic(diagnostic: ts.Diagnostic) {
|
||||
this.diagnostics.push({ kind: DiagnosticKind.Error, diagnostic });
|
||||
}
|
||||
|
||||
reportSolutionBuilderStatus(diagnostic: ts.Diagnostic) {
|
||||
this.diagnostics.push({ kind: DiagnosticKind.Status, diagnostic });
|
||||
}
|
||||
|
||||
clearDiagnostics() {
|
||||
this.diagnostics.length = 0;
|
||||
}
|
||||
|
||||
assertDiagnosticMessages(...expectedDiagnostics: ExpectedDiagnostic[]) {
|
||||
const actual = this.diagnostics.slice().map(diagnosticToText);
|
||||
const expected = expectedDiagnostics.map(expectedDiagnosticToText);
|
||||
assert.deepEqual(
|
||||
actual,
|
||||
expected,
|
||||
`Diagnostic arrays did not match:
|
||||
Actual: ${JSON.stringify(actual, /*replacer*/ undefined, " ")}
|
||||
Expected: ${JSON.stringify(expected, /*replacer*/ undefined, " ")}`,
|
||||
);
|
||||
}
|
||||
|
||||
assertErrors(...expectedDiagnostics: ExpectedErrorDiagnostic[]) {
|
||||
const actual = this.diagnostics.filter(d => d.kind === DiagnosticKind.Error).map(diagnosticToText);
|
||||
const expected = expectedDiagnostics.map(expectedDiagnosticToText);
|
||||
assert.deepEqual(
|
||||
actual,
|
||||
expected,
|
||||
`Diagnostics arrays did not match:
|
||||
Actual: ${JSON.stringify(actual, /*replacer*/ undefined, " ")}
|
||||
Expected: ${JSON.stringify(expected, /*replacer*/ undefined, " ")}
|
||||
Actual All:: ${JSON.stringify(this.diagnostics.slice().map(diagnosticToText), /*replacer*/ undefined, " ")}`,
|
||||
);
|
||||
}
|
||||
|
||||
printDiagnostics(header = "== Diagnostics ==") {
|
||||
const out = ts.createDiagnosticReporter(ts.sys);
|
||||
ts.sys.write(header + "\r\n");
|
||||
for (const { diagnostic } of this.diagnostics) {
|
||||
out(diagnostic);
|
||||
}
|
||||
}
|
||||
|
||||
now() {
|
||||
return this.sys.now();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,11 @@ import * as vpath from "./_namespaces/vpath.js";
|
||||
import { LoggerWithInMemoryLogs } from "./tsserverLogger.js";
|
||||
|
||||
import ArrayOrSingle = FourSlashInterface.ArrayOrSingle;
|
||||
import {
|
||||
harnessSessionLibLocation,
|
||||
harnessTypingInstallerCacheLocation,
|
||||
} from "./harnessLanguageService.js";
|
||||
import { ensureWatchablePath } from "./watchUtils.js";
|
||||
|
||||
export const enum FourSlashTestType {
|
||||
Native,
|
||||
@@ -318,7 +323,17 @@ export class TestState {
|
||||
let startResolveFileRef: FourSlashFile | undefined;
|
||||
|
||||
let configFileName: string | undefined;
|
||||
if (testData.symlinks && this.testType === FourSlashTestType.Server) {
|
||||
for (const symlink of ts.getOwnKeys(testData.symlinks)) {
|
||||
ensureWatchablePath(ts.getDirectoryPath(symlink), `Directory of input link: ${symlink}`);
|
||||
const target = (testData.symlinks[symlink] as vfs.Symlink).symlink;
|
||||
ensureWatchablePath(ts.getDirectoryPath(target), `Directory of target link: ${target} for symlink ${symlink}`);
|
||||
}
|
||||
}
|
||||
for (const file of testData.files) {
|
||||
if (this.testType === FourSlashTestType.Server) {
|
||||
ensureWatchablePath(ts.getDirectoryPath(file.fileName), `Directory of input file: ${file.fileName}`);
|
||||
}
|
||||
// Create map between fileName and its content for easily looking up when resolveReference flag is specified
|
||||
this.inputFiles.set(file.fileName, file.content);
|
||||
if (isConfig(file)) {
|
||||
@@ -348,6 +363,11 @@ export class TestState {
|
||||
}
|
||||
}
|
||||
|
||||
const libName = (name: string) =>
|
||||
this.testType !== FourSlashTestType.Server ?
|
||||
name :
|
||||
`${harnessSessionLibLocation}/${name}`;
|
||||
|
||||
let configParseResult: ts.ParsedCommandLine | undefined;
|
||||
if (configFileName) {
|
||||
const baseDir = ts.normalizePath(ts.getDirectoryPath(configFileName));
|
||||
@@ -401,13 +421,21 @@ export class TestState {
|
||||
|
||||
// Check if no-default-lib flag is false and if so add default library
|
||||
if (!resolvedResult.isLibFile) {
|
||||
this.languageServiceAdapterHost.addScript(Harness.Compiler.defaultLibFileName, Harness.Compiler.getDefaultLibrarySourceFile()!.text, /*isRootFile*/ false);
|
||||
this.languageServiceAdapterHost.addScript(
|
||||
libName(Harness.Compiler.defaultLibFileName),
|
||||
Harness.Compiler.getDefaultLibrarySourceFile()!.text,
|
||||
/*isRootFile*/ false,
|
||||
);
|
||||
|
||||
compilationOptions.lib?.forEach(fileName => {
|
||||
const libFile = Harness.Compiler.getDefaultLibrarySourceFile(fileName);
|
||||
ts.Debug.assertIsDefined(libFile, `Could not find lib file '${fileName}'`);
|
||||
if (libFile) {
|
||||
this.languageServiceAdapterHost.addScript(fileName, libFile.text, /*isRootFile*/ false);
|
||||
this.languageServiceAdapterHost.addScript(
|
||||
libName(fileName),
|
||||
libFile.text,
|
||||
/*isRootFile*/ false,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -419,7 +447,7 @@ export class TestState {
|
||||
// all files if config file not specified, otherwise root files from the config and typings cache files are root files
|
||||
const isRootFile = !configParseResult ||
|
||||
ts.contains(configParseResult.fileNames, fileName) ||
|
||||
(ts.isDeclarationFileName(fileName) && ts.containsPath("/Library/Caches/typescript", fileName));
|
||||
(ts.isDeclarationFileName(fileName) && ts.containsPath(harnessTypingInstallerCacheLocation, fileName));
|
||||
this.languageServiceAdapterHost.addScript(fileName, file, isRootFile);
|
||||
}
|
||||
});
|
||||
@@ -431,7 +459,7 @@ export class TestState {
|
||||
seen.add(fileName);
|
||||
const libFile = Harness.Compiler.getDefaultLibrarySourceFile(fileName);
|
||||
ts.Debug.assertIsDefined(libFile, `Could not find lib file '${fileName}'`);
|
||||
this.languageServiceAdapterHost.addScript(fileName, libFile.text, /*isRootFile*/ false);
|
||||
this.languageServiceAdapterHost.addScript(libName(fileName), libFile.text, /*isRootFile*/ false);
|
||||
if (!ts.some(libFile.libReferenceDirectives)) return;
|
||||
for (const directive of libFile.libReferenceDirectives) {
|
||||
addSourceFile(`lib.${directive.fileName}.d.ts`);
|
||||
|
||||
@@ -249,6 +249,8 @@ export abstract class LanguageServiceAdapterHost {
|
||||
}
|
||||
}
|
||||
|
||||
/** TypeScript Typings Installer global cache location for the tests */
|
||||
export const harnessTypingInstallerCacheLocation = "/home/src/Library/Caches/typescript";
|
||||
/// Native adapter
|
||||
class NativeLanguageServiceHost extends LanguageServiceAdapterHost implements ts.LanguageServiceHost, LanguageServiceAdapterHost {
|
||||
isKnownTypesPackageName(name: string): boolean {
|
||||
@@ -256,7 +258,7 @@ class NativeLanguageServiceHost extends LanguageServiceAdapterHost implements ts
|
||||
}
|
||||
|
||||
getGlobalTypingsCacheLocation() {
|
||||
return "/Library/Caches/typescript";
|
||||
return harnessTypingInstallerCacheLocation;
|
||||
}
|
||||
|
||||
installPackage = ts.notImplemented;
|
||||
@@ -348,6 +350,11 @@ export class NativeLanguageServiceAdapter implements LanguageServiceAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is set to vscode so that in tsserver tests its what is expected
|
||||
* and is unrelated and is error to not specify for tsc tests
|
||||
*/
|
||||
export const harnessSessionCurrentDirectory = "/home/src/Vscode/Projects/bin";
|
||||
// Server adapter
|
||||
class SessionClientHost extends NativeLanguageServiceHost implements ts.server.SessionClientHost {
|
||||
private client!: ts.server.SessionClient;
|
||||
@@ -356,6 +363,10 @@ class SessionClientHost extends NativeLanguageServiceHost implements ts.server.S
|
||||
super(cancellationToken, settings);
|
||||
}
|
||||
|
||||
override getCurrentDirectory(): string {
|
||||
return harnessSessionCurrentDirectory;
|
||||
}
|
||||
|
||||
onMessage = ts.noop;
|
||||
writeMessage = ts.noop;
|
||||
|
||||
@@ -382,6 +393,9 @@ interface ServerHostFileWatcher {
|
||||
interface ServerHostDirectoryWatcher {
|
||||
cb: ts.DirectoryWatcherCallback;
|
||||
}
|
||||
|
||||
/** Default typescript and lib installs location for tests */
|
||||
export const harnessSessionLibLocation = "/home/src/tslibs/TS/Lib";
|
||||
class SessionServerHost implements ts.server.ServerHost {
|
||||
args: string[] = [];
|
||||
newLine: string;
|
||||
@@ -404,10 +418,6 @@ class SessionServerHost implements ts.server.ServerHost {
|
||||
}
|
||||
|
||||
readFile(fileName: string): string | undefined {
|
||||
if (fileName.includes(Compiler.defaultLibFileName)) {
|
||||
fileName = Compiler.defaultLibFileName;
|
||||
}
|
||||
|
||||
// System FS would follow symlinks, even though snapshots are stored by original file name
|
||||
const snapshot = this.host.getScriptSnapshot(fileName) || this.host.getScriptSnapshot(this.realpath(fileName));
|
||||
return snapshot && ts.getSnapshotText(snapshot);
|
||||
@@ -433,7 +443,7 @@ class SessionServerHost implements ts.server.ServerHost {
|
||||
}
|
||||
|
||||
getExecutingFilePath(): string {
|
||||
return "";
|
||||
return harnessSessionLibLocation + "/tsc.js";
|
||||
}
|
||||
|
||||
exit = ts.noop;
|
||||
@@ -631,7 +641,10 @@ export class ServerLanguageServiceAdapter implements LanguageServiceAdapter {
|
||||
cancellationToken: ts.server.nullCancellationToken,
|
||||
useSingleInferredProject: false,
|
||||
useInferredProjectPerProjectRoot: false,
|
||||
typingsInstaller: { ...ts.server.nullTypingsInstaller, globalTypingsCacheLocation: "/Library/Caches/typescript" },
|
||||
typingsInstaller: {
|
||||
...ts.server.nullTypingsInstaller,
|
||||
globalTypingsCacheLocation: harnessTypingInstallerCacheLocation,
|
||||
},
|
||||
byteLength: Buffer.byteLength,
|
||||
hrtime: process.hrtime,
|
||||
logger: this.logger,
|
||||
|
||||
@@ -57,7 +57,6 @@ function handleLoggerGroup(logger: Logger, host: ts.server.ServerHost, sanitizeL
|
||||
logger.hasLevel = ts.returnTrue;
|
||||
logger.loggingEnabled = ts.returnTrue;
|
||||
logger.host = host;
|
||||
if (host) logger.logs!.push(`currentDirectory:: ${host.getCurrentDirectory()} useCaseSensitiveFileNames: ${host.useCaseSensitiveFileNames}`);
|
||||
|
||||
let inGroup = false;
|
||||
let firstInGroup = false;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import {
|
||||
arrayFrom,
|
||||
canWatchDirectoryOrFile,
|
||||
compareStringsCaseSensitive,
|
||||
contains,
|
||||
createMultiMap,
|
||||
@@ -7,11 +8,20 @@ import {
|
||||
FileWatcher,
|
||||
FileWatcherCallback,
|
||||
GetCanonicalFileName,
|
||||
getPathComponents,
|
||||
MultiMap,
|
||||
Path,
|
||||
PollingInterval,
|
||||
System,
|
||||
} from "./_namespaces/ts.js";
|
||||
|
||||
export function ensureWatchablePath(path: string, locationType: string) {
|
||||
Debug.assert(
|
||||
canWatchDirectoryOrFile(getPathComponents(path as Path)),
|
||||
`Not a watchable location: ${locationType} like "/home/src/workspaces/project" or refer canWatchDirectoryOrFile for more allowed locations`,
|
||||
);
|
||||
}
|
||||
|
||||
export interface TestFileWatcher {
|
||||
cb: FileWatcherCallback;
|
||||
pollingInterval: PollingInterval;
|
||||
|
||||
@@ -1336,6 +1336,10 @@ export class ProjectService {
|
||||
: undefined;
|
||||
this.throttledOperations = new ThrottledOperations(this.host, this.logger);
|
||||
|
||||
this.logger.info(`currentDirectory:: ${this.host.getCurrentDirectory()} useCaseSensitiveFileNames:: ${this.host.useCaseSensitiveFileNames}`);
|
||||
this.logger.info(`libs Location:: ${getDirectoryPath(this.host.getExecutingFilePath())}`);
|
||||
this.logger.info(`globalTypingsCacheLocation:: ${this.typingsInstaller.globalTypingsCacheLocation}`);
|
||||
|
||||
if (this.typesMapLocation) {
|
||||
this.loadTypesMap();
|
||||
}
|
||||
@@ -2684,7 +2688,6 @@ export class ProjectService {
|
||||
/** @internal */
|
||||
createConfiguredProject(configFileName: NormalizedPath, reason: string) {
|
||||
tracing?.instant(tracing.Phase.Session, "createConfiguredProject", { configFilePath: configFileName });
|
||||
this.logger.info(`Creating configuration project ${configFileName}`);
|
||||
const canonicalConfigFilePath = asNormalizedPath(this.toCanonicalFileName(configFileName));
|
||||
let configFileExistenceInfo = this.configFileExistenceInfoCache.get(canonicalConfigFilePath);
|
||||
// We could be in this scenario if project is the configured project tracked by external project
|
||||
|
||||
@@ -573,6 +573,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo
|
||||
directoryStructureHost: DirectoryStructureHost,
|
||||
currentDirectory: string,
|
||||
) {
|
||||
projectService.logger.info(`Creating ${ProjectKind[projectKind]}Project: ${projectName}, currentDirectory: ${currentDirectory}`);
|
||||
this.projectName = projectName;
|
||||
this.directoryStructureHost = directoryStructureHost;
|
||||
this.currentDirectory = this.projectService.getNormalizedAbsolutePath(currentDirectory);
|
||||
@@ -1622,7 +1623,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo
|
||||
|
||||
protected removeExistingTypings(include: string[]): string[] {
|
||||
if (!include.length) return include;
|
||||
const existing = getAutomaticTypeDirectiveNames(this.getCompilerOptions(), this.directoryStructureHost);
|
||||
const existing = getAutomaticTypeDirectiveNames(this.getCompilerOptions(), this);
|
||||
return filter(include, i => !existing.includes(i));
|
||||
}
|
||||
|
||||
|
||||
@@ -136,6 +136,7 @@ export * from "./unittests/tscWatch/extends.js";
|
||||
export * from "./unittests/tscWatch/forceConsistentCasingInFileNames.js";
|
||||
export * from "./unittests/tscWatch/incremental.js";
|
||||
export * from "./unittests/tscWatch/libraryResolution.js";
|
||||
export * from "./unittests/tscWatch/listFilesOnly.js";
|
||||
export * from "./unittests/tscWatch/moduleResolution.js";
|
||||
export * from "./unittests/tscWatch/nodeNextWatch.js";
|
||||
export * from "./unittests/tscWatch/noEmit.js";
|
||||
@@ -200,7 +201,6 @@ export * from "./unittests/tsserver/pasteEdits.js";
|
||||
export * from "./unittests/tsserver/plugins.js";
|
||||
export * from "./unittests/tsserver/pluginsAsync.js";
|
||||
export * from "./unittests/tsserver/projectErrors.js";
|
||||
export * from "./unittests/tsserver/projectImportHelpers.js";
|
||||
export * from "./unittests/tsserver/projectReferenceCompileOnSave.js";
|
||||
export * from "./unittests/tsserver/projectReferenceErrors.js";
|
||||
export * from "./unittests/tsserver/projectReferences.js";
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { dedent } from "../../_namespaces/Utils.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import { FsContents } from "./contents.js";
|
||||
import { libFile } from "./virtualFileSystemWithWatch.js";
|
||||
import { TscWatchCompileChange } from "./tscWatch.js";
|
||||
import { TestServerHost } from "./virtualFileSystemWithWatch.js";
|
||||
|
||||
export function getFsConentsForAlternateResultAtTypesPackageJson(packageName: string, addTypesCondition: boolean) {
|
||||
function getFsConentsForAlternateResultAtTypesPackageJson(packageName: string, addTypesCondition: boolean) {
|
||||
return jsonToReadableText({
|
||||
name: `@types/${packageName}`,
|
||||
version: "1.0.0",
|
||||
@@ -17,7 +17,7 @@ export function getFsConentsForAlternateResultAtTypesPackageJson(packageName: st
|
||||
});
|
||||
}
|
||||
|
||||
export function getFsContentsForAlternateResultPackageJson(packageName: string, addTypes: boolean, addTypesCondition: boolean) {
|
||||
function getFsContentsForAlternateResultPackageJson(packageName: string, addTypes: boolean, addTypesCondition: boolean) {
|
||||
return jsonToReadableText({
|
||||
name: packageName,
|
||||
version: "1.0.0",
|
||||
@@ -33,7 +33,7 @@ export function getFsContentsForAlternateResultPackageJson(packageName: string,
|
||||
});
|
||||
}
|
||||
|
||||
export function getFsContentsForAlternateResultDts(packageName: string) {
|
||||
function getFsContentsForAlternateResultDts(packageName: string) {
|
||||
return `export declare const ${packageName}: number;`;
|
||||
}
|
||||
|
||||
@@ -45,8 +45,8 @@ function mjs(packageName: string) {
|
||||
return `export const ${packageName} = 1;`;
|
||||
}
|
||||
|
||||
export function getFsContentsForAlternateResult(): FsContents {
|
||||
return {
|
||||
function getSysForAlternateResult(forTsserver: boolean) {
|
||||
return TestServerHost.getCreateWatchedSystem(forTsserver)({
|
||||
"/home/src/projects/project/node_modules/@types/bar/package.json": getFsConentsForAlternateResultAtTypesPackageJson("bar", /*addTypesCondition*/ false),
|
||||
"/home/src/projects/project/node_modules/@types/bar/index.d.ts": getFsContentsForAlternateResultDts("bar"),
|
||||
"/home/src/projects/project/node_modules/bar/package.json": getFsContentsForAlternateResultPackageJson("bar", /*addTypes*/ false, /*addTypesCondition*/ false),
|
||||
@@ -81,6 +81,117 @@ export function getFsContentsForAlternateResult(): FsContents {
|
||||
},
|
||||
files: ["index.mts"],
|
||||
}),
|
||||
[libFile.path]: libFile.content,
|
||||
};
|
||||
}, { currentDirectory: "/home/src/projects/project" });
|
||||
}
|
||||
|
||||
export function verifyAlternateResultScenario(
|
||||
forTsserver: boolean,
|
||||
action: (
|
||||
scenario: string,
|
||||
sys: () => TestServerHost,
|
||||
edits: () => readonly TscWatchCompileChange[],
|
||||
) => void,
|
||||
) {
|
||||
action(
|
||||
"alternateResult",
|
||||
() => getSysForAlternateResult(forTsserver),
|
||||
() => [
|
||||
{
|
||||
caption: "delete the alternateResult in @types",
|
||||
edit: sys => sys.deleteFile("/home/src/projects/project/node_modules/@types/bar/index.d.ts"),
|
||||
timeouts: sys => {
|
||||
sys.runQueuedTimeoutCallbacks();
|
||||
sys.runQueuedTimeoutCallbacks();
|
||||
},
|
||||
},
|
||||
{
|
||||
caption: "delete the ndoe10Result in package/types",
|
||||
edit: sys => sys.deleteFile("/home/src/projects/project/node_modules/foo/index.d.ts"),
|
||||
timeouts: sys => {
|
||||
sys.runQueuedTimeoutCallbacks();
|
||||
sys.runQueuedTimeoutCallbacks();
|
||||
},
|
||||
},
|
||||
{
|
||||
caption: "add the alternateResult in @types",
|
||||
edit: sys => sys.writeFile("/home/src/projects/project/node_modules/@types/bar/index.d.ts", getFsContentsForAlternateResultDts("bar")),
|
||||
timeouts: sys => {
|
||||
sys.runQueuedTimeoutCallbacks();
|
||||
sys.runQueuedTimeoutCallbacks();
|
||||
},
|
||||
},
|
||||
{
|
||||
caption: "add the alternateResult in package/types",
|
||||
edit: sys => sys.writeFile("/home/src/projects/project/node_modules/foo/index.d.ts", getFsContentsForAlternateResultDts("foo")),
|
||||
timeouts: sys => {
|
||||
sys.runQueuedTimeoutCallbacks();
|
||||
sys.runQueuedTimeoutCallbacks();
|
||||
},
|
||||
},
|
||||
{
|
||||
caption: "update package.json from @types so error is fixed",
|
||||
edit: sys => sys.writeFile("/home/src/projects/project/node_modules/@types/bar/package.json", getFsConentsForAlternateResultAtTypesPackageJson("bar", /*addTypesCondition*/ true)),
|
||||
timeouts: sys => {
|
||||
sys.runQueuedTimeoutCallbacks();
|
||||
sys.runQueuedTimeoutCallbacks();
|
||||
},
|
||||
},
|
||||
{
|
||||
caption: "update package.json so error is fixed",
|
||||
edit: sys => sys.writeFile("/home/src/projects/project/node_modules/foo/package.json", getFsContentsForAlternateResultPackageJson("foo", /*addTypes*/ true, /*addTypesCondition*/ true)),
|
||||
timeouts: sys => {
|
||||
sys.runQueuedTimeoutCallbacks();
|
||||
sys.runQueuedTimeoutCallbacks();
|
||||
},
|
||||
},
|
||||
{
|
||||
caption: "update package.json from @types so error is introduced",
|
||||
edit: sys => sys.writeFile("/home/src/projects/project/node_modules/@types/bar2/package.json", getFsConentsForAlternateResultAtTypesPackageJson("bar2", /*addTypesCondition*/ false)),
|
||||
timeouts: sys => {
|
||||
sys.runQueuedTimeoutCallbacks();
|
||||
sys.runQueuedTimeoutCallbacks();
|
||||
},
|
||||
},
|
||||
{
|
||||
caption: "update package.json so error is introduced",
|
||||
edit: sys => sys.writeFile("/home/src/projects/project/node_modules/foo2/package.json", getFsContentsForAlternateResultPackageJson("foo2", /*addTypes*/ true, /*addTypesCondition*/ false)),
|
||||
timeouts: sys => {
|
||||
sys.runQueuedTimeoutCallbacks();
|
||||
sys.runQueuedTimeoutCallbacks();
|
||||
},
|
||||
},
|
||||
{
|
||||
caption: "delete the alternateResult in @types",
|
||||
edit: sys => sys.deleteFile("/home/src/projects/project/node_modules/@types/bar2/index.d.ts"),
|
||||
timeouts: sys => {
|
||||
sys.runQueuedTimeoutCallbacks();
|
||||
sys.runQueuedTimeoutCallbacks();
|
||||
},
|
||||
},
|
||||
{
|
||||
caption: "delete the ndoe10Result in package/types",
|
||||
edit: sys => sys.deleteFile("/home/src/projects/project/node_modules/foo2/index.d.ts"),
|
||||
timeouts: sys => {
|
||||
sys.runQueuedTimeoutCallbacks();
|
||||
sys.runQueuedTimeoutCallbacks();
|
||||
},
|
||||
},
|
||||
{
|
||||
caption: "add the alternateResult in @types",
|
||||
edit: sys => sys.writeFile("/home/src/projects/project/node_modules/@types/bar2/index.d.ts", getFsContentsForAlternateResultDts("bar2")),
|
||||
timeouts: sys => {
|
||||
sys.runQueuedTimeoutCallbacks();
|
||||
sys.runQueuedTimeoutCallbacks();
|
||||
},
|
||||
},
|
||||
{
|
||||
caption: "add the ndoe10Result in package/types",
|
||||
edit: sys => sys.writeFile("/home/src/projects/project/node_modules/foo2/index.d.ts", getFsContentsForAlternateResultDts("foo2")),
|
||||
timeouts: sys => {
|
||||
sys.runQueuedTimeoutCallbacks();
|
||||
sys.runQueuedTimeoutCallbacks();
|
||||
},
|
||||
},
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
import * as fakes from "../../_namespaces/fakes.js";
|
||||
import * as Harness from "../../_namespaces/Harness.js";
|
||||
import { SourceMapRecorder } from "../../_namespaces/Harness.js";
|
||||
import * as ts from "../../_namespaces/ts.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import { TscCompileSystem } from "./tsc.js";
|
||||
import { TestServerHost } from "./virtualFileSystemWithWatch.js";
|
||||
|
||||
export function sanitizeSysOutput(output: string) {
|
||||
return output
|
||||
.replace(/Elapsed::\s\d+(?:\.\d+)?ms/g, "Elapsed:: *ms")
|
||||
.replace(/\d\d:\d\d:\d\d\s(?:A|P)M/g, "HH:MM:SS AM");
|
||||
}
|
||||
import {
|
||||
changeToHostTrackingWrittenFiles,
|
||||
SerializeOutputOrder,
|
||||
StateLogger,
|
||||
TestServerHost,
|
||||
TestServerHostTrackingWrittenFiles,
|
||||
} from "./virtualFileSystemWithWatch.js";
|
||||
|
||||
export type CommandLineProgram = [ts.Program, ts.BuilderProgram?];
|
||||
export interface CommandLineCallbacks {
|
||||
@@ -21,7 +19,7 @@ function isAnyProgram(program: ts.Program | ts.BuilderProgram | ts.ParsedCommand
|
||||
return !!(program as ts.Program | ts.BuilderProgram).getCompilerOptions;
|
||||
}
|
||||
export function commandLineCallbacks(
|
||||
sys: TscCompileSystem | TestServerHost,
|
||||
sys: TestServerHost,
|
||||
originalReadCall?: ts.System["readFile"],
|
||||
): CommandLineCallbacks {
|
||||
let programs: CommandLineProgram[] | undefined;
|
||||
@@ -48,7 +46,12 @@ export function commandLineCallbacks(
|
||||
};
|
||||
}
|
||||
|
||||
export function baselinePrograms(baseline: string[], programs: readonly CommandLineProgram[], oldPrograms: readonly (CommandLineProgram | undefined)[], baselineDependencies: boolean | undefined) {
|
||||
function baselinePrograms(
|
||||
baseline: string[],
|
||||
programs: readonly CommandLineProgram[],
|
||||
oldPrograms: readonly (CommandLineProgram | undefined)[],
|
||||
baselineDependencies: boolean | undefined,
|
||||
) {
|
||||
for (let i = 0; i < programs.length; i++) {
|
||||
baselineProgram(baseline, programs[i], oldPrograms[i], baselineDependencies);
|
||||
}
|
||||
@@ -127,10 +130,10 @@ function baselineProgram(baseline: string[], [program, builderProgram]: CommandL
|
||||
baseline.push("");
|
||||
}
|
||||
|
||||
export function generateSourceMapBaselineFiles(sys: ts.System & { writtenFiles: ts.ReadonlyCollection<ts.Path>; }) {
|
||||
function generateSourceMapBaselineFiles(sys: ts.System & { writtenFiles: ts.ReadonlyCollection<ts.Path>; }) {
|
||||
const mapFileNames = ts.mapDefinedIterator(sys.writtenFiles.keys(), f => f.endsWith(".map") ? f : undefined);
|
||||
for (const mapFile of mapFileNames) {
|
||||
const text = Harness.SourceMapRecorder.getSourceMapRecordWithSystem(sys, mapFile);
|
||||
const text = SourceMapRecorder.getSourceMapRecordWithSystem(sys, mapFile);
|
||||
sys.writeFile(`${mapFile}.baseline.txt`, text);
|
||||
}
|
||||
}
|
||||
@@ -228,7 +231,7 @@ export interface ReadableBuildInfo extends ts.BuildInfo {
|
||||
function generateBuildInfoBaseline(sys: ts.System, buildInfoPath: string, buildInfo: ts.BuildInfo) {
|
||||
let fileIdsList: string[][] | undefined;
|
||||
let result;
|
||||
const version = buildInfo.version === ts.version ? fakes.version : buildInfo.version;
|
||||
const version = buildInfo.version === ts.version ? fakeTsVersion : buildInfo.version;
|
||||
if (!ts.isIncrementalBuildInfo(buildInfo)) {
|
||||
result = {
|
||||
...buildInfo,
|
||||
@@ -396,7 +399,7 @@ export function toPathWithSystem(sys: ts.System, fileName: string): ts.Path {
|
||||
|
||||
export function baselineBuildInfo(
|
||||
options: ts.CompilerOptions,
|
||||
sys: TscCompileSystem | TestServerHost,
|
||||
sys: TestServerHost,
|
||||
originalReadCall?: ts.System["readFile"],
|
||||
) {
|
||||
const buildInfoPath = ts.getTsBuildInfoEmitOutputFilePath(options);
|
||||
@@ -408,6 +411,119 @@ export function baselineBuildInfo(
|
||||
generateBuildInfoBaseline(sys, buildInfoPath, buildInfo);
|
||||
}
|
||||
|
||||
export function tscBaselineName(scenario: string, subScenario: string, commandLineArgs: readonly string[], isWatch?: boolean, suffix?: string) {
|
||||
return `${ts.isBuild(commandLineArgs) ? "tsbuild" : "tsc"}${isWatch ? "Watch" : ""}/${scenario}/${subScenario.split(" ").join("-")}${suffix ? suffix : ""}.js`;
|
||||
export function isWatch(commandLineArgs: readonly string[]) {
|
||||
return ts.forEach(commandLineArgs, arg => {
|
||||
if (arg.charCodeAt(0) !== ts.CharacterCodes.minus) return false;
|
||||
const option = arg.slice(arg.charCodeAt(1) === ts.CharacterCodes.minus ? 2 : 1).toLowerCase();
|
||||
return option === "watch" || option === "w";
|
||||
});
|
||||
}
|
||||
|
||||
export type TscWatchSystem = TestServerHostTrackingWrittenFiles;
|
||||
|
||||
function changeToTestServerHostWithTimeoutLogging(host: TestServerHostTrackingWrittenFiles, baseline: string[]): TscWatchSystem {
|
||||
const logger: StateLogger = {
|
||||
log: s => baseline.push(s),
|
||||
logs: baseline,
|
||||
};
|
||||
host.switchToBaseliningInvoke(logger, SerializeOutputOrder.BeforeDiff);
|
||||
return host;
|
||||
}
|
||||
|
||||
export interface BaselineBase {
|
||||
baseline: string[];
|
||||
sys: TscWatchSystem;
|
||||
}
|
||||
|
||||
export interface Baseline extends BaselineBase, CommandLineCallbacks {
|
||||
}
|
||||
|
||||
export const fakeTsVersion = "FakeTSVersion";
|
||||
|
||||
export function patchHostForBuildInfoReadWrite<T extends ts.System>(sys: T) {
|
||||
const originalReadFile = sys.readFile;
|
||||
sys.readFile = (path, encoding) => {
|
||||
const value = originalReadFile.call(sys, path, encoding);
|
||||
if (!value || !ts.isBuildInfoFile(path)) return value;
|
||||
const buildInfo = ts.getBuildInfo(path, value);
|
||||
if (!buildInfo) return value;
|
||||
ts.Debug.assert(buildInfo.version === fakeTsVersion);
|
||||
buildInfo.version = ts.version;
|
||||
return ts.getBuildInfoText(buildInfo);
|
||||
};
|
||||
return patchHostForBuildInfoWrite(sys, fakeTsVersion);
|
||||
}
|
||||
|
||||
export function patchHostForBuildInfoWrite<T extends ts.System>(sys: T, version: string) {
|
||||
const originalWrite = sys.write;
|
||||
sys.write = msg => originalWrite.call(sys, msg.replace(ts.version, version));
|
||||
const originalWriteFile = sys.writeFile;
|
||||
sys.writeFile = (fileName: string, content: string, writeByteOrderMark: boolean) => {
|
||||
if (ts.isBuildInfoFile(fileName)) {
|
||||
const buildInfo = ts.getBuildInfo(fileName, content);
|
||||
if (buildInfo) {
|
||||
buildInfo.version = version;
|
||||
return originalWriteFile.call(sys, fileName, ts.getBuildInfoText(buildInfo), writeByteOrderMark);
|
||||
}
|
||||
}
|
||||
return originalWriteFile.call(sys, fileName, content, writeByteOrderMark);
|
||||
};
|
||||
return sys;
|
||||
}
|
||||
|
||||
export function createBaseline(
|
||||
system: TestServerHost,
|
||||
modifySystem?: (sys: TestServerHost, originalRead: TestServerHost["readFile"]) => void,
|
||||
): Baseline {
|
||||
const originalRead = system.readFile;
|
||||
const initialSys = patchHostForBuildInfoReadWrite(system);
|
||||
modifySystem?.(initialSys, originalRead);
|
||||
const baseline: string[] = [];
|
||||
const sys = changeToTestServerHostWithTimeoutLogging(changeToHostTrackingWrittenFiles(initialSys), baseline);
|
||||
baseline.push(`currentDirectory:: ${sys.getCurrentDirectory()} useCaseSensitiveFileNames:: ${sys.useCaseSensitiveFileNames}`);
|
||||
baseline.push("Input::");
|
||||
sys.serializeState(baseline, SerializeOutputOrder.None);
|
||||
const { cb, getPrograms } = commandLineCallbacks(sys);
|
||||
return { sys, baseline, cb, getPrograms };
|
||||
}
|
||||
|
||||
export function applyEdit(
|
||||
sys: BaselineBase["sys"],
|
||||
baseline: BaselineBase["baseline"],
|
||||
edit: (sys: TscWatchSystem) => void,
|
||||
caption?: string,
|
||||
) {
|
||||
baseline.push(`Change::${caption ? " " + caption : ""}`, "");
|
||||
edit(sys);
|
||||
baseline.push("Input::");
|
||||
sys.serializeState(baseline, SerializeOutputOrder.AfterDiff);
|
||||
}
|
||||
|
||||
export function baselineAfterTscCompile(
|
||||
sys: BaselineBase["sys"],
|
||||
baseline: BaselineBase["baseline"],
|
||||
getPrograms: CommandLineCallbacks["getPrograms"],
|
||||
oldPrograms: readonly (CommandLineProgram | undefined)[],
|
||||
baselineSourceMap: boolean | undefined,
|
||||
shouldBaselinePrograms: boolean | undefined,
|
||||
baselineDependencies: boolean | undefined,
|
||||
) {
|
||||
if (baselineSourceMap) generateSourceMapBaselineFiles(sys);
|
||||
const programs = getPrograms();
|
||||
sys.writtenFiles.forEach((value, key) => {
|
||||
// When buildinfo is same for two projects,
|
||||
// it gives error and doesnt write buildinfo but because buildInfo is written for one project,
|
||||
// readable baseline will be written two times for those two projects with same contents and is ok
|
||||
ts.Debug.assert(value === 1 || ts.endsWith(key, "baseline.txt"), `Expected to write file ${key} only once`);
|
||||
});
|
||||
sys.serializeState(baseline, SerializeOutputOrder.BeforeDiff);
|
||||
if (shouldBaselinePrograms) {
|
||||
baselinePrograms(baseline, programs, oldPrograms, baselineDependencies);
|
||||
}
|
||||
baseline.push(`exitCode:: ExitStatus.${ts.ExitStatus[sys.exitCode as ts.ExitStatus]}`, "");
|
||||
return programs;
|
||||
}
|
||||
|
||||
export function tscBaselineName(scenario: string, subScenario: string, commandLineArgs: readonly string[], suffix?: string) {
|
||||
return `${ts.isBuild(commandLineArgs) ? "tsbuild" : "tsc"}${isWatch(commandLineArgs) ? "Watch" : ""}/${scenario}/${subScenario.split(" ").join("-")}${suffix ? suffix : ""}.js`;
|
||||
}
|
||||
|
||||
@@ -1,14 +1,27 @@
|
||||
import {
|
||||
harnessSessionLibLocation,
|
||||
harnessTypingInstallerCacheLocation,
|
||||
} from "../../../harness/harnessLanguageService.js";
|
||||
import * as ts from "../../_namespaces/ts.js";
|
||||
import { libFile } from "./virtualFileSystemWithWatch.js";
|
||||
|
||||
/** Default typescript and lib installs location for tests */
|
||||
export const tscTypeScriptTestLocation = getPathForTypeScriptTestLocation("tsc.js");
|
||||
export function getPathForTypeScriptTestLocation(fileName: string) {
|
||||
return ts.combinePaths(harnessSessionLibLocation, fileName);
|
||||
}
|
||||
|
||||
export function getTypeScriptLibTestLocation(libName: string) {
|
||||
return getPathForTypeScriptTestLocation(ts.libMap.get(libName) ?? `lib.${libName}.d.ts`);
|
||||
}
|
||||
|
||||
export function getPathForTypeScriptTypingInstallerCacheTest(fileName: string) {
|
||||
return `${harnessTypingInstallerCacheLocation}/${fileName}`;
|
||||
}
|
||||
|
||||
export function compilerOptionsToConfigJson(options: ts.CompilerOptions) {
|
||||
return ts.optionMapToObject(ts.serializeCompilerOptions(options));
|
||||
}
|
||||
|
||||
export const libContent = `${libFile.content}
|
||||
interface ReadonlyArray<T> {}
|
||||
declare const console: { log(msg: any): void; };`;
|
||||
|
||||
export const symbolLibContent = `
|
||||
interface SymbolConstructor {
|
||||
readonly species: symbol;
|
||||
@@ -20,14 +33,6 @@ interface Symbol {
|
||||
}
|
||||
`;
|
||||
|
||||
export interface FsContents {
|
||||
[path: string]: string;
|
||||
}
|
||||
|
||||
export function libPath(forLib: string) {
|
||||
return `${ts.getDirectoryPath(libFile.path)}/lib.${forLib}.d.ts`;
|
||||
}
|
||||
|
||||
export function getProjectConfigWithNodeNext(withNodeNext: boolean | undefined) {
|
||||
return withNodeNext ? { module: "nodenext", target: "es5" } : undefined;
|
||||
}
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
import { CompilerOptions } from "../../_namespaces/ts.js";
|
||||
import { dedent } from "../../_namespaces/Utils.js";
|
||||
import { FileSystem } from "../../_namespaces/vfs.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import { libContent } from "./contents.js";
|
||||
import { loadProjectFromFiles } from "./vfs.js";
|
||||
import { TestServerHost } from "./virtualFileSystemWithWatch.js";
|
||||
|
||||
export function getFsForDeclarationEmitWithErrors(options: CompilerOptions, incremental: true | undefined) {
|
||||
return loadProjectFromFiles({
|
||||
"/src/project/tsconfig.json": jsonToReadableText({
|
||||
function getSysForDeclarationEmitWithErrors(options: CompilerOptions, incremental: true | undefined) {
|
||||
return TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
module: "NodeNext",
|
||||
moduleResolution: "NodeNext",
|
||||
@@ -17,32 +15,31 @@ export function getFsForDeclarationEmitWithErrors(options: CompilerOptions, incr
|
||||
skipDefaultLibCheck: true,
|
||||
},
|
||||
}),
|
||||
"/src/project/index.ts": dedent`
|
||||
"/home/src/workspaces/project/index.ts": dedent`
|
||||
import ky from 'ky';
|
||||
export const api = ky.extend({});
|
||||
`,
|
||||
"/src/project/package.json": jsonToReadableText({
|
||||
"/home/src/workspaces/project/package.json": jsonToReadableText({
|
||||
type: "module",
|
||||
}),
|
||||
"/src/project/node_modules/ky/distribution/index.d.ts": dedent`
|
||||
"/home/src/workspaces/project/node_modules/ky/distribution/index.d.ts": dedent`
|
||||
type KyInstance = {
|
||||
extend(options: Record<string,unknown>): KyInstance;
|
||||
}
|
||||
declare const ky: KyInstance;
|
||||
export default ky;
|
||||
`,
|
||||
"/src/project/node_modules/ky/package.json": jsonToReadableText({
|
||||
"/home/src/workspaces/project/node_modules/ky/package.json": jsonToReadableText({
|
||||
name: "ky",
|
||||
type: "module",
|
||||
main: "./distribution/index.js",
|
||||
}),
|
||||
"/lib/lib.esnext.full.d.ts": libContent,
|
||||
});
|
||||
}, { currentDirectory: "/home/src/workspaces/project" });
|
||||
}
|
||||
|
||||
export function getFsForDeclarationEmitWithErrorsWithOutFile(options: CompilerOptions, incremental: true | undefined) {
|
||||
return loadProjectFromFiles({
|
||||
"/src/project/tsconfig.json": jsonToReadableText({
|
||||
function getSysForDeclarationEmitWithErrorsWithOutFile(options: CompilerOptions, incremental: true | undefined) {
|
||||
return TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
module: "amd",
|
||||
...options,
|
||||
@@ -53,25 +50,24 @@ export function getFsForDeclarationEmitWithErrorsWithOutFile(options: CompilerOp
|
||||
},
|
||||
include: ["src"],
|
||||
}),
|
||||
"/src/project/src/index.ts": dedent`
|
||||
"/home/src/workspaces/project/src/index.ts": dedent`
|
||||
import ky from 'ky';
|
||||
export const api = ky.extend({});
|
||||
`,
|
||||
"/src/project/ky.d.ts": dedent`
|
||||
"/home/src/workspaces/project/ky.d.ts": dedent`
|
||||
type KyInstance = {
|
||||
extend(options: Record<string,unknown>): KyInstance;
|
||||
}
|
||||
declare const ky: KyInstance;
|
||||
export default ky;
|
||||
`,
|
||||
"/lib/lib.esnext.full.d.ts": libContent,
|
||||
});
|
||||
}, { currentDirectory: "/home/src/workspaces/project" });
|
||||
}
|
||||
|
||||
export function forEachDeclarationEmitWithErrorsScenario(
|
||||
action: (
|
||||
scenarioName: (scenario: string) => string,
|
||||
fs: () => FileSystem,
|
||||
sys: () => TestServerHost,
|
||||
) => void,
|
||||
withComposite: boolean,
|
||||
) {
|
||||
@@ -80,8 +76,8 @@ export function forEachDeclarationEmitWithErrorsScenario(
|
||||
action(
|
||||
scenario => `${outFile ? "outFile" : "multiFile"}/${scenario}${incremental ? " with incremental" : ""}`,
|
||||
() =>
|
||||
(outFile ? getFsForDeclarationEmitWithErrorsWithOutFile :
|
||||
getFsForDeclarationEmitWithErrors)(
|
||||
(outFile ? getSysForDeclarationEmitWithErrorsWithOutFile :
|
||||
getSysForDeclarationEmitWithErrors)(
|
||||
withComposite && incremental ?
|
||||
{ composite: true } :
|
||||
{ declaration: true },
|
||||
|
||||
@@ -1,14 +1,6 @@
|
||||
import { dedent } from "../../_namespaces/Utils.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import {
|
||||
FsContents,
|
||||
libContent,
|
||||
} from "./contents.js";
|
||||
import { loadProjectFromFiles } from "./vfs.js";
|
||||
import {
|
||||
createWatchedSystem,
|
||||
libFile,
|
||||
} from "./virtualFileSystemWithWatch.js";
|
||||
import { TestServerHost } from "./virtualFileSystemWithWatch.js";
|
||||
|
||||
export function getFsContentsForDemoProjectReferencesCoreConfig(additional?: object) {
|
||||
return jsonToReadableText({
|
||||
@@ -20,8 +12,8 @@ export function getFsContentsForDemoProjectReferencesCoreConfig(additional?: obj
|
||||
...additional,
|
||||
});
|
||||
}
|
||||
export function getFsContentsForDemoProjectReferences(): FsContents {
|
||||
return {
|
||||
export function getSysForDemoProjectReferences() {
|
||||
return TestServerHost.createWatchedSystem({
|
||||
"/user/username/projects/demo/animals/animal.ts": dedent`
|
||||
export type Size = "small" | "medium" | "large";
|
||||
export default interface Animal {
|
||||
@@ -124,25 +116,5 @@ export function getFsContentsForDemoProjectReferences(): FsContents {
|
||||
},
|
||||
],
|
||||
}),
|
||||
[libFile.path]: libContent,
|
||||
};
|
||||
}
|
||||
|
||||
export function getFsForDemoProjectReferences() {
|
||||
return loadProjectFromFiles(
|
||||
getFsContentsForDemoProjectReferences(),
|
||||
{
|
||||
cwd: "/user/username/projects/demo",
|
||||
executingFilePath: libFile.path,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
export function getSysForDemoProjectReferences() {
|
||||
return createWatchedSystem(
|
||||
getFsContentsForDemoProjectReferences(),
|
||||
{
|
||||
currentDirectory: "/user/username/projects/demo",
|
||||
},
|
||||
);
|
||||
}, { currentDirectory: "/user/username/projects/demo" });
|
||||
}
|
||||
|
||||
@@ -1,15 +1,10 @@
|
||||
import { dedent } from "../../_namespaces/Utils.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import { FsContents } from "./contents.js";
|
||||
import {
|
||||
createServerHost,
|
||||
createWatchedSystem,
|
||||
libFile,
|
||||
TestServerHost,
|
||||
} from "./virtualFileSystemWithWatch.js";
|
||||
import { TscWatchCompileChange } from "./tscWatch.js";
|
||||
import { TestServerHost } from "./virtualFileSystemWithWatch.js";
|
||||
|
||||
export function getSymlinkedExtendsSys(forTsserver?: true): TestServerHost {
|
||||
return (!forTsserver ? createWatchedSystem : createServerHost)({
|
||||
return TestServerHost.getCreateWatchedSystem(forTsserver)({
|
||||
"/users/user/projects/myconfigs/node_modules/@something/tsconfig-node/tsconfig.json": jsonToReadableText({
|
||||
extends: "@something/tsconfig-base/tsconfig.json",
|
||||
compilerOptions: {
|
||||
@@ -29,12 +24,11 @@ export function getSymlinkedExtendsSys(forTsserver?: true): TestServerHost {
|
||||
"/users/user/projects/myproject/node_modules/@something/tsconfig-node": {
|
||||
symLink: "/users/user/projects/myconfigs/node_modules/@something/tsconfig-node",
|
||||
},
|
||||
[libFile.path]: libFile.content,
|
||||
}, { currentDirectory: "/users/user/projects/myproject" });
|
||||
}
|
||||
|
||||
export function getConfigDirExtendsSys(): FsContents {
|
||||
return {
|
||||
export function getConfigDirExtendsSys(forTsserver?: boolean): TestServerHost {
|
||||
return TestServerHost.getCreateWatchedSystem(forTsserver)({
|
||||
"/home/src/projects/configs/first/tsconfig.json": jsonToReadableText({
|
||||
extends: "../second/tsconfig.json",
|
||||
include: ["${configDir}/src"], // eslint-disable-line no-template-curly-in-string
|
||||
@@ -82,11 +76,10 @@ export function getConfigDirExtendsSys(): FsContents {
|
||||
"/home/src/projects/myproject/root2/other/sometype2/index.d.ts": dedent`
|
||||
export const k = 10;
|
||||
`,
|
||||
[libFile.path]: libFile.content,
|
||||
};
|
||||
}, { currentDirectory: "/home/src/projects/myproject" });
|
||||
}
|
||||
|
||||
export function modifyFirstExtendedConfigOfConfigDirExtendsSys(sys: TestServerHost) {
|
||||
function modifyFirstExtendedConfigOfConfigDirExtendsSys(sys: TestServerHost) {
|
||||
sys.modifyFile(
|
||||
"/home/src/projects/configs/first/tsconfig.json",
|
||||
jsonToReadableText({
|
||||
@@ -99,3 +92,22 @@ export function modifyFirstExtendedConfigOfConfigDirExtendsSys(sys: TestServerHo
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
export function forConfigDirExtendsSysScenario(
|
||||
forTsserver: boolean,
|
||||
action: (
|
||||
scenario: string,
|
||||
sys: () => TestServerHost,
|
||||
edits: () => readonly TscWatchCompileChange[],
|
||||
) => void,
|
||||
) {
|
||||
action(
|
||||
"configDir template",
|
||||
() => getConfigDirExtendsSys(forTsserver),
|
||||
() => [{
|
||||
caption: "edit extended config file",
|
||||
edit: modifyFirstExtendedConfigOfConfigDirExtendsSys,
|
||||
timeouts: sys => sys.runQueuedTimeoutCallbacks(),
|
||||
}],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
import { dedent } from "../../_namespaces/Utils.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import {
|
||||
FsContents,
|
||||
libContent,
|
||||
} from "./contents.js";
|
||||
import { libFile } from "./virtualFileSystemWithWatch.js";
|
||||
import { TestServerHost } from "./virtualFileSystemWithWatch.js";
|
||||
|
||||
export function getFsContentsForMultipleErrorsForceConsistentCasingInFileNames(): FsContents {
|
||||
return {
|
||||
export function getSysForMultipleErrorsForceConsistentCasingInFileNames(forTsserver?: boolean) {
|
||||
return TestServerHost.getCreateWatchedSystem(forTsserver)({
|
||||
"/home/src/projects/project/src/struct.d.ts": dedent`
|
||||
import * as xs1 from "fp-ts/lib/Struct";
|
||||
import * as xs2 from "fp-ts/lib/struct";
|
||||
@@ -28,6 +24,5 @@ export function getFsContentsForMultipleErrorsForceConsistentCasingInFileNames()
|
||||
`,
|
||||
"/home/src/projects/project/tsconfig.json": jsonToReadableText({}),
|
||||
"/home/src/projects/project/node_modules/fp-ts/lib/struct.d.ts": `export function foo(): void`,
|
||||
[libFile.path]: libContent,
|
||||
};
|
||||
}, { currentDirectory: "/home/src/projects/project" });
|
||||
}
|
||||
|
||||
@@ -1,89 +1,217 @@
|
||||
import { emptyArray } from "../../_namespaces/ts.js";
|
||||
import { dedent } from "../../_namespaces/Utils.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import { TscWatchSystem } from "./baseline.js";
|
||||
import { getTypeScriptLibTestLocation } from "./contents.js";
|
||||
import { TscWatchCompileChange } from "./tscWatch.js";
|
||||
import {
|
||||
FsContents,
|
||||
libContent,
|
||||
} from "./contents.js";
|
||||
import { loadProjectFromFiles } from "./vfs.js";
|
||||
import {
|
||||
createServerHost,
|
||||
createWatchedSystem,
|
||||
libFile,
|
||||
TestServerHost,
|
||||
} from "./virtualFileSystemWithWatch.js";
|
||||
|
||||
function getFsContentsForLibResolution(libRedirection?: boolean): FsContents {
|
||||
return {
|
||||
"/home/src/projects/project1/utils.d.ts": `export const y = 10;`,
|
||||
"/home/src/projects/project1/file.ts": `export const file = 10;`,
|
||||
"/home/src/projects/project1/core.d.ts": `export const core = 10;`,
|
||||
"/home/src/projects/project1/index.ts": `export const x = "type1";`,
|
||||
"/home/src/projects/project1/file2.ts": dedent`
|
||||
function getSysForLibResolution(libRedirection?: boolean, forTsserver?: boolean) {
|
||||
return TestServerHost.getCreateWatchedSystem(forTsserver)({
|
||||
"/home/src/workspace/projects/project1/utils.d.ts": `export const y = 10;`,
|
||||
"/home/src/workspace/projects/project1/file.ts": `export const file = 10;`,
|
||||
"/home/src/workspace/projects/project1/core.d.ts": `export const core = 10;`,
|
||||
"/home/src/workspace/projects/project1/index.ts": `export const x = "type1";`,
|
||||
"/home/src/workspace/projects/project1/file2.ts": dedent`
|
||||
/// <reference lib="webworker"/>
|
||||
/// <reference lib="scripthost"/>
|
||||
/// <reference lib="es5"/>
|
||||
`,
|
||||
"/home/src/projects/project1/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspace/projects/project1/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: { composite: true, typeRoots: ["./typeroot1"], lib: ["es5", "dom"], traceResolution: true },
|
||||
}),
|
||||
"/home/src/projects/project1/typeroot1/sometype/index.d.ts": `export type TheNum = "type1";`,
|
||||
"/home/src/projects/project2/utils.d.ts": `export const y = 10;`,
|
||||
"/home/src/projects/project2/index.ts": `export const y = 10`,
|
||||
"/home/src/projects/project2/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspace/projects/project1/typeroot1/sometype/index.d.ts": `export type TheNum = "type1";`,
|
||||
"/home/src/workspace/projects/project2/utils.d.ts": `export const y = 10;`,
|
||||
"/home/src/workspace/projects/project2/index.ts": `export const y = 10`,
|
||||
"/home/src/workspace/projects/project2/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: { composite: true, lib: ["es5", "dom"], traceResolution: true },
|
||||
}),
|
||||
"/home/src/projects/project3/utils.d.ts": `export const y = 10;`,
|
||||
"/home/src/projects/project3/index.ts": `export const z = 10`,
|
||||
"/home/src/projects/project3/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspace/projects/project3/utils.d.ts": `export const y = 10;`,
|
||||
"/home/src/workspace/projects/project3/index.ts": `export const z = 10`,
|
||||
"/home/src/workspace/projects/project3/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: { composite: true, lib: ["es5", "dom"], traceResolution: true },
|
||||
}),
|
||||
"/home/src/projects/project4/utils.d.ts": `export const y = 10;`,
|
||||
"/home/src/projects/project4/index.ts": `export const z = 10`,
|
||||
"/home/src/projects/project4/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspace/projects/project4/utils.d.ts": `export const y = 10;`,
|
||||
"/home/src/workspace/projects/project4/index.ts": `export const z = 10`,
|
||||
"/home/src/workspace/projects/project4/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: { composite: true, lib: ["esnext", "dom", "webworker"], traceResolution: true },
|
||||
}),
|
||||
"/home/src/lib/lib.es5.d.ts": libContent,
|
||||
"/home/src/lib/lib.esnext.d.ts": libContent,
|
||||
"/home/src/lib/lib.dom.d.ts": "interface DOMInterface { }",
|
||||
"/home/src/lib/lib.webworker.d.ts": "interface WebWorkerInterface { }",
|
||||
"/home/src/lib/lib.scripthost.d.ts": "interface ScriptHostInterface { }",
|
||||
"/home/src/projects/node_modules/@typescript/unlreated/index.d.ts": "export const unrelated = 10;",
|
||||
[getTypeScriptLibTestLocation("dom")]: "interface DOMInterface { }",
|
||||
[getTypeScriptLibTestLocation("webworker")]: "interface WebWorkerInterface { }",
|
||||
[getTypeScriptLibTestLocation("scripthost")]: "interface ScriptHostInterface { }",
|
||||
"/home/src/workspace/projects/node_modules/@typescript/unlreated/index.d.ts": "export const unrelated = 10;",
|
||||
...libRedirection ? {
|
||||
"/home/src/projects/node_modules/@typescript/lib-es5/index.d.ts": libContent,
|
||||
"/home/src/projects/node_modules/@typescript/lib-esnext/index.d.ts": libContent,
|
||||
"/home/src/projects/node_modules/@typescript/lib-dom/index.d.ts": "interface DOMInterface { }",
|
||||
"/home/src/projects/node_modules/@typescript/lib-webworker/index.d.ts": "interface WebworkerInterface { }",
|
||||
"/home/src/projects/node_modules/@typescript/lib-scripthost/index.d.ts": "interface ScriptHostInterface { }",
|
||||
"/home/src/workspace/projects/node_modules/@typescript/lib-es5/index.d.ts": libFile.content,
|
||||
"/home/src/workspace/projects/node_modules/@typescript/lib-esnext/index.d.ts": libFile.content,
|
||||
"/home/src/workspace/projects/node_modules/@typescript/lib-dom/index.d.ts": "interface DOMInterface { }",
|
||||
"/home/src/workspace/projects/node_modules/@typescript/lib-webworker/index.d.ts": "interface WebWorkerInterface { }",
|
||||
"/home/src/workspace/projects/node_modules/@typescript/lib-scripthost/index.d.ts": "interface ScriptHostInterface { }",
|
||||
} : undefined,
|
||||
};
|
||||
}, { currentDirectory: "/home/src/workspace/projects" });
|
||||
}
|
||||
|
||||
export function getFsForLibResolution(libRedirection: true | undefined) {
|
||||
return loadProjectFromFiles(
|
||||
getFsContentsForLibResolution(libRedirection),
|
||||
{
|
||||
cwd: "/home/src/projects",
|
||||
executingFilePath: "/home/src/lib/tsc.js",
|
||||
},
|
||||
);
|
||||
function getLibResolutionEditOptions(
|
||||
withoutConfig: true | undefined,
|
||||
changeLib: (sys: TscWatchSystem) => void,
|
||||
): readonly TscWatchCompileChange[] {
|
||||
return withoutConfig ?
|
||||
emptyArray :
|
||||
[
|
||||
{
|
||||
caption: "change program options to update module resolution",
|
||||
edit: sys =>
|
||||
sys.writeFile(
|
||||
"/home/src/workspace/projects/project1/tsconfig.json",
|
||||
jsonToReadableText({
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
typeRoots: ["./typeroot1", "./typeroot2"],
|
||||
lib: ["es5", "dom"],
|
||||
traceResolution: true,
|
||||
},
|
||||
}),
|
||||
),
|
||||
timeouts: sys => {
|
||||
sys.runQueuedTimeoutCallbacks();
|
||||
sys.runQueuedTimeoutCallbacks();
|
||||
},
|
||||
},
|
||||
{
|
||||
caption: "change program options to update module resolution and also update lib file",
|
||||
edit: sys => {
|
||||
sys.writeFile(
|
||||
"/home/src/workspace/projects/project1/tsconfig.json",
|
||||
jsonToReadableText({
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
typeRoots: ["./typeroot1"],
|
||||
lib: ["es5", "dom"],
|
||||
traceResolution: true,
|
||||
},
|
||||
}),
|
||||
);
|
||||
changeLib(sys);
|
||||
},
|
||||
timeouts: sys => {
|
||||
sys.runQueuedTimeoutCallbacks();
|
||||
sys.runQueuedTimeoutCallbacks();
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
export function getSysForLibResolution(libRedirection?: true) {
|
||||
return createWatchedSystem(
|
||||
getFsContentsForLibResolution(libRedirection),
|
||||
function getLibResolutionWithoutRedirection(withoutConfig: true | undefined): readonly TscWatchCompileChange[] {
|
||||
return [
|
||||
{
|
||||
currentDirectory: "/home/src/projects",
|
||||
executingFilePath: "/home/src/lib/tsc.js",
|
||||
caption: "write redirect file dom",
|
||||
edit: sys => sys.ensureFileOrFolder({ path: "/home/src/workspace/projects/node_modules/@typescript/lib-dom/index.d.ts", content: "interface DOMInterface { }" }),
|
||||
timeouts: sys => {
|
||||
sys.runQueuedTimeoutCallbacks();
|
||||
sys.runQueuedTimeoutCallbacks();
|
||||
},
|
||||
},
|
||||
);
|
||||
{
|
||||
caption: "edit file",
|
||||
edit: sys => sys.appendFile("/home/src/workspace/projects/project1/file.ts", "export const xyz = 10;"),
|
||||
timeouts: sys => sys.runQueuedTimeoutCallbacks(),
|
||||
},
|
||||
{
|
||||
caption: "delete core",
|
||||
edit: sys => sys.deleteFile("/home/src/workspace/projects/project1/core.d.ts"),
|
||||
timeouts: sys => sys.runQueuedTimeoutCallbacks(),
|
||||
},
|
||||
{
|
||||
caption: "delete redirect file dom",
|
||||
edit: sys => sys.deleteFile("/home/src/workspace/projects/node_modules/@typescript/lib-dom/index.d.ts"),
|
||||
timeouts: sys => sys.runQueuedTimeoutCallbacks(),
|
||||
},
|
||||
...getLibResolutionEditOptions(
|
||||
withoutConfig,
|
||||
sys =>
|
||||
sys.ensureFileOrFolder({
|
||||
path: "/home/src/workspace/projects/node_modules/@typescript/lib-dom/index.d.ts",
|
||||
content: "interface DOMInterface { }",
|
||||
}),
|
||||
),
|
||||
{
|
||||
caption: "write redirect file webworker",
|
||||
edit: sys => sys.ensureFileOrFolder({ path: "/home/src/workspace/projects/node_modules/@typescript/lib-webworker/index.d.ts", content: "interface WebWorkerInterface { }" }),
|
||||
timeouts: sys => {
|
||||
sys.runQueuedTimeoutCallbacks();
|
||||
sys.runQueuedTimeoutCallbacks();
|
||||
},
|
||||
},
|
||||
{
|
||||
caption: "delete redirect file webworker",
|
||||
edit: sys => sys.deleteFile("/home/src/workspace/projects/node_modules/@typescript/lib-webworker/index.d.ts"),
|
||||
timeouts: sys => sys.runQueuedTimeoutCallbacks(),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
export function getServerHostForLibResolution(libRedirection?: true) {
|
||||
return createServerHost(
|
||||
getFsContentsForLibResolution(libRedirection),
|
||||
function getLibResolutionWithRedirection(withoutConfig: true | undefined): readonly TscWatchCompileChange[] {
|
||||
return [
|
||||
{
|
||||
currentDirectory: "/home/src/projects",
|
||||
executingFilePath: "/home/src/lib/tsc.js",
|
||||
caption: "delete redirect file dom",
|
||||
edit: sys => sys.deleteFile("/home/src/workspace/projects/node_modules/@typescript/lib-dom/index.d.ts"),
|
||||
timeouts: sys => sys.runQueuedTimeoutCallbacks(),
|
||||
},
|
||||
);
|
||||
{
|
||||
caption: "edit file",
|
||||
edit: sys => sys.appendFile("/home/src/workspace/projects/project1/file.ts", "export const xyz = 10;"),
|
||||
timeouts: sys => sys.runQueuedTimeoutCallbacks(),
|
||||
},
|
||||
{
|
||||
caption: "delete core",
|
||||
edit: sys => sys.deleteFile("/home/src/workspace/projects/project1/core.d.ts"),
|
||||
timeouts: sys => sys.runQueuedTimeoutCallbacks(),
|
||||
},
|
||||
{
|
||||
caption: "write redirect file dom",
|
||||
edit: sys => sys.ensureFileOrFolder({ path: "/home/src/workspace/projects/node_modules/@typescript/lib-dom/index.d.ts", content: "interface DOMInterface { }" }),
|
||||
timeouts: sys => {
|
||||
sys.runQueuedTimeoutCallbacks();
|
||||
sys.runQueuedTimeoutCallbacks();
|
||||
},
|
||||
},
|
||||
...getLibResolutionEditOptions(
|
||||
withoutConfig,
|
||||
sys => sys.deleteFile("/home/src/workspace/projects/node_modules/@typescript/lib-dom/index.d.ts"),
|
||||
),
|
||||
{
|
||||
caption: "delete redirect file webworker",
|
||||
edit: sys => sys.deleteFile("/home/src/workspace/projects/node_modules/@typescript/lib-webworker/index.d.ts"),
|
||||
timeouts: sys => sys.runQueuedTimeoutCallbacks(),
|
||||
},
|
||||
{
|
||||
caption: "write redirect file webworker",
|
||||
edit: sys => sys.ensureFileOrFolder({ path: "/home/src/workspace/projects/node_modules/@typescript/lib-webworker/index.d.ts", content: "interface WebWorkerInterface { }" }),
|
||||
timeouts: sys => {
|
||||
sys.runQueuedTimeoutCallbacks();
|
||||
sys.runQueuedTimeoutCallbacks();
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
export function forEachLibResolutionScenario(
|
||||
forTsserver: boolean,
|
||||
withoutConfig: true | undefined,
|
||||
action: (scenario: string, sys: () => TestServerHost, edits: () => readonly TscWatchCompileChange[]) => void,
|
||||
) {
|
||||
[undefined, true].forEach(libRedirection => {
|
||||
action(
|
||||
`${withoutConfig ? "without" : "with"} config${libRedirection ? " with redirection" : ""}`,
|
||||
() => getSysForLibResolution(libRedirection, forTsserver),
|
||||
() =>
|
||||
libRedirection ?
|
||||
getLibResolutionWithRedirection(withoutConfig) :
|
||||
getLibResolutionWithoutRedirection(withoutConfig),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
export function getCommandLineArgsForLibResolution(withoutConfig: true | undefined) {
|
||||
@@ -92,45 +220,24 @@ export function getCommandLineArgsForLibResolution(withoutConfig: true | undefin
|
||||
["-p", "project1", "--explainFiles"];
|
||||
}
|
||||
|
||||
function getFsContentsForLibResolutionUnknown(): FsContents {
|
||||
return {
|
||||
"/home/src/projects/project1/utils.d.ts": `export const y = 10;`,
|
||||
"/home/src/projects/project1/file.ts": `export const file = 10;`,
|
||||
"/home/src/projects/project1/core.d.ts": `export const core = 10;`,
|
||||
"/home/src/projects/project1/index.ts": `export const x = "type1";`,
|
||||
"/home/src/projects/project1/file2.ts": dedent`
|
||||
export function getSysForLibResolutionUnknown() {
|
||||
return TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspace/projects/project1/utils.d.ts": `export const y = 10;`,
|
||||
"/home/src/workspace/projects/project1/file.ts": `export const file = 10;`,
|
||||
"/home/src/workspace/projects/project1/core.d.ts": `export const core = 10;`,
|
||||
"/home/src/workspace/projects/project1/index.ts": `export const x = "type1";`,
|
||||
"/home/src/workspace/projects/project1/file2.ts": dedent`
|
||||
/// <reference lib="webworker2"/>
|
||||
/// <reference lib="unknownlib"/>
|
||||
/// <reference lib="scripthost"/>
|
||||
`,
|
||||
"/home/src/projects/project1/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspace/projects/project1/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
traceResolution: true,
|
||||
},
|
||||
}),
|
||||
"/home/src/lib/lib.d.ts": libContent,
|
||||
"/home/src/lib/lib.webworker.d.ts": "interface WebWorkerInterface { }",
|
||||
"/home/src/lib/lib.scripthost.d.ts": "interface ScriptHostInterface { }",
|
||||
};
|
||||
}
|
||||
|
||||
export function getFsForLibResolutionUnknown() {
|
||||
return loadProjectFromFiles(
|
||||
getFsContentsForLibResolutionUnknown(),
|
||||
{
|
||||
cwd: "/home/src/projects",
|
||||
executingFilePath: "/home/src/lib/tsc.js",
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
export function getSysForLibResolutionUnknown() {
|
||||
return createWatchedSystem(
|
||||
getFsContentsForLibResolutionUnknown(),
|
||||
{
|
||||
currentDirectory: "/home/src/projects",
|
||||
executingFilePath: "/home/src/lib/tsc.js",
|
||||
},
|
||||
);
|
||||
[getTypeScriptLibTestLocation("webworker")]: "interface WebWorkerInterface { }",
|
||||
[getTypeScriptLibTestLocation("scripthost")]: "interface ScriptHostInterface { }",
|
||||
}, { currentDirectory: "/home/src/workspace/projects" });
|
||||
}
|
||||
|
||||
@@ -4,16 +4,10 @@ import {
|
||||
} from "../../_namespaces/ts.js";
|
||||
import { dedent } from "../../_namespaces/Utils.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import { libContent } from "./contents.js";
|
||||
import { TscWatchSystem } from "./baseline.js";
|
||||
import { solutionBuildWithBaseline } from "./solutionBuilder.js";
|
||||
import { TscWatchCompileChange } from "./tscWatch.js";
|
||||
import {
|
||||
TscWatchCompileChange,
|
||||
TscWatchSystem,
|
||||
} from "./tscWatch.js";
|
||||
import {
|
||||
createServerHost,
|
||||
createWatchedSystem,
|
||||
libFile,
|
||||
osFlavorToString,
|
||||
TestServerHost,
|
||||
TestServerHostOsFlavor,
|
||||
@@ -38,7 +32,7 @@ function getMonorepoSymlinkedSiblingPackagesSys(forTsserver: boolean, built: boo
|
||||
"dist/**/*",
|
||||
],
|
||||
});
|
||||
const sys = (!forTsserver ? createWatchedSystem : createServerHost)({
|
||||
const sys = TestServerHost.getCreateWatchedSystem(forTsserver)({
|
||||
"/home/src/projects/project/packages/package1/package.json": getPackageJson("package1"),
|
||||
"/home/src/projects/project/packages/package1/tsconfig.json": configText,
|
||||
"/home/src/projects/project/packages/package1/src/index.ts": dedent`
|
||||
@@ -53,7 +47,6 @@ function getMonorepoSymlinkedSiblingPackagesSys(forTsserver: boolean, built: boo
|
||||
type MyBarType = BarType;
|
||||
`,
|
||||
"/home/src/projects/project/node_modules/package1": { symLink: "/home/src/projects/project/packages/package1" },
|
||||
"/a/lib/lib.es2016.full.d.ts": libContent,
|
||||
}, { currentDirectory: "/home/src/projects/project", osFlavor });
|
||||
if (built) buildMonorepoSymlinkedSiblingPackage1(sys);
|
||||
return sys;
|
||||
@@ -68,7 +61,7 @@ function getPackageJson(packageName: string) {
|
||||
}
|
||||
|
||||
function buildMonorepoSymlinkedSiblingPackage1(host: TestServerHost) {
|
||||
solutionBuildWithBaseline(host, ["packages/package1"]);
|
||||
solutionBuildWithBaseline(host, ["/home/src/projects/project/packages/package1"]);
|
||||
}
|
||||
|
||||
function cleanMonorepoSymlinkedSiblingPackage1(host: TestServerHost) {
|
||||
@@ -82,6 +75,7 @@ function forEachMonorepoSymlinkedSiblingPackagesSys(
|
||||
sys: () => TestServerHost,
|
||||
edits: () => readonly TscWatchCompileChange[],
|
||||
project: string,
|
||||
currentDirectory: string,
|
||||
) => void,
|
||||
) {
|
||||
for (const built of [false, true]) {
|
||||
@@ -98,6 +92,7 @@ function forEachMonorepoSymlinkedSiblingPackagesSys(
|
||||
cleanMonorepoSymlinkedSiblingPackage1,
|
||||
),
|
||||
"packages/package2",
|
||||
"/home/src/projects/project",
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -149,7 +144,7 @@ function getMonorepoSymlinkedSiblingPackagesSysWithUnRelatedFolders(
|
||||
built: boolean,
|
||||
osFlavor: TestServerHostOsFlavor,
|
||||
): TestServerHost {
|
||||
const sys = (!forTsserver ? createWatchedSystem : createServerHost)({
|
||||
const sys = TestServerHost.getCreateWatchedSystem(forTsserver)({
|
||||
"/home/src/projects/c/3/c-impl/c/src/c.ts": `export const c: string = 'test';`,
|
||||
"/home/src/projects/c/3/c-impl/c/src/index.ts": `export * from './c';`,
|
||||
"/home/src/projects/c/3/c-impl/c/tsconfig.json": jsonToReadableText({
|
||||
@@ -192,14 +187,13 @@ function getMonorepoSymlinkedSiblingPackagesSysWithUnRelatedFolders(
|
||||
include: ["src/**/*.ts"],
|
||||
}),
|
||||
"/home/src/projects/b/2/b-impl/b/node_modules/a": { symLink: "/home/src/projects/a/1/a-impl/a" },
|
||||
[libFile.path]: libContent,
|
||||
}, { currentDirectory: "/home/src/projects/b/2/b-impl/b", osFlavor });
|
||||
if (built) buildDependenciesOfMonorepoSymlinkedSiblingPackagesSysWithUnRelatedFolders(sys);
|
||||
return sys;
|
||||
}
|
||||
|
||||
function buildDependenciesOfMonorepoSymlinkedSiblingPackagesSysWithUnRelatedFolders(host: TestServerHost) {
|
||||
solutionBuildWithBaseline(host, ["../../../../c/3/c-impl/c", "../../../../a/1/a-impl/a"]);
|
||||
solutionBuildWithBaseline(host, ["/home/src/projects/c/3/c-impl/c", "/home/src/projects/a/1/a-impl/a"]);
|
||||
}
|
||||
|
||||
function cleanDependenciesOfMonorepoSymlinkedSiblingPackagesSysWithUnRelatedFolders(host: TestServerHost) {
|
||||
@@ -214,6 +208,7 @@ function forEachMonorepoSymlinkedSiblingPackagesSysWithUnRelatedFolders(
|
||||
sys: () => TestServerHost,
|
||||
edits: () => readonly TscWatchCompileChange[],
|
||||
indexFile: string,
|
||||
currentDirectory: string,
|
||||
) => void,
|
||||
) {
|
||||
for (const built of [false, true]) {
|
||||
@@ -266,6 +261,7 @@ function forEachMonorepoSymlinkedSiblingPackagesSysWithUnRelatedFolders(
|
||||
],
|
||||
),
|
||||
".",
|
||||
"/home/src/projects/b/2/b-impl/b",
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -278,6 +274,7 @@ export function forEachMonorepoSymlinkScenario(
|
||||
sys: () => TestServerHost,
|
||||
edits: () => readonly TscWatchCompileChange[],
|
||||
indexFile: string,
|
||||
currentDirectory: string,
|
||||
) => void,
|
||||
) {
|
||||
describe("monorepoSymlinkedSiblingPackages:: monorepo style sibling packages symlinked", () => {
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
import { emptyArray } from "../../_namespaces/ts.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import {
|
||||
noChangeRun,
|
||||
TestTscEdit,
|
||||
verifyTsc,
|
||||
} from "./tsc.js";
|
||||
import { loadProjectFromFiles } from "./vfs.js";
|
||||
import { TestServerHost } from "./virtualFileSystemWithWatch.js";
|
||||
|
||||
export function forEachTscScenarioWithNoCheck(buildType: "-b" | "-p") {
|
||||
const commandLineArgs = buildType === "-b" ?
|
||||
["-b", "/src/tsconfig.json", "-v"] :
|
||||
["-p", "/src/tsconfig.json"];
|
||||
["-b", "-v"] :
|
||||
emptyArray;
|
||||
|
||||
function forEachNoCheckScenarioWorker(
|
||||
subScenario: string,
|
||||
@@ -22,11 +23,11 @@ export function forEachTscScenarioWithNoCheck(buildType: "-b" | "-p") {
|
||||
};
|
||||
const noCheckFixError: TestTscEdit = {
|
||||
caption: "Fix `a` error with noCheck",
|
||||
edit: fs => fs.writeFileSync("/src/a.ts", `export const a = "hello";`),
|
||||
edit: sys => sys.writeFile("/home/src/workspaces/project/a.ts", `export const a = "hello";`),
|
||||
};
|
||||
const noCheckError: TestTscEdit = {
|
||||
caption: "Introduce error with noCheck",
|
||||
edit: fs => fs.writeFileSync("/src/a.ts", aText),
|
||||
edit: sys => sys.writeFile("/home/src/workspaces/project/a.ts", aText),
|
||||
};
|
||||
const noChangeRunWithCheckPendingDiscrepancy: TestTscEdit = {
|
||||
...noChangeRun,
|
||||
@@ -41,18 +42,18 @@ export function forEachTscScenarioWithNoCheck(buildType: "-b" | "-p") {
|
||||
verifyTsc({
|
||||
scenario: "noCheck",
|
||||
subScenario: `${options.outFile ? "outFile" : "multiFile"}/${subScenario}${incremental ? " with incremental" : ""}`,
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/a.ts": aText,
|
||||
"/src/b.ts": `export const b = 10;`,
|
||||
"/src/tsconfig.json": jsonToReadableText({
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/a.ts": aText,
|
||||
"/home/src/workspaces/project/b.ts": `export const b = 10;`,
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
declaration: true,
|
||||
incremental,
|
||||
...options,
|
||||
},
|
||||
}),
|
||||
}),
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
commandLineArgs: [...commandLineArgs, "--noCheck"],
|
||||
edits: [
|
||||
noChangeRun, // Should be no op
|
||||
@@ -70,7 +71,7 @@ export function forEachTscScenarioWithNoCheck(buildType: "-b" | "-p") {
|
||||
checkNoChangeRun, // Should check errors and update buildInfo
|
||||
{
|
||||
caption: "Add file with error",
|
||||
edit: fs => fs.writeFileSync("/src/c.ts", `export const c: number = "hello";`),
|
||||
edit: sys => sys.writeFile("/home/src/workspaces/project/c.ts", `export const c: number = "hello";`),
|
||||
commandLineArgs,
|
||||
},
|
||||
noCheckError,
|
||||
|
||||
@@ -6,25 +6,14 @@ import {
|
||||
} from "../../_namespaces/ts.js";
|
||||
import { dedent } from "../../_namespaces/Utils.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import {
|
||||
compilerOptionsToConfigJson,
|
||||
FsContents,
|
||||
libContent,
|
||||
} from "./contents.js";
|
||||
import { compilerOptionsToConfigJson } from "./contents.js";
|
||||
import {
|
||||
noChangeRun,
|
||||
TestTscEdit,
|
||||
verifyTsc,
|
||||
} from "./tsc.js";
|
||||
import { verifyTscWatch } from "./tscWatch.js";
|
||||
import {
|
||||
loadProjectFromFiles,
|
||||
replaceText,
|
||||
} from "./vfs.js";
|
||||
import {
|
||||
createWatchedSystem,
|
||||
libFile,
|
||||
} from "./virtualFileSystemWithWatch.js";
|
||||
import { TestServerHost } from "./virtualFileSystemWithWatch.js";
|
||||
|
||||
function forEachNoEmitChangesWorker(commandType: string[], compilerOptions: CompilerOptions) {
|
||||
const discrepancyExplanation = () => [
|
||||
@@ -34,7 +23,7 @@ function forEachNoEmitChangesWorker(commandType: string[], compilerOptions: Comp
|
||||
const noChangeRunWithNoEmit: TestTscEdit = {
|
||||
...noChangeRun,
|
||||
caption: "No Change run with noEmit",
|
||||
commandLineArgs: [...commandType, "src/project", "--noEmit"],
|
||||
commandLineArgs: [...commandType, ".", "--noEmit"],
|
||||
discrepancyExplanation: compilerOptions.composite ?
|
||||
discrepancyExplanation :
|
||||
undefined,
|
||||
@@ -42,7 +31,7 @@ function forEachNoEmitChangesWorker(commandType: string[], compilerOptions: Comp
|
||||
const noChangeRunWithEmit: TestTscEdit = {
|
||||
...noChangeRun,
|
||||
caption: "No Change run with emit",
|
||||
commandLineArgs: [...commandType, "src/project"],
|
||||
commandLineArgs: [...commandType, "."],
|
||||
};
|
||||
let optionsString = "";
|
||||
for (const key in compilerOptions) {
|
||||
@@ -57,22 +46,22 @@ function forEachNoEmitChangesWorker(commandType: string[], compilerOptions: Comp
|
||||
verifyTsc({
|
||||
scenario: "noEmit",
|
||||
subScenario: scenarioName("changes"),
|
||||
commandLineArgs: [...commandType, "src/project"],
|
||||
fs,
|
||||
commandLineArgs: [...commandType, "."],
|
||||
sys,
|
||||
edits: [
|
||||
noChangeRunWithNoEmit,
|
||||
noChangeRunWithNoEmit,
|
||||
{
|
||||
caption: "Introduce error but still noEmit",
|
||||
commandLineArgs: [...commandType, "src/project", "--noEmit"],
|
||||
edit: fs => replaceText(fs, "/src/project/src/class.ts", "prop", "prop1"),
|
||||
commandLineArgs: [...commandType, ".", "--noEmit"],
|
||||
edit: sys => sys.replaceFileText("/home/src/workspaces/project/src/class.ts", "prop", "prop1"),
|
||||
discrepancyExplanation: compilerOptions.composite ?
|
||||
discrepancyExplanation :
|
||||
undefined,
|
||||
},
|
||||
{
|
||||
caption: "Fix error and emit",
|
||||
edit: fs => replaceText(fs, "/src/project/src/class.ts", "prop1", "prop"),
|
||||
edit: sys => sys.replaceFileText("/home/src/workspaces/project/src/class.ts", "prop1", "prop"),
|
||||
},
|
||||
noChangeRunWithEmit,
|
||||
noChangeRunWithNoEmit,
|
||||
@@ -80,7 +69,7 @@ function forEachNoEmitChangesWorker(commandType: string[], compilerOptions: Comp
|
||||
noChangeRunWithEmit,
|
||||
{
|
||||
caption: "Introduce error and emit",
|
||||
edit: fs => replaceText(fs, "/src/project/src/class.ts", "prop", "prop1"),
|
||||
edit: sys => sys.replaceFileText("/home/src/workspaces/project/src/class.ts", "prop", "prop1"),
|
||||
},
|
||||
noChangeRunWithEmit,
|
||||
noChangeRunWithNoEmit,
|
||||
@@ -88,8 +77,8 @@ function forEachNoEmitChangesWorker(commandType: string[], compilerOptions: Comp
|
||||
noChangeRunWithEmit,
|
||||
{
|
||||
caption: "Fix error and no emit",
|
||||
commandLineArgs: [...commandType, "src/project", "--noEmit"],
|
||||
edit: fs => replaceText(fs, "/src/project/src/class.ts", "prop1", "prop"),
|
||||
commandLineArgs: [...commandType, ".", "--noEmit"],
|
||||
edit: sys => sys.replaceFileText("/home/src/workspaces/project/src/class.ts", "prop1", "prop"),
|
||||
discrepancyExplanation: compilerOptions.composite ?
|
||||
discrepancyExplanation :
|
||||
undefined,
|
||||
@@ -104,18 +93,18 @@ function forEachNoEmitChangesWorker(commandType: string[], compilerOptions: Comp
|
||||
verifyTsc({
|
||||
scenario: "noEmit",
|
||||
subScenario: scenarioName("changes with initial noEmit"),
|
||||
commandLineArgs: [...commandType, "src/project", "--noEmit"],
|
||||
fs,
|
||||
commandLineArgs: [...commandType, ".", "--noEmit"],
|
||||
sys,
|
||||
edits: [
|
||||
noChangeRunWithEmit,
|
||||
{
|
||||
caption: "Introduce error with emit",
|
||||
commandLineArgs: [...commandType, "src/project"],
|
||||
edit: fs => replaceText(fs, "/src/project/src/class.ts", "prop", "prop1"),
|
||||
commandLineArgs: [...commandType, "."],
|
||||
edit: sys => sys.replaceFileText("/home/src/workspaces/project/src/class.ts", "prop", "prop1"),
|
||||
},
|
||||
{
|
||||
caption: "Fix error and no emit",
|
||||
edit: fs => replaceText(fs, "/src/project/src/class.ts", "prop1", "prop"),
|
||||
edit: sys => sys.replaceFileText("/home/src/workspaces/project/src/class.ts", "prop1", "prop"),
|
||||
discrepancyExplanation: compilerOptions.composite ?
|
||||
discrepancyExplanation :
|
||||
undefined,
|
||||
@@ -124,33 +113,33 @@ function forEachNoEmitChangesWorker(commandType: string[], compilerOptions: Comp
|
||||
],
|
||||
});
|
||||
|
||||
function fs() {
|
||||
return loadProjectFromFiles({
|
||||
"/src/project/src/class.ts": dedent`
|
||||
function sys() {
|
||||
return TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/src/class.ts": dedent`
|
||||
export class classC {
|
||||
prop = 1;
|
||||
}`,
|
||||
"/src/project/src/indirectClass.ts": dedent`
|
||||
"/home/src/workspaces/project/src/indirectClass.ts": dedent`
|
||||
import { classC } from './class';
|
||||
export class indirectClass {
|
||||
classC = new classC();
|
||||
}`,
|
||||
"/src/project/src/directUse.ts": dedent`
|
||||
"/home/src/workspaces/project/src/directUse.ts": dedent`
|
||||
import { indirectClass } from './indirectClass';
|
||||
new indirectClass().classC.prop;`,
|
||||
"/src/project/src/indirectUse.ts": dedent`
|
||||
"/home/src/workspaces/project/src/indirectUse.ts": dedent`
|
||||
import { indirectClass } from './indirectClass';
|
||||
new indirectClass().classC.prop;`,
|
||||
"/src/project/src/noChangeFile.ts": dedent`
|
||||
"/home/src/workspaces/project/src/noChangeFile.ts": dedent`
|
||||
export function writeLog(s: string) {
|
||||
}`,
|
||||
"/src/project/src/noChangeFileWithEmitSpecificError.ts": dedent`
|
||||
"/home/src/workspaces/project/src/noChangeFileWithEmitSpecificError.ts": dedent`
|
||||
function someFunc(arguments: boolean, ...rest: any[]) {
|
||||
}`,
|
||||
"/src/project/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: compilerOptionsToConfigJson(compilerOptions),
|
||||
}),
|
||||
});
|
||||
}, { currentDirectory: "/home/src/workspaces/project" });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,12 +165,12 @@ function editsForDtsChanges(
|
||||
{
|
||||
caption: "With declaration enabled noEmit - Should report errors",
|
||||
edit: noop,
|
||||
commandLineArgs: [...commandType, "/home/src/projects/project", "--noEmit", "--declaration"],
|
||||
commandLineArgs: [...commandType, ".", "--noEmit", "--declaration"],
|
||||
},
|
||||
{
|
||||
caption: "With declaration and declarationMap noEmit - Should report errors",
|
||||
edit: noop,
|
||||
commandLineArgs: [...commandType, "/home/src/projects/project", "--noEmit", "--declaration", "--declarationMap"],
|
||||
commandLineArgs: [...commandType, ".", "--noEmit", "--declaration", "--declarationMap"],
|
||||
},
|
||||
incremental ? {
|
||||
...noChangeRun,
|
||||
@@ -193,21 +182,21 @@ function editsForDtsChanges(
|
||||
{
|
||||
caption: "Dts Emit with error",
|
||||
edit: noop,
|
||||
commandLineArgs: [...commandType, "/home/src/projects/project", "--declaration"],
|
||||
commandLineArgs: [...commandType, ".", "--declaration"],
|
||||
},
|
||||
{
|
||||
caption: "Fix the error",
|
||||
edit: fs => fs.writeFileSync("/home/src/projects/project/a.ts", aContent.replace("private", "public")),
|
||||
edit: sys => sys.writeFile("/home/src/projects/project/a.ts", aContent.replace("private", "public")),
|
||||
},
|
||||
{
|
||||
caption: "With declaration enabled noEmit",
|
||||
edit: noop,
|
||||
commandLineArgs: [...commandType, "/home/src/projects/project", "--noEmit", "--declaration"],
|
||||
commandLineArgs: [...commandType, ".", "--noEmit", "--declaration"],
|
||||
},
|
||||
{
|
||||
caption: "With declaration and declarationMap noEmit",
|
||||
edit: noop,
|
||||
commandLineArgs: [...commandType, "/home/src/projects/project", "--noEmit", "--declaration", "--declarationMap"],
|
||||
commandLineArgs: [...commandType, ".", "--noEmit", "--declaration", "--declarationMap"],
|
||||
// Multi file still needs to report error so will emit build info (for pending dtsMap)
|
||||
discrepancyExplanation: incremental && !multiFile ? () => [
|
||||
"Clean build will have declaration and declarationMap",
|
||||
@@ -228,16 +217,16 @@ export function forEachNoEmitDtsChanges(commandType: string[]) {
|
||||
verifyTsc({
|
||||
scenario: "noEmit",
|
||||
subScenario: `${options.outFile ? "outFile" : "multiFile"}/dts errors with declaration enable changes${incremental ? " with incremental" : ""}${asModules ? " as modules" : ""}`,
|
||||
commandLineArgs: [...commandType, "/home/src/projects/project", "--noEmit"],
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
commandLineArgs: [...commandType, ".", "--noEmit"],
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/projects/project/a.ts": aContent,
|
||||
"/home/src/projects/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: { ...options, incremental },
|
||||
}),
|
||||
}),
|
||||
modifyFs: asModules ?
|
||||
fs => fs.writeFileSync("/home/src/projects/project/b.ts", `export const b = 10;`) :
|
||||
}, { currentDirectory: "/home/src/projects/project" }),
|
||||
modifySystem: asModules ?
|
||||
sys => sys.writeFile("/home/src/projects/project/b.ts", `export const b = 10;`) :
|
||||
undefined,
|
||||
edits: editsForDtsChanges(commandType, aContent, incremental, /*multiFile*/ false),
|
||||
baselinePrograms: true,
|
||||
@@ -253,9 +242,9 @@ export function forEachNoEmitDtsChanges(commandType: string[]) {
|
||||
verifyTsc({
|
||||
scenario: "noEmit",
|
||||
subScenario: `${options.outFile ? "outFile" : "multiFile"}/dts errors with declaration enable changes with multiple files`,
|
||||
commandLineArgs: [...commandType, "/home/src/projects/project", "--noEmit"],
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
commandLineArgs: [...commandType, ".", "--noEmit"],
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/projects/project/a.ts": aContent,
|
||||
"/home/src/projects/project/b.ts": `export const b = 10;`,
|
||||
"/home/src/projects/project/c.ts": aContent.replace("a", "c"),
|
||||
@@ -263,13 +252,13 @@ export function forEachNoEmitDtsChanges(commandType: string[]) {
|
||||
"/home/src/projects/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: { ...options, incremental: true },
|
||||
}),
|
||||
}),
|
||||
}, { currentDirectory: "/home/src/projects/project" }),
|
||||
edits: [
|
||||
...editsForDtsChanges(commandType, aContent, /*incremental*/ true, /*multiFile*/ true),
|
||||
{
|
||||
caption: "Fix the another ",
|
||||
edit: fs => fs.writeFileSync("/home/src/projects/project/c.ts", aContent.replace("a", "c").replace("private", "public")),
|
||||
commandLineArgs: [...commandType, "/home/src/projects/project", "--noEmit", "--declaration", "--declarationMap"],
|
||||
edit: sys => sys.writeFile("/home/src/projects/project/c.ts", aContent.replace("a", "c").replace("private", "public")),
|
||||
commandLineArgs: [...commandType, ".", "--noEmit", "--declaration", "--declarationMap"],
|
||||
},
|
||||
],
|
||||
baselinePrograms: true,
|
||||
@@ -284,7 +273,7 @@ function forEachNoEmitAndErrorsWorker(
|
||||
additionalOptions: CompilerOptions | undefined,
|
||||
action: (
|
||||
subScenario: string,
|
||||
fsContents: FsContents,
|
||||
sys: () => TestServerHost,
|
||||
aTsContent: string,
|
||||
fixedATsContent: string,
|
||||
compilerOptions: CompilerOptions,
|
||||
@@ -300,16 +289,18 @@ function forEachNoEmitAndErrorsWorker(
|
||||
incremental,
|
||||
...additionalOptions,
|
||||
};
|
||||
const fsContents: FsContents = {
|
||||
"/home/src/projects/project/a.ts": aContent,
|
||||
"/home/src/projects/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: compilerOptionsToConfigJson(compilerOptions),
|
||||
}),
|
||||
};
|
||||
if (asModules) fsContents["/home/src/projects/project/b.ts"] = `export const b = 10;`;
|
||||
action(
|
||||
`${options.outFile ? "outFile" : "multiFile"}/${subScenario}${incremental ? " with incremental" : ""}${asModules ? " as modules" : ""}`,
|
||||
fsContents,
|
||||
() => {
|
||||
const sys = TestServerHost.createWatchedSystem({
|
||||
"/home/src/projects/project/a.ts": aContent,
|
||||
"/home/src/projects/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: compilerOptionsToConfigJson(compilerOptions),
|
||||
}),
|
||||
}, { currentDirectory: "/home/src/projects/project" });
|
||||
if (asModules) sys.writeFile("/home/src/projects/project/b.ts", `export const b = 10;`);
|
||||
return sys;
|
||||
},
|
||||
aContent,
|
||||
`${asModules ? "export " : ""}const a = "hello";`,
|
||||
compilerOptions,
|
||||
@@ -322,7 +313,7 @@ function forEachNoEmitAndErrorsWorker(
|
||||
function forEachNoEmitAndErrors(
|
||||
action: (
|
||||
subScenario: string,
|
||||
fsContents: FsContents,
|
||||
sys: () => TestServerHost,
|
||||
aTsContent: string,
|
||||
fixedATsContent: string,
|
||||
compilerOptions: CompilerOptions,
|
||||
@@ -351,28 +342,28 @@ function forEachNoEmitAndErrors(
|
||||
}
|
||||
|
||||
export function forEachNoEmitTsc(commandType: string[]) {
|
||||
forEachNoEmitAndErrors((subScenario, fsContents, aTsContent, fixedATsContent, compilerOptions) =>
|
||||
forEachNoEmitAndErrors((subScenario, sys, aTsContent, fixedATsContent, compilerOptions) =>
|
||||
verifyTsc({
|
||||
scenario: "noEmit",
|
||||
subScenario,
|
||||
commandLineArgs: [...commandType, "/home/src/projects/project", "--noEmit"],
|
||||
fs: () => loadProjectFromFiles(fsContents),
|
||||
commandLineArgs: [...commandType, ".", "--noEmit"],
|
||||
sys,
|
||||
edits: [
|
||||
noChangeRun,
|
||||
{
|
||||
caption: "Fix error",
|
||||
edit: fs => fs.writeFileSync("/home/src/projects/project/a.ts", fixedATsContent),
|
||||
edit: sys => sys.writeFile("/home/src/projects/project/a.ts", fixedATsContent),
|
||||
},
|
||||
noChangeRun,
|
||||
{
|
||||
caption: "Emit after fixing error",
|
||||
edit: noop,
|
||||
commandLineArgs: [...commandType, "/home/src/projects/project"],
|
||||
commandLineArgs: [...commandType, "."],
|
||||
},
|
||||
noChangeRun,
|
||||
{
|
||||
caption: "Introduce error",
|
||||
edit: fs => fs.writeFileSync("/home/src/projects/project/a.ts", aTsContent),
|
||||
edit: sys => sys.writeFile("/home/src/projects/project/a.ts", aTsContent),
|
||||
discrepancyExplanation: compilerOptions.incremental && subScenario.indexOf("multiFile/syntax") !== -1 ? () => [
|
||||
"DtsSignature of ts files: Incremental build have dts signature for ts files from emit so its not d.ts or same as file version",
|
||||
] : undefined,
|
||||
@@ -380,7 +371,7 @@ export function forEachNoEmitTsc(commandType: string[]) {
|
||||
{
|
||||
caption: "Emit when error",
|
||||
edit: noop,
|
||||
commandLineArgs: [...commandType, "/home/src/projects/project"],
|
||||
commandLineArgs: [...commandType, "."],
|
||||
},
|
||||
compilerOptions.incremental && subScenario.indexOf("multiFile/syntax") !== -1 ? {
|
||||
...noChangeRun,
|
||||
@@ -395,20 +386,23 @@ export function forEachNoEmitTsc(commandType: string[]) {
|
||||
}
|
||||
|
||||
export function forEachNoEmitTscWatch(commandType: string[]) {
|
||||
forEachNoEmitAndErrors((subScenario, fsContents, aTsContent, fixedATsContent, compilerOptions) =>
|
||||
forEachNoEmitAndErrors((subScenario, sys, aTsContent, fixedATsContent, compilerOptions) =>
|
||||
verifyTscWatch({
|
||||
scenario: "noEmit",
|
||||
subScenario,
|
||||
commandLineArgs: [...commandType, "/home/src/projects/project", "-w"],
|
||||
commandLineArgs: [...commandType, "-w"],
|
||||
sys: () => {
|
||||
fsContents["/home/src/projects/project/tsconfig.json"] = jsonToReadableText({
|
||||
compilerOptions: compilerOptionsToConfigJson({
|
||||
...compilerOptions,
|
||||
noEmit: true,
|
||||
const result = sys();
|
||||
result.writeFile(
|
||||
"/home/src/projects/project/tsconfig.json",
|
||||
jsonToReadableText({
|
||||
compilerOptions: compilerOptionsToConfigJson({
|
||||
...compilerOptions,
|
||||
noEmit: true,
|
||||
}),
|
||||
}),
|
||||
});
|
||||
fsContents[libFile.path] = libContent;
|
||||
return createWatchedSystem(fsContents);
|
||||
);
|
||||
return result;
|
||||
},
|
||||
edits: [
|
||||
{
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
import { dedent } from "../../_namespaces/Utils.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import {
|
||||
FsContents,
|
||||
libContent,
|
||||
} from "./contents.js";
|
||||
import {
|
||||
noChangeRun,
|
||||
verifyTsc,
|
||||
@@ -12,19 +8,15 @@ import {
|
||||
TscWatchCompileChange,
|
||||
verifyTscWatch,
|
||||
} from "./tscWatch.js";
|
||||
import { loadProjectFromFiles } from "./vfs.js";
|
||||
import {
|
||||
createWatchedSystem,
|
||||
libFile,
|
||||
} from "./virtualFileSystemWithWatch.js";
|
||||
import { TestServerHost } from "./virtualFileSystemWithWatch.js";
|
||||
|
||||
function getFsContentsForNoEmitOnError(
|
||||
function getSysForNoEmitOnError(
|
||||
mainErrorContent: string,
|
||||
outFile: boolean,
|
||||
declaration: true | undefined,
|
||||
incremental: true | undefined,
|
||||
): FsContents {
|
||||
return {
|
||||
) {
|
||||
return TestServerHost.createWatchedSystem({
|
||||
"/user/username/projects/noEmitOnError/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
...outFile ? { outFile: "../dev-build.js", module: "amd" } : { outDir: "./dev-build" },
|
||||
@@ -43,15 +35,14 @@ function getFsContentsForNoEmitOnError(
|
||||
console.log("hi");
|
||||
export { }
|
||||
`,
|
||||
[libFile.path]: libContent,
|
||||
};
|
||||
}, { currentDirectory: "/user/username/projects/noEmitOnError" });
|
||||
}
|
||||
|
||||
function forEachNoEmitOnErrorScenario(
|
||||
subScenario: string,
|
||||
action: (
|
||||
subScenario: string,
|
||||
fsContents: (mainErrorContent: string) => FsContents,
|
||||
fsContents: (mainErrorContent: string) => TestServerHost,
|
||||
) => void,
|
||||
) {
|
||||
for (const outFile of [false, true]) {
|
||||
@@ -60,7 +51,7 @@ function forEachNoEmitOnErrorScenario(
|
||||
action(
|
||||
`${outFile ? "outFile" : "multiFile"}/${subScenario}${declaration ? " with declaration" : ""}${incremental ? " with incremental" : ""}`,
|
||||
mainErrorContent =>
|
||||
getFsContentsForNoEmitOnError(
|
||||
getSysForNoEmitOnError(
|
||||
mainErrorContent,
|
||||
outFile,
|
||||
declaration,
|
||||
@@ -115,25 +106,18 @@ export function forEachNoEmitOnErrorScenarioTsc(commandLineArgs: string[]) {
|
||||
getNoEmitOnErrorErrorsType().forEach(([subScenario, mainErrorContent, fixedErrorContent]) =>
|
||||
forEachNoEmitOnErrorScenario(
|
||||
subScenario,
|
||||
(subScenario, fsContents) => {
|
||||
(subScenario, sys) => {
|
||||
describe(subScenario, () => {
|
||||
verifyTsc({
|
||||
scenario: "noEmitOnError",
|
||||
subScenario,
|
||||
fs: () =>
|
||||
loadProjectFromFiles(
|
||||
fsContents(mainErrorContent),
|
||||
{
|
||||
cwd: "/user/username/projects/noEmitOnError",
|
||||
executingFilePath: libFile.path,
|
||||
},
|
||||
),
|
||||
sys: () => sys(mainErrorContent),
|
||||
commandLineArgs,
|
||||
edits: [
|
||||
noChangeRun,
|
||||
{
|
||||
caption: "Fix error",
|
||||
edit: fs => fs.writeFileSync("src/main.ts", fixedErrorContent, "utf-8"),
|
||||
edit: sys => sys.writeFile("src/main.ts", fixedErrorContent),
|
||||
},
|
||||
noChangeRun,
|
||||
],
|
||||
@@ -149,16 +133,12 @@ export function forEachNoEmitOnErrorScenarioTscWatch(commandLineArgs: string[])
|
||||
const errorTypes = getNoEmitOnErrorErrorsType();
|
||||
forEachNoEmitOnErrorScenario(
|
||||
"noEmitOnError",
|
||||
(subScenario, fsContents) =>
|
||||
(subScenario, sys) =>
|
||||
verifyTscWatch({
|
||||
scenario: "noEmitOnError",
|
||||
subScenario,
|
||||
commandLineArgs: [...commandLineArgs, "--w"],
|
||||
sys: () =>
|
||||
createWatchedSystem(
|
||||
fsContents(errorTypes[0][1]),
|
||||
{ currentDirectory: "/user/username/projects/noEmitOnError" },
|
||||
),
|
||||
sys: () => sys(errorTypes[0][1]),
|
||||
edits: getEdits(errorTypes),
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { dedent } from "../../_namespaces/Utils.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import {
|
||||
FsContents,
|
||||
libContent,
|
||||
} from "./contents.js";
|
||||
import { libFile } from "./virtualFileSystemWithWatch.js";
|
||||
noopChange,
|
||||
TscWatchCompileChange,
|
||||
} from "./tscWatch.js";
|
||||
import { TestServerHost } from "./virtualFileSystemWithWatch.js";
|
||||
|
||||
function getFsContentsForRootsFromReferencedProject(serverFirst: boolean): FsContents {
|
||||
return {
|
||||
"/home/src/workspaces/tsconfig.json": jsonToReadableText({
|
||||
function getSysForRootsFromReferencedProject(forTsserver: boolean, serverFirst: boolean) {
|
||||
return TestServerHost.getCreateWatchedSystem(forTsserver)({
|
||||
"/home/src/workspaces/solution/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
},
|
||||
@@ -17,29 +17,29 @@ function getFsContentsForRootsFromReferencedProject(serverFirst: boolean): FsCon
|
||||
{ path: "projects/shared" },
|
||||
],
|
||||
}),
|
||||
"/home/src/workspaces/projects/shared/src/myClass.ts": `export class MyClass { }`,
|
||||
"/home/src/workspaces/projects/shared/src/logging.ts": dedent`
|
||||
"/home/src/workspaces/solution/projects/shared/src/myClass.ts": `export class MyClass { }`,
|
||||
"/home/src/workspaces/solution/projects/shared/src/logging.ts": dedent`
|
||||
export function log(str: string) {
|
||||
console.log(str);
|
||||
}
|
||||
`,
|
||||
"/home/src/workspaces/projects/shared/src/random.ts": dedent`
|
||||
"/home/src/workspaces/solution/projects/shared/src/random.ts": dedent`
|
||||
export function randomFn(str: string) {
|
||||
console.log(str);
|
||||
}
|
||||
`,
|
||||
"/home/src/workspaces/projects/shared/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/solution/projects/shared/tsconfig.json": jsonToReadableText({
|
||||
extends: "../../tsconfig.json",
|
||||
compilerOptions: {
|
||||
outDir: "./dist",
|
||||
},
|
||||
include: ["src/**/*.ts"],
|
||||
}),
|
||||
"/home/src/workspaces/projects/server/src/server.ts": dedent`
|
||||
"/home/src/workspaces/solution/projects/server/src/server.ts": dedent`
|
||||
import { MyClass } from ':shared/myClass.js';
|
||||
console.log('Hello, world!');
|
||||
`,
|
||||
"/home/src/workspaces/projects/server/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/solution/projects/server/tsconfig.json": jsonToReadableText({
|
||||
extends: "../../tsconfig.json",
|
||||
compilerOptions: {
|
||||
baseUrl: "./src",
|
||||
@@ -56,11 +56,42 @@ function getFsContentsForRootsFromReferencedProject(serverFirst: boolean): FsCon
|
||||
{ path: "../shared" },
|
||||
],
|
||||
}),
|
||||
[libFile.path]: libContent,
|
||||
};
|
||||
}, { currentDirectory: "/home/src/workspaces/solution" });
|
||||
}
|
||||
|
||||
export function forEachScenarioForRootsFromReferencedProject(action: (subScenario: string, getFsContents: () => FsContents) => void) {
|
||||
action("when root file is from referenced project", () => getFsContentsForRootsFromReferencedProject(/*serverFirst*/ true));
|
||||
action("when root file is from referenced project and shared is first", () => getFsContentsForRootsFromReferencedProject(/*serverFirst*/ false));
|
||||
export function forEachScenarioForRootsFromReferencedProject(
|
||||
forTsserver: boolean,
|
||||
action: (
|
||||
subScenario: string,
|
||||
sys: () => TestServerHost,
|
||||
edits: () => readonly TscWatchCompileChange[],
|
||||
) => void,
|
||||
) {
|
||||
[true, false].forEach(serverFirst =>
|
||||
action(
|
||||
`when root file is from referenced project${!serverFirst ? " and shared is first" : ""}`,
|
||||
() => getSysForRootsFromReferencedProject(forTsserver, serverFirst),
|
||||
() => [
|
||||
noopChange,
|
||||
{
|
||||
caption: "edit logging file",
|
||||
edit: sys => sys.appendFile("/home/src/workspaces/solution/projects/shared/src/logging.ts", "export const x = 10;"),
|
||||
timeouts: sys => {
|
||||
sys.runQueuedTimeoutCallbacks(); // build shared
|
||||
sys.runQueuedTimeoutCallbacks(); // build server
|
||||
},
|
||||
},
|
||||
noopChange,
|
||||
{
|
||||
caption: "delete random file",
|
||||
edit: sys => sys.deleteFile("/home/src/workspaces/solution/projects/shared/src/random.ts"),
|
||||
timeouts: sys => {
|
||||
sys.runQueuedTimeoutCallbacks(); // build shared
|
||||
sys.runQueuedTimeoutCallbacks(); // build server
|
||||
},
|
||||
},
|
||||
noopChange,
|
||||
],
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,15 +1,8 @@
|
||||
import { dedent } from "../../_namespaces/Utils.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import {
|
||||
FsContents,
|
||||
getProjectConfigWithNodeNext,
|
||||
} from "./contents.js";
|
||||
import { loadProjectFromFiles } from "./vfs.js";
|
||||
import {
|
||||
createServerHost,
|
||||
createWatchedSystem,
|
||||
libFile,
|
||||
} from "./virtualFileSystemWithWatch.js";
|
||||
import { getProjectConfigWithNodeNext } from "./contents.js";
|
||||
import { solutionBuildWithBaseline } from "./solutionBuilder.js";
|
||||
import { TestServerHost } from "./virtualFileSystemWithWatch.js";
|
||||
|
||||
export function getFsContentsForSampleProjectReferencesLogicConfig(withNodeNext?: boolean) {
|
||||
return jsonToReadableText({
|
||||
@@ -26,9 +19,13 @@ export function getFsContentsForSampleProjectReferencesLogicConfig(withNodeNext?
|
||||
],
|
||||
});
|
||||
}
|
||||
export function getFsContentsForSampleProjectReferences(withNodeNext?: boolean, skipReferenceCoreFromTest?: boolean): FsContents {
|
||||
return {
|
||||
[libFile.path]: libFile.content,
|
||||
|
||||
export function getSysForSampleProjectReferences(
|
||||
withNodeNext?: boolean,
|
||||
skipReferenceCoreFromTest?: boolean,
|
||||
forTsserver?: boolean,
|
||||
) {
|
||||
return TestServerHost.getCreateWatchedSystem(forTsserver)({
|
||||
"/user/username/projects/sample1/core/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
...getProjectConfigWithNodeNext(withNodeNext),
|
||||
@@ -82,33 +79,12 @@ export function getFsContentsForSampleProjectReferences(withNodeNext?: boolean,
|
||||
import * as mod from '../core/anotherModule';
|
||||
export const m = mod;
|
||||
`,
|
||||
};
|
||||
}, { currentDirectory: "/user/username/projects/sample1" });
|
||||
}
|
||||
|
||||
export function getFsForSampleProjectReferences(withNodeNext?: boolean, skipReferenceCoreFromTest?: boolean) {
|
||||
return loadProjectFromFiles(
|
||||
getFsContentsForSampleProjectReferences(withNodeNext, skipReferenceCoreFromTest),
|
||||
{
|
||||
cwd: "/user/username/projects/sample1",
|
||||
executingFilePath: libFile.path,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
export function getSysForSampleProjectReferences(withNodeNext?: boolean, skipReferenceCoreFromTest?: boolean) {
|
||||
return createWatchedSystem(
|
||||
getFsContentsForSampleProjectReferences(withNodeNext, skipReferenceCoreFromTest),
|
||||
{
|
||||
currentDirectory: "/user/username/projects/sample1",
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
export function getServerHostForSampleProjectReferences() {
|
||||
return createServerHost(
|
||||
getFsContentsForSampleProjectReferences(),
|
||||
{
|
||||
currentDirectory: "/user/username/projects/sample1",
|
||||
},
|
||||
export function getSysForSampleProjectReferencesBuilt(withNodeNext?: boolean) {
|
||||
return solutionBuildWithBaseline(
|
||||
getSysForSampleProjectReferences(withNodeNext),
|
||||
["tests"],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,31 +1,48 @@
|
||||
import * as fakes from "../../_namespaces/fakes.js";
|
||||
import * as ts from "../../_namespaces/ts.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import { commandLineCallbacks } from "./baseline.js";
|
||||
import {
|
||||
makeSystemReadyForBaseline,
|
||||
TscCompileSystem,
|
||||
CommandLineCallbacks,
|
||||
commandLineCallbacks,
|
||||
patchHostForBuildInfoReadWrite,
|
||||
patchHostForBuildInfoWrite,
|
||||
TscWatchSystem,
|
||||
} from "./baseline.js";
|
||||
import {
|
||||
verifyTsc,
|
||||
VerifyTscWithEditsInput,
|
||||
} from "./tsc.js";
|
||||
import {
|
||||
changeToHostTrackingWrittenFiles,
|
||||
TestServerHost,
|
||||
} from "./virtualFileSystemWithWatch.js";
|
||||
|
||||
export type SolutionBuilderHostWithGetPrograms =
|
||||
& ts.SolutionBuilderHost<ts.EmitAndSemanticDiagnosticsBuilderProgram>
|
||||
& { getPrograms: CommandLineCallbacks["getPrograms"]; };
|
||||
export function createSolutionBuilderHostForBaseline(
|
||||
sys: TscCompileSystem | TestServerHost,
|
||||
versionToWrite?: string,
|
||||
originalRead?: (TscCompileSystem | TestServerHost)["readFile"],
|
||||
) {
|
||||
if (sys instanceof fakes.System) makeSystemReadyForBaseline(sys, versionToWrite);
|
||||
const { cb } = commandLineCallbacks(sys, originalRead);
|
||||
const host = ts.createSolutionBuilderHost(sys, /*createProgram*/ undefined, ts.createDiagnosticReporter(sys, /*pretty*/ true), ts.createBuilderStatusReporter(sys, /*pretty*/ true));
|
||||
sys: TscWatchSystem,
|
||||
originalRead?: TestServerHost["readFile"],
|
||||
): ts.SolutionBuilderHost<ts.EmitAndSemanticDiagnosticsBuilderProgram> & { getPrograms: CommandLineCallbacks["getPrograms"]; } {
|
||||
const { cb, getPrograms } = commandLineCallbacks(sys, originalRead);
|
||||
const host = ts.createSolutionBuilderHost(
|
||||
sys,
|
||||
/*createProgram*/ undefined,
|
||||
ts.createDiagnosticReporter(sys, /*pretty*/ true),
|
||||
ts.createBuilderStatusReporter(sys, /*pretty*/ true),
|
||||
) as SolutionBuilderHostWithGetPrograms;
|
||||
host.afterProgramEmitAndDiagnostics = cb;
|
||||
host.getPrograms = getPrograms;
|
||||
return host;
|
||||
}
|
||||
|
||||
export function createSolutionBuilder(system: TestServerHost, rootNames: readonly string[], originalRead?: TestServerHost["readFile"]) {
|
||||
const host = createSolutionBuilderHostForBaseline(system, /*versionToWrite*/ undefined, originalRead);
|
||||
return ts.createSolutionBuilder(host, rootNames, {});
|
||||
export function createSolutionBuilder(
|
||||
system: TscWatchSystem,
|
||||
rootNames: readonly string[],
|
||||
buildOptions?: ts.BuildOptions,
|
||||
originalRead?: TestServerHost["readFile"],
|
||||
) {
|
||||
const host = createSolutionBuilderHostForBaseline(system, originalRead);
|
||||
return ts.createSolutionBuilder(host, rootNames, buildOptions ?? {});
|
||||
}
|
||||
|
||||
export function ensureErrorFreeBuild(host: TestServerHost, rootNames: readonly string[]) {
|
||||
@@ -34,16 +51,25 @@ export function ensureErrorFreeBuild(host: TestServerHost, rootNames: readonly s
|
||||
assert.equal(host.getOutput().length, 0, jsonToReadableText(host.getOutput()));
|
||||
}
|
||||
|
||||
export function solutionBuildWithBaseline(sys: TestServerHost, solutionRoots: readonly string[], originalRead?: TestServerHost["readFile"]) {
|
||||
export function solutionBuildWithBaseline(
|
||||
sys: TestServerHost,
|
||||
solutionRoots: readonly string[],
|
||||
buildOptions?: ts.BuildOptions,
|
||||
versionToWrite?: string,
|
||||
originalRead?: TestServerHost["readFile"],
|
||||
) {
|
||||
if (sys.writtenFiles === undefined) {
|
||||
const originalReadFile = sys.readFile;
|
||||
const originalWrite = sys.write;
|
||||
const originalWriteFile = sys.writeFile;
|
||||
const solutionBuilder = createSolutionBuilder(
|
||||
changeToHostTrackingWrittenFiles(
|
||||
fakes.patchHostForBuildInfoReadWrite(sys),
|
||||
versionToWrite ?
|
||||
patchHostForBuildInfoWrite(sys, versionToWrite) :
|
||||
patchHostForBuildInfoReadWrite(sys),
|
||||
),
|
||||
solutionRoots,
|
||||
buildOptions,
|
||||
originalRead,
|
||||
);
|
||||
solutionBuilder.build();
|
||||
@@ -51,11 +77,41 @@ export function solutionBuildWithBaseline(sys: TestServerHost, solutionRoots: re
|
||||
sys.write = originalWrite;
|
||||
sys.writeFile = originalWriteFile;
|
||||
sys.writtenFiles = undefined;
|
||||
sys.clearOutput();
|
||||
return sys;
|
||||
}
|
||||
else {
|
||||
const solutionBuilder = createSolutionBuilder(sys, solutionRoots);
|
||||
const solutionBuilder = createSolutionBuilder(sys as TscWatchSystem, solutionRoots, buildOptions, originalRead);
|
||||
solutionBuilder.build();
|
||||
return sys;
|
||||
}
|
||||
}
|
||||
|
||||
export function verifySolutionBuilderWithDifferentTsVersion(input: VerifyTscWithEditsInput, rootNames: readonly string[]) {
|
||||
describe(input.subScenario, () => {
|
||||
let originalReadFile: TscWatchSystem["readFile"];
|
||||
let originalWriteFile: TscWatchSystem["writeFile"];
|
||||
verifyTsc({
|
||||
...input,
|
||||
sys: () => {
|
||||
const sys = input.sys();
|
||||
originalReadFile = sys.readFile;
|
||||
originalWriteFile = sys.writeFile;
|
||||
return sys;
|
||||
},
|
||||
compile: sys => {
|
||||
sys.readFile = originalReadFile;
|
||||
sys.writeFile = originalWriteFile;
|
||||
originalReadFile = undefined!;
|
||||
originalWriteFile = undefined!;
|
||||
sys.writtenFiles = undefined!;
|
||||
// Buildinfo will have version which does not match with current ts version
|
||||
changeToHostTrackingWrittenFiles(patchHostForBuildInfoWrite(sys, "FakeTSCurrentVersion"));
|
||||
const buildHost = createSolutionBuilderHostForBaseline(sys);
|
||||
const builder = ts.createSolutionBuilder(buildHost, rootNames, { verbose: true });
|
||||
sys.exit(builder.build());
|
||||
return buildHost.getPrograms;
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
import { dedent } from "../../_namespaces/Utils.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import {
|
||||
FsContents,
|
||||
getProjectConfigWithNodeNext,
|
||||
libContent,
|
||||
} from "./contents.js";
|
||||
import { libFile } from "./virtualFileSystemWithWatch.js";
|
||||
import { getProjectConfigWithNodeNext } from "./contents.js";
|
||||
import { TestServerHost } from "./virtualFileSystemWithWatch.js";
|
||||
|
||||
export function getFsContentsForTransitiveReferencesRefsAdts() {
|
||||
return dedent`
|
||||
@@ -39,8 +35,8 @@ export function getFsContentsForTransitiveReferencesAConfig(withNodeNext: boolea
|
||||
});
|
||||
}
|
||||
|
||||
export function getFsContentsForTransitiveReferences(withNodeNext?: boolean): FsContents {
|
||||
return {
|
||||
export function getSysForTransitiveReferences(withNodeNext?: boolean) {
|
||||
return TestServerHost.createWatchedSystem({
|
||||
"/user/username/projects/transitiveReferences/refs/a.d.ts": getFsContentsForTransitiveReferencesRefsAdts(),
|
||||
"/user/username/projects/transitiveReferences/a.ts": dedent`
|
||||
export class A {}
|
||||
@@ -68,6 +64,5 @@ export function getFsContentsForTransitiveReferences(withNodeNext?: boolean): Fs
|
||||
},
|
||||
references: [{ path: "tsconfig.b.json" }],
|
||||
}),
|
||||
[libFile.path]: libContent,
|
||||
};
|
||||
}, { currentDirectory: "/user/username/projects/transitiveReferences" });
|
||||
}
|
||||
|
||||
@@ -1,33 +1,32 @@
|
||||
import * as fakes from "../../_namespaces/fakes.js";
|
||||
import * as Harness from "../../_namespaces/Harness.js";
|
||||
import { Baseline } from "../../_namespaces/Harness.js";
|
||||
import * as ts from "../../_namespaces/ts.js";
|
||||
import * as vfs from "../../_namespaces/vfs.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import {
|
||||
baselinePrograms,
|
||||
applyEdit,
|
||||
baselineAfterTscCompile as baseline_baselineAfterTscCompile,
|
||||
BaselineBase,
|
||||
CommandLineCallbacks,
|
||||
commandLineCallbacks,
|
||||
CommandLineProgram,
|
||||
generateSourceMapBaselineFiles,
|
||||
createBaseline,
|
||||
isReadableIncrementalBuildInfo,
|
||||
isReadableIncrementalBundleEmitBuildInfo,
|
||||
isReadableIncrementalMultiFileEmitBuildInfo,
|
||||
isWatch,
|
||||
ReadableBuildInfo,
|
||||
ReadableIncrementalBuildInfo,
|
||||
ReadableIncrementalBuildInfoFileInfo,
|
||||
ReadableIncrementalBundleEmitBuildInfo,
|
||||
ReadableIncrementalMultiFileEmitBuildInfo,
|
||||
sanitizeSysOutput,
|
||||
toPathWithSystem,
|
||||
tscBaselineName,
|
||||
TscWatchSystem,
|
||||
} from "./baseline.js";
|
||||
|
||||
export type TscCompileSystem = fakes.System & {
|
||||
writtenFiles: Set<ts.Path>;
|
||||
baseLine(): { file: string; text: string; };
|
||||
dtsSignaures?: Map<ts.Path, Map<string, string>>;
|
||||
storeSignatureInfo?: boolean;
|
||||
};
|
||||
import {
|
||||
isFsFile,
|
||||
TestServerHost,
|
||||
TestServerHostSnapshot,
|
||||
} from "./virtualFileSystemWithWatch.js";
|
||||
|
||||
export const noChangeRun: TestTscEdit = {
|
||||
caption: "no-change-run",
|
||||
@@ -35,106 +34,40 @@ export const noChangeRun: TestTscEdit = {
|
||||
};
|
||||
export const noChangeOnlyRuns = [noChangeRun];
|
||||
|
||||
export interface TestTscCompile extends TestTscCompileLikeBase {
|
||||
export interface TestTscCompile {
|
||||
commandLineArgs: readonly string[];
|
||||
sys: () => TestServerHost;
|
||||
modifySystem?: (fs: TestServerHost) => void;
|
||||
computeDtsSignatures?: boolean;
|
||||
getWrittenFiles?: boolean;
|
||||
baselineSourceMap?: boolean;
|
||||
baselineReadFileCalls?: boolean;
|
||||
baselinePrograms?: boolean;
|
||||
baselineDependencies?: boolean;
|
||||
}
|
||||
|
||||
export interface TestTscCompileLikeBase extends VerifyTscCompileLike {
|
||||
diffWithInitial?: boolean;
|
||||
modifyFs?: (fs: vfs.FileSystem) => void;
|
||||
computeDtsSignatures?: boolean;
|
||||
environmentVariables?: Record<string, string>;
|
||||
}
|
||||
|
||||
export interface TestTscCompileLike extends TestTscCompileLikeBase {
|
||||
compile: (sys: TscCompileSystem) => void;
|
||||
additionalBaseline?: (sys: TscCompileSystem) => void;
|
||||
}
|
||||
/**
|
||||
* Initialize FS, run compile function and save baseline
|
||||
*/
|
||||
export function testTscCompileLike(input: TestTscCompileLike) {
|
||||
const initialFs = input.fs();
|
||||
const inputFs = initialFs.shadow();
|
||||
const {
|
||||
scenario,
|
||||
subScenario,
|
||||
diffWithInitial,
|
||||
commandLineArgs,
|
||||
modifyFs,
|
||||
environmentVariables,
|
||||
compile: worker,
|
||||
additionalBaseline,
|
||||
} = input;
|
||||
if (modifyFs) modifyFs(inputFs);
|
||||
inputFs.makeReadonly();
|
||||
const fs = inputFs.shadow();
|
||||
|
||||
// Create system
|
||||
const sys = new fakes.System(fs, { executingFilePath: `${fs.meta.get("defaultLibLocation")}/tsc`, env: environmentVariables }) as TscCompileSystem;
|
||||
sys.storeSignatureInfo = true;
|
||||
sys.write(`${sys.getExecutingFilePath()} ${commandLineArgs.join(" ")}\n`);
|
||||
sys.exit = exitCode => sys.exitCode = exitCode;
|
||||
worker(sys);
|
||||
sys.write(`exitCode:: ExitStatus.${ts.ExitStatus[sys.exitCode as ts.ExitStatus]}\n`);
|
||||
additionalBaseline?.(sys);
|
||||
fs.makeReadonly();
|
||||
sys.baseLine = () => {
|
||||
const baseFsPatch = diffWithInitial ?
|
||||
inputFs.diff(initialFs, { includeChangedFileWithSameContent: true }) :
|
||||
inputFs.diff(/*base*/ undefined, { baseIsNotShadowRoot: true });
|
||||
const patch = fs.diff(inputFs, { includeChangedFileWithSameContent: true });
|
||||
return {
|
||||
file: tscBaselineName(scenario, subScenario, commandLineArgs),
|
||||
text: `Input::
|
||||
${baseFsPatch ? vfs.formatPatch(baseFsPatch) : ""}
|
||||
|
||||
Output::
|
||||
${sys.output.map(sanitizeSysOutput).join("")}
|
||||
|
||||
${patch ? vfs.formatPatch(patch) : ""}`,
|
||||
};
|
||||
};
|
||||
return sys;
|
||||
}
|
||||
|
||||
export function makeSystemReadyForBaseline(sys: TscCompileSystem, versionToWrite?: string) {
|
||||
if (versionToWrite) {
|
||||
fakes.patchHostForBuildInfoWrite(sys, versionToWrite);
|
||||
}
|
||||
else {
|
||||
fakes.patchHostForBuildInfoReadWrite(sys);
|
||||
}
|
||||
const writtenFiles = sys.writtenFiles = new Set();
|
||||
const originalWriteFile = sys.writeFile;
|
||||
sys.writeFile = (fileName, content, writeByteOrderMark) => {
|
||||
const path = toPathWithSystem(sys, fileName);
|
||||
// When buildinfo is same for two projects,
|
||||
// it gives error and doesnt write buildinfo but because buildInfo is written for one project,
|
||||
// readable baseline will be written two times for those two projects with same contents and is ok
|
||||
ts.Debug.assert(!writtenFiles.has(path) || ts.endsWith(path, "baseline.txt"));
|
||||
writtenFiles.add(path);
|
||||
return originalWriteFile.call(sys, fileName, content, writeByteOrderMark);
|
||||
};
|
||||
compile?: (sys: TscWatchSystem) => CommandLineCallbacks["getPrograms"];
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize Fs, execute command line and save baseline
|
||||
*/
|
||||
export function testTscCompile(input: TestTscCompile) {
|
||||
function initialTestTscCompile(input: TestTscCompile) {
|
||||
const { sys, baseline } = createBaseline(input.sys(), input.modifySystem);
|
||||
sys.exit = exitCode => sys.exitCode = exitCode;
|
||||
ts.Debug.assert(!isWatch(input.commandLineArgs), "use verifyTscWatch");
|
||||
return testTscCompileWith(sys, baseline, input);
|
||||
}
|
||||
|
||||
/**
|
||||
* execute command line and save baseline
|
||||
*/
|
||||
function testTscCompileWith(
|
||||
sys: BaselineBase["sys"],
|
||||
baseline: BaselineBase["baseline"],
|
||||
input: TestTscCompileBaselineInput & Pick<TestTscCompile, "compile">,
|
||||
) {
|
||||
let actualReadFileMap: ts.MapLike<number> | undefined;
|
||||
let getPrograms: CommandLineCallbacks["getPrograms"] | undefined;
|
||||
return testTscCompileLike({
|
||||
...input,
|
||||
compile: commandLineCompile,
|
||||
additionalBaseline,
|
||||
});
|
||||
|
||||
function commandLineCompile(sys: TscCompileSystem) {
|
||||
makeSystemReadyForBaseline(sys);
|
||||
if (!input.compile) {
|
||||
actualReadFileMap = {};
|
||||
const originalReadFile = sys.readFile;
|
||||
if (input.baselineReadFileCalls) {
|
||||
@@ -146,7 +79,6 @@ export function testTscCompile(input: TestTscCompile) {
|
||||
return originalReadFile.call(sys, path);
|
||||
};
|
||||
}
|
||||
|
||||
const result = commandLineCallbacks(sys, originalReadFile);
|
||||
ts.executeCommandLine(
|
||||
sys,
|
||||
@@ -156,33 +88,57 @@ export function testTscCompile(input: TestTscCompile) {
|
||||
sys.readFile = originalReadFile;
|
||||
getPrograms = result.getPrograms;
|
||||
}
|
||||
|
||||
function additionalBaseline(sys: TscCompileSystem) {
|
||||
const { baselineSourceMap, baselineReadFileCalls, baselinePrograms: shouldBaselinePrograms, baselineDependencies } = input;
|
||||
const programs = getPrograms!();
|
||||
if (input.computeDtsSignatures) storeDtsSignatures(sys, programs);
|
||||
if (shouldBaselinePrograms) {
|
||||
const baseline: string[] = [];
|
||||
baselinePrograms(baseline, programs, ts.emptyArray, baselineDependencies);
|
||||
sys.write(baseline.join("\n"));
|
||||
}
|
||||
if (baselineReadFileCalls) {
|
||||
sys.write(`readFiles:: ${jsonToReadableText(actualReadFileMap)} `);
|
||||
}
|
||||
if (baselineSourceMap) generateSourceMapBaselineFiles(sys);
|
||||
actualReadFileMap = undefined;
|
||||
getPrograms = undefined;
|
||||
else {
|
||||
getPrograms = input.compile(sys);
|
||||
}
|
||||
const { dtsSignatures, writtenFiles } = baselineAfterTscCompile(sys, baseline, input, getPrograms, actualReadFileMap);
|
||||
return { sys, baseline, dtsSignatures, writtenFiles };
|
||||
}
|
||||
type TestTscCompileBaselineInput = Pick<
|
||||
TestTscCompile,
|
||||
| "commandLineArgs"
|
||||
| "computeDtsSignatures"
|
||||
| "getWrittenFiles"
|
||||
| "baselineSourceMap"
|
||||
| "baselineReadFileCalls"
|
||||
| "baselinePrograms"
|
||||
| "baselineDependencies"
|
||||
>;
|
||||
function baselineAfterTscCompile(
|
||||
sys: BaselineBase["sys"],
|
||||
baseline: BaselineBase["baseline"],
|
||||
input: TestTscCompileBaselineInput,
|
||||
getPrograms: () => readonly CommandLineProgram[],
|
||||
actualReadFileMap: ts.MapLike<number> | undefined,
|
||||
) {
|
||||
baseline.push(`${sys.getExecutingFilePath()} ${input.commandLineArgs.join(" ")}`);
|
||||
const writtenFiles = input.getWrittenFiles ? new Set(sys.writtenFiles.keys()) : undefined;
|
||||
const programs = baseline_baselineAfterTscCompile(
|
||||
sys,
|
||||
baseline,
|
||||
getPrograms,
|
||||
ts.emptyArray,
|
||||
input.baselineSourceMap,
|
||||
input.baselinePrograms,
|
||||
input.baselineDependencies,
|
||||
);
|
||||
const dtsSignatures = input.computeDtsSignatures ? storeDtsSignatures(sys, programs) : undefined;
|
||||
if (input.baselineReadFileCalls) {
|
||||
baseline.push(`readFiles:: ${jsonToReadableText(actualReadFileMap)} `);
|
||||
}
|
||||
actualReadFileMap = undefined;
|
||||
return { dtsSignatures, writtenFiles };
|
||||
}
|
||||
|
||||
function storeDtsSignatures(sys: TscCompileSystem, programs: readonly CommandLineProgram[]) {
|
||||
function storeDtsSignatures(sys: TscWatchSystem, programs: readonly CommandLineProgram[]) {
|
||||
let dtsSignatures: Map<ts.Path, Map<string, string>> | undefined;
|
||||
for (const [program, builderProgram] of programs) {
|
||||
if (!builderProgram) continue;
|
||||
const buildInfoPath = ts.getTsBuildInfoEmitOutputFilePath(program.getCompilerOptions());
|
||||
if (!buildInfoPath) continue;
|
||||
sys.dtsSignaures ??= new Map();
|
||||
dtsSignatures ??= new Map();
|
||||
const dtsSignatureData = new Map<string, string>();
|
||||
sys.dtsSignaures.set(`${toPathWithSystem(sys, buildInfoPath)}.readable.baseline.txt` as ts.Path, dtsSignatureData);
|
||||
dtsSignatures.set(`${toPathWithSystem(sys, buildInfoPath)}.readable.baseline.txt` as ts.Path, dtsSignatureData);
|
||||
builderProgram.state.hasCalledUpdateShapeSignature?.forEach(resolvedPath => {
|
||||
const file = program.getSourceFileByPath(resolvedPath);
|
||||
if (!file || file.isDeclarationFile) return;
|
||||
@@ -203,84 +159,36 @@ function storeDtsSignatures(sys: TscCompileSystem, programs: readonly CommandLin
|
||||
return ts.ensurePathIsNonModuleName(ts.getRelativePathFromDirectory(buildInfoDirectory, path, getCanonicalFileName));
|
||||
}
|
||||
}
|
||||
return dtsSignatures;
|
||||
}
|
||||
|
||||
export function verifyTscBaseline(sys: () => { baseLine: TscCompileSystem["baseLine"]; }) {
|
||||
it(`Generates files matching the baseline`, () => {
|
||||
const { file, text } = sys().baseLine();
|
||||
Harness.Baseline.runBaseline(file, text);
|
||||
});
|
||||
}
|
||||
export interface VerifyTscCompileLike {
|
||||
scenario: string;
|
||||
subScenario: string;
|
||||
commandLineArgs: readonly string[];
|
||||
fs: () => vfs.FileSystem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify by baselining after initializing FS and custom compile
|
||||
*/
|
||||
export function verifyTscCompileLike<T extends VerifyTscCompileLike>(verifier: (input: T) => { baseLine: TscCompileSystem["baseLine"]; }, input: T) {
|
||||
describe(`tsc ${input.commandLineArgs.join(" ")} ${input.scenario}:: ${input.subScenario}`, () => {
|
||||
describe(input.scenario, () => {
|
||||
describe(input.subScenario, () => {
|
||||
verifyTscBaseline(() =>
|
||||
verifier({
|
||||
...input,
|
||||
fs: () => input.fs().makeReadonly(),
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
interface VerifyTscEditDiscrepanciesInput {
|
||||
index: number;
|
||||
edits: readonly TestTscEdit[];
|
||||
scenario: TestTscCompile["scenario"];
|
||||
baselines: string[] | undefined;
|
||||
commandLineArgs: TestTscCompile["commandLineArgs"];
|
||||
modifyFs: TestTscCompile["modifyFs"];
|
||||
baseFs: vfs.FileSystem;
|
||||
newSys: TscCompileSystem;
|
||||
environmentVariables: TestTscCompile["environmentVariables"];
|
||||
}
|
||||
function verifyTscEditDiscrepancies({
|
||||
index,
|
||||
edits,
|
||||
scenario,
|
||||
commandLineArgs,
|
||||
environmentVariables,
|
||||
baselines,
|
||||
modifyFs,
|
||||
baseFs,
|
||||
newSys,
|
||||
}: VerifyTscEditDiscrepanciesInput): string[] | undefined {
|
||||
const { caption, discrepancyExplanation } = edits[index];
|
||||
const sys = testTscCompile({
|
||||
scenario,
|
||||
subScenario: caption,
|
||||
fs: () => baseFs.makeReadonly(),
|
||||
commandLineArgs: edits[index].commandLineArgs || commandLineArgs,
|
||||
modifyFs: fs => {
|
||||
if (modifyFs) modifyFs(fs);
|
||||
function verifyTscEditDiscrepancies(
|
||||
input: VerifyTscWithEditsInput,
|
||||
index: number,
|
||||
snaps: readonly TestServerHostSnapshot[],
|
||||
baselines: string[] | undefined,
|
||||
): string[] | undefined {
|
||||
const result = initialTestTscCompile({
|
||||
...input,
|
||||
modifySystem: fs => {
|
||||
input.modifySystem?.(fs);
|
||||
for (let i = 0; i <= index; i++) {
|
||||
edits[i].edit(fs);
|
||||
input.edits![i].edit(fs as TscWatchSystem);
|
||||
}
|
||||
},
|
||||
environmentVariables,
|
||||
commandLineArgs: input.edits![index].commandLineArgs ?? input.commandLineArgs,
|
||||
computeDtsSignatures: true,
|
||||
getWrittenFiles: true,
|
||||
});
|
||||
let headerAdded = false;
|
||||
for (const outputFile of sys.writtenFiles.keys()) {
|
||||
const cleanBuildText = sys.readFile(outputFile);
|
||||
const incrementalBuildText = newSys.readFile(outputFile);
|
||||
for (const outputFile of result.writtenFiles!.keys()) {
|
||||
const cleanBuildText = result.sys.readFile(outputFile);
|
||||
const incrementalFsEntry = snaps[index].get(outputFile);
|
||||
const incrementalBuildText = isFsFile(incrementalFsEntry) ? incrementalFsEntry.content : undefined;
|
||||
if (ts.isBuildInfoFile(outputFile)) {
|
||||
// Check only presence and absence and not text as we will do that for readable baseline
|
||||
if (!sys.fileExists(`${outputFile}.readable.baseline.txt`)) addBaseline(`Readable baseline not present in clean build:: File:: ${outputFile}`);
|
||||
if (!newSys.fileExists(`${outputFile}.readable.baseline.txt`)) addBaseline(`Readable baseline not present in incremental build:: File:: ${outputFile}`);
|
||||
if (!result.sys.fileExists(`${outputFile}.readable.baseline.txt`)) addBaseline(`Readable baseline not present in clean build:: File:: ${outputFile}`);
|
||||
if (!isFsFile(snaps[index].get(`${outputFile}.readable.baseline.txt` as ts.Path))) addBaseline(`Readable baseline not present in incremental build:: File:: ${outputFile}`);
|
||||
verifyPresenceAbsence(incrementalBuildText, cleanBuildText, `Incremental and clean tsbuildinfo file presence differs:: File:: ${outputFile}`);
|
||||
}
|
||||
else if (!ts.fileExtensionIs(outputFile, ".tsbuildinfo.readable.baseline.txt")) {
|
||||
@@ -290,14 +198,14 @@ function verifyTscEditDiscrepancies({
|
||||
// Verify build info without affectedFilesPendingEmit
|
||||
const { buildInfo: incrementalBuildInfo, readableBuildInfo: incrementalReadableBuildInfo } = getBuildInfoForIncrementalCorrectnessCheck(incrementalBuildText);
|
||||
const { buildInfo: cleanBuildInfo, readableBuildInfo: cleanReadableBuildInfo } = getBuildInfoForIncrementalCorrectnessCheck(cleanBuildText);
|
||||
const dtsSignaures = sys.dtsSignaures?.get(outputFile);
|
||||
const dtsSignatures = result.dtsSignatures?.get(outputFile);
|
||||
verifyTextEqual(incrementalBuildInfo, cleanBuildInfo, `TsBuild info text without affectedFilesPendingEmit:: ${outputFile}::`);
|
||||
// Verify file info sigantures
|
||||
verifyMapLike(
|
||||
(incrementalReadableBuildInfo as ReadableIncrementalMultiFileEmitBuildInfo)?.fileInfos,
|
||||
(cleanReadableBuildInfo as ReadableIncrementalMultiFileEmitBuildInfo)?.fileInfos,
|
||||
(key, incrementalFileInfo, cleanFileInfo) => {
|
||||
const dtsForKey = dtsSignaures?.get(key);
|
||||
const dtsForKey = dtsSignatures?.get(key);
|
||||
if (
|
||||
!incrementalFileInfo ||
|
||||
!cleanFileInfo ||
|
||||
@@ -436,7 +344,7 @@ function verifyTscEditDiscrepancies({
|
||||
});
|
||||
}
|
||||
}
|
||||
if (!headerAdded && discrepancyExplanation) addBaseline("*** Supplied discrepancy explanation but didnt find any difference");
|
||||
if (!headerAdded && input.edits![index].discrepancyExplanation) addBaseline("*** Supplied discrepancy explanation but didnt find any difference");
|
||||
return baselines;
|
||||
|
||||
function verifyTextEqual(incrementalText: string | undefined, cleanText: string | undefined, message: string) {
|
||||
@@ -487,7 +395,7 @@ function verifyTscEditDiscrepancies({
|
||||
|
||||
function addBaseline(...text: string[]) {
|
||||
if (!baselines || !headerAdded) {
|
||||
(baselines ||= []).push(`${index}:: ${caption}`, ...(discrepancyExplanation?.() || ["*** Needs explanation"]));
|
||||
(baselines ||= []).push(`${index}:: ${input.edits![index].caption}`, ...(input.edits![index].discrepancyExplanation?.() || ["*** Needs explanation"]));
|
||||
headerAdded = true;
|
||||
}
|
||||
baselines.push(...text);
|
||||
@@ -537,107 +445,56 @@ function getBuildInfoForIncrementalCorrectnessCheck(text: string | undefined): {
|
||||
}
|
||||
|
||||
export interface TestTscEdit {
|
||||
edit: (fs: vfs.FileSystem) => void;
|
||||
edit: (sys: TscWatchSystem) => void;
|
||||
caption: string;
|
||||
commandLineArgs?: readonly string[];
|
||||
/** An array of lines to be printed in order when a discrepancy is detected */
|
||||
discrepancyExplanation?: () => readonly string[];
|
||||
}
|
||||
|
||||
export interface VerifyTscWithEditsInput extends TestTscCompile {
|
||||
export interface VerifyTscWithEditsInput extends Omit<TestTscCompile, "computeDtsSignatures" | "getWrittenFiles"> {
|
||||
scenario: string;
|
||||
subScenario: string;
|
||||
edits?: readonly TestTscEdit[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify non watch tsc invokcation after each edit
|
||||
*/
|
||||
export function verifyTsc({
|
||||
subScenario,
|
||||
fs,
|
||||
scenario,
|
||||
commandLineArgs,
|
||||
environmentVariables,
|
||||
baselineSourceMap,
|
||||
modifyFs,
|
||||
baselineReadFileCalls,
|
||||
baselinePrograms,
|
||||
edits,
|
||||
}: VerifyTscWithEditsInput) {
|
||||
describe(`tsc ${commandLineArgs.join(" ")} ${scenario}:: ${subScenario}`, () => {
|
||||
let sys: TscCompileSystem;
|
||||
let baseFs: vfs.FileSystem;
|
||||
let editsSys: TscCompileSystem[] | undefined;
|
||||
before(() => {
|
||||
baseFs = fs().makeReadonly();
|
||||
sys = testTscCompile({
|
||||
scenario,
|
||||
subScenario,
|
||||
fs: () => baseFs,
|
||||
commandLineArgs,
|
||||
modifyFs,
|
||||
baselineSourceMap,
|
||||
baselineReadFileCalls,
|
||||
baselinePrograms,
|
||||
environmentVariables,
|
||||
});
|
||||
edits?.forEach((
|
||||
{ edit, caption, commandLineArgs: editCommandLineArgs },
|
||||
index,
|
||||
) => {
|
||||
(editsSys || (editsSys = [])).push(testTscCompile({
|
||||
scenario,
|
||||
subScenario: caption,
|
||||
diffWithInitial: true,
|
||||
fs: () => index === 0 ? sys.vfs : editsSys![index - 1].vfs,
|
||||
commandLineArgs: editCommandLineArgs || commandLineArgs,
|
||||
modifyFs: edit,
|
||||
baselineSourceMap,
|
||||
baselineReadFileCalls,
|
||||
baselinePrograms,
|
||||
environmentVariables,
|
||||
}));
|
||||
});
|
||||
});
|
||||
export function verifyTsc(input: VerifyTscWithEditsInput) {
|
||||
describe(`tsc ${input.commandLineArgs.join(" ")} ${input.scenario}:: ${input.subScenario}`, () => {
|
||||
let snaps: TestServerHostSnapshot[] | undefined;
|
||||
after(() => {
|
||||
baseFs = undefined!;
|
||||
sys = undefined!;
|
||||
editsSys = undefined!;
|
||||
snaps = undefined;
|
||||
});
|
||||
verifyTscBaseline(() => ({
|
||||
baseLine: () => {
|
||||
const { file, text } = sys.baseLine();
|
||||
const texts: string[] = [text];
|
||||
editsSys?.forEach((sys, index) => {
|
||||
const incrementalScenario = edits![index];
|
||||
texts.push("");
|
||||
texts.push(`Change:: ${incrementalScenario.caption}`);
|
||||
texts.push(sys.baseLine().text);
|
||||
it("baseline for the tsc compiles", () => {
|
||||
const { sys, baseline } = initialTestTscCompile(input);
|
||||
input.edits?.forEach(edit => {
|
||||
applyEdit(sys, baseline, edit.edit, edit.caption);
|
||||
testTscCompileWith(sys, baseline, {
|
||||
...input,
|
||||
commandLineArgs: edit.commandLineArgs ?? input.commandLineArgs,
|
||||
});
|
||||
return {
|
||||
file,
|
||||
text: `currentDirectory:: ${sys.getCurrentDirectory()} useCaseSensitiveFileNames: ${sys.useCaseSensitiveFileNames}\r\n` +
|
||||
texts.join("\r\n"),
|
||||
};
|
||||
},
|
||||
}));
|
||||
if (edits?.length) {
|
||||
(snaps ??= []).push(sys.getSnap());
|
||||
});
|
||||
Baseline.runBaseline(
|
||||
tscBaselineName(input.scenario, input.subScenario, input.commandLineArgs),
|
||||
baseline.join("\r\n"),
|
||||
);
|
||||
});
|
||||
if (input.edits?.length) {
|
||||
it("tsc invocation after edit and clean build correctness", () => {
|
||||
let baselines: string[] | undefined;
|
||||
for (let index = 0; index < edits.length; index++) {
|
||||
baselines = verifyTscEditDiscrepancies({
|
||||
for (let index = 0; index < input.edits!.length; index++) {
|
||||
baselines = verifyTscEditDiscrepancies(
|
||||
input,
|
||||
index,
|
||||
edits,
|
||||
scenario,
|
||||
snaps!,
|
||||
baselines,
|
||||
baseFs,
|
||||
newSys: editsSys![index],
|
||||
commandLineArgs,
|
||||
modifyFs,
|
||||
environmentVariables,
|
||||
});
|
||||
);
|
||||
}
|
||||
Harness.Baseline.runBaseline(
|
||||
tscBaselineName(scenario, subScenario, commandLineArgs, /*isWatch*/ undefined, "-discrepancies"),
|
||||
Baseline.runBaseline(
|
||||
tscBaselineName(input.scenario, input.subScenario, input.commandLineArgs, "-discrepancies"),
|
||||
baselines ? baselines.join("\r\n") : null, // eslint-disable-line no-restricted-syntax
|
||||
);
|
||||
});
|
||||
|
||||
@@ -2,34 +2,20 @@ import {
|
||||
verifyProgramStructure,
|
||||
verifyResolutionCache,
|
||||
} from "../../../harness/incrementalUtils.js";
|
||||
import { patchHostForBuildInfoReadWrite } from "../../_namespaces/fakes.js";
|
||||
import { Baseline } from "../../_namespaces/Harness.js";
|
||||
import * as ts from "../../_namespaces/ts.js";
|
||||
import {
|
||||
baselinePrograms,
|
||||
CommandLineCallbacks,
|
||||
applyEdit,
|
||||
baselineAfterTscCompile,
|
||||
BaselineBase,
|
||||
commandLineCallbacks,
|
||||
CommandLineProgram,
|
||||
generateSourceMapBaselineFiles,
|
||||
createBaseline,
|
||||
isWatch,
|
||||
tscBaselineName,
|
||||
TscWatchSystem,
|
||||
} from "./baseline.js";
|
||||
import {
|
||||
changeToHostTrackingWrittenFiles,
|
||||
File,
|
||||
SerializeOutputOrder,
|
||||
StateLogger,
|
||||
TestServerHost,
|
||||
TestServerHostTrackingWrittenFiles,
|
||||
} from "./virtualFileSystemWithWatch.js";
|
||||
|
||||
export const commonFile1: File = {
|
||||
path: "/a/b/commonFile1.ts",
|
||||
content: "let x = 1",
|
||||
};
|
||||
export const commonFile2: File = {
|
||||
path: "/a/b/commonFile2.ts",
|
||||
content: "let y = 1",
|
||||
};
|
||||
import { TestServerHost } from "./virtualFileSystemWithWatch.js";
|
||||
|
||||
export type WatchOrSolution<T extends ts.BuilderProgram> = void | ts.SolutionBuilder<T> | ts.WatchOfConfigFile<T> | ts.WatchOfFilesAndCompilerOptions<T>;
|
||||
export interface TscWatchCompileChange<T extends ts.BuilderProgram = ts.EmitAndSemanticDiagnosticsBuilderProgram> {
|
||||
@@ -62,7 +48,7 @@ export const noopChange: TscWatchCompileChange = {
|
||||
};
|
||||
|
||||
function tscWatchCompile(input: TscWatchCompile) {
|
||||
it("tsc-watch:: Generates files matching the baseline", () => {
|
||||
it("tscWatch:: Generates files matching the baseline", () => {
|
||||
const { sys, baseline } = createBaseline(input.sys());
|
||||
const {
|
||||
scenario,
|
||||
@@ -72,8 +58,7 @@ function tscWatchCompile(input: TscWatchCompile) {
|
||||
baselineSourceMap,
|
||||
baselineDependencies,
|
||||
} = input;
|
||||
|
||||
if (!isWatch(commandLineArgs)) sys.exit = exitCode => sys.exitCode = exitCode;
|
||||
ts.Debug.assert(isWatch(commandLineArgs), "use verifyTsc");
|
||||
const { cb, getPrograms } = commandLineCallbacks(sys);
|
||||
const watchOrSolution = ts.executeCommandLine(
|
||||
sys,
|
||||
@@ -95,38 +80,6 @@ function tscWatchCompile(input: TscWatchCompile) {
|
||||
});
|
||||
}
|
||||
|
||||
export type TscWatchSystem = TestServerHostTrackingWrittenFiles;
|
||||
|
||||
function changeToTestServerHostWithTimeoutLogging(host: TestServerHostTrackingWrittenFiles, baseline: string[]): TscWatchSystem {
|
||||
const logger: StateLogger = {
|
||||
log: s => baseline.push(s),
|
||||
logs: baseline,
|
||||
};
|
||||
host.switchToBaseliningInvoke(logger, SerializeOutputOrder.BeforeDiff);
|
||||
return host;
|
||||
}
|
||||
|
||||
export interface BaselineBase {
|
||||
baseline: string[];
|
||||
sys: TscWatchSystem;
|
||||
}
|
||||
|
||||
export interface Baseline extends BaselineBase, CommandLineCallbacks {
|
||||
}
|
||||
|
||||
export function createBaseline(system: TestServerHost, modifySystem?: (sys: TestServerHost, originalRead: TestServerHost["readFile"]) => void): Baseline {
|
||||
const originalRead = system.readFile;
|
||||
const initialSys = patchHostForBuildInfoReadWrite(system);
|
||||
modifySystem?.(initialSys, originalRead);
|
||||
const baseline: string[] = [];
|
||||
const sys = changeToTestServerHostWithTimeoutLogging(changeToHostTrackingWrittenFiles(initialSys), baseline);
|
||||
baseline.push(`currentDirectory:: ${sys.getCurrentDirectory()} useCaseSensitiveFileNames: ${sys.useCaseSensitiveFileNames}`);
|
||||
baseline.push("Input::");
|
||||
sys.serializeState(baseline, SerializeOutputOrder.None);
|
||||
const { cb, getPrograms } = commandLineCallbacks(sys);
|
||||
return { sys, baseline, cb, getPrograms };
|
||||
}
|
||||
|
||||
export function createSolutionBuilderWithWatchHostForBaseline(sys: TestServerHost, cb: ts.ExecuteCommandLineCallbacks) {
|
||||
const host = ts.createSolutionBuilderWithWatchHost(sys, /*createProgram*/ undefined, ts.createDiagnosticReporter(sys, /*pretty*/ true), ts.createBuilderStatusReporter(sys, /*pretty*/ true), ts.createWatchStatusReporter(sys, /*pretty*/ true));
|
||||
host.afterProgramEmitAndDiagnostics = cb;
|
||||
@@ -175,13 +128,6 @@ function updateWatchHostForBaseline<T extends ts.BuilderProgram>(host: ts.WatchC
|
||||
return host;
|
||||
}
|
||||
|
||||
export function applyEdit(sys: BaselineBase["sys"], baseline: BaselineBase["baseline"], edit: TscWatchCompileChange["edit"], caption?: TscWatchCompileChange["caption"]) {
|
||||
baseline.push(`Change::${caption ? " " + caption : ""}`, "");
|
||||
edit(sys);
|
||||
baseline.push("Input::");
|
||||
sys.serializeState(baseline, SerializeOutputOrder.AfterDiff);
|
||||
}
|
||||
|
||||
export interface RunWatchBaseline<T extends ts.BuilderProgram> extends BaselineBase, TscWatchCompileBase<T> {
|
||||
sys: TscWatchSystem;
|
||||
getPrograms: () => readonly CommandLineProgram[];
|
||||
@@ -228,15 +174,7 @@ export function runWatchBaseline<T extends ts.BuilderProgram = ts.EmitAndSemanti
|
||||
});
|
||||
}
|
||||
}
|
||||
Baseline.runBaseline(tscBaselineName(scenario, subScenario, commandLineArgs, isWatch(commandLineArgs)), baseline.join("\r\n"));
|
||||
}
|
||||
|
||||
export function isWatch(commandLineArgs: readonly string[]) {
|
||||
return ts.forEach(commandLineArgs, arg => {
|
||||
if (arg.charCodeAt(0) !== ts.CharacterCodes.minus) return false;
|
||||
const option = arg.slice(arg.charCodeAt(1) === ts.CharacterCodes.minus ? 2 : 1).toLowerCase();
|
||||
return option === "watch" || option === "w";
|
||||
});
|
||||
Baseline.runBaseline(tscBaselineName(scenario, subScenario, commandLineArgs), baseline.join("\r\n"));
|
||||
}
|
||||
|
||||
export interface WatchBaseline extends BaselineBase, TscWatchCheckOptions {
|
||||
@@ -257,14 +195,15 @@ export function watchBaseline({
|
||||
resolutionCache,
|
||||
useSourceOfProjectReferenceRedirect,
|
||||
}: WatchBaseline) {
|
||||
if (baselineSourceMap) generateSourceMapBaselineFiles(sys);
|
||||
const programs = getPrograms();
|
||||
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]}`, "");
|
||||
const programs = baselineAfterTscCompile(
|
||||
sys,
|
||||
baseline,
|
||||
getPrograms,
|
||||
oldPrograms,
|
||||
baselineSourceMap,
|
||||
/*shouldBaselinePrograms*/ true,
|
||||
baselineDependencies,
|
||||
);
|
||||
// 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);
|
||||
|
||||
@@ -6,9 +6,9 @@ import {
|
||||
LoggerWithInMemoryLogs,
|
||||
} from "../../../harness/tsserverLogger.js";
|
||||
import { FileRangesRequestArgs } from "../../../server/protocol.js";
|
||||
import { patchHostForBuildInfoReadWrite } from "../../_namespaces/fakes.js";
|
||||
import * as Harness from "../../_namespaces/Harness.js";
|
||||
import { Baseline } from "../../_namespaces/Harness.js";
|
||||
import * as ts from "../../_namespaces/ts.js";
|
||||
import { patchHostForBuildInfoReadWrite } from "./baseline.js";
|
||||
import { ensureErrorFreeBuild } from "./solutionBuilder.js";
|
||||
import { TscWatchCompileChange } from "./tscWatch.js";
|
||||
import {
|
||||
@@ -18,17 +18,15 @@ import {
|
||||
} from "./typingsInstaller.js";
|
||||
import {
|
||||
changeToHostTrackingWrittenFiles,
|
||||
createServerHost,
|
||||
File,
|
||||
FileOrFolderOrSymLink,
|
||||
libFile,
|
||||
SerializeOutputOrder,
|
||||
TestServerHost,
|
||||
TestServerHostTrackingWrittenFiles,
|
||||
} from "./virtualFileSystemWithWatch.js";
|
||||
|
||||
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"));
|
||||
Baseline.runBaseline(`tsserver/${scenario}/${subScenario.split(" ").join("-")}.js`, sessionOrService.logger.logs.join("\r\n"));
|
||||
}
|
||||
|
||||
export function toExternalFile(fileName: string): ts.server.protocol.ExternalFile {
|
||||
@@ -200,7 +198,9 @@ export interface TestSessionOptions extends ts.server.SessionOptions, TestTyping
|
||||
useCancellationToken?: boolean | number;
|
||||
regionDiagLineCountThreshold?: number;
|
||||
}
|
||||
export type TestSessionPartialOptionsAndHost = Partial<Omit<TestSessionOptions, "typingsInstaller" | "cancellationToken">> & Pick<TestSessionOptions, "host">;
|
||||
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">;
|
||||
|
||||
@@ -551,7 +551,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 host = TestServerHost.createServerHost(allFiles());
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession(openFiles(), session);
|
||||
|
||||
@@ -562,7 +562,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 host = TestServerHost.createServerHost(allFiles());
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession(openFiles(), session);
|
||||
|
||||
@@ -579,7 +579,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 host = TestServerHost.createServerHost(allFiles());
|
||||
const session = new TestSession(host);
|
||||
openFilesForSession(openFiles(), session);
|
||||
for (const { file, project } of syncDiagnostics()) {
|
||||
@@ -626,7 +626,7 @@ export function verifyGetErrScenario(scenario: VerifyGetErrScenario) {
|
||||
}
|
||||
|
||||
export function createHostWithSolutionBuild(files: readonly FileOrFolderOrSymLink[], rootNames: readonly string[]) {
|
||||
const host = createServerHost(files);
|
||||
const host = TestServerHost.createServerHost(files);
|
||||
// ts build should succeed
|
||||
ensureErrorFreeBuild(host, rootNames);
|
||||
return host;
|
||||
|
||||
@@ -5,34 +5,35 @@ import {
|
||||
import * as ts from "../../_namespaces/ts.js";
|
||||
import { stringifyIndented } from "../../_namespaces/ts.server.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import { getPathForTypeScriptTestLocation } from "./contents.js";
|
||||
import { TestSession } from "./tsserver.js";
|
||||
import {
|
||||
File,
|
||||
TestServerHost,
|
||||
} from "./virtualFileSystemWithWatch.js";
|
||||
|
||||
export const customTypesMap = {
|
||||
path: "/typesMap.json" as ts.Path,
|
||||
content: `{
|
||||
"typesMap": {
|
||||
"jquery": {
|
||||
"match": "jquery(-(\\\\.?\\\\d+)+)?(\\\\.intellisense)?(\\\\.min)?\\\\.js$",
|
||||
"types": ["jquery"]
|
||||
},
|
||||
"quack": {
|
||||
"match": "/duckquack-(\\\\d+)\\\\.min\\\\.js",
|
||||
"types": ["duck-types"]
|
||||
}
|
||||
export const customTypesMap: File = {
|
||||
path: getPathForTypeScriptTestLocation("typesMap.json"),
|
||||
content: jsonToReadableText({
|
||||
typesMap: {
|
||||
jquery: {
|
||||
match: "jquery(-(\\.?\\d+)+)?(\\.intellisense)?(\\.min)?\\.js$",
|
||||
types: ["jquery"],
|
||||
},
|
||||
"simpleMap": {
|
||||
"Bacon": "baconjs",
|
||||
"bliss": "blissfuljs",
|
||||
"commander": "commander",
|
||||
"cordova": "cordova",
|
||||
"react": "react",
|
||||
"lodash": "lodash"
|
||||
}
|
||||
}`,
|
||||
quack: {
|
||||
match: "/duckquack-(\\d+)\\.min\\.js",
|
||||
types: ["duck-types"],
|
||||
},
|
||||
},
|
||||
simpleMap: {
|
||||
Bacon: "baconjs",
|
||||
bliss: "blissfuljs",
|
||||
commander: "commander",
|
||||
cordova: "cordova",
|
||||
react: "react",
|
||||
lodash: "lodash",
|
||||
},
|
||||
}),
|
||||
};
|
||||
|
||||
export function loggerToTypingsInstallerLog(logger: LoggerWithInMemoryLogs): ts.server.typingsInstaller.Log {
|
||||
@@ -60,7 +61,7 @@ function loadTypesRegistryFile(typesRegistryFilePath: string, host: TestServerHo
|
||||
}
|
||||
}
|
||||
const typesRegistryPackageName = "types-registry";
|
||||
function getTypesRegistryFileLocation(globalTypingsCacheLocation: string): string {
|
||||
export function getTypesRegistryFileLocation(globalTypingsCacheLocation: string): string {
|
||||
return ts.combinePaths(ts.normalizeSlashes(globalTypingsCacheLocation), `node_modules/${typesRegistryPackageName}/index.json`);
|
||||
}
|
||||
|
||||
@@ -86,8 +87,8 @@ export class TestTypingsInstallerWorker extends ts.server.typingsInstaller.Typin
|
||||
super(
|
||||
testTypingInstaller.session.host,
|
||||
testTypingInstaller.globalTypingsCacheLocation,
|
||||
"/safeList.json" as ts.Path,
|
||||
customTypesMap.path,
|
||||
getPathForTypeScriptTestLocation("typingSafeList.json") as ts.Path,
|
||||
customTypesMap.path as ts.Path,
|
||||
testTypingInstaller.throttleLimit,
|
||||
log,
|
||||
);
|
||||
@@ -96,16 +97,7 @@ export class TestTypingsInstallerWorker extends ts.server.typingsInstaller.Typin
|
||||
|
||||
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(
|
||||
testTypingInstaller.typesRegistry ?
|
||||
ts.isString(testTypingInstaller.typesRegistry) ?
|
||||
[testTypingInstaller.typesRegistry] :
|
||||
testTypingInstaller.typesRegistry :
|
||||
ts.emptyArray,
|
||||
)),
|
||||
});
|
||||
testTypingInstaller.session.host.ensureTypingRegistryFile();
|
||||
this.log.writeLine(`Updated ${typesRegistryPackageName} npm package`);
|
||||
|
||||
this.typesRegistry = loadTypesRegistryFile(
|
||||
@@ -170,10 +162,8 @@ export class TestTypingsInstallerWorker extends ts.server.typingsInstaller.Typin
|
||||
export interface TestTypingsInstallerOptions {
|
||||
host: TestServerHost;
|
||||
logger?: LoggerWithInMemoryLogs;
|
||||
globalTypingsCacheLocation?: string;
|
||||
throttleLimit?: number;
|
||||
installAction?: InstallAction;
|
||||
typesRegistry?: string | readonly string[];
|
||||
throttledRequests?: number;
|
||||
}
|
||||
|
||||
@@ -183,25 +173,22 @@ export class TestTypingsInstallerAdapter extends ts.server.TypingsInstallerAdapt
|
||||
// Options
|
||||
readonly throttleLimit: number;
|
||||
readonly installAction: InstallAction;
|
||||
readonly typesRegistry: string | readonly string[] | undefined;
|
||||
readonly throttledRequests: number | undefined;
|
||||
|
||||
constructor(options: TestTypingsInstallerOptions) {
|
||||
const globalTypingsCacheLocation = options.globalTypingsCacheLocation || options.host.getHostSpecificPath("/a/data");
|
||||
super(
|
||||
/*telemetryEnabled*/ false,
|
||||
options.throttledRequests === undefined ?
|
||||
{ ...options.logger!, hasLevel: ts.returnFalse } :
|
||||
options.logger!,
|
||||
options.host,
|
||||
globalTypingsCacheLocation,
|
||||
options.host.globalTypingsCacheLocation,
|
||||
(...args) => this.session.event(...args),
|
||||
// Some large number so requests arent throttled
|
||||
options.throttledRequests === undefined ? 10 : options.throttledRequests,
|
||||
);
|
||||
this.throttleLimit = options.throttleLimit || 5;
|
||||
this.installAction = options.installAction !== undefined ? options.installAction : true;
|
||||
this.typesRegistry = options.typesRegistry;
|
||||
this.throttledRequests = options.throttledRequests;
|
||||
}
|
||||
|
||||
@@ -221,7 +208,8 @@ export class TestTypingsInstallerAdapter extends ts.server.TypingsInstallerAdapt
|
||||
}
|
||||
}
|
||||
}
|
||||
function createTypesRegistryFileContent(list: readonly string[]): TypesRegistryFile {
|
||||
|
||||
export function createTypesRegistryFileContent(list: readonly string[]): TypesRegistryFile {
|
||||
const versionMap = {
|
||||
"latest": "1.3.0",
|
||||
"ts2.0": "1.0.0",
|
||||
|
||||
@@ -1,147 +0,0 @@
|
||||
import { getDirectoryPath } from "../../_namespaces/ts.js";
|
||||
import * as vfs from "../../_namespaces/vfs.js";
|
||||
import { libContent } from "./contents.js";
|
||||
|
||||
export interface FsOptions {
|
||||
libContentToAppend?: string;
|
||||
cwd?: string;
|
||||
executingFilePath?: string;
|
||||
}
|
||||
export type FsOptionsOrLibContentsToAppend = FsOptions | string;
|
||||
|
||||
function valueOfFsOptions(options: FsOptionsOrLibContentsToAppend | undefined, key: keyof FsOptions) {
|
||||
return typeof options === "string" ?
|
||||
key === "libContentToAppend" ? options : undefined :
|
||||
options?.[key];
|
||||
}
|
||||
|
||||
/**
|
||||
* All the files must be in /src
|
||||
*/
|
||||
export function loadProjectFromFiles(
|
||||
files: vfs.FileSet,
|
||||
options?: FsOptionsOrLibContentsToAppend,
|
||||
): vfs.FileSystem {
|
||||
const executingFilePath = valueOfFsOptions(options, "executingFilePath");
|
||||
const defaultLibLocation = executingFilePath ? getDirectoryPath(executingFilePath) : "/lib";
|
||||
const fs = new vfs.FileSystem(/*ignoreCase*/ true, {
|
||||
files,
|
||||
cwd: valueOfFsOptions(options, "cwd") || "/",
|
||||
meta: { defaultLibLocation },
|
||||
});
|
||||
const libContentToAppend = valueOfFsOptions(options, "libContentToAppend");
|
||||
fs.mkdirpSync(defaultLibLocation);
|
||||
fs.writeFileSync(`${defaultLibLocation}/lib.d.ts`, libContentToAppend ? `${libContent}${libContentToAppend}` : libContent);
|
||||
fs.makeReadonly();
|
||||
return fs;
|
||||
}
|
||||
|
||||
export function replaceText(fs: vfs.FileSystem, path: string, oldText: string, newText: string) {
|
||||
if (!fs.statSync(path).isFile()) {
|
||||
throw new Error(`File ${path} does not exist`);
|
||||
}
|
||||
const old = fs.readFileSync(path, "utf-8");
|
||||
if (!old.includes(oldText)) {
|
||||
throw new Error(`Text "${oldText}" does not exist in file ${path}`);
|
||||
}
|
||||
const newContent = old.replace(oldText, newText);
|
||||
fs.writeFileSync(path, newContent, "utf-8");
|
||||
}
|
||||
|
||||
export function prependText(fs: vfs.FileSystem, path: string, additionalContent: string) {
|
||||
if (!fs.statSync(path).isFile()) {
|
||||
throw new Error(`File ${path} does not exist`);
|
||||
}
|
||||
const old = fs.readFileSync(path, "utf-8");
|
||||
fs.writeFileSync(path, `${additionalContent}${old}`, "utf-8");
|
||||
}
|
||||
|
||||
export function appendText(fs: vfs.FileSystem, path: string, additionalContent: string) {
|
||||
if (!fs.statSync(path).isFile()) {
|
||||
throw new Error(`File ${path} does not exist`);
|
||||
}
|
||||
const old = fs.readFileSync(path, "utf-8");
|
||||
fs.writeFileSync(path, `${old}${additionalContent}`);
|
||||
}
|
||||
|
||||
export function enableStrict(fs: vfs.FileSystem, path: string) {
|
||||
replaceText(fs, path, `"strict": false`, `"strict": true`);
|
||||
}
|
||||
|
||||
export function addTestPrologue(fs: vfs.FileSystem, path: string, prologue: string) {
|
||||
prependText(
|
||||
fs,
|
||||
path,
|
||||
`${prologue}
|
||||
`,
|
||||
);
|
||||
}
|
||||
|
||||
export function addShebang(fs: vfs.FileSystem, project: string, file: string) {
|
||||
prependText(
|
||||
fs,
|
||||
`src/${project}/${file}.ts`,
|
||||
`#!someshebang ${project} ${file}
|
||||
`,
|
||||
);
|
||||
}
|
||||
|
||||
export function restContent(project: string, file: string) {
|
||||
return `function for${project}${file}Rest() {
|
||||
const { b, ...rest } = { a: 10, b: 30, yy: 30 };
|
||||
}`;
|
||||
}
|
||||
function nonrestContent(project: string, file: string) {
|
||||
return `function for${project}${file}Rest() { }`;
|
||||
}
|
||||
|
||||
export function addRest(fs: vfs.FileSystem, project: string, file: string) {
|
||||
appendText(fs, `src/${project}/${file}.ts`, restContent(project, file));
|
||||
}
|
||||
|
||||
export function removeRest(fs: vfs.FileSystem, project: string, file: string) {
|
||||
replaceText(fs, `src/${project}/${file}.ts`, restContent(project, file), nonrestContent(project, file));
|
||||
}
|
||||
|
||||
export function addStubFoo(fs: vfs.FileSystem, project: string, file: string) {
|
||||
appendText(fs, `src/${project}/${file}.ts`, nonrestContent(project, file));
|
||||
}
|
||||
|
||||
export function changeStubToRest(fs: vfs.FileSystem, project: string, file: string) {
|
||||
replaceText(fs, `src/${project}/${file}.ts`, nonrestContent(project, file), restContent(project, file));
|
||||
}
|
||||
|
||||
export function addSpread(fs: vfs.FileSystem, project: string, file: string) {
|
||||
const path = `src/${project}/${file}.ts`;
|
||||
const content = fs.readFileSync(path, "utf8");
|
||||
fs.writeFileSync(
|
||||
path,
|
||||
`${content}
|
||||
function ${project}${file}Spread(...b: number[]) { }
|
||||
const ${project}${file}_ar = [20, 30];
|
||||
${project}${file}Spread(10, ...${project}${file}_ar);`,
|
||||
);
|
||||
|
||||
replaceText(
|
||||
fs,
|
||||
`src/${project}/tsconfig.json`,
|
||||
`"strict": false,`,
|
||||
`"strict": false,
|
||||
"downlevelIteration": true,`,
|
||||
);
|
||||
}
|
||||
|
||||
export function getTripleSlashRef(project: string) {
|
||||
return `/src/${project}/tripleRef.d.ts`;
|
||||
}
|
||||
|
||||
export function addTripleSlashRef(fs: vfs.FileSystem, project: string, file: string) {
|
||||
fs.writeFileSync(getTripleSlashRef(project), `declare class ${project}${file} { }`);
|
||||
prependText(
|
||||
fs,
|
||||
`src/${project}/${file}.ts`,
|
||||
`///<reference path="./tripleRef.d.ts"/>
|
||||
const ${file}Const = new ${project}${file}();
|
||||
`,
|
||||
);
|
||||
}
|
||||
@@ -1,5 +1,11 @@
|
||||
import {
|
||||
harnessSessionCurrentDirectory,
|
||||
harnessTypingInstallerCacheLocation,
|
||||
} from "../../../harness/harnessLanguageService.js";
|
||||
import { replaceAll } from "../../../harness/tsserverLogger.js";
|
||||
import {
|
||||
createWatchUtils,
|
||||
ensureWatchablePath,
|
||||
Watches,
|
||||
WatchUtils,
|
||||
} from "../../../harness/watchUtils.js";
|
||||
@@ -18,6 +24,7 @@ import {
|
||||
createSystemWatchFunctions,
|
||||
Debug,
|
||||
directorySeparator,
|
||||
emptyArray,
|
||||
FileSystemEntryKind,
|
||||
FileWatcherCallback,
|
||||
FileWatcherEventKind,
|
||||
@@ -36,6 +43,7 @@ import {
|
||||
insertSorted,
|
||||
isArray,
|
||||
isString,
|
||||
libMap,
|
||||
mapDefined,
|
||||
matchFiles,
|
||||
ModuleImportResult,
|
||||
@@ -47,14 +55,23 @@ import {
|
||||
server,
|
||||
SortedArray,
|
||||
sys,
|
||||
targetToLibMap,
|
||||
toPath,
|
||||
} from "../../_namespaces/ts.js";
|
||||
import { typingsInstaller } from "../../_namespaces/ts.server.js";
|
||||
import { timeIncrements } from "../../_namespaces/vfs.js";
|
||||
import { sanitizeSysOutput } from "./baseline.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import {
|
||||
getPathForTypeScriptTestLocation,
|
||||
tscTypeScriptTestLocation,
|
||||
} from "./contents.js";
|
||||
import {
|
||||
createTypesRegistryFileContent,
|
||||
getTypesRegistryFileLocation,
|
||||
} from "./typingsInstaller.js";
|
||||
|
||||
export const libFile: File = {
|
||||
path: "/a/lib/lib.d.ts",
|
||||
path: getPathForTypeScriptTestLocation("lib.d.ts"),
|
||||
content: `/// <reference no-default-lib="true"/>
|
||||
interface Boolean {}
|
||||
interface Function {}
|
||||
@@ -65,13 +82,11 @@ interface Number { toExponential: any; }
|
||||
interface Object {}
|
||||
interface RegExp {}
|
||||
interface String { charAt: any; }
|
||||
interface Array<T> { length: number; [n: number]: T; }`,
|
||||
interface Array<T> { length: number; [n: number]: T; }
|
||||
interface ReadonlyArray<T> {}
|
||||
declare const console: { log(msg: any): void; };`,
|
||||
};
|
||||
|
||||
function getExecutingFilePathFromLibFile(): string {
|
||||
return combinePaths(getDirectoryPath(libFile.path), "tsc.js");
|
||||
}
|
||||
|
||||
export const enum TestServerHostOsFlavor {
|
||||
Windows,
|
||||
MacOs,
|
||||
@@ -87,45 +102,47 @@ export interface TestServerHostCreationParameters {
|
||||
environmentVariables?: Map<string, string>;
|
||||
runWithFallbackPolling?: boolean;
|
||||
osFlavor?: TestServerHostOsFlavor;
|
||||
typingsInstallerGlobalCacheLocation?: string;
|
||||
typingsInstallerTypesRegistry?: string | readonly string[];
|
||||
}
|
||||
|
||||
export function createWatchedSystem(fileOrFolderList: FileOrFolderOrSymLinkMap | readonly FileOrFolderOrSymLink[], params?: TestServerHostCreationParameters): TestServerHost {
|
||||
return new TestServerHost(fileOrFolderList, params);
|
||||
export interface WatchableExempt {
|
||||
/** Add this field to true only if its the interesting scenario about what to watch */
|
||||
watchableExempt?: boolean;
|
||||
}
|
||||
|
||||
export function createServerHost(fileOrFolderList: FileOrFolderOrSymLinkMap | readonly FileOrFolderOrSymLink[], params?: TestServerHostCreationParameters): TestServerHost {
|
||||
const host = new TestServerHost(fileOrFolderList, params);
|
||||
// Just like sys, patch the host to use writeFile
|
||||
patchWriteFileEnsuringDirectory(host);
|
||||
return host;
|
||||
}
|
||||
|
||||
export interface File {
|
||||
export interface File extends WatchableExempt {
|
||||
path: string;
|
||||
content: string;
|
||||
fileSize?: number;
|
||||
}
|
||||
|
||||
export interface Folder {
|
||||
export interface Folder extends WatchableExempt {
|
||||
path: string;
|
||||
}
|
||||
|
||||
export interface SymLink {
|
||||
export interface SymLink extends WatchableExempt {
|
||||
/** Location of the symlink. */
|
||||
path: string;
|
||||
/** Relative path to the real file. */
|
||||
symLink: string;
|
||||
}
|
||||
|
||||
export interface LibFile extends WatchableExempt {
|
||||
path: string;
|
||||
libFile: true;
|
||||
}
|
||||
|
||||
export type FileOrFolderOrSymLink = File | Folder | SymLink;
|
||||
export type FileOrFolderOrSymLinkOrLibFile = FileOrFolderOrSymLink | LibFile;
|
||||
export interface FileOrFolderOrSymLinkMap {
|
||||
[path: string]: string | Omit<File, "path"> | Omit<SymLink, "path"> | undefined;
|
||||
}
|
||||
export function isFile(fileOrFolderOrSymLink: FileOrFolderOrSymLink): fileOrFolderOrSymLink is File {
|
||||
return isString((fileOrFolderOrSymLink as File).content);
|
||||
export function isFile(fileOrFolderOrSymLink: FileOrFolderOrSymLinkOrLibFile): fileOrFolderOrSymLink is File | LibFile {
|
||||
return isString((fileOrFolderOrSymLink as File).content) || (fileOrFolderOrSymLink as LibFile).libFile;
|
||||
}
|
||||
|
||||
export function isSymLink(fileOrFolderOrSymLink: FileOrFolderOrSymLink): fileOrFolderOrSymLink is SymLink {
|
||||
export function isSymLink(fileOrFolderOrSymLink: FileOrFolderOrSymLinkOrLibFile): fileOrFolderOrSymLink is SymLink {
|
||||
return isString((fileOrFolderOrSymLink as SymLink).symLink);
|
||||
}
|
||||
|
||||
@@ -140,6 +157,11 @@ interface FsFile extends FSEntryBase {
|
||||
fileSize?: number;
|
||||
}
|
||||
|
||||
interface FsLibFile extends FSEntryBase {
|
||||
content?: string;
|
||||
libFile: true;
|
||||
}
|
||||
|
||||
interface FsFolder extends FSEntryBase {
|
||||
entries: SortedArray<FSEntry>;
|
||||
}
|
||||
@@ -148,16 +170,29 @@ interface FsSymLink extends FSEntryBase {
|
||||
symLink: string;
|
||||
}
|
||||
|
||||
export type FSEntry = FsFile | FsFolder | FsSymLink;
|
||||
export type FSEntry = FsFile | FsFolder | FsSymLink | FsLibFile;
|
||||
export type FSFileOrLibFile = FsFile | FsLibFile;
|
||||
|
||||
function isFsFolder(s: FSEntry | undefined): s is FsFolder {
|
||||
return !!s && isArray((s as FsFolder).entries);
|
||||
}
|
||||
|
||||
function isFsFile(s: FSEntry | undefined): s is FsFile {
|
||||
function isFsFileOrFsLibFile(s: FSEntry | undefined) {
|
||||
return isFsFile(s) || isFsLibFile(s);
|
||||
}
|
||||
|
||||
function isFsLibFile(s: FSEntry | undefined): s is FsLibFile {
|
||||
return !!s && (s as FsLibFile).libFile;
|
||||
}
|
||||
|
||||
export function isFsFile(s: FSEntry | undefined): s is FsFile {
|
||||
return !!s && isString((s as FsFile).content);
|
||||
}
|
||||
|
||||
function getFsFileOrLibFileContent(entry: FSFileOrLibFile) {
|
||||
return entry.content ?? (entry.content = libFile.content);
|
||||
}
|
||||
|
||||
function isFsSymLink(s: FSEntry | undefined): s is FsSymLink {
|
||||
return !!s && isString((s as FsSymLink).symLink);
|
||||
}
|
||||
@@ -337,6 +372,28 @@ export enum SerializeOutputOrder {
|
||||
BeforeDiff,
|
||||
AfterDiff,
|
||||
}
|
||||
|
||||
export type TestServerHostSnapshot = Map<Path, FSEntry>;
|
||||
|
||||
export function cloneFsMap(fs: Map<Path, FSEntry>): TestServerHostSnapshot {
|
||||
const snap = new Map<Path, FSEntry>();
|
||||
const clonedMap = new Map<FSEntry, FSEntry>();
|
||||
const getCloned = (entry: FSEntry) => {
|
||||
const existing = clonedMap.get(entry);
|
||||
if (existing) return existing;
|
||||
const cloned = clone(entry);
|
||||
clonedMap.set(entry, cloned);
|
||||
if (isFsFolder(cloned)) {
|
||||
cloned.entries = cloned.entries.map(clone) as SortedArray<FSEntry>;
|
||||
}
|
||||
return cloned;
|
||||
};
|
||||
fs.forEach((value, key) => {
|
||||
snap.set(key, getCloned(value));
|
||||
});
|
||||
return snap;
|
||||
}
|
||||
|
||||
export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, ModuleResolutionHost {
|
||||
args: string[] = [];
|
||||
|
||||
@@ -369,7 +426,9 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost,
|
||||
service?: server.ProjectService;
|
||||
osFlavor: TestServerHostOsFlavor;
|
||||
preferNonRecursiveWatch: boolean;
|
||||
constructor(
|
||||
globalTypingsCacheLocation: string;
|
||||
private readonly typesRegistry: string | readonly string[] | undefined;
|
||||
private constructor(
|
||||
fileOrFolderorSymLinkList: FileOrFolderOrSymLinkMap | readonly FileOrFolderOrSymLink[],
|
||||
{
|
||||
useCaseSensitiveFileNames,
|
||||
@@ -380,6 +439,8 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost,
|
||||
environmentVariables,
|
||||
runWithFallbackPolling,
|
||||
osFlavor,
|
||||
typingsInstallerGlobalCacheLocation,
|
||||
typingsInstallerTypesRegistry,
|
||||
}: TestServerHostCreationParameters = {},
|
||||
) {
|
||||
this.useCaseSensitiveFileNames = !!useCaseSensitiveFileNames;
|
||||
@@ -387,12 +448,11 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost,
|
||||
this.osFlavor = osFlavor || TestServerHostOsFlavor.Windows;
|
||||
this.windowsStyleRoot = windowsStyleRoot;
|
||||
this.environmentVariables = environmentVariables;
|
||||
currentDirectory = currentDirectory || "/";
|
||||
this.currentDirectory = this.getHostSpecificPath(currentDirectory ?? harnessSessionCurrentDirectory);
|
||||
this.getCanonicalFileName = createGetCanonicalFileName(!!useCaseSensitiveFileNames);
|
||||
this.watchUtils = createWatchUtils("PolledWatches", "FsWatches", s => this.getCanonicalFileName(s), this);
|
||||
this.toPath = s => toPath(s, currentDirectory, this.getCanonicalFileName);
|
||||
this.executingFilePath = this.getHostSpecificPath(executingFilePath || getExecutingFilePathFromLibFile());
|
||||
this.currentDirectory = this.getHostSpecificPath(currentDirectory);
|
||||
this.toPath = s => toPath(s, this.currentDirectory, this.getCanonicalFileName);
|
||||
this.executingFilePath = this.getHostSpecificPath(executingFilePath ?? tscTypeScriptTestLocation);
|
||||
this.runWithFallbackPolling = !!runWithFallbackPolling;
|
||||
const tscWatchFile = this.environmentVariables && this.environmentVariables.get("TSC_WATCHFILE");
|
||||
const tscWatchDirectory = this.environmentVariables && this.environmentVariables.get("TSC_WATCHDIRECTORY");
|
||||
@@ -424,6 +484,78 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost,
|
||||
this.watchFile = watchFile;
|
||||
this.watchDirectory = watchDirectory;
|
||||
this.reloadFS(fileOrFolderorSymLinkList);
|
||||
|
||||
// Ensure current directory exists
|
||||
this.ensureFileOrFolder({ path: this.currentDirectory });
|
||||
|
||||
// Ensure libs
|
||||
this.ensureFileOrFolder({
|
||||
path: combinePaths(getDirectoryPath(this.executingFilePath), "lib.d.ts"),
|
||||
content: libFile.content,
|
||||
});
|
||||
targetToLibMap.forEach(libFile => this.ensureLib(libFile));
|
||||
libMap.forEach(libFile => this.ensureLib(libFile));
|
||||
|
||||
// Ensure global cache location has required data
|
||||
this.globalTypingsCacheLocation = this.getHostSpecificPath(
|
||||
typingsInstallerGlobalCacheLocation ??
|
||||
harnessTypingInstallerCacheLocation,
|
||||
);
|
||||
this.typesRegistry = typingsInstallerTypesRegistry;
|
||||
if (this.directoryExists(this.globalTypingsCacheLocation)) {
|
||||
// Package.json
|
||||
const npmConfigPath = combinePaths(this.globalTypingsCacheLocation, "package.json");
|
||||
if (!this.fileExists(npmConfigPath)) {
|
||||
this.writeFile(npmConfigPath, '{ "private": true }');
|
||||
}
|
||||
// Typings registry
|
||||
this.ensureTypingRegistryFile();
|
||||
}
|
||||
}
|
||||
|
||||
private ensureLib(path: string) {
|
||||
this.ensureFileOrFolder({
|
||||
path: combinePaths(getDirectoryPath(this.executingFilePath), path),
|
||||
libFile: true,
|
||||
});
|
||||
}
|
||||
|
||||
ensureTypingRegistryFile() {
|
||||
this.ensureFileOrFolder({
|
||||
path: getTypesRegistryFileLocation(this.globalTypingsCacheLocation),
|
||||
content: jsonToReadableText(createTypesRegistryFileContent(
|
||||
this.typesRegistry ?
|
||||
isString(this.typesRegistry) ?
|
||||
[this.typesRegistry] :
|
||||
this.typesRegistry :
|
||||
emptyArray,
|
||||
)),
|
||||
});
|
||||
}
|
||||
|
||||
static createWatchedSystem(
|
||||
fileOrFolderList: FileOrFolderOrSymLinkMap | readonly FileOrFolderOrSymLink[],
|
||||
params:
|
||||
& Omit<TestServerHostCreationParameters, "typingsInstallerGlobalCacheLocation" | "typingsInstallerTypesRegistry">
|
||||
& { currentDirectory: string; },
|
||||
): TestServerHost {
|
||||
ensureWatchablePath(params.currentDirectory, `currentDirectory: ${params.currentDirectory}`);
|
||||
return new TestServerHost(fileOrFolderList, params);
|
||||
}
|
||||
|
||||
static createServerHost(
|
||||
fileOrFolderList: FileOrFolderOrSymLinkMap | readonly FileOrFolderOrSymLink[],
|
||||
params?: Omit<TestServerHostCreationParameters, "currentDirectory">,
|
||||
): TestServerHost {
|
||||
if ((params as TestServerHostCreationParameters)?.currentDirectory) (params as TestServerHostCreationParameters).currentDirectory = undefined;
|
||||
const host = new TestServerHost(fileOrFolderList, params);
|
||||
// Just like sys, patch the host to use writeFile
|
||||
patchWriteFileEnsuringDirectory(host);
|
||||
return host;
|
||||
}
|
||||
|
||||
static getCreateWatchedSystem(forTsserver: boolean | undefined) {
|
||||
return (!forTsserver ? TestServerHost.createWatchedSystem : TestServerHost.createServerHost);
|
||||
}
|
||||
|
||||
private nextInode = 0;
|
||||
@@ -449,8 +581,13 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost,
|
||||
}
|
||||
|
||||
getHostSpecificPath(s: string) {
|
||||
if (this.windowsStyleRoot && s.startsWith(directorySeparator)) {
|
||||
return this.windowsStyleRoot + s.substring(1);
|
||||
if (this.windowsStyleRoot) {
|
||||
let result = s;
|
||||
if (s.startsWith(directorySeparator)) {
|
||||
result = this.windowsStyleRoot + s.substring(1);
|
||||
}
|
||||
if (!result.startsWith(directorySeparator)) result = replaceAll(result, directorySeparator, "\\");
|
||||
return result;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
@@ -479,11 +616,16 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost,
|
||||
this.pendingInstalls.switchToBaseliningInvoke(logger, serializeOutputOrder);
|
||||
}
|
||||
|
||||
private ensureInitialFileOrFolder(f: FileOrFolderOrSymLink) {
|
||||
if (!f.watchableExempt) ensureWatchablePath(getDirectoryPath(f.path), `Directory path of FileOrFolderOrSymLink: ${f.path}`);
|
||||
this.ensureFileOrFolder(f);
|
||||
}
|
||||
|
||||
private reloadFS(fileOrFolderOrSymLinkList: FileOrFolderOrSymLinkMap | readonly FileOrFolderOrSymLink[]) {
|
||||
Debug.assert(this.fs.size === 0);
|
||||
if (isArray(fileOrFolderOrSymLinkList)) {
|
||||
fileOrFolderOrSymLinkList.forEach(f =>
|
||||
this.ensureFileOrFolder(
|
||||
this.ensureInitialFileOrFolder(
|
||||
!this.windowsStyleRoot ?
|
||||
f :
|
||||
{ ...f, path: this.getHostSpecificPath(f.path) },
|
||||
@@ -496,10 +638,10 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost,
|
||||
const path = this.getHostSpecificPath(key);
|
||||
const value = fileOrFolderOrSymLinkList[key];
|
||||
if (isString(value)) {
|
||||
this.ensureFileOrFolder({ path, content: value });
|
||||
this.ensureInitialFileOrFolder({ path, content: value });
|
||||
}
|
||||
else {
|
||||
this.ensureFileOrFolder({ path, ...value });
|
||||
this.ensureInitialFileOrFolder({ path, ...value });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -511,11 +653,11 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost,
|
||||
modifyFile(filePath: string, content: string, options?: Partial<WatchInvokeOptions>) {
|
||||
const path = this.toFullPath(filePath);
|
||||
const currentEntry = this.fs.get(path);
|
||||
if (!currentEntry || !isFsFile(currentEntry)) {
|
||||
if (!currentEntry || !isFsFileOrFsLibFile(currentEntry)) {
|
||||
throw new Error(`file not present: ${filePath}`);
|
||||
}
|
||||
|
||||
if (options && options.invokeFileDeleteCreateAsPartInsteadOfChange) {
|
||||
if (isFsLibFile(currentEntry) || options?.invokeFileDeleteCreateAsPartInsteadOfChange) {
|
||||
this.removeFileOrFolder(currentEntry, /*isRenaming*/ false, options);
|
||||
this.ensureFileOrFolder({ path: filePath, content }, /*ignoreWatchInvokedWithTriggerAsFileCreate*/ undefined, /*ignoreParentWatch*/ undefined, options);
|
||||
}
|
||||
@@ -547,11 +689,11 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost,
|
||||
|
||||
// Add updated folder with new folder name
|
||||
const newFullPath = getNormalizedAbsolutePath(newFileName, this.currentDirectory);
|
||||
const newFile = this.toFsFile({ path: newFullPath, content: file.content });
|
||||
const newFile = this.toFsFileOrLibFile({ path: newFullPath, content: file.content });
|
||||
const newPath = newFile.path;
|
||||
const basePath = getDirectoryPath(path);
|
||||
const basePath = getDirectoryPath(newPath);
|
||||
Debug.assert(basePath !== path);
|
||||
Debug.assert(basePath === getDirectoryPath(newPath));
|
||||
this.ensureFileOrFolder({ path: getDirectoryPath(newFullPath) });
|
||||
const baseFolder = this.fs.get(basePath) as FsFolder;
|
||||
this.addFileOrFolderInFolder(baseFolder, newFile);
|
||||
}
|
||||
@@ -598,9 +740,9 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost,
|
||||
}
|
||||
}
|
||||
|
||||
ensureFileOrFolder(fileOrDirectoryOrSymLink: FileOrFolderOrSymLink, ignoreWatchInvokedWithTriggerAsFileCreate?: boolean, ignoreParentWatch?: boolean, options?: Partial<WatchInvokeOptions>) {
|
||||
ensureFileOrFolder(fileOrDirectoryOrSymLink: FileOrFolderOrSymLinkOrLibFile, ignoreWatchInvokedWithTriggerAsFileCreate?: boolean, ignoreParentWatch?: boolean, options?: Partial<WatchInvokeOptions>) {
|
||||
if (isFile(fileOrDirectoryOrSymLink)) {
|
||||
const file = this.toFsFile(fileOrDirectoryOrSymLink);
|
||||
const file = this.toFsFileOrLibFile(fileOrDirectoryOrSymLink);
|
||||
// file may already exist when updating existing type declaration file
|
||||
if (!this.fs.get(file.path)) {
|
||||
const baseFolder = this.ensureFolder(getDirectoryPath(file.fullPath), ignoreParentWatch, options);
|
||||
@@ -642,7 +784,7 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost,
|
||||
return folder;
|
||||
}
|
||||
|
||||
private addFileOrFolderInFolder(folder: FsFolder, fileOrDirectory: FsFile | FsFolder | FsSymLink, ignoreWatch?: boolean, options?: Partial<WatchInvokeOptions>) {
|
||||
private addFileOrFolderInFolder(folder: FsFolder, fileOrDirectory: FSEntry, ignoreWatch?: boolean, options?: Partial<WatchInvokeOptions>) {
|
||||
if (!this.fs.has(fileOrDirectory.path)) {
|
||||
insertSorted(folder.entries, fileOrDirectory, (a, b) => compareStringsCaseSensitive(getBaseFileName(a.path), getBaseFileName(b.path)));
|
||||
}
|
||||
@@ -666,7 +808,7 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost,
|
||||
this.inodeWatching = inodeWatching;
|
||||
}
|
||||
|
||||
private removeFileOrFolder(fileOrDirectory: FsFile | FsFolder | FsSymLink, isRenaming?: boolean, options?: Partial<WatchInvokeOptions>) {
|
||||
private removeFileOrFolder(fileOrDirectory: FSEntry, isRenaming?: boolean, options?: Partial<WatchInvokeOptions>) {
|
||||
const basePath = getDirectoryPath(fileOrDirectory.path);
|
||||
const baseFolder = this.fs.get(basePath) as FsFolder;
|
||||
if (basePath !== fileOrDirectory.path) {
|
||||
@@ -683,9 +825,15 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost,
|
||||
this.inodes?.delete(fileOrDirectory.path);
|
||||
}
|
||||
|
||||
rimrafSync(fileOrFolderPath: string) {
|
||||
const fileOrFolder = this.getRealFileOrFolder(fileOrFolderPath);
|
||||
if (isFsFileOrFsLibFile(fileOrFolder)) this.removeFileOrFolder(fileOrFolder);
|
||||
else if (isFsFolder(fileOrFolder)) this.deleteFolder(fileOrFolder.fullPath, /*recursive*/ true);
|
||||
}
|
||||
|
||||
deleteFile(filePath: string) {
|
||||
const file = this.getRealFileOrFolder(filePath);
|
||||
Debug.assert(isFsFile(file));
|
||||
Debug.assert(isFsFileOrFsLibFile(file));
|
||||
this.removeFileOrFolder(file);
|
||||
}
|
||||
|
||||
@@ -801,10 +949,11 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost,
|
||||
};
|
||||
}
|
||||
|
||||
private toFsFile(file: File): FsFile {
|
||||
const fsFile = this.toFsEntry(file.path) as FsFile;
|
||||
fsFile.content = file.content;
|
||||
fsFile.fileSize = file.fileSize;
|
||||
private toFsFileOrLibFile(file: File | LibFile): FsFile | FsLibFile {
|
||||
const fsFile = this.toFsEntry(file.path) as FsFile & FsLibFile;
|
||||
fsFile.content = (file as File).content;
|
||||
fsFile.fileSize = (file as File).fileSize;
|
||||
fsFile.libFile = (file as LibFile).libFile;
|
||||
return fsFile;
|
||||
}
|
||||
|
||||
@@ -846,8 +995,8 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost,
|
||||
return !!this.getRealFile(fsEntry.path, fsEntry);
|
||||
}
|
||||
|
||||
private getRealFile(path: Path, fsEntry?: FSEntry): FsFile | undefined {
|
||||
return this.getRealFsEntry(isFsFile, path, fsEntry);
|
||||
private getRealFile(path: Path, fsEntry?: FSEntry): FSFileOrLibFile | undefined {
|
||||
return this.getRealFsEntry(isFsFileOrFsLibFile, path, fsEntry);
|
||||
}
|
||||
|
||||
private isFsFolder(fsEntry: FSEntry) {
|
||||
@@ -885,14 +1034,14 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost,
|
||||
|
||||
readFile(s: string): string | undefined {
|
||||
const fsEntry = this.getRealFile(this.toFullPath(s));
|
||||
return fsEntry ? fsEntry.content : undefined;
|
||||
return fsEntry ? getFsFileOrLibFileContent(fsEntry) : undefined;
|
||||
}
|
||||
|
||||
getFileSize(s: string) {
|
||||
const path = this.toFullPath(s);
|
||||
const entry = this.fs.get(path)!;
|
||||
if (isFsFile(entry)) {
|
||||
return entry.fileSize ? entry.fileSize : entry.content.length;
|
||||
if (isFsFileOrFsLibFile(entry)) {
|
||||
return (entry as FsFile).fileSize ? (entry as FsFile).fileSize! : getFsFileOrLibFileContent(entry).length;
|
||||
}
|
||||
return undefined!; // TODO: GH#18217
|
||||
}
|
||||
@@ -996,7 +1145,7 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost,
|
||||
}
|
||||
|
||||
writeFile(path: string, content: string): void {
|
||||
const file = this.toFsFile({ path, content });
|
||||
const file = this.toFsFileOrLibFile({ path, content });
|
||||
|
||||
// base folder has to be present
|
||||
const base = getDirectoryPath(file.path);
|
||||
@@ -1057,15 +1206,12 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost,
|
||||
this.clearOutput();
|
||||
}
|
||||
|
||||
getSnap() {
|
||||
return cloneFsMap(this.fs);
|
||||
}
|
||||
|
||||
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>;
|
||||
}
|
||||
this.serializedDiff.set(key, cloneValue);
|
||||
});
|
||||
this.serializedDiff = cloneFsMap(this.fs);
|
||||
}
|
||||
|
||||
serializeState(baseline: string[], serializeOutput: SerializeOutputOrder) {
|
||||
@@ -1080,7 +1226,7 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost,
|
||||
}
|
||||
|
||||
writtenFiles?: Map<Path, number>;
|
||||
private serializedDiff = new Map<Path, FSEntry>();
|
||||
private serializedDiff: TestServerHostSnapshot = new Map<Path, FSEntry>();
|
||||
diff(baseline: string[]) {
|
||||
this.fs.forEach((newFsEntry, path) => {
|
||||
diffFsEntry(baseline, this.serializedDiff.get(path), newFsEntry, this.inodes?.get(path), this.writtenFiles);
|
||||
@@ -1131,19 +1277,24 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost,
|
||||
}
|
||||
}
|
||||
|
||||
function diffFsFile(baseline: string[], fsEntry: FsFile, newInode: number | undefined) {
|
||||
baseline.push(`//// [${fsEntry.fullPath}]${inodeString(newInode)}\r\n${fsEntry.content}`, "");
|
||||
function diffFsFile(baseline: string[], fsEntry: FSFileOrLibFile, newInode: number | undefined) {
|
||||
if (!isFsLibFile(fsEntry)) {
|
||||
baseline.push(`//// [${fsEntry.fullPath}]${inodeString(newInode)}\r\n${fsEntry.content}`, "");
|
||||
}
|
||||
else if (fsEntry.content) {
|
||||
baseline.push(`//// [${fsEntry.fullPath}] *Lib*${inodeString(newInode)}`, "");
|
||||
}
|
||||
}
|
||||
function diffFsSymLink(baseline: string[], fsEntry: FsSymLink, newInode: number | undefined) {
|
||||
baseline.push(`//// [${fsEntry.fullPath}] symlink(${fsEntry.symLink})${inodeString(newInode)}`);
|
||||
baseline.push(`//// [${fsEntry.fullPath}] symlink(${fsEntry.symLink})${inodeString(newInode)}`, "");
|
||||
}
|
||||
function inodeString(inode: number | undefined) {
|
||||
return inode !== undefined ? ` Inode:: ${inode}` : "";
|
||||
}
|
||||
function diffFsEntry(baseline: string[], oldFsEntry: FSEntry | undefined, newFsEntry: FSEntry | undefined, newInode: number | undefined, writtenFiles: Map<string, any> | undefined): void {
|
||||
const file = newFsEntry && newFsEntry.fullPath;
|
||||
if (isFsFile(oldFsEntry)) {
|
||||
if (isFsFile(newFsEntry)) {
|
||||
if (isFsFileOrFsLibFile(oldFsEntry)) {
|
||||
if (isFsFileOrFsLibFile(newFsEntry)) {
|
||||
if (oldFsEntry.content !== newFsEntry.content) {
|
||||
diffFsFile(baseline, newFsEntry, newInode);
|
||||
}
|
||||
@@ -1185,12 +1336,12 @@ function diffFsEntry(baseline: string[], oldFsEntry: FSEntry | undefined, newFsE
|
||||
}
|
||||
else {
|
||||
baseline.push(`//// [${oldFsEntry.fullPath}] deleted symlink`);
|
||||
if (isFsFile(newFsEntry)) {
|
||||
if (isFsFileOrFsLibFile(newFsEntry)) {
|
||||
diffFsFile(baseline, newFsEntry, newInode);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (isFsFile(newFsEntry)) {
|
||||
else if (isFsFileOrFsLibFile(newFsEntry)) {
|
||||
diffFsFile(baseline, newFsEntry, newInode);
|
||||
}
|
||||
else if (isFsSymLink(newFsEntry)) {
|
||||
@@ -1206,6 +1357,12 @@ function baselineOutputs(baseline: string[], output: readonly string[], start: n
|
||||
if (baselinedOutput) baseline.push(baselinedOutput.join(""));
|
||||
}
|
||||
|
||||
function sanitizeSysOutput(output: string) {
|
||||
return output
|
||||
.replace(/Elapsed::\s\d+(?:\.\d+)?ms/g, "Elapsed:: *ms")
|
||||
.replace(/\d\d:\d\d:\d\d\s(?:A|P)M/g, "HH:MM:SS AM");
|
||||
}
|
||||
|
||||
export type TestServerHostTrackingWrittenFiles = TestServerHost & { writtenFiles: Map<Path, number>; };
|
||||
|
||||
export function changeToHostTrackingWrittenFiles(inputHost: TestServerHost) {
|
||||
|
||||
@@ -4,8 +4,7 @@ import * as Harness from "../_namespaces/Harness.js";
|
||||
import * as ts from "../_namespaces/ts.js";
|
||||
import * as vfs from "../_namespaces/vfs.js";
|
||||
import { jsonToReadableText } from "./helpers.js";
|
||||
import { libContent } from "./helpers/contents.js";
|
||||
import { loadProjectFromFiles } from "./helpers/vfs.js";
|
||||
import { TestServerHost } from "./helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: Public APIs", () => {
|
||||
function verifyApi(fileName: string) {
|
||||
@@ -264,10 +263,10 @@ class C {
|
||||
|
||||
describe("unittests:: Public APIs:: createProgram", () => {
|
||||
function verifyAPI(useJsonParsingApi: boolean) {
|
||||
const fs = loadProjectFromFiles({
|
||||
"/src/projects/project/packages/a/index.js": `export const a = 'a';`,
|
||||
"/src/projects/project/packages/a/test/index.js": `import 'a';`,
|
||||
"/src/projects/project/packages/a/tsconfig.json": jsonToReadableText({
|
||||
const sys = TestServerHost.createWatchedSystem({
|
||||
"/home/src/projects/project/packages/a/index.js": `export const a = 'a';`,
|
||||
"/home/src/projects/project/packages/a/test/index.js": `import 'a';`,
|
||||
"/home/src/projects/project/packages/a/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
checkJs: true,
|
||||
composite: true,
|
||||
@@ -277,7 +276,7 @@ describe("unittests:: Public APIs:: createProgram", () => {
|
||||
outDir: "types",
|
||||
},
|
||||
}),
|
||||
"/src/projects/project/packages/a/package.json": jsonToReadableText({
|
||||
"/home/src/projects/project/packages/a/package.json": jsonToReadableText({
|
||||
name: "a",
|
||||
version: "0.0.0",
|
||||
type: "module",
|
||||
@@ -288,11 +287,9 @@ describe("unittests:: Public APIs:: createProgram", () => {
|
||||
},
|
||||
},
|
||||
}),
|
||||
"/lib/lib.esnext.full.d.ts": libContent,
|
||||
}, { cwd: "/src/projects/project", executingFilePath: "/lib/tsc.js" });
|
||||
const sys = new fakes.System(fs, { executingFilePath: "/lib/tsc.js" });
|
||||
}, { currentDirectory: "/home/src/projects/project" });
|
||||
const commandLine = ts.getParsedCommandLineOfConfigFile(
|
||||
"/src/projects/project/packages/a/tsconfig.json",
|
||||
"/home/src/projects/project/packages/a/tsconfig.json",
|
||||
/*optionsToExtend*/ undefined,
|
||||
{
|
||||
fileExists: sys.fileExists.bind(sys),
|
||||
@@ -306,7 +303,7 @@ describe("unittests:: Public APIs:: createProgram", () => {
|
||||
realpath: sys.realpath.bind(sys),
|
||||
},
|
||||
)!;
|
||||
const config = !useJsonParsingApi ? JSON.parse(fs.readFileSync("/src/projects/project/packages/a/tsconfig.json", "utf-8")) : undefined;
|
||||
const config = !useJsonParsingApi ? JSON.parse(sys.readFile("/home/src/projects/project/packages/a/tsconfig.json")!) : undefined;
|
||||
// This is really createCompilerHost but we want to use our own sys so simple usage
|
||||
const host = ts.createCompilerHostWorker(
|
||||
useJsonParsingApi ? commandLine.options : config.compilerOptions,
|
||||
|
||||
@@ -14,9 +14,8 @@ import {
|
||||
updateProgramText,
|
||||
} from "./helpers.js";
|
||||
import {
|
||||
createWatchedSystem,
|
||||
File,
|
||||
libFile,
|
||||
TestServerHost,
|
||||
} from "./helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: reuseProgramStructure:: General", () => {
|
||||
@@ -115,17 +114,17 @@ describe("unittests:: reuseProgramStructure:: General", () => {
|
||||
|
||||
it("successful if change affects a single module of a package", () => {
|
||||
const files = [
|
||||
{ name: "/a.ts", text: SourceText.New("", "import {b} from 'b'", "var a = b;") },
|
||||
{ name: "/node_modules/b/index.d.ts", text: SourceText.New("", "export * from './internal';", "") },
|
||||
{ name: "/node_modules/b/internal.d.ts", text: SourceText.New("", "", "export const b = 1;") },
|
||||
{ name: "/node_modules/b/package.json", text: SourceText.New("", "", jsonToReadableText({ name: "b", version: "1.2.3" })) },
|
||||
{ name: "/home/src/workspaces/project/a.ts", text: SourceText.New("", "import {b} from 'b'", "var a = b;") },
|
||||
{ name: "/home/src/workspaces/project/node_modules/b/index.d.ts", text: SourceText.New("", "export * from './internal';", "") },
|
||||
{ name: "/home/src/workspaces/project/node_modules/b/internal.d.ts", text: SourceText.New("", "", "export const b = 1;") },
|
||||
{ name: "/home/src/workspaces/project/node_modules/b/package.json", text: SourceText.New("", "", jsonToReadableText({ name: "b", version: "1.2.3" })) },
|
||||
];
|
||||
|
||||
const options: ts.CompilerOptions = { target, moduleResolution: ts.ModuleResolutionKind.Node10 };
|
||||
const program1 = newProgram(files, ["/a.ts"], options);
|
||||
const program1 = newProgram(files, ["/home/src/workspaces/project/a.ts"], options);
|
||||
const baselines: string[] = [];
|
||||
baselineProgram(baselines, program1);
|
||||
const program2 = updateProgram(program1, ["/a.ts"], options, files => {
|
||||
const program2 = updateProgram(program1, ["/home/src/workspaces/project/a.ts"], options, files => {
|
||||
files[2].text = files[2].text.updateProgram("export const b = 2;");
|
||||
});
|
||||
baselineProgram(baselines, program2);
|
||||
@@ -200,19 +199,19 @@ describe("unittests:: reuseProgramStructure:: General", () => {
|
||||
});
|
||||
|
||||
it("succeeds if rootdir changes", () => {
|
||||
const program1 = newProgram(getFiles(), ["a.ts"], { target, module: ts.ModuleKind.CommonJS, rootDir: "/a/b" });
|
||||
const program1 = newProgram(getFiles(), ["a.ts"], { target, module: ts.ModuleKind.CommonJS, rootDir: "/home/src/workspaces/project/a/b" });
|
||||
const baselines: string[] = [];
|
||||
baselineProgram(baselines, program1);
|
||||
const program2 = updateProgram(program1, ["a.ts"], { target, module: ts.ModuleKind.CommonJS, rootDir: "/a/c" }, ts.noop);
|
||||
const program2 = updateProgram(program1, ["a.ts"], { target, module: ts.ModuleKind.CommonJS, rootDir: "/home/src/workspaces/project/a/c" }, ts.noop);
|
||||
baselineProgram(baselines, program2);
|
||||
runBaseline("rootdir changes", baselines);
|
||||
});
|
||||
|
||||
it("fails if config path changes", () => {
|
||||
const program1 = newProgram(getFiles(), ["a.ts"], { target, module: ts.ModuleKind.CommonJS, configFilePath: "/a/b/tsconfig.json" });
|
||||
const program1 = newProgram(getFiles(), ["a.ts"], { target, module: ts.ModuleKind.CommonJS, configFilePath: "/home/src/workspaces/project/a/b/tsconfig.json" });
|
||||
const baselines: string[] = [];
|
||||
baselineProgram(baselines, program1);
|
||||
const program2 = updateProgram(program1, ["a.ts"], { target, module: ts.ModuleKind.CommonJS, configFilePath: "/a/c/tsconfig.json" }, ts.noop);
|
||||
const program2 = updateProgram(program1, ["a.ts"], { target, module: ts.ModuleKind.CommonJS, configFilePath: "/home/src/workspaces/project/a/c/tsconfig.json" }, ts.noop);
|
||||
baselineProgram(baselines, program2);
|
||||
runBaseline("config path changes", baselines);
|
||||
});
|
||||
@@ -273,14 +272,14 @@ describe("unittests:: reuseProgramStructure:: General", () => {
|
||||
|
||||
it("set the resolvedImports after re-using an ambient external module declaration", () => {
|
||||
const files = [
|
||||
{ name: "/a.ts", text: SourceText.New("", "", 'import * as a from "a";') },
|
||||
{ name: "/types/zzz/index.d.ts", text: SourceText.New("", "", 'declare module "a" { }') },
|
||||
{ name: "/home/src/workspaces/project/a.ts", text: SourceText.New("", "", 'import * as a from "a";') },
|
||||
{ name: "/home/src/workspaces/project/types/zzz/index.d.ts", text: SourceText.New("", "", 'declare module "a" { }') },
|
||||
];
|
||||
const options: ts.CompilerOptions = { target, typeRoots: ["/types"] };
|
||||
const program1 = newProgram(files, ["/a.ts"], options);
|
||||
const options: ts.CompilerOptions = { target, typeRoots: ["/home/src/workspaces/project/types"] };
|
||||
const program1 = newProgram(files, ["/home/src/workspaces/project/a.ts"], options);
|
||||
const baselines: string[] = [];
|
||||
baselineProgram(baselines, program1);
|
||||
const program2 = updateProgram(program1, ["/a.ts"], options, files => {
|
||||
const program2 = updateProgram(program1, ["/home/src/workspaces/project/a.ts"], options, files => {
|
||||
files[0].text = files[0].text.updateProgram('import * as aa from "a";');
|
||||
});
|
||||
baselineProgram(baselines, program2);
|
||||
@@ -290,14 +289,14 @@ describe("unittests:: reuseProgramStructure:: General", () => {
|
||||
it("works with updated SourceFiles", () => {
|
||||
// adapted repro from https://github.com/Microsoft/TypeScript/issues/26166
|
||||
const files = [
|
||||
{ name: "/a.ts", text: SourceText.New("", "", 'import * as a from "a";a;') },
|
||||
{ name: "/types/zzz/index.d.ts", text: SourceText.New("", "", 'declare module "a" { }') },
|
||||
{ name: "/home/src/workspaces/project/a.ts", text: SourceText.New("", "", 'import * as a from "a";a;') },
|
||||
{ name: "/home/src/workspaces/project/types/zzz/index.d.ts", text: SourceText.New("", "", 'declare module "a" { }') },
|
||||
];
|
||||
const host = createTestCompilerHost(files, target);
|
||||
const options: ts.CompilerOptions = { target, typeRoots: ["/types"] };
|
||||
const program1 = ts.createProgram(["/a.ts"], options, host) as ProgramToBaseline;
|
||||
const options: ts.CompilerOptions = { target, typeRoots: ["/home/src/workspaces/project/types"] };
|
||||
const program1 = ts.createProgram(["/home/src/workspaces/project/a.ts"], options, host) as ProgramToBaseline;
|
||||
program1.version = 1;
|
||||
let sourceFile = program1.getSourceFile("/a.ts")!;
|
||||
let sourceFile = program1.getSourceFile("/home/src/workspaces/project/a.ts")!;
|
||||
const baselines: string[] = [];
|
||||
baselineProgram(baselines, program1, host);
|
||||
sourceFile = ts.updateSourceFile(sourceFile, "'use strict';" + sourceFile.text, { newLength: "'use strict';".length, span: { start: 0, length: 0 } });
|
||||
@@ -308,7 +307,7 @@ describe("unittests:: reuseProgramStructure:: General", () => {
|
||||
return fileName === sourceFile.fileName ? sourceFile : program1.getSourceFile(fileName);
|
||||
},
|
||||
};
|
||||
const program2 = ts.createProgram(["/a.ts"], options, updateHost, program1) as ProgramToBaseline;
|
||||
const program2 = ts.createProgram(["/home/src/workspaces/project/a.ts"], options, updateHost, program1) as ProgramToBaseline;
|
||||
program2.version = 2;
|
||||
baselineProgram(baselines, program2, updateHost);
|
||||
baselines.push(`parent pointers are not altered: ${sourceFile.statements[2].getSourceFile() === sourceFile}`);
|
||||
@@ -317,28 +316,28 @@ describe("unittests:: reuseProgramStructure:: General", () => {
|
||||
|
||||
it("resolved type directives cache follows type directives", () => {
|
||||
const files = [
|
||||
{ name: "/a.ts", text: SourceText.New("/// <reference types='typedefs'/>", "", "var x = $") },
|
||||
{ name: "/types/typedefs/index.d.ts", text: SourceText.New("", "", "declare var $: number") },
|
||||
{ name: "/home/src/workspaces/project/a.ts", text: SourceText.New("/// <reference types='typedefs'/>", "", "var x = $") },
|
||||
{ name: "/home/src/workspaces/project/types/typedefs/index.d.ts", text: SourceText.New("", "", "declare var $: number") },
|
||||
];
|
||||
const options: ts.CompilerOptions = { target, typeRoots: ["/types"] };
|
||||
const options: ts.CompilerOptions = { target, typeRoots: ["/home/src/workspaces/project/types"] };
|
||||
|
||||
const program1 = newProgram(files, ["/a.ts"], options);
|
||||
const program1 = newProgram(files, ["/home/src/workspaces/project/a.ts"], options);
|
||||
const baselines: string[] = [];
|
||||
baselineProgram(baselines, program1);
|
||||
|
||||
const program2 = updateProgram(program1, ["/a.ts"], options, files => {
|
||||
const program2 = updateProgram(program1, ["/home/src/workspaces/project/a.ts"], options, files => {
|
||||
files[0].text = files[0].text.updateProgram("var x = 2");
|
||||
});
|
||||
baselineProgram(baselines, program2);
|
||||
|
||||
// type reference directives has changed - program is not reused
|
||||
const program3 = updateProgram(program2, ["/a.ts"], options, files => {
|
||||
const program3 = updateProgram(program2, ["/home/src/workspaces/project/a.ts"], options, files => {
|
||||
files[0].text = files[0].text.updateReferences("");
|
||||
});
|
||||
|
||||
baselineProgram(baselines, program3);
|
||||
|
||||
const program4 = updateProgram(program3, ["/a.ts"], options, files => {
|
||||
const program4 = updateProgram(program3, ["/home/src/workspaces/project/a.ts"], options, files => {
|
||||
const newReferences = `/// <reference types="typedefs"/>
|
||||
/// <reference types="typedefs2"/>
|
||||
`;
|
||||
@@ -369,8 +368,8 @@ describe("unittests:: reuseProgramStructure:: General", () => {
|
||||
|
||||
it("should not reuse ambient module declarations from non-modified files", () => {
|
||||
const files = [
|
||||
{ name: "/a/b/app.ts", text: SourceText.New("", "import * as fs from 'fs'", "") },
|
||||
{ name: "/a/b/node.d.ts", text: SourceText.New("", "", "declare module 'fs' {}") },
|
||||
{ name: "/home/src/workspaces/project/a/b/app.ts", text: SourceText.New("", "import * as fs from 'fs'", "") },
|
||||
{ name: "/home/src/workspaces/project/a/b/node.d.ts", text: SourceText.New("", "", "declare module 'fs' {}") },
|
||||
];
|
||||
const options = { target: ts.ScriptTarget.ES2015, traceResolution: true };
|
||||
const program = newProgram(files, files.map(f => f.name), options);
|
||||
@@ -460,17 +459,17 @@ describe("unittests:: reuseProgramStructure:: General", () => {
|
||||
});
|
||||
|
||||
describe("redirects", () => {
|
||||
const axIndex = "/node_modules/a/node_modules/x/index.d.ts";
|
||||
const axPackage = "/node_modules/a/node_modules/x/package.json";
|
||||
const bxIndex = "/node_modules/b/node_modules/x/index.d.ts";
|
||||
const bxPackage = "/node_modules/b/node_modules/x/package.json";
|
||||
const root = "/a.ts";
|
||||
const axIndex = "/home/src/workspaces/project/node_modules/a/node_modules/x/index.d.ts";
|
||||
const axPackage = "/home/src/workspaces/project/node_modules/a/node_modules/x/package.json";
|
||||
const bxIndex = "/home/src/workspaces/project/node_modules/b/node_modules/x/index.d.ts";
|
||||
const bxPackage = "/home/src/workspaces/project/node_modules/b/node_modules/x/package.json";
|
||||
const root = "/home/src/workspaces/project/a.ts";
|
||||
const compilerOptions = { target, moduleResolution: ts.ModuleResolutionKind.Node10 };
|
||||
|
||||
function createRedirectProgram(useGetSourceFileByPath: boolean, options?: { bText: string; bVersion: string; }): ProgramWithSourceTexts {
|
||||
const files: NamedSourceText[] = [
|
||||
{
|
||||
name: "/node_modules/a/index.d.ts",
|
||||
name: "/home/src/workspaces/project/node_modules/a/index.d.ts",
|
||||
text: SourceText.New("", 'import X from "x";', "export function a(x: X): void;"),
|
||||
},
|
||||
{
|
||||
@@ -482,7 +481,7 @@ describe("unittests:: reuseProgramStructure:: General", () => {
|
||||
text: SourceText.New("", "", jsonToReadableText({ name: "x", version: "1.2.3" })),
|
||||
},
|
||||
{
|
||||
name: "/node_modules/b/index.d.ts",
|
||||
name: "/home/src/workspaces/project/node_modules/b/index.d.ts",
|
||||
text: SourceText.New("", 'import X from "x";', "export const b: X;"),
|
||||
},
|
||||
{
|
||||
@@ -574,7 +573,7 @@ describe("unittests:: reuseProgramStructure:: General", () => {
|
||||
it("forceConsistentCasingInFileNames:: handles file preprocessing dignostics", () => {
|
||||
const files = [
|
||||
{
|
||||
name: "/src/project/src/struct.d.ts",
|
||||
name: "/home/src/workspaces/project/src/project/src/struct.d.ts",
|
||||
text: SourceText.New(
|
||||
"",
|
||||
"",
|
||||
@@ -587,7 +586,7 @@ describe("unittests:: reuseProgramStructure:: General", () => {
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "/src/project/src/anotherFile.ts",
|
||||
name: "/home/src/workspaces/project/src/project/src/anotherFile.ts",
|
||||
text: SourceText.New(
|
||||
"",
|
||||
"",
|
||||
@@ -600,7 +599,7 @@ describe("unittests:: reuseProgramStructure:: General", () => {
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "/src/project/src/oneMore.ts",
|
||||
name: "/home/src/workspaces/project/src/project/src/oneMore.ts",
|
||||
text: SourceText.New(
|
||||
"",
|
||||
"",
|
||||
@@ -613,7 +612,7 @@ describe("unittests:: reuseProgramStructure:: General", () => {
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "/src/project/node_modules/fp-ts/lib/struct.d.ts",
|
||||
name: "/home/src/workspaces/project/src/project/node_modules/fp-ts/lib/struct.d.ts",
|
||||
text: SourceText.New("", "", `export function foo(): void`),
|
||||
},
|
||||
];
|
||||
@@ -659,7 +658,7 @@ describe("unittests:: reuseProgramStructure:: General", () => {
|
||||
it("forceConsistentCasingInFileNames:: handles file preprocessing dignostics when diagnostics are not queried", () => {
|
||||
const files = [
|
||||
{
|
||||
name: "/src/project/src/struct.d.ts",
|
||||
name: "/home/src/workspaces/project/src/project/src/struct.d.ts",
|
||||
text: SourceText.New(
|
||||
"",
|
||||
"",
|
||||
@@ -672,7 +671,7 @@ describe("unittests:: reuseProgramStructure:: General", () => {
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "/src/project/src/anotherFile.ts",
|
||||
name: "/home/src/workspaces/project/src/project/src/anotherFile.ts",
|
||||
text: SourceText.New(
|
||||
"",
|
||||
"",
|
||||
@@ -685,7 +684,7 @@ describe("unittests:: reuseProgramStructure:: General", () => {
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "/src/project/src/oneMore.ts",
|
||||
name: "/home/src/workspaces/project/src/project/src/oneMore.ts",
|
||||
text: SourceText.New(
|
||||
"",
|
||||
"",
|
||||
@@ -698,7 +697,7 @@ describe("unittests:: reuseProgramStructure:: General", () => {
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "/src/project/node_modules/fp-ts/lib/struct.d.ts",
|
||||
name: "/home/src/workspaces/project/src/project/node_modules/fp-ts/lib/struct.d.ts",
|
||||
text: SourceText.New("", "", `export function foo(): void`),
|
||||
},
|
||||
];
|
||||
@@ -836,43 +835,46 @@ describe("unittests:: reuseProgramStructure:: isProgramUptoDate::", () => {
|
||||
}
|
||||
|
||||
function verifyProgram(files: File[], rootFiles: string[], options: ts.CompilerOptions, configFile: string) {
|
||||
const system = createWatchedSystem(files);
|
||||
const system = TestServerHost.createWatchedSystem(
|
||||
files,
|
||||
{ currentDirectory: ts.getDirectoryPath(configFile) },
|
||||
);
|
||||
verifyProgramWithoutConfigFile(system, rootFiles, options);
|
||||
verifyProgramWithConfigFile(system, configFile);
|
||||
}
|
||||
|
||||
it("has empty options", () => {
|
||||
const file1: File = {
|
||||
path: "/a/b/file1.ts",
|
||||
path: "/home/src/workspaces/project/a/b/file1.ts",
|
||||
content: "let x = 1",
|
||||
};
|
||||
const file2: File = {
|
||||
path: "/a/b/file2.ts",
|
||||
path: "/home/src/workspaces/project/a/b/file2.ts",
|
||||
content: "let y = 1",
|
||||
};
|
||||
const configFile: File = {
|
||||
path: "/a/b/tsconfig.json",
|
||||
path: "/home/src/workspaces/project/a/b/tsconfig.json",
|
||||
content: "{}",
|
||||
};
|
||||
verifyProgram([file1, file2, libFile, configFile], [file1.path, file2.path], {}, configFile.path);
|
||||
verifyProgram([file1, file2, configFile], [file1.path, file2.path], {}, configFile.path);
|
||||
});
|
||||
|
||||
it("has lib specified in the options", () => {
|
||||
const compilerOptions: ts.CompilerOptions = { lib: ["es5", "es2015.promise"] };
|
||||
const app: File = {
|
||||
path: "/src/app.ts",
|
||||
path: "/home/src/workspaces/project/src/app.ts",
|
||||
content: "var x: Promise<string>;",
|
||||
};
|
||||
const configFile: File = {
|
||||
path: "/src/tsconfig.json",
|
||||
path: "/home/src/workspaces/project/src/tsconfig.json",
|
||||
content: jsonToReadableText({ compilerOptions }),
|
||||
};
|
||||
const es5Lib: File = {
|
||||
path: "/compiler/lib.es5.d.ts",
|
||||
path: "/home/src/workspaces/project/compiler/lib.es5.d.ts",
|
||||
content: "declare const eval: any",
|
||||
};
|
||||
const es2015Promise: File = {
|
||||
path: "/compiler/lib.es2015.promise.d.ts",
|
||||
path: "/home/src/workspaces/project/compiler/lib.es2015.promise.d.ts",
|
||||
content: "declare class Promise<T> {}",
|
||||
};
|
||||
|
||||
@@ -891,30 +893,30 @@ describe("unittests:: reuseProgramStructure:: isProgramUptoDate::", () => {
|
||||
},
|
||||
};
|
||||
const app: File = {
|
||||
path: "/src/packages/framework/app.ts",
|
||||
path: "/home/src/workspaces/project/src/packages/framework/app.ts",
|
||||
content: 'import classc from "module1/lib/file1";\
|
||||
import classD from "module3/file3";\
|
||||
let x = new classc();\
|
||||
let y = new classD();',
|
||||
};
|
||||
const module1: File = {
|
||||
path: "/src/packages/mail/data/module1/lib/file1.ts",
|
||||
path: "/home/src/workspaces/project/src/packages/mail/data/module1/lib/file1.ts",
|
||||
content: 'import classc from "module2/file2";export default classc;',
|
||||
};
|
||||
const module2: File = {
|
||||
path: "/src/packages/mail/data/module1/lib/module2/file2.ts",
|
||||
path: "/home/src/workspaces/project/src/packages/mail/data/module1/lib/module2/file2.ts",
|
||||
content: 'class classc { method2() { return "hello"; } }\nexport default classc',
|
||||
};
|
||||
const module3: File = {
|
||||
path: "/src/packages/styles/module3/file3.ts",
|
||||
path: "/home/src/workspaces/project/src/packages/styles/module3/file3.ts",
|
||||
content: "class classD { method() { return 10; } }\nexport default classD;",
|
||||
};
|
||||
const configFile: File = {
|
||||
path: "/src/tsconfig.json",
|
||||
path: "/home/src/workspaces/project/src/tsconfig.json",
|
||||
content: jsonToReadableText({ compilerOptions }),
|
||||
};
|
||||
|
||||
verifyProgram([app, module1, module2, module3, libFile, configFile], [app.path], compilerOptions, configFile.path);
|
||||
verifyProgram([app, module1, module2, module3, configFile], [app.path], compilerOptions, configFile.path);
|
||||
});
|
||||
|
||||
it("has include paths specified in tsconfig file", () => {
|
||||
@@ -929,45 +931,54 @@ describe("unittests:: reuseProgramStructure:: isProgramUptoDate::", () => {
|
||||
},
|
||||
};
|
||||
const app: File = {
|
||||
path: "/src/packages/framework/app.ts",
|
||||
path: "/home/src/workspaces/project/home/src/packages/framework/app.ts",
|
||||
content: 'import classc from "module1/lib/file1";\
|
||||
import classD from "module3/file3";\
|
||||
let x = new classc();\
|
||||
let y = new classD();',
|
||||
};
|
||||
const module1: File = {
|
||||
path: "/src/packages/mail/data/module1/lib/file1.ts",
|
||||
path: "/home/src/workspaces/project/src/packages/mail/data/module1/lib/file1.ts",
|
||||
content: 'import classc from "module2/file2";export default classc;',
|
||||
};
|
||||
const module2: File = {
|
||||
path: "/src/packages/mail/data/module1/lib/module2/file2.ts",
|
||||
path: "/home/src/workspaces/project/src/packages/mail/data/module1/lib/module2/file2.ts",
|
||||
content: 'class classc { method2() { return "hello"; } }\nexport default classc',
|
||||
};
|
||||
const module3: File = {
|
||||
path: "/src/packages/styles/module3/file3.ts",
|
||||
path: "/home/src/workspaces/project/src/packages/styles/module3/file3.ts",
|
||||
content: "class classD { method() { return 10; } }\nexport default classD;",
|
||||
};
|
||||
const configFile: File = {
|
||||
path: "/src/tsconfig.json",
|
||||
path: "/home/src/workspaces/project/src/tsconfig.json",
|
||||
content: jsonToReadableText({ compilerOptions, include: ["packages/**/*.ts"] }),
|
||||
};
|
||||
verifyProgramWithConfigFile(createWatchedSystem([app, module1, module2, module3, libFile, configFile]), configFile.path);
|
||||
verifyProgramWithConfigFile(
|
||||
TestServerHost.createWatchedSystem(
|
||||
[app, module1, module2, module3, configFile],
|
||||
{ currentDirectory: ts.getDirectoryPath(configFile.path) },
|
||||
),
|
||||
configFile.path,
|
||||
);
|
||||
});
|
||||
it("has the same root file names", () => {
|
||||
const module1: File = {
|
||||
path: "/src/packages/mail/data/module1/lib/file1.ts",
|
||||
path: "/home/src/workspaces/project/src/packages/mail/data/module1/lib/file1.ts",
|
||||
content: 'import classc from "module2/file2";export default classc;',
|
||||
};
|
||||
const module2: File = {
|
||||
path: "/src/packages/mail/data/module1/lib/module2/file2.ts",
|
||||
path: "/home/src/workspaces/project/src/packages/mail/data/module1/lib/module2/file2.ts",
|
||||
content: 'class classc { method2() { return "hello"; } }\nexport default classc',
|
||||
};
|
||||
const module3: File = {
|
||||
path: "/src/packages/styles/module3/file3.ts",
|
||||
path: "/home/src/workspaces/project/src/packages/styles/module3/file3.ts",
|
||||
content: "class classD { method() { return 10; } }\nexport default classD;",
|
||||
};
|
||||
const rootFiles = [module1.path, module2.path, module3.path];
|
||||
const system = createWatchedSystem([module1, module2, module3]);
|
||||
const system = TestServerHost.createWatchedSystem(
|
||||
[module1, module2, module3],
|
||||
{ currentDirectory: "/home/src/workspaces/project/src/packages" },
|
||||
);
|
||||
const options = {};
|
||||
const program = ts.createWatchProgram(ts.createWatchCompilerHostOfFilesAndCompilerOptions({
|
||||
rootFiles,
|
||||
@@ -989,20 +1000,23 @@ describe("unittests:: reuseProgramStructure:: isProgramUptoDate::", () => {
|
||||
}
|
||||
it("has more root file names", () => {
|
||||
const module1: File = {
|
||||
path: "/src/packages/mail/data/module1/lib/file1.ts",
|
||||
path: "/home/src/workspaces/project/src/packages/mail/data/module1/lib/file1.ts",
|
||||
content: 'import classc from "module2/file2";export default classc;',
|
||||
};
|
||||
const module2: File = {
|
||||
path: "/src/packages/mail/data/module1/lib/module2/file2.ts",
|
||||
path: "/home/src/workspaces/project/src/packages/mail/data/module1/lib/module2/file2.ts",
|
||||
content: 'class classc { method2() { return "hello"; } }\nexport default classc',
|
||||
};
|
||||
const module3: File = {
|
||||
path: "/src/packages/styles/module3/file3.ts",
|
||||
path: "/home/src/workspaces/project/src/packages/styles/module3/file3.ts",
|
||||
content: "class classD { method() { return 10; } }\nexport default classD;",
|
||||
};
|
||||
const rootFiles = [module1.path, module2.path];
|
||||
const newRootFiles = [module1.path, module2.path, module3.path];
|
||||
const system = createWatchedSystem([module1, module2, module3]);
|
||||
const system = TestServerHost.createWatchedSystem(
|
||||
[module1, module2, module3],
|
||||
{ currentDirectory: "/home/src/workspaces/project/src/packages" },
|
||||
);
|
||||
const options = {};
|
||||
const program = ts.createWatchProgram(ts.createWatchCompilerHostOfFilesAndCompilerOptions({
|
||||
rootFiles,
|
||||
@@ -1014,20 +1028,23 @@ describe("unittests:: reuseProgramStructure:: isProgramUptoDate::", () => {
|
||||
});
|
||||
it("has one root file replaced by another", () => {
|
||||
const module1: File = {
|
||||
path: "/src/packages/mail/data/module1/lib/file1.ts",
|
||||
path: "/home/src/workspaces/project/src/packages/mail/data/module1/lib/file1.ts",
|
||||
content: 'import classc from "module2/file2";export default classc;',
|
||||
};
|
||||
const module2: File = {
|
||||
path: "/src/packages/mail/data/module1/lib/module2/file2.ts",
|
||||
path: "/home/src/workspaces/project/src/packages/mail/data/module1/lib/module2/file2.ts",
|
||||
content: 'class classc { method2() { return "hello"; } }\nexport default classc',
|
||||
};
|
||||
const module3: File = {
|
||||
path: "/src/packages/styles/module3/file3.ts",
|
||||
path: "/home/src/workspaces/project/src/packages/styles/module3/file3.ts",
|
||||
content: "class classD { method() { return 10; } }\nexport default classD;",
|
||||
};
|
||||
const rootFiles = [module1.path, module2.path];
|
||||
const newRootFiles = [module2.path, module3.path];
|
||||
const system = createWatchedSystem([module1, module2, module3]);
|
||||
const system = TestServerHost.createWatchedSystem(
|
||||
[module1, module2, module3],
|
||||
{ currentDirectory: "/home/src/workspaces/project/src/packages" },
|
||||
);
|
||||
const options = {};
|
||||
const program = ts.createWatchProgram(ts.createWatchCompilerHostOfFilesAndCompilerOptions({
|
||||
rootFiles,
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import * as Harness from "../../_namespaces/Harness.js";
|
||||
import * as ts from "../../_namespaces/ts.js";
|
||||
import {
|
||||
createServerHost,
|
||||
File,
|
||||
libFile as vfsWatch_LibFile,
|
||||
TestServerHost,
|
||||
} from "../helpers/virtualFileSystemWithWatch.js";
|
||||
import {
|
||||
extractTest,
|
||||
@@ -12,7 +13,7 @@ import {
|
||||
} from "./extract/helpers.js";
|
||||
|
||||
const libFile: File = {
|
||||
path: "/a/lib/lib.d.ts",
|
||||
path: vfsWatch_LibFile.path,
|
||||
content: `/// <reference no-default-lib="true"/>
|
||||
interface Boolean {}
|
||||
interface Function {}
|
||||
@@ -275,7 +276,7 @@ interface Array<T> {}`,
|
||||
};
|
||||
|
||||
const moduleFile: File = {
|
||||
path: "/module.ts",
|
||||
path: "/home/src/workspaces/project/module.ts",
|
||||
content: `export function fn(res: any): any {
|
||||
return res;
|
||||
}`,
|
||||
@@ -330,7 +331,7 @@ function testConvertToAsyncFunction(it: Mocha.PendingTestFunction, caption: stri
|
||||
extensions.forEach(extension => it(`${caption} [${extension}]`, () => runBaseline(extension)));
|
||||
|
||||
function runBaseline(extension: ts.Extension) {
|
||||
const path = "/a" + extension;
|
||||
const path = "/home/src/workspaces/project/a" + extension;
|
||||
const languageService = makeLanguageService({ path, content: t.source }, includeLib, includeModule);
|
||||
const program = languageService.getProgram()!;
|
||||
|
||||
@@ -412,7 +413,7 @@ function testConvertToAsyncFunction(it: Mocha.PendingTestFunction, caption: stri
|
||||
if (includeModule) {
|
||||
files.push(moduleFile);
|
||||
}
|
||||
const host = createServerHost(files);
|
||||
const host = TestServerHost.createServerHost(files);
|
||||
const projectService = new TestProjectService(host);
|
||||
projectService.openClientFile(file.path);
|
||||
return ts.first(projectService.inferredProjects).getLanguageService();
|
||||
@@ -444,7 +445,7 @@ const _testConvertToAsyncFunctionWithModule = createTestWrapper((it, caption: st
|
||||
testConvertToAsyncFunction(it, caption, text, "convertToAsyncFunction", ConvertToAsyncTestFlags.IncludeLib | ConvertToAsyncTestFlags.IncludeModule | ConvertToAsyncTestFlags.ExpectSuccess);
|
||||
});
|
||||
|
||||
describe("unittests:: services:: convertToAsyncFunction", () => {
|
||||
describe("unittests:: services:: convertToAsyncFunction::", () => {
|
||||
_testConvertToAsyncFunction(
|
||||
"convertToAsyncFunction_basic",
|
||||
`
|
||||
|
||||
@@ -223,7 +223,6 @@ describe("unittests:: services:: extract:: extractFunctions", () => {
|
||||
[#|t2.toString();|]
|
||||
}
|
||||
}`,
|
||||
/*includeLib*/ true,
|
||||
);
|
||||
// Confirm that the contextual type of an extracted expression counts as a use.
|
||||
testExtractFunction(
|
||||
@@ -231,7 +230,6 @@ describe("unittests:: services:: extract:: extractFunctions", () => {
|
||||
`function F<T>() {
|
||||
const array: T[] = [#|[]|];
|
||||
}`,
|
||||
/*includeLib*/ true,
|
||||
);
|
||||
// Class type parameter
|
||||
testExtractFunction(
|
||||
@@ -257,7 +255,6 @@ describe("unittests:: services:: extract:: extractFunctions", () => {
|
||||
`function F<T, U extends T[], V extends U[]>(v: V) {
|
||||
[#|v.toString()|];
|
||||
}`,
|
||||
/*includeLib*/ true,
|
||||
);
|
||||
|
||||
testExtractFunction(
|
||||
@@ -717,6 +714,6 @@ function F() {
|
||||
);
|
||||
});
|
||||
|
||||
function testExtractFunction(caption: string, text: string, includeLib?: boolean) {
|
||||
testExtractSymbol(caption, text, "extractFunction", ts.Diagnostics.Extract_function, includeLib);
|
||||
function testExtractFunction(caption: string, text: string) {
|
||||
testExtractSymbol(caption, text, "extractFunction", ts.Diagnostics.Extract_function);
|
||||
}
|
||||
|
||||
@@ -3,11 +3,7 @@ import { createHasErrorMessageLogger } from "../../../../harness/tsserverLogger.
|
||||
import * as Harness from "../../../_namespaces/Harness.js";
|
||||
import * as ts from "../../../_namespaces/ts.js";
|
||||
import { customTypesMap } from "../../helpers/typingsInstaller.js";
|
||||
import {
|
||||
createServerHost,
|
||||
libFile,
|
||||
TestServerHost,
|
||||
} from "../../helpers/virtualFileSystemWithWatch.js";
|
||||
import { TestServerHost } from "../../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
export interface TestProjectServiceOptions extends ts.server.ProjectServiceOptions {
|
||||
host: TestServerHost;
|
||||
@@ -112,7 +108,7 @@ export const notImplementedHost: ts.LanguageServiceHost = {
|
||||
fileExists: ts.notImplemented,
|
||||
};
|
||||
|
||||
export function testExtractSymbol(caption: string, text: string, baselineFolder: string, description: ts.DiagnosticMessage, includeLib?: boolean) {
|
||||
export function testExtractSymbol(caption: string, text: string, baselineFolder: string, description: ts.DiagnosticMessage) {
|
||||
const t = extractTest(text);
|
||||
const selectionRange = t.ranges.get("selection")!;
|
||||
if (!selectionRange) {
|
||||
@@ -122,8 +118,8 @@ export function testExtractSymbol(caption: string, text: string, baselineFolder:
|
||||
[ts.Extension.Ts, ts.Extension.Js].forEach(extension => it(`${caption} [${extension}]`, () => runBaseline(extension)));
|
||||
|
||||
function runBaseline(extension: ts.Extension) {
|
||||
const path = "/a" + extension;
|
||||
const { program } = makeProgram({ path, content: t.source }, includeLib);
|
||||
const path = "/home/src/workspaces/project/a" + extension;
|
||||
const { program } = makeProgram({ path, content: t.source });
|
||||
|
||||
if (hasSyntacticDiagnostics(program)) {
|
||||
// Don't bother generating JS baselines for inputs that aren't valid JS.
|
||||
@@ -158,14 +154,14 @@ export function testExtractSymbol(caption: string, text: string, baselineFolder:
|
||||
const newTextWithRename = newText.slice(0, renameLocation) + "/*RENAME*/" + newText.slice(renameLocation);
|
||||
data.push(newTextWithRename);
|
||||
|
||||
const { program: diagProgram } = makeProgram({ path, content: newText }, includeLib);
|
||||
const { program: diagProgram } = makeProgram({ path, content: newText });
|
||||
assert.isFalse(hasSyntacticDiagnostics(diagProgram));
|
||||
}
|
||||
Harness.Baseline.runBaseline(`${baselineFolder}/${caption}${extension}`, data.join(newLineCharacter));
|
||||
}
|
||||
|
||||
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
|
||||
function makeProgram(f: { path: string; content: string; }) {
|
||||
const host = TestServerHost.createServerHost([f]); // libFile is expensive to parse repeatedly - only test when required
|
||||
const projectService = new TestProjectService(host);
|
||||
projectService.openClientFile(f.path);
|
||||
const program = projectService.inferredProjects[0].getLanguageService().getProgram()!;
|
||||
@@ -187,10 +183,10 @@ export function testExtractSymbolFailed(caption: string, text: string, descripti
|
||||
throw new Error(`Test ${caption} does not specify selection range`);
|
||||
}
|
||||
const f = {
|
||||
path: "/a.ts",
|
||||
path: "/home/src/workspaces/project/a.ts",
|
||||
content: t.source,
|
||||
};
|
||||
const host = createServerHost([f, libFile]);
|
||||
const host = TestServerHost.createServerHost([f]);
|
||||
const projectService = new TestProjectService(host);
|
||||
projectService.openClientFile(f.path);
|
||||
const program = projectService.inferredProjects[0].getLanguageService().getProgram()!;
|
||||
|
||||
@@ -3,12 +3,12 @@ import { expect } from "chai";
|
||||
import * as ts from "../../_namespaces/ts.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import {
|
||||
createServerHost,
|
||||
File,
|
||||
libFile,
|
||||
TestServerHost,
|
||||
} from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: services:: languageService", () => {
|
||||
describe("unittests:: services:: languageService::", () => {
|
||||
const files: { [index: string]: string; } = {
|
||||
"foo.ts": `import Vue from "./vue";
|
||||
import Component from "./vue-class-component";
|
||||
@@ -183,7 +183,7 @@ export function Component(x: Config): any;`,
|
||||
path: `/user/username/projects/myproject/projects/project2/class2.ts`,
|
||||
content: `class class2 {}`,
|
||||
};
|
||||
const system = createServerHost([config1, class1, class1Dts, config2, class2, libFile]);
|
||||
const system = TestServerHost.createServerHost([config1, class1, class1Dts, config2, class2]);
|
||||
const result = ts.getParsedCommandLineOfConfigFile(`/user/username/projects/myproject/projects/project2/tsconfig.json`, /*optionsToExtend*/ undefined, {
|
||||
useCaseSensitiveFileNames: true,
|
||||
fileExists: path => system.fileExists(path),
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import * as Harness from "../../_namespaces/Harness.js";
|
||||
import * as ts from "../../_namespaces/ts.js";
|
||||
import {
|
||||
createServerHost,
|
||||
File,
|
||||
TestServerHost,
|
||||
} from "../helpers/virtualFileSystemWithWatch.js";
|
||||
import {
|
||||
newLineCharacter,
|
||||
TestProjectService,
|
||||
} from "./extract/helpers.js";
|
||||
|
||||
describe("unittests:: services:: organizeImports", () => {
|
||||
describe("unittests:: services:: organizeImports::", () => {
|
||||
describe("Sort imports", () => {
|
||||
it("Sort - non-relative vs non-relative", () => {
|
||||
assertSortsBefore(
|
||||
@@ -338,7 +338,7 @@ describe("unittests:: services:: organizeImports", () => {
|
||||
|
||||
describe("Baselines", () => {
|
||||
const libFile = {
|
||||
path: "/lib.ts",
|
||||
path: "/home/src/workspaces/project/lib.ts",
|
||||
content: `
|
||||
export function F1();
|
||||
export default function F2();
|
||||
@@ -346,7 +346,7 @@ export default function F2();
|
||||
};
|
||||
|
||||
const reactLibFile = {
|
||||
path: "/react.ts",
|
||||
path: "/home/src/workspaces/project/react.ts",
|
||||
content: `
|
||||
export const React = {
|
||||
createElement: (_type, _props, _children) => {},
|
||||
@@ -359,7 +359,7 @@ export const Other = 1;
|
||||
// Don't bother to actually emit a baseline for this.
|
||||
it("NoImports", () => {
|
||||
const testFile = {
|
||||
path: "/a.ts",
|
||||
path: "/home/src/workspaces/project/a.ts",
|
||||
content: "function F() { }",
|
||||
};
|
||||
const languageService = makeLanguageService(testFile);
|
||||
@@ -369,7 +369,7 @@ export const Other = 1;
|
||||
|
||||
it("doesn't crash on shorthand ambient module", () => {
|
||||
const testFile = {
|
||||
path: "/a.ts",
|
||||
path: "/home/src/workspaces/project/a.ts",
|
||||
content: "declare module '*';",
|
||||
};
|
||||
const languageService = makeLanguageService(testFile);
|
||||
@@ -379,7 +379,7 @@ export const Other = 1;
|
||||
|
||||
it("doesn't return any changes when the text would be identical", () => {
|
||||
const testFile = {
|
||||
path: "/a.ts",
|
||||
path: "/home/src/workspaces/project/a.ts",
|
||||
content: `import { f } from 'foo';\nf();`,
|
||||
};
|
||||
const languageService = makeLanguageService(testFile);
|
||||
@@ -388,35 +388,35 @@ export const Other = 1;
|
||||
});
|
||||
|
||||
testDetectionBaseline("detection1", /*skipDestructiveCodeActions*/ false, {
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `import { abc, Abc } from 'b';
|
||||
import { I, M, R } from 'a';
|
||||
const x = abc + Abc + I + M + R;`,
|
||||
});
|
||||
|
||||
testDetectionBaseline("detection2", /*skipDestructiveCodeActions*/ false, {
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `import { abc, Abc } from 'a';
|
||||
import { I, M, R } from 'b';
|
||||
const x = abc + Abc + I + M + R;`,
|
||||
});
|
||||
|
||||
testDetectionBaseline("detection3", /*skipDestructiveCodeActions*/ false, {
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `import { I, M, R } from 'a';
|
||||
import { Abc, abc } from 'b';
|
||||
const x = abc + Abc + I + M + R;`,
|
||||
});
|
||||
|
||||
testDetectionBaseline("detection4", /*skipDestructiveCodeActions*/ false, {
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `import { I, M, R } from 'a';
|
||||
import { abc, Abc } from 'b';
|
||||
const x = abc + Abc + I + M + R;`,
|
||||
});
|
||||
|
||||
testDetectionBaseline("detection5", /*skipDestructiveCodeActions*/ false, {
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `import {
|
||||
Type9,
|
||||
Type2,
|
||||
@@ -441,37 +441,37 @@ console.log(Type1, Type2, Type3, Type4, Type5, Type6, Type7, Type8, Type9, func1
|
||||
});
|
||||
|
||||
testDetectionBaseline("detection6", /*skipDestructiveCodeActions*/ false, {
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `import { A, B, a, b } from 'foo';
|
||||
console.log(A, B, a, b);`,
|
||||
});
|
||||
|
||||
testDetectionBaseline("detection7", /*skipDestructiveCodeActions*/ false, {
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `import { A, a, B, b } from 'foo';
|
||||
console.log(A, B, a, b);`,
|
||||
});
|
||||
|
||||
testDetectionBaseline("detection8", /*skipDestructiveCodeActions*/ false, {
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `import { A, a, b, B } from 'foo';
|
||||
console.log(A, B, a, b);`,
|
||||
});
|
||||
|
||||
testDetectionBaseline("detection9", /*skipDestructiveCodeActions*/ false, {
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `import { a, b, A, B } from 'foo';
|
||||
console.log(A, B, a, b);`,
|
||||
});
|
||||
|
||||
testDetectionBaseline("detection10", /*skipDestructiveCodeActions*/ false, {
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `import { a, A, b, B } from 'foo';
|
||||
console.log(A, B, a, b);`,
|
||||
});
|
||||
|
||||
testOrganizeImports("parseErrors", /*skipDestructiveCodeActions*/ false, {
|
||||
path: "/test.js",
|
||||
path: "/home/src/workspaces/project/test.js",
|
||||
content: `declare module 'mod1' {
|
||||
declare export type P = {|
|
||||
|};
|
||||
@@ -493,7 +493,7 @@ declare module 'mod2' {
|
||||
});
|
||||
|
||||
testOrganizeImports("Renamed_used", /*skipDestructiveCodeActions*/ false, {
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `
|
||||
import { F1 as EffOne, F2 as EffTwo } from "lib";
|
||||
EffOne();
|
||||
@@ -501,7 +501,7 @@ EffOne();
|
||||
}, libFile);
|
||||
|
||||
testOrganizeImports("Simple", /*skipDestructiveCodeActions*/ false, {
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `
|
||||
import { F1, F2 } from "lib";
|
||||
import * as NS from "lib";
|
||||
@@ -515,7 +515,7 @@ F2();
|
||||
}, libFile);
|
||||
|
||||
testOrganizeImports("Unused_Some", /*skipDestructiveCodeActions*/ false, {
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `
|
||||
import { F1, F2 } from "lib";
|
||||
import * as NS from "lib";
|
||||
@@ -527,7 +527,7 @@ D();
|
||||
|
||||
describe("skipDestructiveCodeActions=true", () => {
|
||||
testOrganizeImports("Syntax_Error_Body_skipDestructiveCodeActions", /*skipDestructiveCodeActions*/ true, {
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `
|
||||
import { F1, F2 } from "lib";
|
||||
import * as NS from "lib";
|
||||
@@ -540,7 +540,7 @@ D;
|
||||
});
|
||||
|
||||
testOrganizeImports("Syntax_Error_Imports_skipDestructiveCodeActions", /*skipDestructiveCodeActions*/ true, {
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `
|
||||
import { F1, F2 class class class; } from "lib";
|
||||
import * as NS from "lib";
|
||||
@@ -553,7 +553,7 @@ D;
|
||||
|
||||
describe("skipDestructiveCodeActions=false", () => {
|
||||
testOrganizeImports("Syntax_Error_Body", /*skipDestructiveCodeActions*/ false, {
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `
|
||||
import { F1, F2 } from "lib";
|
||||
import * as NS from "lib";
|
||||
@@ -565,7 +565,7 @@ D;
|
||||
}, libFile);
|
||||
|
||||
testOrganizeImports("Syntax_Error_Imports", /*skipDestructiveCodeActions*/ false, {
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `
|
||||
import { F1, F2 class class class; } from "lib";
|
||||
import * as NS from "lib";
|
||||
@@ -579,7 +579,7 @@ D;
|
||||
|
||||
it("doesn't return any changes when the text would be identical", () => {
|
||||
const testFile = {
|
||||
path: "/a.ts",
|
||||
path: "/home/src/workspaces/project/a.ts",
|
||||
content: `import { f } from 'foo';\nf();`,
|
||||
};
|
||||
const languageService = makeLanguageService(testFile);
|
||||
@@ -588,7 +588,7 @@ D;
|
||||
});
|
||||
|
||||
testOrganizeImports("Unused_All", /*skipDestructiveCodeActions*/ false, {
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `
|
||||
import { F1, F2 } from "lib";
|
||||
import * as NS from "lib";
|
||||
@@ -598,7 +598,7 @@ import D from "lib";
|
||||
|
||||
it("Unused_Empty", () => {
|
||||
const testFile = {
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `
|
||||
import { } from "lib";
|
||||
`,
|
||||
@@ -609,7 +609,7 @@ import { } from "lib";
|
||||
});
|
||||
|
||||
testOrganizeImports("Unused_false_positive_module_augmentation", /*skipDestructiveCodeActions*/ false, {
|
||||
path: "/test.d.ts",
|
||||
path: "/home/src/workspaces/project/test.d.ts",
|
||||
content: `
|
||||
import foo from 'foo';
|
||||
import { Caseless } from 'caseless';
|
||||
@@ -623,7 +623,7 @@ declare module 'caseless' {
|
||||
});
|
||||
|
||||
testOrganizeImports("Unused_preserve_imports_for_module_augmentation_in_non_declaration_file", /*skipDestructiveCodeActions*/ false, {
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `
|
||||
import foo from 'foo';
|
||||
import { Caseless } from 'caseless';
|
||||
@@ -638,7 +638,7 @@ declare module 'caseless' {
|
||||
|
||||
it("Unused_false_positive_shorthand_assignment", () => {
|
||||
const testFile = {
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `
|
||||
import { x } from "a";
|
||||
const o = { x };
|
||||
@@ -651,7 +651,7 @@ const o = { x };
|
||||
|
||||
it("Unused_false_positive_export_shorthand", () => {
|
||||
const testFile = {
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `
|
||||
import { x } from "a";
|
||||
export { x };
|
||||
@@ -663,7 +663,7 @@ export { x };
|
||||
});
|
||||
|
||||
testOrganizeImports("MoveToTop", /*skipDestructiveCodeActions*/ false, {
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `
|
||||
import { F1, F2 } from "lib";
|
||||
F1();
|
||||
@@ -677,7 +677,7 @@ D();
|
||||
|
||||
/* eslint-disable no-template-curly-in-string */
|
||||
testOrganizeImports("MoveToTop_Invalid", /*skipDestructiveCodeActions*/ false, {
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `
|
||||
import { F1, F2 } from "lib";
|
||||
F1();
|
||||
@@ -693,7 +693,7 @@ D();
|
||||
/* eslint-enable no-template-curly-in-string */
|
||||
|
||||
testOrganizeImports("TypeOnly", /*skipDestructiveCodeActions*/ false, {
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `
|
||||
import { X } from "lib";
|
||||
import type Y from "lib";
|
||||
@@ -707,7 +707,7 @@ export { A, B, X, Y, Z };`,
|
||||
"CoalesceMultipleModules",
|
||||
/*skipDestructiveCodeActions*/ false,
|
||||
{
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `
|
||||
import { d } from "lib1";
|
||||
import { b } from "lib1";
|
||||
@@ -716,12 +716,12 @@ import { a } from "lib2";
|
||||
a + b + c + d;
|
||||
`,
|
||||
},
|
||||
{ path: "/lib1.ts", content: "export const b = 1, d = 2;" },
|
||||
{ path: "/lib2.ts", content: "export const a = 3, c = 4;" },
|
||||
{ path: "/home/src/workspaces/project/lib1.ts", content: "export const b = 1, d = 2;" },
|
||||
{ path: "/home/src/workspaces/project/lib2.ts", content: "export const a = 3, c = 4;" },
|
||||
);
|
||||
|
||||
testOrganizeImports("CoalesceTrivia", /*skipDestructiveCodeActions*/ false, {
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `
|
||||
/*A*/import /*B*/ { /*C*/ F2 /*D*/ } /*E*/ from /*F*/ "lib" /*G*/;/*H*/ //I
|
||||
/*J*/import /*K*/ { /*L*/ F1 /*M*/ } /*N*/ from /*O*/ "lib" /*P*/;/*Q*/ //R
|
||||
@@ -735,25 +735,25 @@ F2();
|
||||
"SortTrivia",
|
||||
/*skipDestructiveCodeActions*/ false,
|
||||
{
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `
|
||||
/*A*/import /*B*/ "lib2" /*C*/;/*D*/ //E
|
||||
/*F*/import /*G*/ "lib1" /*H*/;/*I*/ //J
|
||||
`,
|
||||
},
|
||||
{ path: "/lib1.ts", content: "" },
|
||||
{ path: "/lib2.ts", content: "" },
|
||||
{ path: "/home/src/workspaces/project/lib1.ts", content: "" },
|
||||
{ path: "/home/src/workspaces/project/lib2.ts", content: "" },
|
||||
);
|
||||
|
||||
testOrganizeImports("UnusedTrivia1", /*skipDestructiveCodeActions*/ false, {
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `
|
||||
/*A*/import /*B*/ { /*C*/ F1 /*D*/ } /*E*/ from /*F*/ "lib" /*G*/;/*H*/ //I
|
||||
`,
|
||||
}, libFile);
|
||||
|
||||
testOrganizeImports("UnusedTrivia2", /*skipDestructiveCodeActions*/ false, {
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `
|
||||
/*A*/import /*B*/ { /*C*/ F1 /*D*/, /*E*/ F2 /*F*/ } /*G*/ from /*H*/ "lib" /*I*/;/*J*/ //K
|
||||
|
||||
@@ -762,7 +762,7 @@ F1();
|
||||
}, libFile);
|
||||
|
||||
testOrganizeImports("UnusedHeaderComment", /*skipDestructiveCodeActions*/ false, {
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `
|
||||
// Header
|
||||
import { F1 } from "lib";
|
||||
@@ -773,19 +773,19 @@ import { F1 } from "lib";
|
||||
"SortHeaderComment",
|
||||
/*skipDestructiveCodeActions*/ false,
|
||||
{
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `
|
||||
// Header
|
||||
import "lib2";
|
||||
import "lib1";
|
||||
`,
|
||||
},
|
||||
{ path: "/lib1.ts", content: "" },
|
||||
{ path: "/lib2.ts", content: "" },
|
||||
{ path: "/home/src/workspaces/project/lib1.ts", content: "" },
|
||||
{ path: "/home/src/workspaces/project/lib2.ts", content: "" },
|
||||
);
|
||||
|
||||
testOrganizeImports("AmbientModule", /*skipDestructiveCodeActions*/ false, {
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `
|
||||
declare module "mod" {
|
||||
import { F1 } from "lib";
|
||||
@@ -798,7 +798,7 @@ declare module "mod" {
|
||||
}, libFile);
|
||||
|
||||
testOrganizeImports("TopLevelAndAmbientModule", /*skipDestructiveCodeActions*/ false, {
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `
|
||||
import D from "lib";
|
||||
|
||||
@@ -818,7 +818,7 @@ D();
|
||||
}, libFile);
|
||||
|
||||
testOrganizeImports("JsxFactoryUsedJsx", /*skipDestructiveCodeActions*/ false, {
|
||||
path: "/test.jsx",
|
||||
path: "/home/src/workspaces/project/test.jsx",
|
||||
content: `
|
||||
import { React, Other } from "react";
|
||||
|
||||
@@ -827,7 +827,7 @@ import { React, Other } from "react";
|
||||
}, reactLibFile);
|
||||
|
||||
testOrganizeImports("JsxFactoryUsedJs", /*skipDestructiveCodeActions*/ false, {
|
||||
path: "/test.js",
|
||||
path: "/home/src/workspaces/project/test.js",
|
||||
content: `
|
||||
import { React, Other } from "react";
|
||||
|
||||
@@ -836,7 +836,7 @@ import { React, Other } from "react";
|
||||
}, reactLibFile);
|
||||
|
||||
testOrganizeImports("JsxFactoryUsedTsx", /*skipDestructiveCodeActions*/ false, {
|
||||
path: "/test.tsx",
|
||||
path: "/home/src/workspaces/project/test.tsx",
|
||||
content: `
|
||||
import { React, Other } from "react";
|
||||
|
||||
@@ -846,7 +846,7 @@ import { React, Other } from "react";
|
||||
|
||||
// TS files are not JSX contexts, so the parser does not treat `<div/>` as a JSX element.
|
||||
testOrganizeImports("JsxFactoryUsedTs", /*skipDestructiveCodeActions*/ false, {
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `
|
||||
import { React, Other } from "react";
|
||||
|
||||
@@ -855,7 +855,7 @@ import { React, Other } from "react";
|
||||
}, reactLibFile);
|
||||
|
||||
testOrganizeImports("JsxFactoryUnusedJsx", /*skipDestructiveCodeActions*/ false, {
|
||||
path: "/test.jsx",
|
||||
path: "/home/src/workspaces/project/test.jsx",
|
||||
content: `
|
||||
import { React, Other } from "react";
|
||||
`,
|
||||
@@ -864,28 +864,28 @@ import { React, Other } from "react";
|
||||
// Note: Since the file extension does not end with "x", the jsx compiler option
|
||||
// will not be enabled. The import should be retained regardless.
|
||||
testOrganizeImports("JsxFactoryUnusedJs", /*skipDestructiveCodeActions*/ false, {
|
||||
path: "/test.js",
|
||||
path: "/home/src/workspaces/project/test.js",
|
||||
content: `
|
||||
import { React, Other } from "react";
|
||||
`,
|
||||
}, reactLibFile);
|
||||
|
||||
testOrganizeImports("JsxFactoryUnusedTsx", /*skipDestructiveCodeActions*/ false, {
|
||||
path: "/test.tsx",
|
||||
path: "/home/src/workspaces/project/test.tsx",
|
||||
content: `
|
||||
import { React, Other } from "react";
|
||||
`,
|
||||
}, reactLibFile);
|
||||
|
||||
testOrganizeImports("JsxFactoryUnusedTs", /*skipDestructiveCodeActions*/ false, {
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `
|
||||
import { React, Other } from "react";
|
||||
`,
|
||||
}, reactLibFile);
|
||||
|
||||
testOrganizeImports("JsxPragmaTsx", /*skipDestructiveCodeActions*/ false, {
|
||||
path: "/test.tsx",
|
||||
path: "/home/src/workspaces/project/test.tsx",
|
||||
content: `/** @jsx jsx */
|
||||
|
||||
import { Global, jsx } from '@emotion/core';
|
||||
@@ -894,7 +894,7 @@ import * as React from 'react';
|
||||
export const App: React.FunctionComponent = _ => <Global><h1>Hello!</h1></Global>
|
||||
`,
|
||||
}, {
|
||||
path: "/@emotion/core/index.d.ts",
|
||||
path: "/home/src/workspaces/project/@emotion/core/index.d.ts",
|
||||
content: `import { createElement } from 'react'
|
||||
export const jsx: typeof createElement;
|
||||
export function Global(props: any): ReactElement<any>;`,
|
||||
@@ -909,7 +909,7 @@ export namespace React {
|
||||
});
|
||||
|
||||
testOrganizeImports("JsxFragmentPragmaTsx", /*skipDestructiveCodeActions*/ false, {
|
||||
path: "/test.tsx",
|
||||
path: "/home/src/workspaces/project/test.tsx",
|
||||
content: `/** @jsx h */
|
||||
/** @jsxFrag frag */
|
||||
import { h, frag } from "@foo/core";
|
||||
@@ -917,7 +917,7 @@ import { h, frag } from "@foo/core";
|
||||
const elem = <><div>Foo</div></>;
|
||||
`,
|
||||
}, {
|
||||
path: "/@foo/core/index.d.ts",
|
||||
path: "/home/src/workspaces/project/@foo/core/index.d.ts",
|
||||
content: `export function h(): void;
|
||||
export function frag(): void;
|
||||
`,
|
||||
@@ -925,7 +925,7 @@ export function frag(): void;
|
||||
|
||||
describe("Exports", () => {
|
||||
testOrganizeExports("MoveToTop", {
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `
|
||||
export { F1, F2 } from "lib";
|
||||
1;
|
||||
@@ -936,7 +936,7 @@ export * from "lib";
|
||||
|
||||
/* eslint-disable no-template-curly-in-string */
|
||||
testOrganizeExports("MoveToTop_Invalid", {
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `
|
||||
export { F1, F2 } from "lib";
|
||||
1;
|
||||
@@ -951,7 +951,7 @@ export { D } from "lib";
|
||||
/* eslint-enable no-template-curly-in-string */
|
||||
|
||||
testOrganizeExports("MoveToTop_WithImportsFirst", {
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `
|
||||
import { F1, F2 } from "lib";
|
||||
1;
|
||||
@@ -966,7 +966,7 @@ F1(); F2(); NS.F1();
|
||||
}, libFile);
|
||||
|
||||
testOrganizeExports("MoveToTop_WithExportsFirst", {
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `
|
||||
export { F1, F2 } from "lib";
|
||||
1;
|
||||
@@ -983,7 +983,7 @@ F1(); F2(); NS.F1();
|
||||
testOrganizeExports(
|
||||
"CoalesceMultipleModules",
|
||||
{
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `
|
||||
export { d } from "lib1";
|
||||
export { b } from "lib1";
|
||||
@@ -991,12 +991,12 @@ export { c } from "lib2";
|
||||
export { a } from "lib2";
|
||||
`,
|
||||
},
|
||||
{ path: "/lib1.ts", content: "export const b = 1, d = 2;" },
|
||||
{ path: "/lib2.ts", content: "export const a = 3, c = 4;" },
|
||||
{ path: "/home/src/workspaces/project/lib1.ts", content: "export const b = 1, d = 2;" },
|
||||
{ path: "/home/src/workspaces/project/lib2.ts", content: "export const a = 3, c = 4;" },
|
||||
);
|
||||
|
||||
testOrganizeExports("CoalesceTrivia", {
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `
|
||||
/*A*/export /*B*/ { /*C*/ F2 /*D*/ } /*E*/ from /*F*/ "lib" /*G*/;/*H*/ //I
|
||||
/*J*/export /*K*/ { /*L*/ F1 /*M*/ } /*N*/ from /*O*/ "lib" /*P*/;/*Q*/ //R
|
||||
@@ -1006,32 +1006,32 @@ export { a } from "lib2";
|
||||
testOrganizeExports(
|
||||
"SortTrivia",
|
||||
{
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `
|
||||
/*A*/export /*B*/ * /*C*/ from /*D*/ "lib2" /*E*/;/*F*/ //G
|
||||
/*H*/export /*I*/ * /*J*/ from /*K*/ "lib1" /*L*/;/*M*/ //N
|
||||
`,
|
||||
},
|
||||
{ path: "/lib1.ts", content: "" },
|
||||
{ path: "/lib2.ts", content: "" },
|
||||
{ path: "/home/src/workspaces/project/lib1.ts", content: "" },
|
||||
{ path: "/home/src/workspaces/project/lib2.ts", content: "" },
|
||||
);
|
||||
|
||||
testOrganizeExports(
|
||||
"SortHeaderComment",
|
||||
{
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `
|
||||
// Header
|
||||
export * from "lib2";
|
||||
export * from "lib1";
|
||||
`,
|
||||
},
|
||||
{ path: "/lib1.ts", content: "" },
|
||||
{ path: "/lib2.ts", content: "" },
|
||||
{ path: "/home/src/workspaces/project/lib1.ts", content: "" },
|
||||
{ path: "/home/src/workspaces/project/lib2.ts", content: "" },
|
||||
);
|
||||
|
||||
testOrganizeExports("AmbientModule", {
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `
|
||||
declare module "mod" {
|
||||
export { F1 } from "lib";
|
||||
@@ -1042,7 +1042,7 @@ declare module "mod" {
|
||||
}, libFile);
|
||||
|
||||
testOrganizeExports("TopLevelAndAmbientModule", {
|
||||
path: "/test.ts",
|
||||
path: "/home/src/workspaces/project/test.ts",
|
||||
content: `
|
||||
export { D } from "lib";
|
||||
|
||||
@@ -1120,7 +1120,7 @@ export * from "lib";
|
||||
}
|
||||
|
||||
function makeLanguageService(...files: File[]) {
|
||||
const host = createServerHost(files);
|
||||
const host = TestServerHost.createServerHost(files);
|
||||
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));
|
||||
|
||||
@@ -10,9 +10,9 @@ import {
|
||||
Deferred,
|
||||
} from "../../_namespaces/Utils.js";
|
||||
import {
|
||||
createWatchedSystem,
|
||||
FileOrFolderOrSymLinkMap,
|
||||
osFlavorToString,
|
||||
TestServerHost,
|
||||
TestServerHostOsFlavor,
|
||||
} from "../helpers/virtualFileSystemWithWatch.js";
|
||||
describe("unittests:: sys:: symlinkWatching::", () => {
|
||||
@@ -27,7 +27,7 @@ describe("unittests:: sys:: symlinkWatching::", () => {
|
||||
|
||||
function verifyWatchFile(
|
||||
scenario: string,
|
||||
sys: ts.System,
|
||||
getSys: () => ts.System,
|
||||
file: string,
|
||||
link: string,
|
||||
watchOptions: Pick<ts.WatchOptions, "watchFile">,
|
||||
@@ -35,6 +35,7 @@ describe("unittests:: sys:: symlinkWatching::", () => {
|
||||
) {
|
||||
if (skipSysTests) return;
|
||||
it(scenario, async () => {
|
||||
const sys = getSys();
|
||||
const fileResult = watchFile(file);
|
||||
const linkResult = watchFile(link);
|
||||
|
||||
@@ -211,7 +212,7 @@ describe("unittests:: sys:: symlinkWatching::", () => {
|
||||
linkFileDelete: readonly ExpectedEventAndFileName[];
|
||||
}
|
||||
function verifyWatchDirectoryUsingFsEvents<System extends ts.System>(
|
||||
sys: System,
|
||||
getSys: () => System,
|
||||
fsWatch: FsWatch<System>,
|
||||
dir: string,
|
||||
link: string,
|
||||
@@ -219,6 +220,7 @@ describe("unittests:: sys:: symlinkWatching::", () => {
|
||||
) {
|
||||
if (skipSysTests) return;
|
||||
it(`watchDirectory using fsEvents ${osFlavorToString(osFlavor)}`, async () => {
|
||||
const sys = getSys();
|
||||
const tableOfEvents: FsEventsForWatchDirectory = osFlavor === TestServerHostOsFlavor.MacOs ?
|
||||
{
|
||||
fileCreate: [
|
||||
@@ -328,7 +330,7 @@ describe("unittests:: sys:: symlinkWatching::", () => {
|
||||
],
|
||||
);
|
||||
|
||||
function operation(opType: keyof FsEventsForWatchDirectory) {
|
||||
function operation(sys: System, opType: keyof FsEventsForWatchDirectory) {
|
||||
switch (opType) {
|
||||
case "init":
|
||||
sys.writeFile(`${dir}/init.ts`, "export const x = 100;");
|
||||
@@ -376,7 +378,7 @@ describe("unittests:: sys:: symlinkWatching::", () => {
|
||||
parallelLinkFileDelete: readonly ExpectedEventAndFileName[] | undefined;
|
||||
}
|
||||
function verifyRecursiveWatchDirectoryUsingFsEvents<System extends ts.System>(
|
||||
sys: System,
|
||||
getSys: () => System,
|
||||
fsWatch: FsWatch<System>,
|
||||
dir: string,
|
||||
link: string,
|
||||
@@ -495,6 +497,7 @@ describe("unittests:: sys:: symlinkWatching::", () => {
|
||||
};
|
||||
|
||||
it(`recursive watchDirectory using fsEvents ${osFlavorToString(osFlavor)}`, async () => {
|
||||
const sys = getSys();
|
||||
await testWatchDirectoryOperations(
|
||||
sys,
|
||||
fsWatch,
|
||||
@@ -518,6 +521,7 @@ describe("unittests:: sys:: symlinkWatching::", () => {
|
||||
});
|
||||
|
||||
it(`recursive watchDirectory using fsEvents when linked in same folder ${osFlavorToString(osFlavor)}`, async () => {
|
||||
const sys = getSys();
|
||||
await testWatchDirectoryOperations(
|
||||
sys,
|
||||
fsWatch,
|
||||
@@ -537,6 +541,7 @@ describe("unittests:: sys:: symlinkWatching::", () => {
|
||||
});
|
||||
|
||||
it(`recursive watchDirectory using fsEvents when links not in directory ${osFlavorToString(osFlavor)}`, async () => {
|
||||
const sys = getSys();
|
||||
await testWatchDirectoryOperations(
|
||||
sys,
|
||||
fsWatch,
|
||||
@@ -560,6 +565,7 @@ describe("unittests:: sys:: symlinkWatching::", () => {
|
||||
});
|
||||
|
||||
function watchDirectoryOperation(
|
||||
sys: System,
|
||||
opType: keyof RecursiveFsEventsForWatchDirectory,
|
||||
dir: string,
|
||||
link: string,
|
||||
@@ -614,12 +620,12 @@ describe("unittests:: sys:: symlinkWatching::", () => {
|
||||
}
|
||||
|
||||
type EventRecord = Record<string, readonly ExpectedEventAndFileName[] | undefined>;
|
||||
type Operation<Events extends EventRecord> = (opType: keyof Events, dir: string, link: string) => void;
|
||||
type Operation<System extends ts.System, Events extends EventRecord> = (sys: System, opType: keyof Events, dir: string, link: string) => void;
|
||||
async function testWatchDirectoryOperations<System extends ts.System, Events extends EventRecord>(
|
||||
sys: System,
|
||||
fsWatch: FsWatch<System>,
|
||||
tableOfEvents: Events,
|
||||
operation: Operation<Events>,
|
||||
operation: Operation<System, Events>,
|
||||
directoryName: string,
|
||||
linkName: string,
|
||||
recursive: boolean,
|
||||
@@ -629,24 +635,25 @@ describe("unittests:: sys:: symlinkWatching::", () => {
|
||||
const linkResult = watchDirectory(sys, fsWatch, linkName, recursive);
|
||||
|
||||
for (const opType of opTypes) {
|
||||
await watchDirectoryOperation(tableOfEvents, opType, operation, directoryName, linkName, dirResult, linkResult);
|
||||
await watchDirectoryOperation(sys, tableOfEvents, opType, operation, directoryName, linkName, dirResult, linkResult);
|
||||
}
|
||||
|
||||
dirResult.watcher.close();
|
||||
linkResult.watcher.close();
|
||||
}
|
||||
|
||||
async function watchDirectoryOperation<Events extends EventRecord>(
|
||||
async function watchDirectoryOperation<System extends ts.System, Events extends EventRecord>(
|
||||
sys: System,
|
||||
tableOfEvents: Events,
|
||||
opType: keyof Events & string,
|
||||
operation: Operation<Events>,
|
||||
operation: Operation<System, Events>,
|
||||
directoryName: string,
|
||||
linkName: string,
|
||||
dirResult: WatchDirectoryResult,
|
||||
linkResult: WatchDirectoryResult,
|
||||
) {
|
||||
initializeWatchDirectoryResult(dirResult, linkResult);
|
||||
operation(opType, directoryName, linkName);
|
||||
operation(sys, opType, directoryName, linkName);
|
||||
await verfiyWatchDirectoryResult(
|
||||
opType,
|
||||
dirResult,
|
||||
@@ -688,7 +695,7 @@ describe("unittests:: sys:: symlinkWatching::", () => {
|
||||
});
|
||||
verifyWatchFile(
|
||||
"watchFile using polling",
|
||||
ts.sys,
|
||||
() => ts.sys,
|
||||
`${root}/polling/file.ts`,
|
||||
`${root}/linkedpolling/file.ts`,
|
||||
{ watchFile: ts.WatchFileKind.PriorityPollingInterval },
|
||||
@@ -701,7 +708,7 @@ describe("unittests:: sys:: symlinkWatching::", () => {
|
||||
});
|
||||
verifyWatchFile(
|
||||
"watchFile using fsEvents",
|
||||
ts.sys,
|
||||
() => ts.sys,
|
||||
`${root}/fsevents/file.ts`,
|
||||
`${root}/linkedfsevents/file.ts`,
|
||||
{ watchFile: ts.WatchFileKind.UseFsEvents },
|
||||
@@ -714,7 +721,7 @@ describe("unittests:: sys:: symlinkWatching::", () => {
|
||||
});
|
||||
verifyWatchFile(
|
||||
"watchDirectory using polling",
|
||||
ts.sys,
|
||||
() => ts.sys,
|
||||
`${root}/dirpolling`,
|
||||
`${root}/linkeddirpolling`,
|
||||
{ watchFile: ts.WatchFileKind.PriorityPollingInterval },
|
||||
@@ -727,7 +734,7 @@ describe("unittests:: sys:: symlinkWatching::", () => {
|
||||
withSwallowException(() => fs.symlinkSync(`${root}/dirfsevents`, `${root}/linkeddirfsevents`, "junction"));
|
||||
});
|
||||
verifyWatchDirectoryUsingFsEvents(
|
||||
ts.sys,
|
||||
() => ts.sys,
|
||||
(dir, _recursive, cb) => fs.watch(dir, { persistent: true }, cb),
|
||||
`${root}/dirfsevents`,
|
||||
`${root}/linkeddirfsevents`,
|
||||
@@ -743,7 +750,7 @@ describe("unittests:: sys:: symlinkWatching::", () => {
|
||||
setupRecursiveFsEvents("recursivefseventsparallel");
|
||||
});
|
||||
verifyRecursiveWatchDirectoryUsingFsEvents(
|
||||
ts.sys,
|
||||
() => ts.sys,
|
||||
(dir, recursive, cb) => fs.watch(dir, { persistent: true, recursive }, cb),
|
||||
`${root}/recursivefsevents`,
|
||||
`${root}/linkedrecursivefsevents`,
|
||||
@@ -762,23 +769,23 @@ describe("unittests:: sys:: symlinkWatching::", () => {
|
||||
});
|
||||
|
||||
describe("with virtualFileSystem::", () => {
|
||||
const root = ts.normalizePath("/tests/baselines/symlinks");
|
||||
const root = ts.normalizePath("/home/tests/baselines/symlinks");
|
||||
function getSys(osFlavor?: TestServerHostOsFlavor) {
|
||||
return createWatchedSystem({
|
||||
return TestServerHost.createWatchedSystem({
|
||||
[`${root}/folder/file.ts`]: "export const x = 10;",
|
||||
[`${root}/linked`]: { symLink: `${root}/folder` },
|
||||
}, { osFlavor });
|
||||
}, { osFlavor, currentDirectory: root });
|
||||
}
|
||||
verifyWatchFile(
|
||||
"watchFile using polling",
|
||||
getSys(),
|
||||
getSys,
|
||||
`${root}/folder/file.ts`,
|
||||
`${root}/linked/file.ts`,
|
||||
{ watchFile: ts.WatchFileKind.PriorityPollingInterval },
|
||||
);
|
||||
verifyWatchFile(
|
||||
"watchFile using fsEvents",
|
||||
getSys(),
|
||||
getSys,
|
||||
`${root}/folder/file.ts`,
|
||||
`${root}/linked/file.ts`,
|
||||
{ watchFile: ts.WatchFileKind.UseFsEvents },
|
||||
@@ -786,7 +793,7 @@ describe("unittests:: sys:: symlinkWatching::", () => {
|
||||
|
||||
verifyWatchFile(
|
||||
"watchDirectory using polling",
|
||||
getSys(),
|
||||
getSys,
|
||||
`${root}/folder`,
|
||||
`${root}/linked`,
|
||||
{ watchFile: ts.WatchFileKind.PriorityPollingInterval },
|
||||
@@ -795,7 +802,7 @@ describe("unittests:: sys:: symlinkWatching::", () => {
|
||||
|
||||
function verifyWatchDirectoryUsingFsEventsTestServerHost(osFlavor: TestServerHostOsFlavor) {
|
||||
verifyWatchDirectoryUsingFsEvents(
|
||||
getSys(osFlavor),
|
||||
() => getSys(osFlavor),
|
||||
(dir, recursive, cb, sys) => sys.fsWatchWorker(dir, recursive, cb),
|
||||
`${root}/folder`,
|
||||
`${root}/linked`,
|
||||
@@ -807,11 +814,11 @@ describe("unittests:: sys:: symlinkWatching::", () => {
|
||||
verifyWatchDirectoryUsingFsEventsTestServerHost(TestServerHostOsFlavor.Linux);
|
||||
|
||||
function getRecursiveSys(osFlavor: TestServerHostOsFlavor) {
|
||||
return createWatchedSystem({
|
||||
return TestServerHost.createWatchedSystem({
|
||||
...getRecursiveFs("recursivefsevents"),
|
||||
...getRecursiveFs("recursivefseventssub"),
|
||||
...getRecursiveFs("recursivefseventsparallel"),
|
||||
}, { osFlavor });
|
||||
}, { osFlavor, currentDirectory: root });
|
||||
|
||||
function getRecursiveFs(recursiveName: string): FileOrFolderOrSymLinkMap {
|
||||
return {
|
||||
@@ -826,7 +833,7 @@ describe("unittests:: sys:: symlinkWatching::", () => {
|
||||
|
||||
function verifyRecursiveWatchDirectoryUsingFsEventsTestServerHost(osFlavor: TestServerHostOsFlavor.Windows | TestServerHostOsFlavor.MacOs) {
|
||||
verifyRecursiveWatchDirectoryUsingFsEvents(
|
||||
getRecursiveSys(osFlavor),
|
||||
() => getRecursiveSys(osFlavor),
|
||||
(dir, recursive, cb, sys) => sys.fsWatchWorker(dir, recursive, cb),
|
||||
`${root}/recursivefsevents`,
|
||||
`${root}/linkedrecursivefsevents`,
|
||||
|
||||
@@ -1,22 +1,17 @@
|
||||
import { dedent } from "../../_namespaces/Utils.js";
|
||||
import * as vfs from "../../_namespaces/vfs.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import { verifyTsc } from "../helpers/tsc.js";
|
||||
import {
|
||||
appendText,
|
||||
loadProjectFromFiles,
|
||||
replaceText,
|
||||
} from "../helpers/vfs.js";
|
||||
import { TestServerHost } from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsbuild:: outFile:: on amd modules with --out", () => {
|
||||
function outFileFs(prepend?: boolean) {
|
||||
return loadProjectFromFiles({
|
||||
"/src/app/file3.ts": dedent`
|
||||
describe("unittests:: tsbuild:: outFile:: amdModulesWithOut:: on amd modules with --out", () => {
|
||||
function outFileSys(prepend?: boolean) {
|
||||
return TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/soltion/app/file3.ts": dedent`
|
||||
export const z = 30;
|
||||
import { x } from "file1";
|
||||
`,
|
||||
"/src/app/file4.ts": `const myVar = 30;`,
|
||||
"/src/app/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/soltion/app/file4.ts": `const myVar = 30;`,
|
||||
"/home/src/workspaces/soltion/app/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
target: "es5",
|
||||
module: "amd",
|
||||
@@ -31,11 +26,11 @@ describe("unittests:: tsbuild:: outFile:: on amd modules with --out", () => {
|
||||
{ path: "../lib", prepend },
|
||||
],
|
||||
}),
|
||||
"/src/lib/file0.ts": `const myGlob = 20;`,
|
||||
"/src/lib/file1.ts": `export const x = 10;`,
|
||||
"/src/lib/file2.ts": `export const y = 20;`,
|
||||
"/src/lib/global.ts": `const globalConst = 10;`,
|
||||
"/src/lib/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/soltion/lib/file0.ts": `const myGlob = 20;`,
|
||||
"/home/src/workspaces/soltion/lib/file1.ts": `export const x = 10;`,
|
||||
"/home/src/workspaces/soltion/lib/file2.ts": `export const y = 20;`,
|
||||
"/home/src/workspaces/soltion/lib/global.ts": `const globalConst = 10;`,
|
||||
"/home/src/workspaces/soltion/lib/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
target: "es5",
|
||||
module: "amd",
|
||||
@@ -47,47 +42,45 @@ describe("unittests:: tsbuild:: outFile:: on amd modules with --out", () => {
|
||||
},
|
||||
exclude: ["module.d.ts"],
|
||||
}),
|
||||
});
|
||||
}, { currentDirectory: "/home/src/workspaces/soltion" });
|
||||
}
|
||||
|
||||
verifyTsc({
|
||||
scenario: "amdModulesWithOut",
|
||||
subScenario: "modules and globals mixed in amd",
|
||||
fs: outFileFs,
|
||||
commandLineArgs: ["--b", "/src/app", "--verbose"],
|
||||
sys: outFileSys,
|
||||
commandLineArgs: ["--b", "app", "--verbose"],
|
||||
baselineSourceMap: true,
|
||||
edits: [{
|
||||
caption: "incremental-declaration-doesnt-change",
|
||||
edit: fs => appendText(fs, "/src/lib/file1.ts", "console.log(x);"),
|
||||
edit: sys => sys.appendFile("/home/src/workspaces/soltion/lib/file1.ts", "console.log(x);"),
|
||||
}],
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "amdModulesWithOut",
|
||||
subScenario: "prepend reports deprecation error",
|
||||
fs: () => outFileFs(/*prepend*/ true),
|
||||
commandLineArgs: ["--b", "/src/app", "--verbose"],
|
||||
sys: () => outFileSys(/*prepend*/ true),
|
||||
commandLineArgs: ["--b", "app", "--verbose"],
|
||||
baselineSourceMap: true,
|
||||
edits: [{
|
||||
caption: "incremental-declaration-doesnt-change",
|
||||
edit: fs => appendText(fs, "/src/lib/file1.ts", "console.log(x);"),
|
||||
edit: sys => sys.appendFile("/home/src/workspaces/soltion/lib/file1.ts", "console.log(x);"),
|
||||
}],
|
||||
});
|
||||
|
||||
describe("when the module resolution finds original source file", () => {
|
||||
function modifyFs(fs: vfs.FileSystem) {
|
||||
// Make lib to output to parent dir
|
||||
replaceText(fs, "/src/lib/tsconfig.json", `"outFile": "module.js"`, `"outFile": "../module.js", "rootDir": "../"`);
|
||||
// Change reference to file1 module to resolve to lib/file1
|
||||
replaceText(fs, "/src/app/file3.ts", "file1", "lib/file1");
|
||||
}
|
||||
|
||||
verifyTsc({
|
||||
scenario: "amdModulesWithOut",
|
||||
subScenario: "when the module resolution finds original source file",
|
||||
fs: outFileFs,
|
||||
commandLineArgs: ["-b", "/src/app", "--verbose"],
|
||||
modifyFs,
|
||||
sys: outFileSys,
|
||||
commandLineArgs: ["-b", "app", "--verbose"],
|
||||
modifySystem: sys => {
|
||||
// Make lib to output to parent dir
|
||||
sys.replaceFileText("/home/src/workspaces/soltion/lib/tsconfig.json", `"outFile": "module.js"`, `"outFile": "../module.js", "rootDir": "../"`);
|
||||
// Change reference to file1 module to resolve to lib/file1
|
||||
sys.replaceFileText("/home/src/workspaces/soltion/app/file3.ts", "file1", "lib/file1");
|
||||
},
|
||||
baselineSourceMap: true,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,41 +4,41 @@ import {
|
||||
noChangeRun,
|
||||
verifyTsc,
|
||||
} from "../helpers/tsc.js";
|
||||
import { loadProjectFromFiles } from "../helpers/vfs.js";
|
||||
import { TestServerHost } from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsbuild - clean::", () => {
|
||||
verifyTsc({
|
||||
scenario: "clean",
|
||||
subScenario: `file name and output name clashing`,
|
||||
commandLineArgs: ["--b", "/src/tsconfig.json", "-clean"],
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/index.js": "",
|
||||
"/src/bar.ts": "",
|
||||
"/src/tsconfig.json": jsonToReadableText({
|
||||
commandLineArgs: ["--b", "-clean"],
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/solution/index.js": "",
|
||||
"/home/src/workspaces/solution/bar.ts": "",
|
||||
"/home/src/workspaces/solution/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: { allowJs: true },
|
||||
}),
|
||||
}),
|
||||
}, { currentDirectory: "/home/src/workspaces/solution" }),
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "clean",
|
||||
subScenario: "tsx with dts emit",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/project/src/main.tsx": "export const x = 10;",
|
||||
"/src/project/tsconfig.json": jsonToReadableText({
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/solution/project/src/main.tsx": "export const x = 10;",
|
||||
"/home/src/workspaces/solution/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: { declaration: true },
|
||||
include: ["src/**/*.tsx", "src/**/*.ts"],
|
||||
}),
|
||||
}),
|
||||
commandLineArgs: ["--b", "src/project", "-v", "--explainFiles"],
|
||||
}, { currentDirectory: "/home/src/workspaces/solution" }),
|
||||
commandLineArgs: ["--b", "project", "-v", "--explainFiles"],
|
||||
edits: [
|
||||
noChangeRun,
|
||||
{
|
||||
caption: "clean build",
|
||||
edit: noop,
|
||||
commandLineArgs: ["-b", "/src/project", "--clean"],
|
||||
commandLineArgs: ["-b", "project", "--clean"],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
@@ -6,11 +6,7 @@ import {
|
||||
TestTscEdit,
|
||||
verifyTsc,
|
||||
} from "../helpers/tsc.js";
|
||||
import {
|
||||
appendText,
|
||||
loadProjectFromFiles,
|
||||
replaceText,
|
||||
} from "../helpers/vfs.js";
|
||||
import { TestServerHost } from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsbuild:: commandLine::", () => {
|
||||
function scenarioName(text: string, options: ts.CompilerOptions) {
|
||||
@@ -21,7 +17,7 @@ describe("unittests:: tsbuild:: commandLine::", () => {
|
||||
return {
|
||||
caption,
|
||||
edit: ts.noop,
|
||||
commandLineArgs: ["--b", "/src/project", "--verbose", ...options],
|
||||
commandLineArgs: ["--b", "--verbose", ...options],
|
||||
};
|
||||
}
|
||||
function noChangeWithSubscenario(caption: string): TestTscEdit {
|
||||
@@ -48,24 +44,24 @@ describe("unittests:: tsbuild:: commandLine::", () => {
|
||||
function localChange(): TestTscEdit {
|
||||
return {
|
||||
caption: "local change",
|
||||
edit: fs => replaceText(fs, "/src/project/a.ts", "Local = 1", "Local = 10"),
|
||||
edit: sys => sys.replaceFileText("/home/src/workspaces/project/a.ts", "Local = 1", "Local = 10"),
|
||||
};
|
||||
}
|
||||
function fs(options: ts.CompilerOptions) {
|
||||
return loadProjectFromFiles({
|
||||
"/src/project/tsconfig.json": jsonToReadableText({ compilerOptions: compilerOptionsToConfigJson(options) }),
|
||||
"/src/project/a.ts": `export const a = 10;const aLocal = 10;`,
|
||||
"/src/project/b.ts": `export const b = 10;const bLocal = 10;`,
|
||||
"/src/project/c.ts": `import { a } from "./a";export const c = a;`,
|
||||
"/src/project/d.ts": `import { b } from "./b";export const d = b;`,
|
||||
});
|
||||
function sys(options: ts.CompilerOptions) {
|
||||
return TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({ compilerOptions: compilerOptionsToConfigJson(options) }),
|
||||
"/home/src/workspaces/project/a.ts": `export const a = 10;const aLocal = 10;`,
|
||||
"/home/src/workspaces/project/b.ts": `export const b = 10;const bLocal = 10;`,
|
||||
"/home/src/workspaces/project/c.ts": `import { a } from "./a";export const c = a;`,
|
||||
"/home/src/workspaces/project/d.ts": `import { b } from "./b";export const d = b;`,
|
||||
}, { currentDirectory: "/home/src/workspaces/project" });
|
||||
}
|
||||
function verify(options: ts.CompilerOptions) {
|
||||
verifyTsc({
|
||||
scenario: "commandLine",
|
||||
subScenario: scenarioName("different options", options),
|
||||
fs: () => fs({ composite: true, ...options }),
|
||||
commandLineArgs: ["--b", "/src/project", "--verbose"],
|
||||
sys: () => sys({ composite: true, ...options }),
|
||||
commandLineArgs: ["--b", "--verbose"],
|
||||
edits: [
|
||||
withOptionChange("with sourceMap", "--sourceMap"),
|
||||
noChangeWithSubscenario("should re-emit only js so they dont contain sourcemap"),
|
||||
@@ -85,8 +81,8 @@ describe("unittests:: tsbuild:: commandLine::", () => {
|
||||
verifyTsc({
|
||||
scenario: "commandLine",
|
||||
subScenario: scenarioName("different options with incremental", options),
|
||||
fs: () => fs({ incremental: true, ...options }),
|
||||
commandLineArgs: ["--b", "/src/project", "--verbose"],
|
||||
sys: () => sys({ incremental: true, ...options }),
|
||||
commandLineArgs: ["--b", "--verbose"],
|
||||
edits: [
|
||||
withOptionChange("with sourceMap", "--sourceMap"),
|
||||
withOptionChange("should re-emit only js so they dont contain sourcemap"),
|
||||
@@ -109,44 +105,44 @@ describe("unittests:: tsbuild:: commandLine::", () => {
|
||||
verify({ outFile: "../outFile.js", module: ts.ModuleKind.AMD });
|
||||
});
|
||||
describe("emitDeclarationOnly::", () => {
|
||||
function fs(options: ts.CompilerOptions) {
|
||||
return loadProjectFromFiles({
|
||||
"/src/project1/src/tsconfig.json": jsonToReadableText({
|
||||
function sys(options: ts.CompilerOptions) {
|
||||
return TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/solution/project1/src/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: compilerOptionsToConfigJson(options),
|
||||
}),
|
||||
"/src/project1/src/a.ts": `export const a = 10;const aLocal = 10;`,
|
||||
"/src/project1/src/b.ts": `export const b = 10;const bLocal = 10;`,
|
||||
"/src/project1/src/c.ts": `import { a } from "./a";export const c = a;`,
|
||||
"/src/project1/src/d.ts": `import { b } from "./b";export const d = b;`,
|
||||
"/src/project2/src/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/solution/project1/src/a.ts": `export const a = 10;const aLocal = 10;`,
|
||||
"/home/src/workspaces/solution/project1/src/b.ts": `export const b = 10;const bLocal = 10;`,
|
||||
"/home/src/workspaces/solution/project1/src/c.ts": `import { a } from "./a";export const c = a;`,
|
||||
"/home/src/workspaces/solution/project1/src/d.ts": `import { b } from "./b";export const d = b;`,
|
||||
"/home/src/workspaces/solution/project2/src/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: compilerOptionsToConfigJson(options),
|
||||
references: [{ path: "../../project1/src" }],
|
||||
}),
|
||||
"/src/project2/src/e.ts": `export const e = 10;`,
|
||||
"/src/project2/src/f.ts": `import { a } from "${options.outFile ? "a" : "../../project1/src/a"}"; export const f = a;`,
|
||||
"/src/project2/src/g.ts": `import { b } from "${options.outFile ? "b" : "../../project1/src/b"}"; export const g = b;`,
|
||||
});
|
||||
"/home/src/workspaces/solution/project2/src/e.ts": `export const e = 10;`,
|
||||
"/home/src/workspaces/solution/project2/src/f.ts": `import { a } from "${options.outFile ? "a" : "../../project1/src/a"}"; export const f = a;`,
|
||||
"/home/src/workspaces/solution/project2/src/g.ts": `import { b } from "${options.outFile ? "b" : "../../project1/src/b"}"; export const g = b;`,
|
||||
}, { currentDirectory: "/home/src/workspaces/solution" });
|
||||
}
|
||||
function verifyWithIncremental(options: ts.CompilerOptions) {
|
||||
verifyTsc({
|
||||
scenario: "commandLine",
|
||||
subScenario: subScenario("emitDeclarationOnly on commandline"),
|
||||
fs: () => fs(options),
|
||||
commandLineArgs: ["--b", "/src/project2/src", "--verbose", "--emitDeclarationOnly"],
|
||||
sys: () => sys(options),
|
||||
commandLineArgs: ["--b", "project2/src", "--verbose", "--emitDeclarationOnly"],
|
||||
edits: [
|
||||
noChangeRun,
|
||||
{
|
||||
caption: "local change",
|
||||
edit: fs => appendText(fs, "/src/project1/src/a.ts", "const aa = 10;"),
|
||||
edit: sys => sys.appendFile("/home/src/workspaces/solution/project1/src/a.ts", "const aa = 10;"),
|
||||
},
|
||||
{
|
||||
caption: "non local change",
|
||||
edit: fs => appendText(fs, "/src/project1/src/a.ts", "export const aaa = 10;"),
|
||||
edit: sys => sys.appendFile("/home/src/workspaces/solution/project1/src/a.ts", "export const aaa = 10;"),
|
||||
},
|
||||
{
|
||||
caption: "emit js files",
|
||||
edit: ts.noop,
|
||||
commandLineArgs: ["--b", "/src/project2/src", "--verbose"],
|
||||
commandLineArgs: ["--b", "project2/src", "--verbose"],
|
||||
},
|
||||
{
|
||||
...noChangeRun,
|
||||
@@ -157,12 +153,12 @@ describe("unittests:: tsbuild:: commandLine::", () => {
|
||||
},
|
||||
{
|
||||
caption: "js emit with change without emitDeclarationOnly",
|
||||
edit: fs => appendText(fs, "/src/project1/src/b.ts", "const alocal = 10;"),
|
||||
commandLineArgs: ["--b", "/src/project2/src", "--verbose"],
|
||||
edit: sys => sys.appendFile("/home/src/workspaces/solution/project1/src/b.ts", "const alocal = 10;"),
|
||||
commandLineArgs: ["--b", "project2/src", "--verbose"],
|
||||
},
|
||||
{
|
||||
caption: "local change",
|
||||
edit: fs => appendText(fs, "/src/project1/src/b.ts", "const aaaa = 10;"),
|
||||
edit: sys => sys.appendFile("/home/src/workspaces/solution/project1/src/b.ts", "const aaaa = 10;"),
|
||||
discrepancyExplanation: () => [
|
||||
`Clean build tsbuildinfo for project2 will have compilerOptions with composite and emitDeclarationOnly`,
|
||||
`Incremental build will detect that it doesnt need to rebuild project2 so tsbuildinfo for it is from before which has option composite only`,
|
||||
@@ -170,12 +166,12 @@ describe("unittests:: tsbuild:: commandLine::", () => {
|
||||
},
|
||||
{
|
||||
caption: "non local change",
|
||||
edit: fs => appendText(fs, "/src/project1/src/b.ts", "export const aaaaa = 10;"),
|
||||
edit: sys => sys.appendFile("/home/src/workspaces/solution/project1/src/b.ts", "export const aaaaa = 10;"),
|
||||
},
|
||||
{
|
||||
caption: "js emit with change without emitDeclarationOnly",
|
||||
edit: fs => appendText(fs, "/src/project1/src/b.ts", "export const a2 = 10;"),
|
||||
commandLineArgs: ["--b", "/src/project2/src", "--verbose"],
|
||||
edit: sys => sys.appendFile("/home/src/workspaces/solution/project1/src/b.ts", "export const a2 = 10;"),
|
||||
commandLineArgs: ["--b", "project2/src", "--verbose"],
|
||||
},
|
||||
],
|
||||
baselinePrograms: true,
|
||||
@@ -183,18 +179,18 @@ describe("unittests:: tsbuild:: commandLine::", () => {
|
||||
verifyTsc({
|
||||
scenario: "commandLine",
|
||||
subScenario: subScenario("emitDeclarationOnly false on commandline"),
|
||||
fs: () => fs({ ...options, emitDeclarationOnly: true }),
|
||||
commandLineArgs: ["--b", "/src/project2/src", "--verbose"],
|
||||
sys: () => sys({ ...options, emitDeclarationOnly: true }),
|
||||
commandLineArgs: ["--b", "project2/src", "--verbose"],
|
||||
edits: [
|
||||
noChangeRun,
|
||||
{
|
||||
caption: "change",
|
||||
edit: fs => appendText(fs, "/src/project1/src/a.ts", "const aa = 10;"),
|
||||
edit: sys => sys.appendFile("/home/src/workspaces/solution/project1/src/a.ts", "const aa = 10;"),
|
||||
},
|
||||
{
|
||||
caption: "emit js files",
|
||||
edit: ts.noop,
|
||||
commandLineArgs: ["--b", "/src/project2/src", "--verbose", "--emitDeclarationOnly", "false"],
|
||||
commandLineArgs: ["--b", "project2/src", "--verbose", "--emitDeclarationOnly", "false"],
|
||||
},
|
||||
{
|
||||
...noChangeRun,
|
||||
@@ -206,12 +202,12 @@ describe("unittests:: tsbuild:: commandLine::", () => {
|
||||
{
|
||||
caption: "no change run with js emit",
|
||||
edit: ts.noop,
|
||||
commandLineArgs: ["--b", "/src/project2/src", "--verbose", "--emitDeclarationOnly", "false"],
|
||||
commandLineArgs: ["--b", "project2/src", "--verbose", "--emitDeclarationOnly", "false"],
|
||||
},
|
||||
{
|
||||
caption: "js emit with change",
|
||||
edit: fs => appendText(fs, "/src/project1/src/b.ts", "const blocal = 10;"),
|
||||
commandLineArgs: ["--b", "/src/project2/src", "--verbose", "--emitDeclarationOnly", "false"],
|
||||
edit: sys => sys.appendFile("/home/src/workspaces/solution/project1/src/b.ts", "const blocal = 10;"),
|
||||
commandLineArgs: ["--b", "project2/src", "--verbose", "--emitDeclarationOnly", "false"],
|
||||
},
|
||||
],
|
||||
baselinePrograms: true,
|
||||
@@ -229,41 +225,41 @@ describe("unittests:: tsbuild:: commandLine::", () => {
|
||||
verifyTsc({
|
||||
scenario: "commandLine",
|
||||
subScenario: scenarioName("emitDeclarationOnly on commandline with declaration", options),
|
||||
fs: () => fs({ declaration: true, ...options }),
|
||||
commandLineArgs: ["--b", "/src/project2/src", "--verbose", "--emitDeclarationOnly"],
|
||||
sys: () => sys({ declaration: true, ...options }),
|
||||
commandLineArgs: ["--b", "project2/src", "--verbose", "--emitDeclarationOnly"],
|
||||
edits: [
|
||||
noChangeRun,
|
||||
{
|
||||
caption: "local change",
|
||||
edit: fs => appendText(fs, "/src/project1/src/a.ts", "const aa = 10;"),
|
||||
edit: sys => sys.appendFile("/home/src/workspaces/solution/project1/src/a.ts", "const aa = 10;"),
|
||||
},
|
||||
{
|
||||
caption: "non local change",
|
||||
edit: fs => appendText(fs, "/src/project1/src/a.ts", "export const aaa = 10;"),
|
||||
edit: sys => sys.appendFile("/home/src/workspaces/solution/project1/src/a.ts", "export const aaa = 10;"),
|
||||
},
|
||||
{
|
||||
caption: "emit js files",
|
||||
edit: ts.noop,
|
||||
commandLineArgs: ["--b", "/src/project2/src", "--verbose"],
|
||||
commandLineArgs: ["--b", "project2/src", "--verbose"],
|
||||
},
|
||||
noChangeRun,
|
||||
{
|
||||
caption: "js emit with change without emitDeclarationOnly",
|
||||
edit: fs => appendText(fs, "/src/project1/src/b.ts", "const alocal = 10;"),
|
||||
commandLineArgs: ["--b", "/src/project2/src", "--verbose"],
|
||||
edit: sys => sys.appendFile("/home/src/workspaces/solution/project1/src/b.ts", "const alocal = 10;"),
|
||||
commandLineArgs: ["--b", "project2/src", "--verbose"],
|
||||
},
|
||||
{
|
||||
caption: "local change",
|
||||
edit: fs => appendText(fs, "/src/project1/src/b.ts", "const aaaa = 10;"),
|
||||
edit: sys => sys.appendFile("/home/src/workspaces/solution/project1/src/b.ts", "const aaaa = 10;"),
|
||||
},
|
||||
{
|
||||
caption: "non local change",
|
||||
edit: fs => appendText(fs, "/src/project1/src/b.ts", "export const aaaaa = 10;"),
|
||||
edit: sys => sys.appendFile("/home/src/workspaces/solution/project1/src/b.ts", "export const aaaaa = 10;"),
|
||||
},
|
||||
{
|
||||
caption: "js emit with change without emitDeclarationOnly",
|
||||
edit: fs => appendText(fs, "/src/project1/src/b.ts", "export const a2 = 10;"),
|
||||
commandLineArgs: ["--b", "/src/project2/src", "--verbose"],
|
||||
edit: sys => sys.appendFile("/home/src/workspaces/solution/project1/src/b.ts", "export const a2 = 10;"),
|
||||
commandLineArgs: ["--b", "project2/src", "--verbose"],
|
||||
},
|
||||
],
|
||||
baselinePrograms: true,
|
||||
@@ -272,29 +268,29 @@ describe("unittests:: tsbuild:: commandLine::", () => {
|
||||
verifyTsc({
|
||||
scenario: "commandLine",
|
||||
subScenario: scenarioName("emitDeclarationOnly false on commandline with declaration", options),
|
||||
fs: () => fs({ declaration: true, emitDeclarationOnly: true, ...options }),
|
||||
commandLineArgs: ["--b", "/src/project2/src", "--verbose"],
|
||||
sys: () => sys({ declaration: true, emitDeclarationOnly: true, ...options }),
|
||||
commandLineArgs: ["--b", "project2/src", "--verbose"],
|
||||
edits: [
|
||||
noChangeRun,
|
||||
{
|
||||
caption: "change",
|
||||
edit: fs => appendText(fs, "/src/project1/src/a.ts", "const aa = 10;"),
|
||||
edit: sys => sys.appendFile("/home/src/workspaces/solution/project1/src/a.ts", "const aa = 10;"),
|
||||
},
|
||||
{
|
||||
caption: "emit js files",
|
||||
edit: ts.noop,
|
||||
commandLineArgs: ["--b", "/src/project2/src", "--verbose", "--emitDeclarationOnly", "false"],
|
||||
commandLineArgs: ["--b", "project2/src", "--verbose", "--emitDeclarationOnly", "false"],
|
||||
},
|
||||
noChangeRun,
|
||||
{
|
||||
caption: "no change run with js emit",
|
||||
edit: ts.noop,
|
||||
commandLineArgs: ["--b", "/src/project2/src", "--verbose", "--emitDeclarationOnly", "false"],
|
||||
commandLineArgs: ["--b", "project2/src", "--verbose", "--emitDeclarationOnly", "false"],
|
||||
},
|
||||
{
|
||||
caption: "js emit with change",
|
||||
edit: fs => appendText(fs, "/src/project1/src/b.ts", "const blocal = 10;"),
|
||||
commandLineArgs: ["--b", "/src/project2/src", "--verbose", "--emitDeclarationOnly", "false"],
|
||||
edit: sys => sys.appendFile("/home/src/workspaces/solution/project1/src/b.ts", "const blocal = 10;"),
|
||||
commandLineArgs: ["--b", "project2/src", "--verbose", "--emitDeclarationOnly", "false"],
|
||||
},
|
||||
],
|
||||
baselinePrograms: true,
|
||||
|
||||
@@ -4,31 +4,27 @@ import {
|
||||
noChangeRun,
|
||||
verifyTsc,
|
||||
} from "../helpers/tsc.js";
|
||||
import {
|
||||
appendText,
|
||||
loadProjectFromFiles,
|
||||
replaceText,
|
||||
} from "../helpers/vfs.js";
|
||||
import { TestServerHost } from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsbuild:: configFileErrors:: when tsconfig extends the missing file", () => {
|
||||
verifyTsc({
|
||||
scenario: "configFileErrors",
|
||||
subScenario: "when tsconfig extends the missing file",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/tsconfig.first.json": jsonToReadableText({
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/tsconfig.first.json": jsonToReadableText({
|
||||
extends: "./foobar.json",
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
},
|
||||
}),
|
||||
"/src/tsconfig.second.json": jsonToReadableText({
|
||||
"/home/src/workspaces/project/tsconfig.second.json": jsonToReadableText({
|
||||
extends: "./foobar.json",
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
},
|
||||
}),
|
||||
"/src/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
},
|
||||
@@ -37,8 +33,8 @@ describe("unittests:: tsbuild:: configFileErrors:: when tsconfig extends the mis
|
||||
{ path: "./tsconfig.second.json" },
|
||||
],
|
||||
}),
|
||||
}),
|
||||
commandLineArgs: ["--b", "/src/tsconfig.json"],
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
commandLineArgs: ["--b"],
|
||||
});
|
||||
});
|
||||
|
||||
@@ -47,11 +43,11 @@ describe("unittests:: tsbuild:: configFileErrors:: reports syntax errors in conf
|
||||
verifyTsc({
|
||||
scenario: "configFileErrors",
|
||||
subScenario: `${outFile ? "outFile" : "multiFile"}/reports syntax errors in config file`,
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/a.ts": "export function foo() { }",
|
||||
"/src/b.ts": "export function bar() { }",
|
||||
"/src/tsconfig.json": dedent`
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/a.ts": "export function foo() { }",
|
||||
"/home/src/workspaces/project/b.ts": "export function bar() { }",
|
||||
"/home/src/workspaces/project/tsconfig.json": dedent`
|
||||
{
|
||||
"compilerOptions": {
|
||||
"composite": true,${outFile ? jsonToReadableText(outFile).replace(/[{}]/g, "") : ""}
|
||||
@@ -61,14 +57,13 @@ describe("unittests:: tsbuild:: configFileErrors:: reports syntax errors in conf
|
||||
"b.ts"
|
||||
]
|
||||
}`,
|
||||
}),
|
||||
commandLineArgs: ["--b", "/src/tsconfig.json"],
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
commandLineArgs: ["--b"],
|
||||
edits: [
|
||||
{
|
||||
edit: fs =>
|
||||
replaceText(
|
||||
fs,
|
||||
"/src/tsconfig.json",
|
||||
edit: sys =>
|
||||
sys.replaceFileText(
|
||||
"/home/src/workspaces/project/tsconfig.json",
|
||||
",",
|
||||
`,
|
||||
"declaration": true,`,
|
||||
@@ -80,14 +75,14 @@ describe("unittests:: tsbuild:: configFileErrors:: reports syntax errors in conf
|
||||
],
|
||||
},
|
||||
{
|
||||
edit: fs => appendText(fs, "/src/a.ts", "export function fooBar() { }"),
|
||||
edit: sys => sys.appendFile("/home/src/workspaces/project/a.ts", "export function fooBar() { }"),
|
||||
caption: "reports syntax errors after change to ts file",
|
||||
},
|
||||
noChangeRun,
|
||||
{
|
||||
edit: fs =>
|
||||
fs.writeFileSync(
|
||||
"/src/tsconfig.json",
|
||||
edit: sys =>
|
||||
sys.writeFile(
|
||||
"/home/src/workspaces/project/tsconfig.json",
|
||||
jsonToReadableText({
|
||||
compilerOptions: { composite: true, declaration: true, ...outFile },
|
||||
files: ["a.ts", "b.ts"],
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import { verifyTsc } from "../helpers/tsc.js";
|
||||
import { loadProjectFromFiles } from "../helpers/vfs.js";
|
||||
import { TestServerHost } from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsbuild:: configFileExtends:: when tsconfig extends another config", () => {
|
||||
function getConfigExtendsWithIncludeFs() {
|
||||
return loadProjectFromFiles({
|
||||
"/src/tsconfig.json": jsonToReadableText({
|
||||
function getConfigExtendsWithIncludeSys() {
|
||||
return TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/solution/tsconfig.json": jsonToReadableText({
|
||||
references: [
|
||||
{ path: "./shared/tsconfig.json" },
|
||||
{ path: "./webpack/tsconfig.json" },
|
||||
],
|
||||
files: [],
|
||||
}),
|
||||
"/src/shared/tsconfig-base.json": jsonToReadableText({
|
||||
"/home/src/workspaces/solution/shared/tsconfig-base.json": jsonToReadableText({
|
||||
include: ["./typings-base/"],
|
||||
}),
|
||||
"/src/shared/typings-base/globals.d.ts": `type Unrestricted = any;`,
|
||||
"/src/shared/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/solution/shared/typings-base/globals.d.ts": `type Unrestricted = any;`,
|
||||
"/home/src/workspaces/solution/shared/tsconfig.json": jsonToReadableText({
|
||||
extends: "./tsconfig-base.json",
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
@@ -25,8 +25,8 @@ describe("unittests:: tsbuild:: configFileExtends:: when tsconfig extends anothe
|
||||
},
|
||||
files: ["./index.ts"],
|
||||
}),
|
||||
"/src/shared/index.ts": `export const a: Unrestricted = 1;`,
|
||||
"/src/webpack/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/solution/shared/index.ts": `export const a: Unrestricted = 1;`,
|
||||
"/home/src/workspaces/solution/webpack/tsconfig.json": jsonToReadableText({
|
||||
extends: "../shared/tsconfig-base.json",
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
@@ -36,19 +36,19 @@ describe("unittests:: tsbuild:: configFileExtends:: when tsconfig extends anothe
|
||||
files: ["./index.ts"],
|
||||
references: [{ path: "../shared/tsconfig.json" }],
|
||||
}),
|
||||
"/src/webpack/index.ts": `export const b: Unrestricted = 1;`,
|
||||
});
|
||||
"/home/src/workspaces/solution/webpack/index.ts": `export const b: Unrestricted = 1;`,
|
||||
}, { currentDirectory: "/home/src/workspaces/solution" });
|
||||
}
|
||||
verifyTsc({
|
||||
scenario: "configFileExtends",
|
||||
subScenario: "when building solution with projects extends config with include",
|
||||
fs: getConfigExtendsWithIncludeFs,
|
||||
commandLineArgs: ["--b", "/src/tsconfig.json", "--v", "--listFiles"],
|
||||
sys: getConfigExtendsWithIncludeSys,
|
||||
commandLineArgs: ["--b", "--v", "--listFiles"],
|
||||
});
|
||||
verifyTsc({
|
||||
scenario: "configFileExtends",
|
||||
subScenario: "when building project uses reference and both extend config with include",
|
||||
fs: getConfigExtendsWithIncludeFs,
|
||||
commandLineArgs: ["--b", "/src/webpack/tsconfig.json", "--v", "--listFiles"],
|
||||
sys: getConfigExtendsWithIncludeSys,
|
||||
commandLineArgs: ["--b", "webpack/tsconfig.json", "--v", "--listFiles"],
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,32 +3,29 @@ import {
|
||||
noChangeOnlyRuns,
|
||||
verifyTsc,
|
||||
} from "../helpers/tsc.js";
|
||||
import {
|
||||
loadProjectFromFiles,
|
||||
replaceText,
|
||||
} from "../helpers/vfs.js";
|
||||
import { TestServerHost } from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsbuild:: when containerOnly project is referenced", () => {
|
||||
verifyTsc({
|
||||
scenario: "containerOnlyReferenced",
|
||||
subScenario: "verify that subsequent builds after initial build doesnt build anything",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/src/folder/index.ts": `export const x = 10;`,
|
||||
"/src/src/folder/tsconfig.json": jsonToReadableText({
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/solution/src/folder/index.ts": `export const x = 10;`,
|
||||
"/home/src/workspaces/solution/src/folder/tsconfig.json": jsonToReadableText({
|
||||
files: ["index.ts"],
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
},
|
||||
}),
|
||||
"/src/src/folder2/index.ts": `export const x = 10;`,
|
||||
"/src/src/folder2/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/solution/src/folder2/index.ts": `export const x = 10;`,
|
||||
"/home/src/workspaces/solution/src/folder2/tsconfig.json": jsonToReadableText({
|
||||
files: ["index.ts"],
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
},
|
||||
}),
|
||||
"/src/src/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/solution/src/tsconfig.json": jsonToReadableText({
|
||||
files: [],
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
@@ -38,8 +35,8 @@ describe("unittests:: tsbuild:: when containerOnly project is referenced", () =>
|
||||
{ path: "./folder2" },
|
||||
],
|
||||
}),
|
||||
"/src/tests/index.ts": `export const x = 10;`,
|
||||
"/src/tests/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/solution/tests/index.ts": `export const x = 10;`,
|
||||
"/home/src/workspaces/solution/tests/tsconfig.json": jsonToReadableText({
|
||||
files: ["index.ts"],
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
@@ -48,7 +45,7 @@ describe("unittests:: tsbuild:: when containerOnly project is referenced", () =>
|
||||
{ path: "../src" },
|
||||
],
|
||||
}),
|
||||
"/src/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/solution/tsconfig.json": jsonToReadableText({
|
||||
files: [],
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
@@ -58,40 +55,40 @@ describe("unittests:: tsbuild:: when containerOnly project is referenced", () =>
|
||||
{ path: "./tests" },
|
||||
],
|
||||
}),
|
||||
}),
|
||||
commandLineArgs: ["--b", "/src", "--verbose"],
|
||||
}, { currentDirectory: "/home/src/workspaces/solution" }),
|
||||
commandLineArgs: ["--b", "--verbose"],
|
||||
edits: noChangeOnlyRuns,
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "containerOnlyReferenced",
|
||||
subScenario: "when solution is referenced indirectly",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/project1/tsconfig.json": jsonToReadableText({
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/solution/project1/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: { composite: true },
|
||||
references: [],
|
||||
}),
|
||||
"/src/project2/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/solution/project2/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: { composite: true },
|
||||
references: [],
|
||||
}),
|
||||
"/src/project2/src/b.ts": "export const b = 10;",
|
||||
"/src/project3/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/solution/project2/src/b.ts": "export const b = 10;",
|
||||
"/home/src/workspaces/solution/project3/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: { composite: true },
|
||||
references: [{ path: "../project1" }, { path: "../project2" }],
|
||||
}),
|
||||
"/src/project3/src/c.ts": "export const c = 10;",
|
||||
"/src/project4/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/solution/project3/src/c.ts": "export const c = 10;",
|
||||
"/home/src/workspaces/solution/project4/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: { composite: true },
|
||||
references: [{ path: "../project3" }],
|
||||
}),
|
||||
"/src/project4/src/d.ts": "export const d = 10;",
|
||||
}),
|
||||
commandLineArgs: ["--b", "/src/project4", "--verbose", "--explainFiles"],
|
||||
"/home/src/workspaces/solution/project4/src/d.ts": "export const d = 10;",
|
||||
}, { currentDirectory: "/home/src/workspaces/solution" }),
|
||||
commandLineArgs: ["--b", "project4", "--verbose", "--explainFiles"],
|
||||
edits: [{
|
||||
caption: "modify project3 file",
|
||||
edit: fs => replaceText(fs, "/src/project3/src/c.ts", "c = ", "cc = "),
|
||||
edit: sys => sys.replaceFileText("/home/src/workspaces/solution/project3/src/c.ts", "c = ", "cc = "),
|
||||
}],
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,48 +1,50 @@
|
||||
import { dedent } from "../../_namespaces/Utils.js";
|
||||
import { FileSet } from "../../_namespaces/vfs.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import { forEachDeclarationEmitWithErrorsScenario } from "../helpers/declarationEmit.js";
|
||||
import {
|
||||
noChangeOnlyRuns,
|
||||
verifyTsc,
|
||||
} from "../helpers/tsc.js";
|
||||
import { loadProjectFromFiles } from "../helpers/vfs.js";
|
||||
import {
|
||||
FileOrFolderOrSymLinkMap,
|
||||
TestServerHost,
|
||||
} from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsbuild:: declarationEmit", () => {
|
||||
function getFiles(): FileSet {
|
||||
return {
|
||||
"/src/solution/tsconfig.base.json": jsonToReadableText({
|
||||
describe("unittests:: tsbuild:: declarationEmit::", () => {
|
||||
function sys(additionalFiles?: FileOrFolderOrSymLinkMap) {
|
||||
return TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/solution/tsconfig.base.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
rootDir: "./",
|
||||
outDir: "lib",
|
||||
},
|
||||
}),
|
||||
"/src/solution/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/solution/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: { composite: true },
|
||||
references: [{ path: "./src" }],
|
||||
include: [],
|
||||
}),
|
||||
"/src/solution/src/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/solution/src/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: { composite: true },
|
||||
references: [{ path: "./subProject" }, { path: "./subProject2" }],
|
||||
include: [],
|
||||
}),
|
||||
"/src/solution/src/subProject/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/solution/src/subProject/tsconfig.json": jsonToReadableText({
|
||||
extends: "../../tsconfig.base.json",
|
||||
compilerOptions: { composite: true },
|
||||
references: [{ path: "../common" }],
|
||||
include: ["./index.ts"],
|
||||
}),
|
||||
"/src/solution/src/subProject/index.ts": dedent`
|
||||
"/home/src/workspaces/solution/src/subProject/index.ts": dedent`
|
||||
import { Nominal } from '../common/nominal';
|
||||
export type MyNominal = Nominal<string, 'MyNominal'>;`,
|
||||
"/src/solution/src/subProject2/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/solution/src/subProject2/tsconfig.json": jsonToReadableText({
|
||||
extends: "../../tsconfig.base.json",
|
||||
compilerOptions: { composite: true },
|
||||
references: [{ path: "../subProject" }],
|
||||
include: ["./index.ts"],
|
||||
}),
|
||||
"/src/solution/src/subProject2/index.ts": dedent`
|
||||
"/home/src/workspaces/solution/src/subProject2/index.ts": dedent`
|
||||
import { MyNominal } from '../subProject/index';
|
||||
const variable = {
|
||||
key: 'value' as MyNominal,
|
||||
@@ -50,89 +52,89 @@ const variable = {
|
||||
export function getVar(): keyof typeof variable {
|
||||
return 'key';
|
||||
}`,
|
||||
"/src/solution/src/common/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/solution/src/common/tsconfig.json": jsonToReadableText({
|
||||
extends: "../../tsconfig.base.json",
|
||||
compilerOptions: { composite: true },
|
||||
include: ["./nominal.ts"],
|
||||
}),
|
||||
"/src/solution/src/common/nominal.ts": dedent`
|
||||
"/home/src/workspaces/solution/src/common/nominal.ts": dedent`
|
||||
/// <reference path="./types.d.ts" preserve="true" />
|
||||
export declare type Nominal<T, Name extends string> = MyNominal<T, Name>;`,
|
||||
"/src/solution/src/common/types.d.ts": dedent`
|
||||
"/home/src/workspaces/solution/src/common/types.d.ts": dedent`
|
||||
declare type MyNominal<T, Name extends string> = T & {
|
||||
specialKey: Name;
|
||||
};`,
|
||||
};
|
||||
...additionalFiles,
|
||||
}, { currentDirectory: "/home/src/workspaces/solution" });
|
||||
}
|
||||
verifyTsc({
|
||||
scenario: "declarationEmit",
|
||||
subScenario: "when declaration file is referenced through triple slash",
|
||||
fs: () => loadProjectFromFiles(getFiles()),
|
||||
commandLineArgs: ["--b", "/src/solution/tsconfig.json", "--verbose"],
|
||||
sys,
|
||||
commandLineArgs: ["--b", "--verbose"],
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "declarationEmit",
|
||||
subScenario: "when declaration file is referenced through triple slash but uses no references",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
...getFiles(),
|
||||
"/src/solution/tsconfig.json": jsonToReadableText({
|
||||
sys: () =>
|
||||
sys({
|
||||
"/home/src/workspaces/solution/tsconfig.json": jsonToReadableText({
|
||||
extends: "./tsconfig.base.json",
|
||||
compilerOptions: { composite: true },
|
||||
include: ["./src/**/*.ts"],
|
||||
}),
|
||||
}),
|
||||
commandLineArgs: ["--b", "/src/solution/tsconfig.json", "--verbose"],
|
||||
commandLineArgs: ["--b", "--verbose"],
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "declarationEmit",
|
||||
subScenario: "when declaration file used inferred type from referenced project",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/tsconfig.json": jsonToReadableText({
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
baseUrl: ".",
|
||||
paths: { "@fluentui/*": ["packages/*/src"] },
|
||||
},
|
||||
}),
|
||||
"/src/packages/pkg1/src/index.ts": dedent`
|
||||
"/home/src/workspaces/project/packages/pkg1/src/index.ts": dedent`
|
||||
export interface IThing {
|
||||
a: string;
|
||||
}
|
||||
export interface IThings {
|
||||
thing1: IThing;
|
||||
}`,
|
||||
"/src/packages/pkg1/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/project/packages/pkg1/tsconfig.json": jsonToReadableText({
|
||||
extends: "../../tsconfig",
|
||||
compilerOptions: { outDir: "lib" },
|
||||
include: ["src"],
|
||||
}),
|
||||
"/src/packages/pkg2/src/index.ts": dedent`
|
||||
"/home/src/workspaces/project/packages/pkg2/src/index.ts": dedent`
|
||||
import { IThings } from '@fluentui/pkg1';
|
||||
export function fn4() {
|
||||
const a: IThings = { thing1: { a: 'b' } };
|
||||
return a.thing1;
|
||||
}`,
|
||||
"/src/packages/pkg2/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/project/packages/pkg2/tsconfig.json": jsonToReadableText({
|
||||
extends: "../../tsconfig",
|
||||
compilerOptions: { outDir: "lib" },
|
||||
include: ["src"],
|
||||
references: [{ path: "../pkg1" }],
|
||||
}),
|
||||
}),
|
||||
commandLineArgs: ["--b", "/src/packages/pkg2/tsconfig.json", "--verbose"],
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
commandLineArgs: ["--b", "packages/pkg2/tsconfig.json", "--verbose"],
|
||||
});
|
||||
|
||||
forEachDeclarationEmitWithErrorsScenario(
|
||||
(scenario, fs) => {
|
||||
(scenario, sys) => {
|
||||
verifyTsc({
|
||||
scenario: "declarationEmit",
|
||||
subScenario: scenario("reports dts generation errors"),
|
||||
commandLineArgs: ["-b", `/src/project`, "--explainFiles", "--listEmittedFiles", "--v"],
|
||||
fs,
|
||||
commandLineArgs: ["-b", "--explainFiles", "--listEmittedFiles", "--v"],
|
||||
sys,
|
||||
edits: noChangeOnlyRuns,
|
||||
});
|
||||
},
|
||||
|
||||
@@ -1,35 +1,24 @@
|
||||
import * as vfs from "../../_namespaces/vfs.js";
|
||||
import {
|
||||
getFsContentsForDemoProjectReferencesCoreConfig,
|
||||
getFsForDemoProjectReferences,
|
||||
getSysForDemoProjectReferences,
|
||||
} from "../helpers/demoProjectReferences.js";
|
||||
import { verifyTsc } from "../helpers/tsc.js";
|
||||
import { prependText } from "../helpers/vfs.js";
|
||||
|
||||
describe("unittests:: tsbuild:: on demo project", () => {
|
||||
let projFs: vfs.FileSystem;
|
||||
before(() => {
|
||||
projFs = getFsForDemoProjectReferences();
|
||||
});
|
||||
|
||||
after(() => {
|
||||
projFs = undefined!; // Release the contents
|
||||
});
|
||||
|
||||
describe("unittests:: tsbuild:: on demo:: project", () => {
|
||||
verifyTsc({
|
||||
scenario: "demo",
|
||||
subScenario: "in master branch with everything setup correctly and reports no error",
|
||||
fs: () => projFs,
|
||||
sys: getSysForDemoProjectReferences,
|
||||
commandLineArgs: ["--b", "--verbose"],
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "demo",
|
||||
subScenario: "in circular branch reports the error about it by stopping build",
|
||||
fs: () => projFs,
|
||||
sys: getSysForDemoProjectReferences,
|
||||
commandLineArgs: ["--b", "--verbose"],
|
||||
modifyFs: fs =>
|
||||
fs.writeFileSync(
|
||||
modifySystem: sys =>
|
||||
sys.writeFile(
|
||||
"core/tsconfig.json",
|
||||
getFsContentsForDemoProjectReferencesCoreConfig({
|
||||
references: [{
|
||||
@@ -41,11 +30,10 @@ describe("unittests:: tsbuild:: on demo project", () => {
|
||||
verifyTsc({
|
||||
scenario: "demo",
|
||||
subScenario: "in bad-ref branch reports the error about files not in rootDir at the import location",
|
||||
fs: () => projFs,
|
||||
sys: getSysForDemoProjectReferences,
|
||||
commandLineArgs: ["--b", "--verbose"],
|
||||
modifyFs: fs =>
|
||||
prependText(
|
||||
fs,
|
||||
modifySystem: sys =>
|
||||
sys.prependFile(
|
||||
"core/utilities.ts",
|
||||
`import * as A from '../animals';
|
||||
`,
|
||||
|
||||
@@ -1,43 +1,38 @@
|
||||
import { dedent } from "../../_namespaces/Utils.js";
|
||||
import * as vfs from "../../_namespaces/vfs.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import { verifyTsc } from "../helpers/tsc.js";
|
||||
import {
|
||||
loadProjectFromFiles,
|
||||
replaceText,
|
||||
} from "../helpers/vfs.js";
|
||||
import { TestServerHost } from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsbuild:: on project with emitDeclarationOnly set to true", () => {
|
||||
let projFs: vfs.FileSystem;
|
||||
before(() => {
|
||||
projFs = loadProjectFromFiles({
|
||||
"/src/src/a.ts": dedent`
|
||||
describe("unittests:: tsbuild:: on project with emitDeclarationOnly:: set to true", () => {
|
||||
function getEmitDeclarationOnlySys() {
|
||||
return TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/src/a.ts": dedent`
|
||||
import { B } from "./b";
|
||||
|
||||
export interface A {
|
||||
b: B;
|
||||
}
|
||||
`,
|
||||
"/src/src/b.ts": dedent`
|
||||
"/home/src/workspaces/project/src/b.ts": dedent`
|
||||
import { C } from "./c";
|
||||
|
||||
export interface B {
|
||||
b: C;
|
||||
}
|
||||
`,
|
||||
"/src/src/c.ts": dedent`
|
||||
"/home/src/workspaces/project/src/c.ts": dedent`
|
||||
import { A } from "./a";
|
||||
|
||||
export interface C {
|
||||
a: A;
|
||||
}
|
||||
`,
|
||||
"/src/src/index.ts": dedent`
|
||||
"/home/src/workspaces/project/src/index.ts": dedent`
|
||||
export { A } from "./a";
|
||||
export { B } from "./b";
|
||||
export { C } from "./c";
|
||||
`,
|
||||
"/src/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
incremental: true,
|
||||
target: "es5",
|
||||
@@ -54,24 +49,21 @@ describe("unittests:: tsbuild:: on project with emitDeclarationOnly set to true"
|
||||
emitDeclarationOnly: true,
|
||||
},
|
||||
}),
|
||||
});
|
||||
});
|
||||
after(() => {
|
||||
projFs = undefined!;
|
||||
});
|
||||
}, { currentDirectory: "/home/src/workspaces/project" });
|
||||
}
|
||||
|
||||
function verifyEmitDeclarationOnly(disableMap?: true) {
|
||||
verifyTsc({
|
||||
subScenario: `only dts output in circular import project with emitDeclarationOnly${disableMap ? "" : " and declarationMap"}`,
|
||||
fs: () => projFs,
|
||||
sys: getEmitDeclarationOnlySys,
|
||||
scenario: "emitDeclarationOnly",
|
||||
commandLineArgs: ["--b", "/src", "--verbose"],
|
||||
modifyFs: disableMap ?
|
||||
(fs => replaceText(fs, "/src/tsconfig.json", `"declarationMap": true,`, "")) :
|
||||
commandLineArgs: ["--b", "--verbose"],
|
||||
modifySystem: disableMap ?
|
||||
(sys => sys.replaceFileText("/home/src/workspaces/project/tsconfig.json", `"declarationMap": true,`, "")) :
|
||||
undefined,
|
||||
edits: [{
|
||||
caption: "incremental-declaration-changes",
|
||||
edit: fs => replaceText(fs, "/src/src/a.ts", "b: B;", "b: B; foo: any;"),
|
||||
edit: sys => sys.replaceFileText("/home/src/workspaces/project/src/a.ts", "b: B;", "b: B; foo: any;"),
|
||||
}],
|
||||
});
|
||||
}
|
||||
@@ -80,20 +72,19 @@ describe("unittests:: tsbuild:: on project with emitDeclarationOnly set to true"
|
||||
|
||||
verifyTsc({
|
||||
subScenario: `only dts output in non circular imports project with emitDeclarationOnly`,
|
||||
fs: () => projFs,
|
||||
sys: getEmitDeclarationOnlySys,
|
||||
scenario: "emitDeclarationOnly",
|
||||
commandLineArgs: ["--b", "/src", "--verbose"],
|
||||
modifyFs: fs => {
|
||||
fs.rimrafSync("/src/src/index.ts");
|
||||
replaceText(fs, "/src/src/a.ts", `import { B } from "./b";`, `export class B { prop = "hello"; }`);
|
||||
commandLineArgs: ["--b", "--verbose"],
|
||||
modifySystem: sys => {
|
||||
sys.rimrafSync("/home/src/workspaces/project/src/index.ts");
|
||||
sys.replaceFileText("/home/src/workspaces/project/src/a.ts", `import { B } from "./b";`, `export class B { prop = "hello"; }`);
|
||||
},
|
||||
edits: [
|
||||
{
|
||||
caption: "incremental-declaration-doesnt-change",
|
||||
edit: fs =>
|
||||
replaceText(
|
||||
fs,
|
||||
"/src/src/a.ts",
|
||||
edit: sys =>
|
||||
sys.replaceFileText(
|
||||
"/home/src/workspaces/project/src/a.ts",
|
||||
"export interface A {",
|
||||
`class C { }
|
||||
export interface A {`,
|
||||
@@ -101,7 +92,7 @@ export interface A {`,
|
||||
},
|
||||
{
|
||||
caption: "incremental-declaration-changes",
|
||||
edit: fs => replaceText(fs, "/src/src/a.ts", "b: B;", "b: B; foo: any;"),
|
||||
edit: sys => sys.replaceFileText("/home/src/workspaces/project/src/a.ts", "b: B;", "b: B; foo: any;"),
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import { verifyTsc } from "../helpers/tsc.js";
|
||||
import { loadProjectFromFiles } from "../helpers/vfs.js";
|
||||
import { TestServerHost } from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsbuild - empty files option in tsconfig", () => {
|
||||
describe("unittests:: tsbuild:: emptyFiles:: option in tsconfig", () => {
|
||||
verifyTsc({
|
||||
scenario: "emptyFiles",
|
||||
subScenario: "has empty files diagnostic when files is empty and no references are provided",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/no-references/tsconfig.json": jsonToReadableText({
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/solution/no-references/tsconfig.json": jsonToReadableText({
|
||||
references: [],
|
||||
files: [],
|
||||
compilerOptions: {
|
||||
@@ -18,17 +18,17 @@ describe("unittests:: tsbuild - empty files option in tsconfig", () => {
|
||||
skipDefaultLibCheck: true,
|
||||
},
|
||||
}),
|
||||
}),
|
||||
commandLineArgs: ["--b", "/src/no-references"],
|
||||
}, { currentDirectory: "/home/src/workspaces/solution" }),
|
||||
commandLineArgs: ["--b", "no-references"],
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "emptyFiles",
|
||||
subScenario: "does not have empty files diagnostic when files is empty and references are provided",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/core/index.ts": "export function multiply(a: number, b: number) { return a * b; }",
|
||||
"/src/core/tsconfig.json": jsonToReadableText({
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/solution/core/index.ts": "export function multiply(a: number, b: number) { return a * b; }",
|
||||
"/home/src/workspaces/solution/core/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
declaration: true,
|
||||
@@ -36,7 +36,7 @@ describe("unittests:: tsbuild - empty files option in tsconfig", () => {
|
||||
skipDefaultLibCheck: true,
|
||||
},
|
||||
}),
|
||||
"/src/with-references/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/solution/with-references/tsconfig.json": jsonToReadableText({
|
||||
references: [
|
||||
{ path: "../core" },
|
||||
],
|
||||
@@ -48,7 +48,7 @@ describe("unittests:: tsbuild - empty files option in tsconfig", () => {
|
||||
skipDefaultLibCheck: true,
|
||||
},
|
||||
}),
|
||||
}),
|
||||
commandLineArgs: ["--b", "/src/with-references"],
|
||||
}, { currentDirectory: "/home/src/workspaces/solution" }),
|
||||
commandLineArgs: ["--b", "with-references"],
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import { emptyArray } from "../../_namespaces/ts.js";
|
||||
import { verifyTsc } from "../helpers/tsc.js";
|
||||
import { loadProjectFromFiles } from "../helpers/vfs.js";
|
||||
import { TestServerHost } from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
// https://github.com/microsoft/TypeScript/issues/33849
|
||||
describe("unittests:: tsbuild:: exitCodeOnBogusFile:: test exit code", () => {
|
||||
verifyTsc({
|
||||
scenario: "exitCodeOnBogusFile",
|
||||
subScenario: `test exit code`,
|
||||
fs: () => loadProjectFromFiles({}),
|
||||
sys: () => TestServerHost.createWatchedSystem(emptyArray, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
commandLineArgs: ["-b", "bogus.json"],
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,11 +3,9 @@ import {
|
||||
getSymlinkedExtendsSys,
|
||||
} from "../helpers/extends.js";
|
||||
import { verifyTsc } from "../helpers/tsc.js";
|
||||
import { verifyTscWatch } from "../helpers/tscWatch.js";
|
||||
import { loadProjectFromFiles } from "../helpers/vfs.js";
|
||||
|
||||
describe("unittests:: tsbuild:: extends::", () => {
|
||||
verifyTscWatch({
|
||||
verifyTsc({
|
||||
scenario: "extends",
|
||||
subScenario: "resolves the symlink path",
|
||||
sys: getSymlinkedExtendsSys,
|
||||
@@ -17,7 +15,7 @@ describe("unittests:: tsbuild:: extends::", () => {
|
||||
verifyTsc({
|
||||
scenario: "extends",
|
||||
subScenario: "configDir template",
|
||||
fs: () => loadProjectFromFiles(getConfigDirExtendsSys(), { cwd: "/home/src/projects/myproject" }),
|
||||
commandLineArgs: ["-b", "/home/src/projects/myproject", "--explainFiles", "--v"],
|
||||
sys: getConfigDirExtendsSys,
|
||||
commandLineArgs: ["-b", "--explainFiles", "--v"],
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,50 +3,50 @@ import { dedent } from "../../_namespaces/Utils.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import { compilerOptionsToConfigJson } from "../helpers/contents.js";
|
||||
import { verifyTsc } from "../helpers/tsc.js";
|
||||
import { loadProjectFromFiles } from "../helpers/vfs.js";
|
||||
import { TestServerHost } from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsbuild:: fileDelete::", () => {
|
||||
function fs(childOptions: ts.CompilerOptions, mainOptions?: ts.CompilerOptions) {
|
||||
return loadProjectFromFiles({
|
||||
"/src/child/child.ts": dedent`
|
||||
function sys(childOptions: ts.CompilerOptions, mainOptions?: ts.CompilerOptions) {
|
||||
return TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/solution/child/child.ts": dedent`
|
||||
import { child2 } from "../child/child2";
|
||||
export function child() {
|
||||
child2();
|
||||
}
|
||||
`,
|
||||
"/src/child/child2.ts": dedent`
|
||||
"/home/src/workspaces/solution/child/child2.ts": dedent`
|
||||
export function child2() {
|
||||
}
|
||||
`,
|
||||
"/src/child/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/solution/child/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: compilerOptionsToConfigJson(childOptions),
|
||||
}),
|
||||
...(mainOptions ? {
|
||||
"/src/main/main.ts": dedent`
|
||||
"/home/src/workspaces/solution/main/main.ts": dedent`
|
||||
import { child } from "${childOptions.outFile ? "child" : "../child/child"}";
|
||||
export function main() {
|
||||
child();
|
||||
}
|
||||
`,
|
||||
"/src/main/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/solution/main/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: compilerOptionsToConfigJson(mainOptions),
|
||||
references: [{ path: "../child" }],
|
||||
}),
|
||||
} : {}),
|
||||
});
|
||||
}, { currentDirectory: "/home/src/workspaces/solution" });
|
||||
}
|
||||
|
||||
verifyTsc({
|
||||
scenario: "fileDelete",
|
||||
subScenario: `multiFile/detects deleted file`,
|
||||
commandLineArgs: ["--b", "/src/main/tsconfig.json", "-v", "--traceResolution", "--explainFiles"],
|
||||
fs: () => fs({ composite: true }, { composite: true }),
|
||||
commandLineArgs: ["--b", "main/tsconfig.json", "-v", "--traceResolution", "--explainFiles"],
|
||||
sys: () => sys({ composite: true }, { composite: true }),
|
||||
edits: [{
|
||||
caption: "delete child2 file",
|
||||
edit: fs => {
|
||||
fs.rimrafSync("/src/child/child2.ts");
|
||||
fs.rimrafSync("/src/child/child2.js");
|
||||
fs.rimrafSync("/src/child/child2.d.ts");
|
||||
edit: sys => {
|
||||
sys.rimrafSync("/home/src/workspaces/solution/child/child2.ts");
|
||||
sys.rimrafSync("/home/src/workspaces/solution/child/child2.js");
|
||||
sys.rimrafSync("/home/src/workspaces/solution/child/child2.d.ts");
|
||||
},
|
||||
}],
|
||||
});
|
||||
@@ -54,24 +54,24 @@ describe("unittests:: tsbuild:: fileDelete::", () => {
|
||||
verifyTsc({
|
||||
scenario: "fileDelete",
|
||||
subScenario: `outFile/detects deleted file`,
|
||||
commandLineArgs: ["--b", "/src/main/tsconfig.json", "-v", "--traceResolution", "--explainFiles"],
|
||||
fs: () => fs({ composite: true, outFile: "../childResult.js", module: ts.ModuleKind.AMD }, { composite: true, outFile: "../mainResult.js", module: ts.ModuleKind.AMD }),
|
||||
commandLineArgs: ["--b", "main/tsconfig.json", "-v", "--traceResolution", "--explainFiles"],
|
||||
sys: () => sys({ composite: true, outFile: "../childResult.js", module: ts.ModuleKind.AMD }, { composite: true, outFile: "../mainResult.js", module: ts.ModuleKind.AMD }),
|
||||
edits: [{
|
||||
caption: "delete child2 file",
|
||||
edit: fs => fs.rimrafSync("/src/child/child2.ts"),
|
||||
edit: sys => sys.rimrafSync("/home/src/workspaces/solution/child/child2.ts"),
|
||||
}],
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "fileDelete",
|
||||
subScenario: `multiFile/deleted file without composite`,
|
||||
commandLineArgs: ["--b", "/src/child/tsconfig.json", "-v", "--traceResolution", "--explainFiles"],
|
||||
fs: () => fs({}),
|
||||
commandLineArgs: ["--b", "child/tsconfig.json", "-v", "--traceResolution", "--explainFiles"],
|
||||
sys: () => sys({}),
|
||||
edits: [{
|
||||
caption: "delete child2 file",
|
||||
edit: fs => {
|
||||
fs.rimrafSync("/src/child/child2.ts");
|
||||
fs.rimrafSync("/src/child/child2.js");
|
||||
edit: sys => {
|
||||
sys.rimrafSync("/home/src/workspaces/solution/child/child2.ts");
|
||||
sys.rimrafSync("/home/src/workspaces/solution/child/child2.js");
|
||||
},
|
||||
}],
|
||||
});
|
||||
@@ -79,11 +79,11 @@ describe("unittests:: tsbuild:: fileDelete::", () => {
|
||||
verifyTsc({
|
||||
scenario: "fileDelete",
|
||||
subScenario: `outFile/deleted file without composite`,
|
||||
commandLineArgs: ["--b", "/src/child/tsconfig.json", "-v", "--traceResolution", "--explainFiles"],
|
||||
fs: () => fs({ outFile: "../childResult.js", module: ts.ModuleKind.AMD }),
|
||||
commandLineArgs: ["--b", "child/tsconfig.json", "-v", "--traceResolution", "--explainFiles"],
|
||||
sys: () => sys({ outFile: "../childResult.js", module: ts.ModuleKind.AMD }),
|
||||
edits: [{
|
||||
caption: "delete child2 file",
|
||||
edit: fs => fs.rimrafSync("/src/child/child2.ts"),
|
||||
edit: sys => sys.rimrafSync("/home/src/workspaces/solution/child/child2.ts"),
|
||||
}],
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import * as fakes from "../../_namespaces/fakes.js";
|
||||
import * as ts from "../../_namespaces/ts.js";
|
||||
import * as vfs from "../../_namespaces/vfs.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import { TestServerHost } from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsbuild - graph-ordering", () => {
|
||||
let host: fakes.SolutionBuilderHost | undefined;
|
||||
describe("unittests:: tsbuild:: graphOrdering::", () => {
|
||||
let host: ts.SolutionBuilderHost<ts.EmitAndSemanticDiagnosticsBuilderProgram> | undefined;
|
||||
const deps: [string, string][] = [
|
||||
["A", "B"],
|
||||
["B", "C"],
|
||||
@@ -20,9 +19,12 @@ describe("unittests:: tsbuild - graph-ordering", () => {
|
||||
];
|
||||
|
||||
before(() => {
|
||||
const fs = new vfs.FileSystem(/*ignoreCase*/ false);
|
||||
host = fakes.SolutionBuilderHost.create(fs);
|
||||
writeProjects(fs, ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J"], deps);
|
||||
const sys = TestServerHost.createWatchedSystem(ts.emptyArray, {
|
||||
useCaseSensitiveFileNames: true,
|
||||
currentDirectory: "/home/src/workspaces/project",
|
||||
});
|
||||
host = ts.createSolutionBuilderHost(sys);
|
||||
writeProjects(sys, ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J"], deps);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
@@ -68,25 +70,25 @@ describe("unittests:: tsbuild - graph-ordering", () => {
|
||||
}
|
||||
|
||||
function getProjectFileName(proj: string) {
|
||||
return `/project/${proj}/tsconfig.json` as ts.ResolvedConfigFileName;
|
||||
return `/home/src/workspaces/project/${proj}/tsconfig.json` as ts.ResolvedConfigFileName;
|
||||
}
|
||||
|
||||
function writeProjects(fileSystem: vfs.FileSystem, projectNames: string[], deps: [string, string][]): string[] {
|
||||
function writeProjects(sys: TestServerHost, projectNames: string[], deps: [string, string][]): string[] {
|
||||
const projFileNames: string[] = [];
|
||||
for (const dep of deps) {
|
||||
if (!projectNames.includes(dep[0])) throw new Error(`Invalid dependency - project ${dep[0]} does not exist`);
|
||||
if (!projectNames.includes(dep[1])) throw new Error(`Invalid dependency - project ${dep[1]} does not exist`);
|
||||
}
|
||||
for (const proj of projectNames) {
|
||||
fileSystem.mkdirpSync(`/project/${proj}`);
|
||||
fileSystem.writeFileSync(`/project/${proj}/${proj}.ts`, "export {}");
|
||||
sys.ensureFileOrFolder({ path: `/home/src/workspaces/project/${proj}` });
|
||||
sys.writeFile(`/home/src/workspaces/project/${proj}/${proj}.ts`, "export {}");
|
||||
const configFileName = getProjectFileName(proj);
|
||||
const configContent = jsonToReadableText({
|
||||
compilerOptions: { composite: true },
|
||||
files: [`./${proj}.ts`],
|
||||
references: deps.filter(d => d[0] === proj).map(d => ({ path: `../${d[1]}` })),
|
||||
});
|
||||
fileSystem.writeFileSync(configFileName, configContent);
|
||||
sys.writeFile(configFileName, configContent);
|
||||
projFileNames.push(configFileName);
|
||||
}
|
||||
return projFileNames;
|
||||
|
||||
@@ -1,18 +1,12 @@
|
||||
import { dedent } from "../../_namespaces/Utils.js";
|
||||
import * as vfs from "../../_namespaces/vfs.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import { verifyTsc } from "../helpers/tsc.js";
|
||||
import {
|
||||
appendText,
|
||||
loadProjectFromFiles,
|
||||
replaceText,
|
||||
} from "../helpers/vfs.js";
|
||||
import { TestServerHost } from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsbuild:: inferredTypeFromTransitiveModule::", () => {
|
||||
let projFs: vfs.FileSystem;
|
||||
before(() => {
|
||||
projFs = loadProjectFromFiles({
|
||||
"/src/bar.ts": dedent`
|
||||
function getInferredTypeFromTransitiveModuleSys() {
|
||||
return TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/bar.ts": dedent`
|
||||
interface RawAction {
|
||||
(...args: any[]): Promise<any> | void;
|
||||
}
|
||||
@@ -23,7 +17,7 @@ describe("unittests:: tsbuild:: inferredTypeFromTransitiveModule::", () => {
|
||||
export default foo()(function foobar(param: string): void {
|
||||
});
|
||||
`,
|
||||
"/src/bundling.ts": dedent`
|
||||
"/home/src/workspaces/project/bundling.ts": dedent`
|
||||
export class LazyModule<TModule> {
|
||||
constructor(private importCallback: () => Promise<TModule>) {}
|
||||
}
|
||||
@@ -36,7 +30,7 @@ describe("unittests:: tsbuild:: inferredTypeFromTransitiveModule::", () => {
|
||||
}
|
||||
}
|
||||
`,
|
||||
"/src/global.d.ts": dedent`
|
||||
"/home/src/workspaces/project/global.d.ts": dedent`
|
||||
interface PromiseConstructor {
|
||||
new <T>(): Promise<T>;
|
||||
}
|
||||
@@ -44,17 +38,17 @@ describe("unittests:: tsbuild:: inferredTypeFromTransitiveModule::", () => {
|
||||
interface Promise<T> {
|
||||
}
|
||||
`,
|
||||
"/src/index.ts": dedent`
|
||||
"/home/src/workspaces/project/index.ts": dedent`
|
||||
import { LazyAction, LazyModule } from './bundling';
|
||||
const lazyModule = new LazyModule(() =>
|
||||
import('./lazyIndex')
|
||||
);
|
||||
export const lazyBar = new LazyAction(lazyModule, m => m.bar);
|
||||
`,
|
||||
"/src/lazyIndex.ts": dedent`
|
||||
"/home/src/workspaces/project/lazyIndex.ts": dedent`
|
||||
export { default as bar } from './bar';
|
||||
`,
|
||||
"/src/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
target: "es5",
|
||||
declaration: true,
|
||||
@@ -62,17 +56,14 @@ describe("unittests:: tsbuild:: inferredTypeFromTransitiveModule::", () => {
|
||||
incremental: true,
|
||||
},
|
||||
}),
|
||||
});
|
||||
});
|
||||
after(() => {
|
||||
projFs = undefined!;
|
||||
});
|
||||
}, { currentDirectory: "/home/src/workspaces/project" });
|
||||
}
|
||||
|
||||
verifyTsc({
|
||||
scenario: "inferredTypeFromTransitiveModule",
|
||||
subScenario: "inferred type from transitive module",
|
||||
fs: () => projFs,
|
||||
commandLineArgs: ["--b", "/src", "--verbose"],
|
||||
sys: getInferredTypeFromTransitiveModuleSys,
|
||||
commandLineArgs: ["--b", "--verbose"],
|
||||
edits: [
|
||||
{
|
||||
caption: "incremental-declaration-changes",
|
||||
@@ -87,10 +78,10 @@ describe("unittests:: tsbuild:: inferredTypeFromTransitiveModule::", () => {
|
||||
|
||||
verifyTsc({
|
||||
subScenario: "inferred type from transitive module with isolatedModules",
|
||||
fs: () => projFs,
|
||||
sys: getInferredTypeFromTransitiveModuleSys,
|
||||
scenario: "inferredTypeFromTransitiveModule",
|
||||
commandLineArgs: ["--b", "/src", "--verbose"],
|
||||
modifyFs: changeToIsolatedModules,
|
||||
commandLineArgs: ["--b", "--verbose"],
|
||||
modifySystem: changeToIsolatedModules,
|
||||
edits: [
|
||||
{
|
||||
caption: "incremental-declaration-changes",
|
||||
@@ -106,13 +97,12 @@ describe("unittests:: tsbuild:: inferredTypeFromTransitiveModule::", () => {
|
||||
verifyTsc({
|
||||
scenario: "inferredTypeFromTransitiveModule",
|
||||
subScenario: "reports errors in files affected by change in signature with isolatedModules",
|
||||
fs: () => projFs,
|
||||
commandLineArgs: ["--b", "/src", "--verbose"],
|
||||
modifyFs: fs => {
|
||||
changeToIsolatedModules(fs);
|
||||
appendText(
|
||||
fs,
|
||||
"/src/lazyIndex.ts",
|
||||
sys: getInferredTypeFromTransitiveModuleSys,
|
||||
commandLineArgs: ["--b", "--verbose"],
|
||||
modifySystem: sys => {
|
||||
changeToIsolatedModules(sys);
|
||||
sys.appendFile(
|
||||
"/home/src/workspaces/project/lazyIndex.ts",
|
||||
`
|
||||
import { default as bar } from './bar';
|
||||
bar("hello");`,
|
||||
@@ -133,20 +123,20 @@ bar("hello");`,
|
||||
},
|
||||
{
|
||||
caption: "Fix Error",
|
||||
edit: fs => replaceText(fs, "/src/lazyIndex.ts", `bar("hello")`, "bar()"),
|
||||
edit: sys => sys.replaceFileText("/home/src/workspaces/project/lazyIndex.ts", `bar("hello")`, "bar()"),
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
function changeToIsolatedModules(fs: vfs.FileSystem) {
|
||||
replaceText(fs, "/src/tsconfig.json", `"incremental": true`, `"incremental": true, "isolatedModules": true`);
|
||||
function changeToIsolatedModules(sys: TestServerHost) {
|
||||
sys.replaceFileText("/home/src/workspaces/project/tsconfig.json", `"incremental": true`, `"incremental": true, "isolatedModules": true`);
|
||||
}
|
||||
|
||||
function changeBarParam(fs: vfs.FileSystem) {
|
||||
replaceText(fs, "/src/bar.ts", "param: string", "");
|
||||
function changeBarParam(sys: TestServerHost) {
|
||||
sys.replaceFileText("/home/src/workspaces/project/bar.ts", "param: string", "");
|
||||
}
|
||||
|
||||
function changeBarParamBack(fs: vfs.FileSystem) {
|
||||
replaceText(fs, "/src/bar.ts", "foobar()", "foobar(param: string)");
|
||||
function changeBarParamBack(sys: TestServerHost) {
|
||||
sys.replaceFileText("/home/src/workspaces/project/bar.ts", "foobar()", "foobar(param: string)");
|
||||
}
|
||||
|
||||
@@ -1,48 +1,50 @@
|
||||
import * as Utils from "../../_namespaces/Utils.js";
|
||||
import { dedent } from "../../_namespaces/Utils.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import { symbolLibContent } from "../helpers/contents.js";
|
||||
import { verifyTsc } from "../helpers/tsc.js";
|
||||
import { loadProjectFromFiles } from "../helpers/vfs.js";
|
||||
import {
|
||||
libFile,
|
||||
TestServerHost,
|
||||
} from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsbuild:: javascriptProjectEmit::", () => {
|
||||
verifyTsc({
|
||||
scenario: "javascriptProjectEmit",
|
||||
subScenario: `loads js-based projects and emits them correctly`,
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/common/nominal.js": Utils.dedent`
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/solution/common/nominal.js": dedent`
|
||||
/**
|
||||
* @template T, Name
|
||||
* @typedef {T & {[Symbol.species]: Name}} Nominal
|
||||
*/
|
||||
module.exports = {};
|
||||
`,
|
||||
"/src/common/tsconfig.json": Utils.dedent`
|
||||
{
|
||||
"extends": "../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"composite": true
|
||||
},
|
||||
"include": ["nominal.js"]
|
||||
}`,
|
||||
"/src/sub-project/index.js": Utils.dedent`
|
||||
"/home/src/workspaces/solution/common/tsconfig.json": jsonToReadableText({
|
||||
extends: "../tsconfig.base.json",
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
},
|
||||
include: ["nominal.js"],
|
||||
}),
|
||||
"/home/src/workspaces/solution/sub-project/index.js": dedent`
|
||||
import { Nominal } from '../common/nominal';
|
||||
|
||||
/**
|
||||
* @typedef {Nominal<string, 'MyNominal'>} MyNominal
|
||||
*/
|
||||
`,
|
||||
"/src/sub-project/tsconfig.json": Utils.dedent`
|
||||
{
|
||||
"extends": "../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"composite": true
|
||||
},
|
||||
"references": [
|
||||
{ "path": "../common" }
|
||||
],
|
||||
"include": ["./index.js"]
|
||||
}`,
|
||||
"/src/sub-project-2/index.js": Utils.dedent`
|
||||
"/home/src/workspaces/solution/sub-project/tsconfig.json": jsonToReadableText({
|
||||
extends: "../tsconfig.base.json",
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
},
|
||||
references: [
|
||||
{ path: "../common" },
|
||||
],
|
||||
include: ["./index.js"],
|
||||
}),
|
||||
"/home/src/workspaces/solution/sub-project-2/index.js": dedent`
|
||||
import { MyNominal } from '../sub-project/index';
|
||||
|
||||
const variable = {
|
||||
@@ -56,82 +58,77 @@ describe("unittests:: tsbuild:: javascriptProjectEmit::", () => {
|
||||
return 'key';
|
||||
}
|
||||
`,
|
||||
"/src/sub-project-2/tsconfig.json": Utils.dedent`
|
||||
{
|
||||
"extends": "../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"composite": true
|
||||
},
|
||||
"references": [
|
||||
{ "path": "../sub-project" }
|
||||
],
|
||||
"include": ["./index.js"]
|
||||
}`,
|
||||
"/src/tsconfig.json": Utils.dedent`
|
||||
{
|
||||
"compilerOptions": {
|
||||
"composite": true
|
||||
},
|
||||
"references": [
|
||||
{ "path": "./sub-project" },
|
||||
{ "path": "./sub-project-2" }
|
||||
],
|
||||
"include": []
|
||||
}`,
|
||||
"/src/tsconfig.base.json": Utils.dedent`
|
||||
{
|
||||
"compilerOptions": {
|
||||
"skipLibCheck": true,
|
||||
"rootDir": "./",
|
||||
"outDir": "../lib",
|
||||
"allowJs": true,
|
||||
"checkJs": true,
|
||||
"declaration": true
|
||||
}
|
||||
}`,
|
||||
}, symbolLibContent),
|
||||
commandLineArgs: ["-b", "/src"],
|
||||
"/home/src/workspaces/solution/sub-project-2/tsconfig.json": jsonToReadableText({
|
||||
extends: "../tsconfig.base.json",
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
},
|
||||
references: [
|
||||
{ path: "../sub-project" },
|
||||
],
|
||||
include: ["./index.js"],
|
||||
}),
|
||||
"/home/src/workspaces/solution/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
},
|
||||
references: [
|
||||
{ path: "./sub-project" },
|
||||
{ path: "./sub-project-2" },
|
||||
],
|
||||
include: [],
|
||||
}),
|
||||
"/home/src/workspaces/solution/tsconfig.base.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
skipLibCheck: true,
|
||||
rootDir: "./",
|
||||
outDir: "../lib",
|
||||
allowJs: true,
|
||||
checkJs: true,
|
||||
declaration: true,
|
||||
},
|
||||
}),
|
||||
[libFile.path]: `${libFile.content}${symbolLibContent}`,
|
||||
}, { currentDirectory: "/home/src/workspaces/solution" }),
|
||||
commandLineArgs: ["-b"],
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "javascriptProjectEmit",
|
||||
subScenario: `loads js-based projects with non-moved json files and emits them correctly`,
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/common/obj.json": Utils.dedent`
|
||||
{
|
||||
"val": 42
|
||||
}`,
|
||||
"/src/common/index.ts": Utils.dedent`
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/solution/common/obj.json": jsonToReadableText({
|
||||
val: 42,
|
||||
}),
|
||||
"/home/src/workspaces/solution/common/index.ts": dedent`
|
||||
import x = require("./obj.json");
|
||||
export = x;
|
||||
`,
|
||||
"/src/common/tsconfig.json": Utils.dedent`
|
||||
{
|
||||
"extends": "../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": null,
|
||||
"composite": true
|
||||
},
|
||||
"include": ["index.ts", "obj.json"]
|
||||
}`,
|
||||
"/src/sub-project/index.js": Utils.dedent`
|
||||
`,
|
||||
"/home/src/workspaces/solution/common/tsconfig.json": jsonToReadableText({
|
||||
extends: "../tsconfig.base.json",
|
||||
compilerOptions: {
|
||||
outDir: null, // eslint-disable-line no-restricted-syntax
|
||||
composite: true,
|
||||
},
|
||||
include: ["index.ts", "obj.json"],
|
||||
}),
|
||||
"/home/src/workspaces/solution/sub-project/index.js": dedent`
|
||||
import mod from '../common';
|
||||
|
||||
export const m = mod;
|
||||
`,
|
||||
"/src/sub-project/tsconfig.json": Utils.dedent`
|
||||
{
|
||||
"extends": "../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"composite": true
|
||||
},
|
||||
"references": [
|
||||
{ "path": "../common" }
|
||||
],
|
||||
"include": ["./index.js"]
|
||||
}`,
|
||||
"/src/sub-project-2/index.js": Utils.dedent`
|
||||
"/home/src/workspaces/solution/sub-project/tsconfig.json": jsonToReadableText({
|
||||
extends: "../tsconfig.base.json",
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
},
|
||||
references: [
|
||||
{ path: "../common" },
|
||||
],
|
||||
include: ["./index.js"],
|
||||
}),
|
||||
"/home/src/workspaces/solution/sub-project-2/index.js": dedent`
|
||||
import { m } from '../sub-project/index';
|
||||
|
||||
const variable = {
|
||||
@@ -142,42 +139,40 @@ describe("unittests:: tsbuild:: javascriptProjectEmit::", () => {
|
||||
return variable;
|
||||
}
|
||||
`,
|
||||
"/src/sub-project-2/tsconfig.json": Utils.dedent`
|
||||
{
|
||||
"extends": "../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"composite": true
|
||||
},
|
||||
"references": [
|
||||
{ "path": "../sub-project" }
|
||||
],
|
||||
"include": ["./index.js"]
|
||||
}`,
|
||||
"/src/tsconfig.json": Utils.dedent`
|
||||
{
|
||||
"compilerOptions": {
|
||||
"composite": true
|
||||
},
|
||||
"references": [
|
||||
{ "path": "./sub-project" },
|
||||
{ "path": "./sub-project-2" }
|
||||
],
|
||||
"include": []
|
||||
}`,
|
||||
"/src/tsconfig.base.json": Utils.dedent`
|
||||
{
|
||||
"compilerOptions": {
|
||||
"skipLibCheck": true,
|
||||
"rootDir": "./",
|
||||
"outDir": "../out",
|
||||
"allowJs": true,
|
||||
"checkJs": true,
|
||||
"resolveJsonModule": true,
|
||||
"esModuleInterop": true,
|
||||
"declaration": true
|
||||
}
|
||||
}`,
|
||||
}, symbolLibContent),
|
||||
commandLineArgs: ["-b", "/src"],
|
||||
"/home/src/workspaces/solution/sub-project-2/tsconfig.json": jsonToReadableText({
|
||||
extends: "../tsconfig.base.json",
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
},
|
||||
references: [
|
||||
{ path: "../sub-project" },
|
||||
],
|
||||
include: ["./index.js"],
|
||||
}),
|
||||
"/home/src/workspaces/solution/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
},
|
||||
references: [
|
||||
{ path: "./sub-project" },
|
||||
{ path: "./sub-project-2" },
|
||||
],
|
||||
include: [],
|
||||
}),
|
||||
"/home/src/workspaces/solution/tsconfig.base.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
skipLibCheck: true,
|
||||
rootDir: "./",
|
||||
outDir: "../out",
|
||||
allowJs: true,
|
||||
checkJs: true,
|
||||
resolveJsonModule: true,
|
||||
esModuleInterop: true,
|
||||
declaration: true,
|
||||
},
|
||||
}),
|
||||
[libFile.path]: `${libFile.content}${symbolLibContent}`,
|
||||
}, { currentDirectory: "/home/src/workspaces/solution" }),
|
||||
commandLineArgs: ["-b"],
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,54 +1,50 @@
|
||||
import { dedent } from "../../_namespaces/Utils.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import { verifyTsc } from "../helpers/tsc.js";
|
||||
import {
|
||||
appendText,
|
||||
loadProjectFromFiles,
|
||||
replaceText,
|
||||
} from "../helpers/vfs.js";
|
||||
import { TestServerHost } from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsbuild:: lateBoundSymbol:: interface is merged and contains late bound member", () => {
|
||||
verifyTsc({
|
||||
subScenario: "interface is merged and contains late bound member",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/src/globals.d.ts": dedent`
|
||||
interface SymbolConstructor {
|
||||
(description?: string | number): symbol;
|
||||
}
|
||||
declare var Symbol: SymbolConstructor;
|
||||
`,
|
||||
"/src/src/hkt.ts": `export interface HKT<T> { }`,
|
||||
"/src/src/main.ts": dedent`
|
||||
import { HKT } from "./hkt";
|
||||
|
||||
const sym = Symbol();
|
||||
|
||||
declare module "./hkt" {
|
||||
interface HKT<T> {
|
||||
[sym]: { a: T }
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/src/globals.d.ts": dedent`
|
||||
interface SymbolConstructor {
|
||||
(description?: string | number): symbol;
|
||||
}
|
||||
}
|
||||
const x = 10;
|
||||
type A = HKT<number>[typeof sym];
|
||||
`,
|
||||
"/src/tsconfig.json": jsonToReadableText({
|
||||
declare var Symbol: SymbolConstructor;
|
||||
`,
|
||||
"/home/src/workspaces/project/src/hkt.ts": `export interface HKT<T> { }`,
|
||||
"/home/src/workspaces/project/src/main.ts": dedent`
|
||||
import { HKT } from "./hkt";
|
||||
|
||||
const sym = Symbol();
|
||||
|
||||
declare module "./hkt" {
|
||||
interface HKT<T> {
|
||||
[sym]: { a: T }
|
||||
}
|
||||
}
|
||||
const x = 10;
|
||||
type A = HKT<number>[typeof sym];
|
||||
`,
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
rootDir: "src",
|
||||
incremental: true,
|
||||
},
|
||||
}),
|
||||
}),
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
scenario: "lateBoundSymbol",
|
||||
commandLineArgs: ["--b", "/src/tsconfig.json", "--verbose"],
|
||||
commandLineArgs: ["--b", "--verbose"],
|
||||
edits: [
|
||||
{
|
||||
caption: "incremental-declaration-doesnt-change",
|
||||
edit: fs => replaceText(fs, "/src/src/main.ts", "const x = 10;", ""),
|
||||
edit: sys => sys.replaceFileText("/home/src/workspaces/project/src/main.ts", "const x = 10;", ""),
|
||||
},
|
||||
{
|
||||
caption: "incremental-declaration-doesnt-change",
|
||||
edit: fs => appendText(fs, "/src/src/main.ts", "const x = 10;"),
|
||||
edit: sys => sys.appendFile("/home/src/workspaces/project/src/main.ts", "const x = 10;"),
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
import { getFsForLibResolution } from "../helpers/libraryResolution.js";
|
||||
import { forEachLibResolutionScenario } from "../helpers/libraryResolution.js";
|
||||
import { verifyTsc } from "../helpers/tsc.js";
|
||||
|
||||
describe("unittests:: tsbuild:: libraryResolution:: library file resolution", () => {
|
||||
function verify(libRedirection?: true) {
|
||||
verifyTsc({
|
||||
scenario: "libraryResolution",
|
||||
subScenario: `with config${libRedirection ? " with redirection" : ""}`,
|
||||
fs: () => getFsForLibResolution(libRedirection),
|
||||
commandLineArgs: ["-b", "project1", "project2", "project3", "project4", "--verbose", "--explainFiles"],
|
||||
baselinePrograms: true,
|
||||
});
|
||||
}
|
||||
verify();
|
||||
verify(/*libRedirection*/ true);
|
||||
forEachLibResolutionScenario(
|
||||
/*forTsserver*/ false,
|
||||
/*withoutConfig*/ undefined,
|
||||
(subScenario, sys) =>
|
||||
verifyTsc({
|
||||
scenario: "libraryResolution",
|
||||
subScenario,
|
||||
sys,
|
||||
commandLineArgs: ["-b", "project1", "project2", "project3", "project4", "--verbose", "--explainFiles"],
|
||||
baselinePrograms: true,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1,24 +1,18 @@
|
||||
import * as ts from "../../_namespaces/ts.js";
|
||||
import * as Utils from "../../_namespaces/Utils.js";
|
||||
import { Symlink } from "../../_namespaces/vfs.js";
|
||||
import { dedent } from "../../_namespaces/Utils.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import {
|
||||
noChangeOnlyRuns,
|
||||
verifyTsc,
|
||||
} from "../helpers/tsc.js";
|
||||
import { verifyTscWatch } from "../helpers/tscWatch.js";
|
||||
import { loadProjectFromFiles } from "../helpers/vfs.js";
|
||||
import {
|
||||
createWatchedSystem,
|
||||
libFile,
|
||||
} from "../helpers/virtualFileSystemWithWatch.js";
|
||||
import { TestServerHost } from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsbuild:: moduleResolution:: handles the modules and options from referenced project correctly", () => {
|
||||
function sys(optionsToExtend?: ts.CompilerOptions) {
|
||||
return createWatchedSystem([
|
||||
return TestServerHost.createWatchedSystem([
|
||||
{
|
||||
path: `/user/username/projects/myproject/packages/pkg1/index.ts`,
|
||||
content: Utils.dedent`
|
||||
content: dedent`
|
||||
import type { TheNum } from 'pkg2'
|
||||
export const theNum: TheNum = 42;`,
|
||||
},
|
||||
@@ -60,18 +54,17 @@ describe("unittests:: tsbuild:: moduleResolution:: handles the modules and optio
|
||||
path: `/user/username/projects/myproject/node_modules/pkg2`,
|
||||
symLink: `/user/username/projects/myproject/packages/pkg2`,
|
||||
},
|
||||
libFile,
|
||||
], { currentDirectory: "/user/username/projects/myproject" });
|
||||
}
|
||||
|
||||
verifyTscWatch({
|
||||
verifyTsc({
|
||||
scenario: "moduleResolution",
|
||||
subScenario: `resolves specifier in output declaration file from referenced project correctly`,
|
||||
sys,
|
||||
commandLineArgs: ["-b", "packages/pkg1", "--verbose", "--traceResolution"],
|
||||
});
|
||||
|
||||
verifyTscWatch({
|
||||
verifyTsc({
|
||||
scenario: "moduleResolution",
|
||||
subScenario: `resolves specifier in output declaration file from referenced project correctly with preserveSymlinks`,
|
||||
sys: () => sys({ preserveSymlinks: true }),
|
||||
@@ -81,22 +74,22 @@ describe("unittests:: tsbuild:: moduleResolution:: handles the modules and optio
|
||||
verifyTsc({
|
||||
scenario: "moduleResolution",
|
||||
subScenario: `type reference resolution uses correct options for different resolution options referenced project`,
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/packages/pkg1_index.ts": `export const theNum: TheNum = "type1";`,
|
||||
"/src/packages/pkg1.tsconfig.json": jsonToReadableText({
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/packages/pkg1_index.ts": `export const theNum: TheNum = "type1";`,
|
||||
"/home/src/workspaces/project/packages/pkg1.tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: { composite: true, typeRoots: ["./typeroot1"] },
|
||||
files: ["./pkg1_index.ts"],
|
||||
}),
|
||||
"/src/packages/typeroot1/sometype/index.d.ts": Utils.dedent`declare type TheNum = "type1";`,
|
||||
"/src/packages/pkg2_index.ts": `export const theNum: TheNum2 = "type2";`,
|
||||
"/src/packages/pkg2.tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/project/packages/typeroot1/sometype/index.d.ts": dedent`declare type TheNum = "type1";`,
|
||||
"/home/src/workspaces/project/packages/pkg2_index.ts": `export const theNum: TheNum2 = "type2";`,
|
||||
"/home/src/workspaces/project/packages/pkg2.tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: { composite: true, typeRoots: ["./typeroot2"] },
|
||||
files: ["./pkg2_index.ts"],
|
||||
}),
|
||||
"/src/packages/typeroot2/sometype/index.d.ts": Utils.dedent`declare type TheNum2 = "type2";`,
|
||||
}),
|
||||
commandLineArgs: ["-b", "/src/packages/pkg1.tsconfig.json", "/src/packages/pkg2.tsconfig.json", "--verbose", "--traceResolution"],
|
||||
"/home/src/workspaces/project/packages/typeroot2/sometype/index.d.ts": dedent`declare type TheNum2 = "type2";`,
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
commandLineArgs: ["-b", "packages/pkg1.tsconfig.json", "packages/pkg2.tsconfig.json", "--verbose", "--traceResolution"],
|
||||
});
|
||||
});
|
||||
|
||||
@@ -104,41 +97,40 @@ describe("unittests:: tsbuild:: moduleResolution:: impliedNodeFormat differs bet
|
||||
verifyTsc({
|
||||
scenario: "moduleResolution",
|
||||
subScenario: "impliedNodeFormat differs between projects for shared file",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/projects/a/src/index.ts": "",
|
||||
"/src/projects/a/tsconfig.json": jsonToReadableText({
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/a/src/index.ts": "",
|
||||
"/home/src/workspaces/project/a/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: { strict: true },
|
||||
}),
|
||||
"/src/projects/b/src/index.ts": Utils.dedent`
|
||||
"/home/src/workspaces/project/b/src/index.ts": dedent`
|
||||
import pg from "pg";
|
||||
pg.foo();
|
||||
`,
|
||||
"/src/projects/b/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/project/b/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: { strict: true, module: "node16" },
|
||||
}),
|
||||
"/src/projects/b/package.json": jsonToReadableText({
|
||||
"/home/src/workspaces/project/b/package.json": jsonToReadableText({
|
||||
name: "b",
|
||||
type: "module",
|
||||
}),
|
||||
"/src/projects/node_modules/@types/pg/index.d.ts": "export function foo(): void;",
|
||||
"/src/projects/node_modules/@types/pg/package.json": jsonToReadableText({
|
||||
"/home/src/workspaces/project/node_modules/@types/pg/index.d.ts": "export function foo(): void;",
|
||||
"/home/src/workspaces/project/node_modules/@types/pg/package.json": jsonToReadableText({
|
||||
name: "@types/pg",
|
||||
types: "index.d.ts",
|
||||
}),
|
||||
}),
|
||||
modifyFs: fs => fs.writeFileSync("/lib/lib.es2022.full.d.ts", libFile.content),
|
||||
commandLineArgs: ["-b", "/src/projects/a", "/src/projects/b", "--verbose", "--traceResolution", "--explainFiles"],
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
commandLineArgs: ["-b", "a", "b", "--verbose", "--traceResolution", "--explainFiles"],
|
||||
edits: noChangeOnlyRuns,
|
||||
});
|
||||
});
|
||||
|
||||
describe("unittests:: tsbuild:: moduleResolution:: resolution sharing", () => {
|
||||
function fs() {
|
||||
return loadProjectFromFiles({
|
||||
"/src/projects/project/packages/a/index.js": `export const a = 'a';`,
|
||||
"/src/projects/project/packages/a/test/index.js": `import 'a';`,
|
||||
"/src/projects/project/packages/a/tsconfig.json": jsonToReadableText({
|
||||
function sys() {
|
||||
return TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/packages/a/index.js": `export const a = 'a';`,
|
||||
"/home/src/workspaces/project/packages/a/test/index.js": `import 'a';`,
|
||||
"/home/src/workspaces/project/packages/a/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
checkJs: true,
|
||||
composite: true,
|
||||
@@ -148,7 +140,7 @@ describe("unittests:: tsbuild:: moduleResolution:: resolution sharing", () => {
|
||||
outDir: "types",
|
||||
},
|
||||
}),
|
||||
"/src/projects/project/packages/a/package.json": jsonToReadableText({
|
||||
"/home/src/workspaces/project/packages/a/package.json": jsonToReadableText({
|
||||
name: "a",
|
||||
version: "0.0.0",
|
||||
type: "module",
|
||||
@@ -159,8 +151,8 @@ describe("unittests:: tsbuild:: moduleResolution:: resolution sharing", () => {
|
||||
},
|
||||
},
|
||||
}),
|
||||
"/src/projects/project/packages/b/index.js": `export { a } from 'a';`,
|
||||
"/src/projects/project/packages/b/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/project/packages/b/index.js": `export { a } from 'a';`,
|
||||
"/home/src/workspaces/project/packages/b/tsconfig.json": jsonToReadableText({
|
||||
references: [{ path: "../a" }],
|
||||
compilerOptions: {
|
||||
checkJs: true,
|
||||
@@ -169,27 +161,26 @@ describe("unittests:: tsbuild:: moduleResolution:: resolution sharing", () => {
|
||||
noImplicitAny: true,
|
||||
},
|
||||
}),
|
||||
"/src/projects/project/packages/b/package.json": jsonToReadableText({
|
||||
"/home/src/workspaces/project/packages/b/package.json": jsonToReadableText({
|
||||
name: "b",
|
||||
version: "0.0.0",
|
||||
type: "module",
|
||||
}),
|
||||
"/src/projects/project/node_modules/a": new Symlink("/src/projects/project/packages/a"),
|
||||
"/lib/lib.esnext.full.d.ts": libFile.content,
|
||||
}, { cwd: "/src/projects/project" });
|
||||
"/home/src/workspaces/project/node_modules/a": { symLink: "/home/src/workspaces/project/packages/a" },
|
||||
}, { currentDirectory: "/home/src/workspaces/project" });
|
||||
}
|
||||
|
||||
verifyTsc({
|
||||
scenario: "moduleResolution",
|
||||
subScenario: "shared resolution should not report error",
|
||||
fs,
|
||||
sys,
|
||||
commandLineArgs: ["-b", "packages/b", "--verbose", "--traceResolution", "--explainFiles"],
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "moduleResolution",
|
||||
subScenario: "when resolution is not shared",
|
||||
fs,
|
||||
sys,
|
||||
commandLineArgs: ["-b", "packages/a", "--verbose", "--traceResolution", "--explainFiles"],
|
||||
edits: [{
|
||||
caption: "build b",
|
||||
|
||||
@@ -1,46 +1,47 @@
|
||||
import * as Utils from "../../_namespaces/Utils.js";
|
||||
import { dedent } from "../../_namespaces/Utils.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import { symbolLibContent } from "../helpers/contents.js";
|
||||
import { verifyTsc } from "../helpers/tsc.js";
|
||||
import { loadProjectFromFiles } from "../helpers/vfs.js";
|
||||
import { libFile } from "../helpers/virtualFileSystemWithWatch.js";
|
||||
import {
|
||||
libFile,
|
||||
TestServerHost,
|
||||
} from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
// https://github.com/microsoft/TypeScript/issues/31696
|
||||
describe("unittests:: tsbuild:: moduleSpecifiers:: synthesized module specifiers to referenced projects resolve correctly", () => {
|
||||
verifyTsc({
|
||||
scenario: "moduleSpecifiers",
|
||||
subScenario: `synthesized module specifiers resolve correctly`,
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/solution/common/nominal.ts": Utils.dedent`
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/packages/solution/common/nominal.ts": dedent`
|
||||
export declare type Nominal<T, Name extends string> = T & {
|
||||
[Symbol.species]: Name;
|
||||
};
|
||||
`,
|
||||
"/src/solution/common/tsconfig.json": Utils.dedent`
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"composite": true
|
||||
},
|
||||
"include": ["nominal.ts"]
|
||||
}`,
|
||||
"/src/solution/sub-project/index.ts": Utils.dedent`
|
||||
"/home/src/workspaces/packages/solution/common/tsconfig.json": jsonToReadableText({
|
||||
extends: "../../tsconfig.base.json",
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
},
|
||||
include: ["nominal.ts"],
|
||||
}),
|
||||
"/home/src/workspaces/packages/solution/sub-project/index.ts": dedent`
|
||||
import { Nominal } from '../common/nominal';
|
||||
|
||||
export type MyNominal = Nominal<string, 'MyNominal'>;
|
||||
`,
|
||||
"/src/solution/sub-project/tsconfig.json": Utils.dedent`
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"composite": true
|
||||
},
|
||||
"references": [
|
||||
{ "path": "../common" }
|
||||
],
|
||||
"include": ["./index.ts"]
|
||||
}`,
|
||||
"/src/solution/sub-project-2/index.ts": Utils.dedent`
|
||||
"/home/src/workspaces/packages/solution/sub-project/tsconfig.json": jsonToReadableText({
|
||||
extends: "../../tsconfig.base.json",
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
},
|
||||
references: [
|
||||
{ path: "../common" },
|
||||
],
|
||||
include: ["./index.ts"],
|
||||
}),
|
||||
"/home/src/workspaces/packages/solution/sub-project-2/index.ts": dedent`
|
||||
import { MyNominal } from '../sub-project/index';
|
||||
|
||||
const variable = {
|
||||
@@ -51,47 +52,45 @@ describe("unittests:: tsbuild:: moduleSpecifiers:: synthesized module specifiers
|
||||
return 'key';
|
||||
}
|
||||
`,
|
||||
"/src/solution/sub-project-2/tsconfig.json": Utils.dedent`
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"composite": true
|
||||
},
|
||||
"references": [
|
||||
{ "path": "../sub-project" }
|
||||
],
|
||||
"include": ["./index.ts"]
|
||||
}`,
|
||||
"/src/solution/tsconfig.json": Utils.dedent`
|
||||
{
|
||||
"compilerOptions": {
|
||||
"composite": true
|
||||
},
|
||||
"references": [
|
||||
{ "path": "./sub-project" },
|
||||
{ "path": "./sub-project-2" }
|
||||
],
|
||||
"include": []
|
||||
}`,
|
||||
"/src/tsconfig.base.json": Utils.dedent`
|
||||
{
|
||||
"compilerOptions": {
|
||||
"skipLibCheck": true,
|
||||
"rootDir": "./",
|
||||
"outDir": "lib",
|
||||
}
|
||||
}`,
|
||||
"/src/tsconfig.json": Utils.dedent`{
|
||||
"compilerOptions": {
|
||||
"composite": true
|
||||
"/home/src/workspaces/packages/solution/sub-project-2/tsconfig.json": jsonToReadableText({
|
||||
extends: "../../tsconfig.base.json",
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
},
|
||||
"references": [
|
||||
{ "path": "./solution" }
|
||||
references: [
|
||||
{ path: "../sub-project" },
|
||||
],
|
||||
"include": []
|
||||
}`,
|
||||
}, symbolLibContent),
|
||||
commandLineArgs: ["-b", "/src", "--verbose"],
|
||||
include: ["./index.ts"],
|
||||
}),
|
||||
"/home/src/workspaces/packages/solution/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
},
|
||||
references: [
|
||||
{ path: "./sub-project" },
|
||||
{ path: "./sub-project-2" },
|
||||
],
|
||||
include: [],
|
||||
}),
|
||||
"/home/src/workspaces/packages/tsconfig.base.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
skipLibCheck: true,
|
||||
rootDir: "./",
|
||||
outDir: "lib",
|
||||
},
|
||||
}),
|
||||
"/home/src/workspaces/packages/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
},
|
||||
references: [
|
||||
{ path: "./solution" },
|
||||
],
|
||||
include: [],
|
||||
}),
|
||||
[libFile.path]: `${libFile.content}${symbolLibContent}`,
|
||||
}, { currentDirectory: "/home/src/workspaces/packages" }),
|
||||
commandLineArgs: ["-b", "--verbose"],
|
||||
});
|
||||
});
|
||||
|
||||
@@ -100,26 +99,26 @@ describe("unittests:: tsbuild:: moduleSpecifiers:: synthesized module specifiers
|
||||
verifyTsc({
|
||||
scenario: "moduleSpecifiers",
|
||||
subScenario: `synthesized module specifiers across projects resolve correctly`,
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/src-types/index.ts": Utils.dedent`
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/packages/src-types/index.ts": dedent`
|
||||
export * from './dogconfig.js';`,
|
||||
"/src/src-types/dogconfig.ts": Utils.dedent`
|
||||
"/home/src/workspaces/packages/src-types/dogconfig.ts": dedent`
|
||||
export interface DogConfig {
|
||||
name: string;
|
||||
}`,
|
||||
"/src/src-dogs/index.ts": Utils.dedent`
|
||||
"/home/src/workspaces/packages/src-dogs/index.ts": dedent`
|
||||
export * from 'src-types';
|
||||
export * from './lassie/lassiedog.js';
|
||||
`,
|
||||
"/src/src-dogs/dogconfig.ts": Utils.dedent`
|
||||
"/home/src/workspaces/packages/src-dogs/dogconfig.ts": dedent`
|
||||
import { DogConfig } from 'src-types';
|
||||
|
||||
export const DOG_CONFIG: DogConfig = {
|
||||
name: 'Default dog',
|
||||
};
|
||||
`,
|
||||
"/src/src-dogs/dog.ts": Utils.dedent`
|
||||
"/home/src/workspaces/packages/src-dogs/dog.ts": dedent`
|
||||
import { DogConfig } from 'src-types';
|
||||
import { DOG_CONFIG } from './dogconfig.js';
|
||||
|
||||
@@ -130,7 +129,7 @@ describe("unittests:: tsbuild:: moduleSpecifiers:: synthesized module specifiers
|
||||
}
|
||||
}
|
||||
`,
|
||||
"/src/src-dogs/lassie/lassiedog.ts": Utils.dedent`
|
||||
"/home/src/workspaces/packages/src-dogs/lassie/lassiedog.ts": dedent`
|
||||
import { Dog } from '../dog.js';
|
||||
import { LASSIE_CONFIG } from './lassieconfig.js';
|
||||
|
||||
@@ -138,57 +137,49 @@ describe("unittests:: tsbuild:: moduleSpecifiers:: synthesized module specifiers
|
||||
protected static getDogConfig = () => LASSIE_CONFIG;
|
||||
}
|
||||
`,
|
||||
"/src/src-dogs/lassie/lassieconfig.ts": Utils.dedent`
|
||||
"/home/src/workspaces/packages/src-dogs/lassie/lassieconfig.ts": dedent`
|
||||
import { DogConfig } from 'src-types';
|
||||
|
||||
export const LASSIE_CONFIG: DogConfig = { name: 'Lassie' };
|
||||
`,
|
||||
"/src/tsconfig-base.json": Utils.dedent`
|
||||
{
|
||||
"compilerOptions": {
|
||||
"declaration": true,
|
||||
"module": "node16"
|
||||
}
|
||||
}`,
|
||||
"/src/src-types/package.json": Utils.dedent`
|
||||
{
|
||||
"type": "module",
|
||||
"exports": "./index.js"
|
||||
}`,
|
||||
"/src/src-dogs/package.json": Utils.dedent`
|
||||
{
|
||||
"type": "module",
|
||||
"exports": "./index.js"
|
||||
}`,
|
||||
"/src/src-types/tsconfig.json": Utils.dedent`
|
||||
{
|
||||
"extends": "../tsconfig-base.json",
|
||||
"compilerOptions": {
|
||||
"composite": true
|
||||
},
|
||||
"include": [
|
||||
"**/*"
|
||||
]
|
||||
}`,
|
||||
"/src/src-dogs/tsconfig.json": Utils.dedent`
|
||||
{
|
||||
"extends": "../tsconfig-base.json",
|
||||
"compilerOptions": {
|
||||
"composite": true
|
||||
},
|
||||
"references": [
|
||||
{ "path": "../src-types" }
|
||||
],
|
||||
"include": [
|
||||
"**/*"
|
||||
]
|
||||
}`,
|
||||
}, ""),
|
||||
modifyFs: fs => {
|
||||
fs.writeFileSync("/lib/lib.es2022.full.d.ts", libFile.content);
|
||||
fs.symlinkSync("/src", "/src/src-types/node_modules");
|
||||
fs.symlinkSync("/src", "/src/src-dogs/node_modules");
|
||||
},
|
||||
commandLineArgs: ["-b", "src/src-types", "src/src-dogs", "--verbose"],
|
||||
"/home/src/workspaces/packages/tsconfig-base.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
declaration: true,
|
||||
module: "node16",
|
||||
},
|
||||
}),
|
||||
"/home/src/workspaces/packages/src-types/package.json": jsonToReadableText({
|
||||
type: "module",
|
||||
exports: "./index.js",
|
||||
}),
|
||||
"/home/src/workspaces/packages/src-dogs/package.json": jsonToReadableText({
|
||||
type: "module",
|
||||
exports: "./index.js",
|
||||
}),
|
||||
"/home/src/workspaces/packages/src-types/tsconfig.json": jsonToReadableText({
|
||||
extends: "../tsconfig-base.json",
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
},
|
||||
include: [
|
||||
"**/*",
|
||||
],
|
||||
}),
|
||||
"/home/src/workspaces/packages/src-dogs/tsconfig.json": jsonToReadableText({
|
||||
extends: "../tsconfig-base.json",
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
},
|
||||
references: [
|
||||
{ path: "../src-types" },
|
||||
],
|
||||
include: [
|
||||
"**/*",
|
||||
],
|
||||
}),
|
||||
"/home/src/workspaces/packages/src-types/node_modules": { symLink: "/home/src/workspaces/packages" },
|
||||
"/home/src/workspaces/packages/src-dogs/node_modules": { symLink: "/home/src/workspaces/packages" },
|
||||
}, { currentDirectory: "/home/src/workspaces/packages" }),
|
||||
commandLineArgs: ["-b", "src-types", "src-dogs", "--verbose"],
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,33 +1,21 @@
|
||||
import * as fakes from "../../_namespaces/fakes.js";
|
||||
import * as ts from "../../_namespaces/ts.js";
|
||||
import { dedent } from "../../_namespaces/Utils.js";
|
||||
import * as vfs from "../../_namespaces/vfs.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import { createSolutionBuilderHostForBaseline } from "../helpers/solutionBuilder.js";
|
||||
import {
|
||||
createSolutionBuilderHostForBaseline,
|
||||
solutionBuildWithBaseline,
|
||||
verifySolutionBuilderWithDifferentTsVersion,
|
||||
} from "../helpers/solutionBuilder.js";
|
||||
import {
|
||||
noChangeOnlyRuns,
|
||||
testTscCompileLike,
|
||||
TscCompileSystem,
|
||||
verifyTsc,
|
||||
verifyTscCompileLike,
|
||||
} from "../helpers/tsc.js";
|
||||
import {
|
||||
appendText,
|
||||
loadProjectFromFiles,
|
||||
replaceText,
|
||||
} from "../helpers/vfs.js";
|
||||
import { TestServerHost } from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsbuild:: outFile::", () => {
|
||||
let outFileFs: vfs.FileSystem;
|
||||
let outFileWithBuildFs: vfs.FileSystem;
|
||||
after(() => {
|
||||
outFileFs = undefined!;
|
||||
outFileWithBuildFs = undefined!;
|
||||
});
|
||||
|
||||
function getOutFileFs() {
|
||||
return outFileFs ??= loadProjectFromFiles({
|
||||
"/src/first/first_PART1.ts": dedent`
|
||||
function getOutFileSys() {
|
||||
return TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/solution/first/first_PART1.ts": dedent`
|
||||
interface TheFirst {
|
||||
none: any;
|
||||
}
|
||||
@@ -40,15 +28,15 @@ describe("unittests:: tsbuild:: outFile::", () => {
|
||||
|
||||
console.log(s);
|
||||
`,
|
||||
"/src/first/first_part2.ts": dedent`
|
||||
"/home/src/workspaces/solution/first/first_part2.ts": dedent`
|
||||
console.log(f());
|
||||
`,
|
||||
"/src/first/first_part3.ts": dedent`
|
||||
"/home/src/workspaces/solution/first/first_part3.ts": dedent`
|
||||
function f() {
|
||||
return "JS does hoists";
|
||||
}
|
||||
`,
|
||||
"/src/first/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/solution/first/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
target: "es5",
|
||||
composite: true,
|
||||
@@ -66,7 +54,7 @@ describe("unittests:: tsbuild:: outFile::", () => {
|
||||
],
|
||||
references: [],
|
||||
}),
|
||||
"/src/second/second_part1.ts": dedent`
|
||||
"/home/src/workspaces/solution/second/second_part1.ts": dedent`
|
||||
namespace N {
|
||||
// Comment text
|
||||
}
|
||||
@@ -79,14 +67,14 @@ describe("unittests:: tsbuild:: outFile::", () => {
|
||||
f();
|
||||
}
|
||||
`,
|
||||
"/src/second/second_part2.ts": dedent`
|
||||
"/home/src/workspaces/solution/second/second_part2.ts": dedent`
|
||||
class C {
|
||||
doSomething() {
|
||||
console.log("something got done");
|
||||
}
|
||||
}
|
||||
`,
|
||||
"/src/second/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/solution/second/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
target: "es5",
|
||||
composite: true,
|
||||
@@ -100,11 +88,11 @@ describe("unittests:: tsbuild:: outFile::", () => {
|
||||
},
|
||||
references: [],
|
||||
}),
|
||||
"/src/third/third_part1.ts": dedent`
|
||||
"/home/src/workspaces/solution/third/third_part1.ts": dedent`
|
||||
var c = new C();
|
||||
c.doSomething();
|
||||
`,
|
||||
"/src/third/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/solution/third/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
target: "es5",
|
||||
composite: true,
|
||||
@@ -124,36 +112,31 @@ describe("unittests:: tsbuild:: outFile::", () => {
|
||||
{ path: "../second" },
|
||||
],
|
||||
}),
|
||||
});
|
||||
}, { currentDirectory: "/home/src/workspaces/solution" });
|
||||
}
|
||||
|
||||
function getOutFileFsAfterBuild() {
|
||||
if (outFileWithBuildFs) return outFileWithBuildFs;
|
||||
const fs = getOutFileFs().shadow();
|
||||
const sys = new fakes.System(fs, { executingFilePath: "/lib/tsc" });
|
||||
const host = createSolutionBuilderHostForBaseline(sys as TscCompileSystem);
|
||||
const builder = ts.createSolutionBuilder(host, ["/src/third"], { dry: false, force: false, verbose: true });
|
||||
builder.build();
|
||||
fs.makeReadonly();
|
||||
return outFileWithBuildFs = fs;
|
||||
function getOutFileSysAfterBuild() {
|
||||
const sys = getOutFileSys();
|
||||
solutionBuildWithBaseline(sys, ["/home/src/workspaces/solution/third"], { dry: false, force: false, verbose: true });
|
||||
return sys;
|
||||
}
|
||||
|
||||
// Verify initial + incremental edits
|
||||
verifyTsc({
|
||||
subScenario: "baseline sectioned sourcemaps",
|
||||
fs: getOutFileFs,
|
||||
sys: getOutFileSys,
|
||||
scenario: "outFile",
|
||||
commandLineArgs: ["--b", "/src/third", "--verbose", "--explainFiles"],
|
||||
commandLineArgs: ["--b", "third", "--verbose", "--explainFiles"],
|
||||
baselineSourceMap: true,
|
||||
baselineReadFileCalls: true,
|
||||
edits: [
|
||||
{
|
||||
caption: "incremental-declaration-changes",
|
||||
edit: fs => replaceText(fs, "/src/first/first_PART1.ts", "Hello", "Hola"),
|
||||
edit: sys => sys.replaceFileText("/home/src/workspaces/solution/first/first_PART1.ts", "Hello", "Hola"),
|
||||
},
|
||||
{
|
||||
caption: "incremental-declaration-doesnt-change",
|
||||
edit: fs => appendText(fs, "/src/first/first_PART1.ts", "console.log(s);"),
|
||||
edit: sys => sys.appendFile("/home/src/workspaces/solution/first/first_PART1.ts", "console.log(s);"),
|
||||
},
|
||||
],
|
||||
});
|
||||
@@ -161,38 +144,37 @@ describe("unittests:: tsbuild:: outFile::", () => {
|
||||
// Verify baseline with build info + dts unChanged
|
||||
verifyTsc({
|
||||
subScenario: "when final project is not composite but uses project references",
|
||||
fs: getOutFileFs,
|
||||
sys: getOutFileSys,
|
||||
scenario: "outFile",
|
||||
commandLineArgs: ["--b", "/src/third", "--verbose"],
|
||||
commandLineArgs: ["--b", "third", "--verbose"],
|
||||
baselineSourceMap: true,
|
||||
modifyFs: fs => replaceText(fs, "/src/third/tsconfig.json", `"composite": true,`, ""),
|
||||
modifySystem: sys => sys.replaceFileText("/home/src/workspaces/solution/third/tsconfig.json", `"composite": true,`, ""),
|
||||
edits: [{
|
||||
caption: "incremental-declaration-doesnt-change",
|
||||
edit: fs => appendText(fs, "/src/first/first_PART1.ts", "console.log(s);"),
|
||||
edit: sys => sys.appendFile("/home/src/workspaces/solution/first/first_PART1.ts", "console.log(s);"),
|
||||
}],
|
||||
});
|
||||
|
||||
// Verify baseline with build info
|
||||
verifyTsc({
|
||||
subScenario: "when final project is not composite but incremental",
|
||||
fs: getOutFileFs,
|
||||
sys: getOutFileSys,
|
||||
scenario: "outFile",
|
||||
commandLineArgs: ["--b", "/src/third", "--verbose"],
|
||||
commandLineArgs: ["--b", "third", "--verbose"],
|
||||
baselineSourceMap: true,
|
||||
modifyFs: fs => replaceText(fs, "/src/third/tsconfig.json", `"composite": true,`, `"incremental": true,`),
|
||||
modifySystem: sys => sys.replaceFileText("/home/src/workspaces/solution/third/tsconfig.json", `"composite": true,`, `"incremental": true,`),
|
||||
});
|
||||
|
||||
// Verify baseline with build info
|
||||
verifyTsc({
|
||||
subScenario: "when final project specifies tsBuildInfoFile",
|
||||
fs: getOutFileFs,
|
||||
sys: getOutFileSys,
|
||||
scenario: "outFile",
|
||||
commandLineArgs: ["--b", "/src/third", "--verbose"],
|
||||
commandLineArgs: ["--b", "third", "--verbose"],
|
||||
baselineSourceMap: true,
|
||||
modifyFs: fs =>
|
||||
replaceText(
|
||||
fs,
|
||||
"/src/third/tsconfig.json",
|
||||
modifySystem: sys =>
|
||||
sys.replaceFileText(
|
||||
"/home/src/workspaces/solution/third/tsconfig.json",
|
||||
`"composite": true,`,
|
||||
`"composite": true,
|
||||
"tsBuildInfoFile": "./thirdjs/output/third.tsbuildinfo",`,
|
||||
@@ -202,53 +184,47 @@ describe("unittests:: tsbuild:: outFile::", () => {
|
||||
verifyTsc({
|
||||
scenario: "outFile",
|
||||
subScenario: "clean projects",
|
||||
fs: getOutFileFsAfterBuild,
|
||||
commandLineArgs: ["--b", "/src/third", "--clean"],
|
||||
sys: getOutFileSysAfterBuild,
|
||||
commandLineArgs: ["--b", "third", "--clean"],
|
||||
edits: noChangeOnlyRuns,
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "outFile",
|
||||
subScenario: "verify buildInfo absence results in new build",
|
||||
fs: getOutFileFsAfterBuild,
|
||||
commandLineArgs: ["--b", "/src/third", "--verbose"],
|
||||
modifyFs: fs => fs.unlinkSync("/src/first/bin/first-output.tsbuildinfo"),
|
||||
sys: getOutFileSysAfterBuild,
|
||||
commandLineArgs: ["--b", "third", "--verbose"],
|
||||
modifySystem: sys => sys.deleteFile("/home/src/workspaces/solution/first/bin/first-output.tsbuildinfo"),
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "outFile",
|
||||
subScenario: "tsbuildinfo is not generated when incremental is set to false",
|
||||
fs: getOutFileFs,
|
||||
commandLineArgs: ["--b", "/src/third", "--verbose"],
|
||||
modifyFs: fs => replaceText(fs, "/src/third/tsconfig.json", `"composite": true,`, ""),
|
||||
sys: getOutFileSys,
|
||||
commandLineArgs: ["--b", "third", "--verbose"],
|
||||
modifySystem: sys => sys.replaceFileText("/home/src/workspaces/solution/third/tsconfig.json", `"composite": true,`, ""),
|
||||
});
|
||||
|
||||
verifyTscCompileLike(testTscCompileLike, {
|
||||
verifySolutionBuilderWithDifferentTsVersion({
|
||||
scenario: "outFile",
|
||||
subScenario: "rebuilds completely when version in tsbuildinfo doesnt match ts version",
|
||||
fs: getOutFileFsAfterBuild,
|
||||
commandLineArgs: ["--b", "/src/third", "--verbose"],
|
||||
compile: sys => {
|
||||
// Buildinfo will have version which does not match with current ts version
|
||||
const buildHost = createSolutionBuilderHostForBaseline(sys, "FakeTSCurrentVersion");
|
||||
const builder = ts.createSolutionBuilder(buildHost, ["/src/third"], { verbose: true });
|
||||
sys.exit(builder.build());
|
||||
},
|
||||
});
|
||||
sys: getOutFileSysAfterBuild,
|
||||
commandLineArgs: ["--b", "third", "--verbose"],
|
||||
}, ["/home/src/workspaces/solution/third"]);
|
||||
|
||||
verifyTsc({
|
||||
scenario: "outFile",
|
||||
subScenario: "rebuilds completely when command line incremental flag changes between non dts changes",
|
||||
fs: getOutFileFs,
|
||||
sys: getOutFileSys,
|
||||
// Make non composite third project
|
||||
modifyFs: fs => replaceText(fs, "/src/third/tsconfig.json", `"composite": true,`, ""),
|
||||
modifySystem: sys => sys.replaceFileText("/home/src/workspaces/solution/third/tsconfig.json", `"composite": true,`, ""),
|
||||
// Build with command line incremental
|
||||
commandLineArgs: ["--b", "/src/third", "--i", "--verbose"],
|
||||
commandLineArgs: ["--b", "third", "--i", "--verbose"],
|
||||
edits: [
|
||||
{
|
||||
caption: "Make non incremental build with change in file that doesnt affect dts",
|
||||
edit: fs => appendText(fs, "/src/first/first_PART1.ts", "console.log(s);"),
|
||||
commandLineArgs: ["--b", "/src/third", "--verbose"],
|
||||
edit: sys => sys.appendFile("/home/src/workspaces/solution/first/first_PART1.ts", "console.log(s);"),
|
||||
commandLineArgs: ["--b", "third", "--verbose"],
|
||||
discrepancyExplanation: () => [
|
||||
"Clean build is non incremental so it will have non incremental tsbuildInfo for third project",
|
||||
"The incremental build does not build third so will only update timestamps for third tsbuildInfo and hence its from incremental build before",
|
||||
@@ -256,8 +232,8 @@ describe("unittests:: tsbuild:: outFile::", () => {
|
||||
},
|
||||
{
|
||||
caption: "Make incremental build with change in file that doesnt affect dts",
|
||||
edit: fs => appendText(fs, "/src/first/first_PART1.ts", "console.log(s);"),
|
||||
commandLineArgs: ["--b", "/src/third", "--verbose", "--incremental"],
|
||||
edit: sys => sys.appendFile("/home/src/workspaces/solution/first/first_PART1.ts", "console.log(s);"),
|
||||
commandLineArgs: ["--b", "third", "--verbose", "--incremental"],
|
||||
},
|
||||
],
|
||||
});
|
||||
@@ -265,58 +241,57 @@ describe("unittests:: tsbuild:: outFile::", () => {
|
||||
verifyTsc({
|
||||
scenario: "outFile",
|
||||
subScenario: "when input file text does not change but its modified time changes",
|
||||
fs: getOutFileFs,
|
||||
commandLineArgs: ["--b", "/src/third", "--verbose"],
|
||||
sys: getOutFileSys,
|
||||
commandLineArgs: ["--b", "third", "--verbose"],
|
||||
edits: [
|
||||
{
|
||||
caption: "upstream project changes without changing file text",
|
||||
edit: fs => {
|
||||
const time = new Date(fs.time());
|
||||
fs.utimesSync("/src/first/first_PART1.ts", time, time);
|
||||
},
|
||||
edit: sys => sys.setModifiedTime("/home/src/workspaces/solution/first/first_PART1.ts", sys.now()),
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
verifyTscCompileLike(testTscCompileLike, {
|
||||
verifyTsc({
|
||||
scenario: "outFile",
|
||||
subScenario: "builds till project specified",
|
||||
fs: getOutFileFs,
|
||||
commandLineArgs: ["--build", "/src/second/tsconfig.json"],
|
||||
sys: getOutFileSys,
|
||||
commandLineArgs: ["--build", "second/tsconfig.json"],
|
||||
compile: sys => {
|
||||
const buildHost = createSolutionBuilderHostForBaseline(sys);
|
||||
const builder = ts.createSolutionBuilder(buildHost, ["/src/third/tsconfig.json"], {});
|
||||
sys.exit(builder.build("/src/second/tsconfig.json"));
|
||||
const builder = ts.createSolutionBuilder(buildHost, ["/home/src/workspaces/solution/third/tsconfig.json"], {});
|
||||
sys.exit(builder.build("/home/src/workspaces/solution/second/tsconfig.json"));
|
||||
return buildHost.getPrograms;
|
||||
},
|
||||
});
|
||||
|
||||
verifyTscCompileLike(testTscCompileLike, {
|
||||
verifyTsc({
|
||||
scenario: "outFile",
|
||||
subScenario: "cleans till project specified",
|
||||
fs: getOutFileFsAfterBuild,
|
||||
commandLineArgs: ["--build", "--clean", "/src/second/tsconfig.json"],
|
||||
sys: getOutFileSysAfterBuild,
|
||||
commandLineArgs: ["--build", "--clean", "second/tsconfig.json"],
|
||||
compile: sys => {
|
||||
const buildHost = createSolutionBuilderHostForBaseline(sys);
|
||||
const builder = ts.createSolutionBuilder(buildHost, ["/src/third/tsconfig.json"], { verbose: true });
|
||||
sys.exit(builder.clean("/src/second/tsconfig.json"));
|
||||
const builder = ts.createSolutionBuilder(buildHost, ["/home/src/workspaces/solution/third/tsconfig.json"], { verbose: true });
|
||||
sys.exit(builder.clean("/home/src/workspaces/solution/second/tsconfig.json"));
|
||||
return buildHost.getPrograms;
|
||||
},
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "outFile",
|
||||
subScenario: "non module projects without prepend",
|
||||
fs: getOutFileFs,
|
||||
commandLineArgs: ["--b", "/src/third", "--verbose"],
|
||||
modifyFs: fs => {
|
||||
sys: getOutFileSys,
|
||||
commandLineArgs: ["--b", "third", "--verbose"],
|
||||
modifySystem: sys => {
|
||||
// Non Modules
|
||||
replaceText(fs, "/src/first/tsconfig.json", `"composite": true,`, `"composite": true, "module": "none",`);
|
||||
replaceText(fs, "/src/second/tsconfig.json", `"composite": true,`, `"composite": true, "module": "none",`);
|
||||
replaceText(fs, "/src/third/tsconfig.json", `"composite": true,`, `"composite": true, "module": "none",`);
|
||||
sys.replaceFileText("/home/src/workspaces/solution/first/tsconfig.json", `"composite": true,`, `"composite": true, "module": "none",`);
|
||||
sys.replaceFileText("/home/src/workspaces/solution/second/tsconfig.json", `"composite": true,`, `"composite": true, "module": "none",`);
|
||||
sys.replaceFileText("/home/src/workspaces/solution/third/tsconfig.json", `"composite": true,`, `"composite": true, "module": "none",`);
|
||||
|
||||
// Own file emit
|
||||
replaceText(fs, "/src/first/tsconfig.json", `"outFile": "./bin/first-output.js",`, "");
|
||||
replaceText(fs, "/src/second/tsconfig.json", `"outFile": "../2/second-output.js",`, "");
|
||||
replaceText(fs, "/src/third/tsconfig.json", `"outFile": "./thirdjs/output/third-output.js",`, "");
|
||||
sys.replaceFileText("/home/src/workspaces/solution/first/tsconfig.json", `"outFile": "./bin/first-output.js",`, "");
|
||||
sys.replaceFileText("/home/src/workspaces/solution/second/tsconfig.json", `"outFile": "../2/second-output.js",`, "");
|
||||
sys.replaceFileText("/home/src/workspaces/solution/third/tsconfig.json", `"outFile": "./thirdjs/output/third-output.js",`, "");
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,40 +1,44 @@
|
||||
import * as fakes from "../../_namespaces/fakes.js";
|
||||
import * as ts from "../../_namespaces/ts.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import {
|
||||
noChangeRun,
|
||||
TestTscEdit,
|
||||
TscCompileSystem,
|
||||
verifyTsc,
|
||||
VerifyTscWithEditsInput,
|
||||
} from "../helpers/tsc.js";
|
||||
import { loadProjectFromFiles } from "../helpers/vfs.js";
|
||||
import { TestServerHost } from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsbuild - output file paths", () => {
|
||||
describe("unittests:: tsbuild:: outputPaths::", () => {
|
||||
const noChangeProject: TestTscEdit = {
|
||||
edit: ts.noop,
|
||||
caption: "Normal build without change, that does not block emit on error to show files that get emitted",
|
||||
commandLineArgs: ["-p", "/src/tsconfig.json"],
|
||||
commandLineArgs: ["-p", "/home/src/workspaces/project/tsconfig.json"],
|
||||
};
|
||||
const edits: TestTscEdit[] = [
|
||||
noChangeRun,
|
||||
noChangeProject,
|
||||
];
|
||||
|
||||
function verify(input: Pick<VerifyTscWithEditsInput, "subScenario" | "fs" | "edits">, expectedOuptutNames: readonly string[]) {
|
||||
function verify(input: Pick<VerifyTscWithEditsInput, "subScenario" | "sys" | "edits">, expectedOuptutNames: readonly string[]) {
|
||||
verifyTsc({
|
||||
scenario: "outputPaths",
|
||||
commandLineArgs: ["--b", "/src/tsconfig.json", "-v"],
|
||||
commandLineArgs: ["--b", "-v"],
|
||||
...input,
|
||||
});
|
||||
|
||||
it("verify getOutputFileNames", () => {
|
||||
const sys = new fakes.System(input.fs().makeReadonly(), { executingFilePath: "/lib/tsc" }) as TscCompileSystem;
|
||||
|
||||
const sys = input.sys();
|
||||
assert.deepEqual(
|
||||
ts.getOutputFileNames(
|
||||
ts.parseConfigFileWithSystem("/src/tsconfig.json", {}, /*extendedConfigCache*/ undefined, {}, sys, ts.noop)!,
|
||||
"/src/src/index.ts",
|
||||
ts.parseConfigFileWithSystem(
|
||||
"/home/src/workspaces/project/tsconfig.json",
|
||||
{},
|
||||
/*extendedConfigCache*/ undefined,
|
||||
{},
|
||||
sys,
|
||||
ts.noop,
|
||||
)!,
|
||||
"/home/src/workspaces/project/src/index.ts",
|
||||
/*ignoreCase*/ false,
|
||||
),
|
||||
expectedOuptutNames,
|
||||
@@ -44,78 +48,78 @@ describe("unittests:: tsbuild - output file paths", () => {
|
||||
|
||||
verify({
|
||||
subScenario: "when rootDir is not specified",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/src/index.ts": "export const x = 10;",
|
||||
"/src/tsconfig.json": jsonToReadableText({
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/src/index.ts": "export const x = 10;",
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
outDir: "dist",
|
||||
},
|
||||
}),
|
||||
}),
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
edits,
|
||||
}, ["/src/dist/index.js"]);
|
||||
}, ["/home/src/workspaces/project/dist/index.js"]);
|
||||
|
||||
verify({
|
||||
subScenario: "when rootDir is not specified and is composite",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/src/index.ts": "export const x = 10;",
|
||||
"/src/tsconfig.json": jsonToReadableText({
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/src/index.ts": "export const x = 10;",
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
outDir: "dist",
|
||||
composite: true,
|
||||
},
|
||||
}),
|
||||
}),
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
edits,
|
||||
}, ["/src/dist/src/index.js", "/src/dist/src/index.d.ts"]);
|
||||
}, ["/home/src/workspaces/project/dist/src/index.js", "/home/src/workspaces/project/dist/src/index.d.ts"]);
|
||||
|
||||
verify({
|
||||
subScenario: "when rootDir is specified",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/src/index.ts": "export const x = 10;",
|
||||
"/src/tsconfig.json": jsonToReadableText({
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/src/index.ts": "export const x = 10;",
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
outDir: "dist",
|
||||
rootDir: "src",
|
||||
},
|
||||
}),
|
||||
}),
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
edits,
|
||||
}, ["/src/dist/index.js"]);
|
||||
}, ["/home/src/workspaces/project/dist/index.js"]);
|
||||
|
||||
verify({
|
||||
subScenario: "when rootDir is specified but not all files belong to rootDir",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/src/index.ts": "export const x = 10;",
|
||||
"/src/types/type.ts": "export type t = string;",
|
||||
"/src/tsconfig.json": jsonToReadableText({
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/src/index.ts": "export const x = 10;",
|
||||
"/home/src/workspaces/project/types/type.ts": "export type t = string;",
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
outDir: "dist",
|
||||
rootDir: "src",
|
||||
},
|
||||
}),
|
||||
}),
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
edits,
|
||||
}, ["/src/dist/index.js"]);
|
||||
}, ["/home/src/workspaces/project/dist/index.js"]);
|
||||
|
||||
verify({
|
||||
subScenario: "when rootDir is specified but not all files belong to rootDir and is composite",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/src/index.ts": "export const x = 10;",
|
||||
"/src/types/type.ts": "export type t = string;",
|
||||
"/src/tsconfig.json": jsonToReadableText({
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/src/index.ts": "export const x = 10;",
|
||||
"/home/src/workspaces/project/types/type.ts": "export type t = string;",
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
outDir: "dist",
|
||||
rootDir: "src",
|
||||
composite: true,
|
||||
},
|
||||
}),
|
||||
}),
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
edits,
|
||||
}, ["/src/dist/index.js", "/src/dist/index.d.ts"]);
|
||||
}, ["/home/src/workspaces/project/dist/index.js", "/home/src/workspaces/project/dist/index.d.ts"]);
|
||||
});
|
||||
|
||||
@@ -1,135 +1,100 @@
|
||||
import * as fakes from "../../_namespaces/fakes.js";
|
||||
import * as ts from "../../_namespaces/ts.js";
|
||||
import * as vfs from "../../_namespaces/vfs.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import {
|
||||
baselinePrograms,
|
||||
commandLineCallbacks,
|
||||
toPathWithSystem,
|
||||
} from "../helpers/baseline.js";
|
||||
import {
|
||||
TscCompileSystem,
|
||||
verifyTscBaseline,
|
||||
} from "../helpers/tsc.js";
|
||||
import { loadProjectFromFiles } from "../helpers/vfs.js";
|
||||
import { commandLineCallbacks } from "../helpers/baseline.js";
|
||||
import { verifyTsc } from "../helpers/tsc.js";
|
||||
import { TestServerHost } from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsbuild:: Public API with custom transformers when passed to build", () => {
|
||||
let sys: TscCompileSystem;
|
||||
before(() => {
|
||||
const inputFs = loadProjectFromFiles({
|
||||
"/src/tsconfig.json": jsonToReadableText({
|
||||
references: [
|
||||
{ path: "./shared/tsconfig.json" },
|
||||
{ path: "./webpack/tsconfig.json" },
|
||||
],
|
||||
files: [],
|
||||
}),
|
||||
"/src/shared/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: { composite: true },
|
||||
}),
|
||||
"/src/shared/index.ts": `export function f1() { }
|
||||
describe("unittests:: tsbuild:: PublicAPI:: with custom transformers when passed to build", () => {
|
||||
verifyTsc({
|
||||
scenario: "publicAPI",
|
||||
subScenario: "build with custom transformers",
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/solution/tsconfig.json": jsonToReadableText({
|
||||
references: [
|
||||
{ path: "./shared/tsconfig.json" },
|
||||
{ path: "./webpack/tsconfig.json" },
|
||||
],
|
||||
files: [],
|
||||
}),
|
||||
"/home/src/workspaces/solution/shared/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: { composite: true },
|
||||
}),
|
||||
"/home/src/workspaces/solution/shared/index.ts": `export function f1() { }
|
||||
export class c { }
|
||||
export enum e { }
|
||||
// leading
|
||||
export function f2() { } // trailing`,
|
||||
"/src/webpack/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
},
|
||||
references: [{ path: "../shared/tsconfig.json" }],
|
||||
}),
|
||||
"/src/webpack/index.ts": `export function f2() { }
|
||||
"/home/src/workspaces/solution/webpack/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
},
|
||||
references: [{ path: "../shared/tsconfig.json" }],
|
||||
}),
|
||||
"/home/src/workspaces/solution/webpack/index.ts": `export function f2() { }
|
||||
export class c2 { }
|
||||
export enum e2 { }
|
||||
// leading
|
||||
export function f22() { } // trailing`,
|
||||
}).makeReadonly();
|
||||
const fs = inputFs.shadow();
|
||||
}, { currentDirectory: "/home/src/workspaces/solution" }),
|
||||
commandLineArgs: ["--b"],
|
||||
compile: sys => {
|
||||
const { cb, getPrograms } = commandLineCallbacks(sys, /*originalReadCall*/ undefined);
|
||||
const buildHost = ts.createSolutionBuilderHost(
|
||||
sys,
|
||||
/*createProgram*/ undefined,
|
||||
ts.createDiagnosticReporter(sys, /*pretty*/ true),
|
||||
ts.createBuilderStatusReporter(sys, /*pretty*/ true),
|
||||
(errorCount, filesInError) => sys.write(ts.getErrorSummaryText(errorCount, filesInError, sys.newLine, sys)),
|
||||
);
|
||||
buildHost.afterProgramEmitAndDiagnostics = cb;
|
||||
const builder = ts.createSolutionBuilder(
|
||||
buildHost,
|
||||
["/home/src/workspaces/solution/tsconfig.json"],
|
||||
{ verbose: true },
|
||||
);
|
||||
const exitStatus = builder.build(
|
||||
/*project*/ undefined,
|
||||
/*cancellationToken*/ undefined,
|
||||
/*writeFile*/ undefined,
|
||||
project => {
|
||||
const before: ts.TransformerFactory<ts.SourceFile> = context => {
|
||||
return file => ts.visitEachChild(file, visit, context);
|
||||
function visit(node: ts.Node): ts.VisitResult<ts.Node> {
|
||||
switch (node.kind) {
|
||||
case ts.SyntaxKind.FunctionDeclaration:
|
||||
return visitFunction(node as ts.FunctionDeclaration);
|
||||
default:
|
||||
return ts.visitEachChild(node, visit, context);
|
||||
}
|
||||
}
|
||||
function visitFunction(node: ts.FunctionDeclaration) {
|
||||
ts.addSyntheticLeadingComment(node, ts.SyntaxKind.MultiLineCommentTrivia, `@before${project}`, /*hasTrailingNewLine*/ true);
|
||||
return node;
|
||||
}
|
||||
};
|
||||
|
||||
// Create system
|
||||
sys = new fakes.System(fs, { executingFilePath: "/lib/tsc" }) as TscCompileSystem;
|
||||
sys.storeSignatureInfo = true;
|
||||
fakes.patchHostForBuildInfoReadWrite(sys);
|
||||
const commandLineArgs = ["--b", "/src/tsconfig.json"];
|
||||
sys.write(`${sys.getExecutingFilePath()} ${commandLineArgs.join(" ")}\n`);
|
||||
sys.exit = exitCode => sys.exitCode = exitCode;
|
||||
const writtenFiles = sys.writtenFiles = new Set();
|
||||
const originalWriteFile = sys.writeFile;
|
||||
sys.writeFile = (fileName, content, writeByteOrderMark) => {
|
||||
const path = toPathWithSystem(sys, fileName);
|
||||
assert.isFalse(writtenFiles.has(path));
|
||||
writtenFiles.add(path);
|
||||
return originalWriteFile.call(sys, fileName, content, writeByteOrderMark);
|
||||
};
|
||||
const { cb, getPrograms } = commandLineCallbacks(sys, /*originalReadCall*/ undefined);
|
||||
const buildHost = ts.createSolutionBuilderHost(
|
||||
sys,
|
||||
/*createProgram*/ undefined,
|
||||
ts.createDiagnosticReporter(sys, /*pretty*/ true),
|
||||
ts.createBuilderStatusReporter(sys, /*pretty*/ true),
|
||||
(errorCount, filesInError) => sys.write(ts.getErrorSummaryText(errorCount, filesInError, sys.newLine, sys)),
|
||||
);
|
||||
buildHost.afterProgramEmitAndDiagnostics = cb;
|
||||
const builder = ts.createSolutionBuilder(buildHost, [commandLineArgs[1]], { verbose: true });
|
||||
const exitStatus = builder.build(/*project*/ undefined, /*cancellationToken*/ undefined, /*writeFile*/ undefined, getCustomTransformers);
|
||||
sys.exit(exitStatus);
|
||||
sys.write(`exitCode:: ExitStatus.${ts.ExitStatus[sys.exitCode as ts.ExitStatus]}\n`);
|
||||
const baseline: string[] = [];
|
||||
baselinePrograms(baseline, getPrograms(), ts.emptyArray, /*baselineDependencies*/ false);
|
||||
sys.write(baseline.join("\n"));
|
||||
fs.makeReadonly();
|
||||
sys.baseLine = () => {
|
||||
const baseFsPatch = inputFs.diff(/*base*/ undefined, { baseIsNotShadowRoot: true });
|
||||
const patch = fs.diff(inputFs, { includeChangedFileWithSameContent: true });
|
||||
return {
|
||||
file: `tsbuild/publicAPI/build-with-custom-transformers.js`,
|
||||
text: `Input::
|
||||
${baseFsPatch ? vfs.formatPatch(baseFsPatch) : ""}
|
||||
|
||||
Output::
|
||||
${sys.output.join("")}
|
||||
|
||||
${patch ? vfs.formatPatch(patch) : ""}`,
|
||||
};
|
||||
};
|
||||
|
||||
function getCustomTransformers(project: string): ts.CustomTransformers {
|
||||
const before: ts.TransformerFactory<ts.SourceFile> = context => {
|
||||
return file => ts.visitEachChild(file, visit, context);
|
||||
function visit(node: ts.Node): ts.VisitResult<ts.Node> {
|
||||
switch (node.kind) {
|
||||
case ts.SyntaxKind.FunctionDeclaration:
|
||||
return visitFunction(node as ts.FunctionDeclaration);
|
||||
default:
|
||||
return ts.visitEachChild(node, visit, context);
|
||||
}
|
||||
}
|
||||
function visitFunction(node: ts.FunctionDeclaration) {
|
||||
ts.addSyntheticLeadingComment(node, ts.SyntaxKind.MultiLineCommentTrivia, `@before${project}`, /*hasTrailingNewLine*/ true);
|
||||
return node;
|
||||
}
|
||||
};
|
||||
|
||||
const after: ts.TransformerFactory<ts.SourceFile> = context => {
|
||||
return file => ts.visitEachChild(file, visit, context);
|
||||
function visit(node: ts.Node): ts.VisitResult<ts.Node> {
|
||||
switch (node.kind) {
|
||||
case ts.SyntaxKind.VariableStatement:
|
||||
return visitVariableStatement(node as ts.VariableStatement);
|
||||
default:
|
||||
return ts.visitEachChild(node, visit, context);
|
||||
}
|
||||
}
|
||||
function visitVariableStatement(node: ts.VariableStatement) {
|
||||
ts.addSyntheticLeadingComment(node, ts.SyntaxKind.SingleLineCommentTrivia, `@after${project}`);
|
||||
return node;
|
||||
}
|
||||
};
|
||||
return { before: [before], after: [after] };
|
||||
}
|
||||
const after: ts.TransformerFactory<ts.SourceFile> = context => {
|
||||
return file => ts.visitEachChild(file, visit, context);
|
||||
function visit(node: ts.Node): ts.VisitResult<ts.Node> {
|
||||
switch (node.kind) {
|
||||
case ts.SyntaxKind.VariableStatement:
|
||||
return visitVariableStatement(node as ts.VariableStatement);
|
||||
default:
|
||||
return ts.visitEachChild(node, visit, context);
|
||||
}
|
||||
}
|
||||
function visitVariableStatement(node: ts.VariableStatement) {
|
||||
ts.addSyntheticLeadingComment(node, ts.SyntaxKind.SingleLineCommentTrivia, `@after${project}`);
|
||||
return node;
|
||||
}
|
||||
};
|
||||
return { before: [before], after: [after] };
|
||||
},
|
||||
);
|
||||
sys.exit(exitStatus);
|
||||
return getPrograms;
|
||||
},
|
||||
baselinePrograms: true,
|
||||
});
|
||||
after(() => {
|
||||
sys = undefined!;
|
||||
});
|
||||
verifyTscBaseline(() => sys);
|
||||
});
|
||||
|
||||
@@ -1,40 +1,35 @@
|
||||
import { noop } from "../../_namespaces/ts.js";
|
||||
import { dedent } from "../../_namespaces/Utils.js";
|
||||
import * as vfs from "../../_namespaces/vfs.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import {
|
||||
noChangeOnlyRuns,
|
||||
verifyTsc,
|
||||
} from "../helpers/tsc.js";
|
||||
import {
|
||||
loadProjectFromFiles,
|
||||
replaceText,
|
||||
} from "../helpers/vfs.js";
|
||||
import { TestServerHost } from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsbuild:: with rootDir of project reference in parentDirectory", () => {
|
||||
let projFs: vfs.FileSystem;
|
||||
before(() => {
|
||||
projFs = loadProjectFromFiles({
|
||||
"/src/src/main/a.ts": dedent`
|
||||
describe("unittests:: tsbuild:: projectReferenceWithRootDirInParent:: with rootDir of project reference in parentDirectory", () => {
|
||||
function getProjectReferenceWithRootDirInParentSys() {
|
||||
return TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/solution/src/main/a.ts": dedent`
|
||||
import { b } from './b';
|
||||
const a = b;
|
||||
`,
|
||||
"/src/src/main/b.ts": dedent`
|
||||
"/home/src/workspaces/solution/src/main/b.ts": dedent`
|
||||
export const b = 0;
|
||||
`,
|
||||
"/src/src/main/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/solution/src/main/tsconfig.json": jsonToReadableText({
|
||||
extends: "../../tsconfig.base.json",
|
||||
references: [
|
||||
{ path: "../other" },
|
||||
],
|
||||
}),
|
||||
"/src/src/other/other.ts": dedent`
|
||||
"/home/src/workspaces/solution/src/other/other.ts": dedent`
|
||||
export const Other = 0;
|
||||
`,
|
||||
"/src/src/other/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/solution/src/other/tsconfig.json": jsonToReadableText({
|
||||
extends: "../../tsconfig.base.json",
|
||||
}),
|
||||
"/src/tsconfig.base.json": jsonToReadableText({
|
||||
"/home/src/workspaces/solution/tsconfig.base.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
declaration: true,
|
||||
@@ -46,43 +41,39 @@ describe("unittests:: tsbuild:: with rootDir of project reference in parentDirec
|
||||
"node_modules",
|
||||
],
|
||||
}),
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
projFs = undefined!; // Release the contents
|
||||
});
|
||||
}, { currentDirectory: "/home/src/workspaces/solution" });
|
||||
}
|
||||
|
||||
verifyTsc({
|
||||
scenario: "projectReferenceWithRootDirInParent",
|
||||
subScenario: "builds correctly",
|
||||
fs: () => projFs,
|
||||
commandLineArgs: ["--b", "/src/src/main", "/src/src/other"],
|
||||
sys: getProjectReferenceWithRootDirInParentSys,
|
||||
commandLineArgs: ["--b", "src/main", "/home/src/workspaces/solution/src/other"],
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "projectReferenceWithRootDirInParent",
|
||||
subScenario: "reports error for same tsbuildinfo file because no rootDir in the base",
|
||||
fs: () => projFs,
|
||||
commandLineArgs: ["--b", "/src/src/main", "--verbose"],
|
||||
modifyFs: fs => replaceText(fs, "/src/tsconfig.base.json", `"rootDir": "./src/",`, ""),
|
||||
sys: getProjectReferenceWithRootDirInParentSys,
|
||||
commandLineArgs: ["--b", "src/main", "--verbose"],
|
||||
modifySystem: sys => sys.replaceFileText("/home/src/workspaces/solution/tsconfig.base.json", `"rootDir": "./src/",`, ""),
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "projectReferenceWithRootDirInParent",
|
||||
subScenario: "reports error for same tsbuildinfo file",
|
||||
fs: () => projFs,
|
||||
commandLineArgs: ["--b", "/src/src/main", "--verbose"],
|
||||
modifyFs: fs => {
|
||||
fs.writeFileSync(
|
||||
"/src/src/main/tsconfig.json",
|
||||
sys: getProjectReferenceWithRootDirInParentSys,
|
||||
commandLineArgs: ["--b", "src/main", "--verbose"],
|
||||
modifySystem: sys => {
|
||||
sys.writeFile(
|
||||
"/home/src/workspaces/solution/src/main/tsconfig.json",
|
||||
jsonToReadableText({
|
||||
compilerOptions: { composite: true, outDir: "../../dist/" },
|
||||
references: [{ path: "../other" }],
|
||||
}),
|
||||
);
|
||||
fs.writeFileSync(
|
||||
"/src/src/other/tsconfig.json",
|
||||
sys.writeFile(
|
||||
"/home/src/workspaces/solution/src/other/tsconfig.json",
|
||||
jsonToReadableText({
|
||||
compilerOptions: { composite: true, outDir: "../../dist/" },
|
||||
}),
|
||||
@@ -94,18 +85,18 @@ describe("unittests:: tsbuild:: with rootDir of project reference in parentDirec
|
||||
verifyTsc({
|
||||
scenario: "projectReferenceWithRootDirInParent",
|
||||
subScenario: "reports error for same tsbuildinfo file without incremental",
|
||||
fs: () => projFs,
|
||||
commandLineArgs: ["--b", "/src/src/main", "--verbose"],
|
||||
modifyFs: fs => {
|
||||
fs.writeFileSync(
|
||||
"/src/src/main/tsconfig.json",
|
||||
sys: getProjectReferenceWithRootDirInParentSys,
|
||||
commandLineArgs: ["--b", "src/main", "--verbose"],
|
||||
modifySystem: sys => {
|
||||
sys.writeFile(
|
||||
"/home/src/workspaces/solution/src/main/tsconfig.json",
|
||||
jsonToReadableText({
|
||||
compilerOptions: { outDir: "../../dist/" },
|
||||
references: [{ path: "../other" }],
|
||||
}),
|
||||
);
|
||||
fs.writeFileSync(
|
||||
"/src/src/other/tsconfig.json",
|
||||
sys.writeFile(
|
||||
"/home/src/workspaces/solution/src/other/tsconfig.json",
|
||||
jsonToReadableText({
|
||||
compilerOptions: { composite: true, outDir: "../../dist/" },
|
||||
}),
|
||||
@@ -116,18 +107,18 @@ describe("unittests:: tsbuild:: with rootDir of project reference in parentDirec
|
||||
verifyTsc({
|
||||
scenario: "projectReferenceWithRootDirInParent",
|
||||
subScenario: "reports error for same tsbuildinfo file without incremental with tsc",
|
||||
fs: () => projFs,
|
||||
commandLineArgs: ["--b", "/src/src/other", "--verbose"],
|
||||
modifyFs: fs => {
|
||||
fs.writeFileSync(
|
||||
"/src/src/main/tsconfig.json",
|
||||
sys: getProjectReferenceWithRootDirInParentSys,
|
||||
commandLineArgs: ["--b", "src/other", "--verbose"],
|
||||
modifySystem: sys => {
|
||||
sys.writeFile(
|
||||
"/home/src/workspaces/solution/src/main/tsconfig.json",
|
||||
jsonToReadableText({
|
||||
compilerOptions: { outDir: "../../dist/" },
|
||||
references: [{ path: "../other" }],
|
||||
}),
|
||||
);
|
||||
fs.writeFileSync(
|
||||
"/src/src/other/tsconfig.json",
|
||||
sys.writeFile(
|
||||
"/home/src/workspaces/solution/src/other/tsconfig.json",
|
||||
jsonToReadableText({
|
||||
compilerOptions: { composite: true, outDir: "../../dist/" },
|
||||
}),
|
||||
@@ -137,7 +128,7 @@ describe("unittests:: tsbuild:: with rootDir of project reference in parentDirec
|
||||
{
|
||||
caption: "Running tsc on main",
|
||||
edit: noop,
|
||||
commandLineArgs: ["-p", "/src/src/main"],
|
||||
commandLineArgs: ["-p", "src/main"],
|
||||
},
|
||||
],
|
||||
});
|
||||
@@ -145,20 +136,20 @@ describe("unittests:: tsbuild:: with rootDir of project reference in parentDirec
|
||||
verifyTsc({
|
||||
scenario: "projectReferenceWithRootDirInParent",
|
||||
subScenario: "reports no error when tsbuildinfo differ",
|
||||
fs: () => projFs,
|
||||
commandLineArgs: ["--b", "/src/src/main/tsconfig.main.json", "--verbose"],
|
||||
modifyFs: fs => {
|
||||
fs.renameSync("/src/src/main/tsconfig.json", "/src/src/main/tsconfig.main.json");
|
||||
fs.renameSync("/src/src/other/tsconfig.json", "/src/src/other/tsconfig.other.json");
|
||||
fs.writeFileSync(
|
||||
"/src/src/main/tsconfig.main.json",
|
||||
sys: getProjectReferenceWithRootDirInParentSys,
|
||||
commandLineArgs: ["--b", "src/main/tsconfig.main.json", "--verbose"],
|
||||
modifySystem: sys => {
|
||||
sys.renameFile("/home/src/workspaces/solution/src/main/tsconfig.json", "/home/src/workspaces/solution/src/main/tsconfig.main.json");
|
||||
sys.renameFile("/home/src/workspaces/solution/src/other/tsconfig.json", "/home/src/workspaces/solution/src/other/tsconfig.other.json");
|
||||
sys.writeFile(
|
||||
"/home/src/workspaces/solution/src/main/tsconfig.main.json",
|
||||
jsonToReadableText({
|
||||
compilerOptions: { composite: true, outDir: "../../dist/" },
|
||||
references: [{ path: "../other/tsconfig.other.json" }],
|
||||
}),
|
||||
);
|
||||
fs.writeFileSync(
|
||||
"/src/src/other/tsconfig.other.json",
|
||||
sys.writeFile(
|
||||
"/home/src/workspaces/solution/src/other/tsconfig.other.json",
|
||||
jsonToReadableText({
|
||||
compilerOptions: { composite: true, outDir: "../../dist/" },
|
||||
}),
|
||||
|
||||
@@ -6,22 +6,19 @@ import {
|
||||
verifyTsc,
|
||||
VerifyTscWithEditsInput,
|
||||
} from "../helpers/tsc.js";
|
||||
import {
|
||||
loadProjectFromFiles,
|
||||
replaceText,
|
||||
} from "../helpers/vfs.js";
|
||||
import { TestServerHost } from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsbuild:: with resolveJsonModule option on project resolveJsonModuleAndComposite", () => {
|
||||
describe("unittests:: tsbuild:: with resolveJsonModule:: option on project resolveJsonModuleAndComposite", () => {
|
||||
function getProjFs(tsconfigFiles: object, additionalCompilerOptions?: CompilerOptions) {
|
||||
return loadProjectFromFiles({
|
||||
"/src/src/hello.json": jsonToReadableText({
|
||||
return TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/solution/project/src/hello.json": jsonToReadableText({
|
||||
hello: "world",
|
||||
}),
|
||||
"/src/src/index.ts": dedent`
|
||||
"/home/src/workspaces/solution/project/src/index.ts": dedent`
|
||||
import hello from "./hello.json"
|
||||
export default hello.hello
|
||||
`,
|
||||
"/src/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/solution/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
moduleResolution: "node",
|
||||
@@ -35,25 +32,25 @@ describe("unittests:: tsbuild:: with resolveJsonModule option on project resolve
|
||||
},
|
||||
...tsconfigFiles,
|
||||
}),
|
||||
});
|
||||
}, { currentDirectory: "/home/src/workspaces/solution" });
|
||||
}
|
||||
|
||||
function verfiyJson(
|
||||
input: Pick<VerifyTscWithEditsInput, "subScenario" | "modifyFs" | "edits"> | string,
|
||||
input: Pick<VerifyTscWithEditsInput, "subScenario" | "modifySystem" | "edits"> | string,
|
||||
tsconfigFiles: object,
|
||||
additionalCompilerOptions?: CompilerOptions,
|
||||
) {
|
||||
if (typeof input === "string") input = { subScenario: input };
|
||||
verifyTsc({
|
||||
scenario: "resolveJsonModule",
|
||||
fs: () => getProjFs(tsconfigFiles, additionalCompilerOptions),
|
||||
commandLineArgs: ["--b", "/src/tsconfig.json", "--v", "--explainFiles", "--listEmittedFiles"],
|
||||
sys: () => getProjFs(tsconfigFiles, additionalCompilerOptions),
|
||||
commandLineArgs: ["--b", "project", "--v", "--explainFiles", "--listEmittedFiles"],
|
||||
...input,
|
||||
});
|
||||
verifyTsc({
|
||||
scenario: "resolveJsonModule",
|
||||
fs: () => getProjFs(tsconfigFiles, { composite: undefined, ...additionalCompilerOptions }),
|
||||
commandLineArgs: ["--b", "/src/tsconfig.json", "--v", "--explainFiles", "--listEmittedFiles"],
|
||||
sys: () => getProjFs(tsconfigFiles, { composite: undefined, ...additionalCompilerOptions }),
|
||||
commandLineArgs: ["--b", "project", "--v", "--explainFiles", "--listEmittedFiles"],
|
||||
...input,
|
||||
subScenario: `${input.subScenario} non-composite`,
|
||||
});
|
||||
@@ -73,9 +70,9 @@ describe("unittests:: tsbuild:: with resolveJsonModule option on project resolve
|
||||
|
||||
verfiyJson({
|
||||
subScenario: "include only with json not in rootDir",
|
||||
modifyFs: fs => {
|
||||
fs.renameSync("/src/src/hello.json", "/src/hello.json");
|
||||
replaceText(fs, "/src/src/index.ts", "./hello.json", "../hello.json");
|
||||
modifySystem: sys => {
|
||||
sys.renameFile("/home/src/workspaces/solution/project/src/hello.json", "/home/src/workspaces/solution/project/hello.json");
|
||||
sys.replaceFileText("/home/src/workspaces/solution/project/src/index.ts", "./hello.json", "../hello.json");
|
||||
},
|
||||
}, {
|
||||
include: [
|
||||
@@ -85,9 +82,9 @@ describe("unittests:: tsbuild:: with resolveJsonModule option on project resolve
|
||||
|
||||
verfiyJson({
|
||||
subScenario: "include only with json without rootDir but outside configDirectory",
|
||||
modifyFs: fs => {
|
||||
fs.renameSync("/src/src/hello.json", "/hello.json");
|
||||
replaceText(fs, "/src/src/index.ts", "./hello.json", "../../hello.json");
|
||||
modifySystem: sys => {
|
||||
sys.renameFile("/home/src/workspaces/solution/project/src/hello.json", "/home/src/workspaces/solution/hello.json");
|
||||
sys.replaceFileText("/home/src/workspaces/solution/project/src/index.ts", "./hello.json", "../../hello.json");
|
||||
},
|
||||
}, {
|
||||
include: [
|
||||
@@ -104,9 +101,9 @@ describe("unittests:: tsbuild:: with resolveJsonModule option on project resolve
|
||||
|
||||
verfiyJson({
|
||||
subScenario: "include of json along with other include and file name matches ts file",
|
||||
modifyFs: fs => {
|
||||
fs.renameSync("/src/src/hello.json", "/src/src/index.json");
|
||||
replaceText(fs, "/src/src/index.ts", "hello.json", "index.json");
|
||||
modifySystem: sys => {
|
||||
sys.renameFile("/home/src/workspaces/solution/project/src/hello.json", "/home/src/workspaces/solution/project/src/index.json");
|
||||
sys.replaceFileText("/home/src/workspaces/solution/project/src/index.ts", "hello.json", "index.json");
|
||||
},
|
||||
}, {
|
||||
include: [
|
||||
@@ -152,25 +149,25 @@ describe("unittests:: tsbuild:: with resolveJsonModule option on project resolve
|
||||
}, { outDir: undefined });
|
||||
});
|
||||
|
||||
describe("unittests:: tsbuild:: with resolveJsonModule option on project importJsonFromProjectReference", () => {
|
||||
describe("unittests:: tsbuild:: with resolveJsonModule:: option on project importJsonFromProjectReference", () => {
|
||||
verifyTsc({
|
||||
scenario: "resolveJsonModule",
|
||||
subScenario: "importing json module from project reference",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/strings/foo.json": jsonToReadableText({
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/solution/project/strings/foo.json": jsonToReadableText({
|
||||
foo: "bar baz",
|
||||
}),
|
||||
"/src/strings/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/solution/project/strings/tsconfig.json": jsonToReadableText({
|
||||
extends: "../tsconfig.json",
|
||||
include: ["foo.json"],
|
||||
references: [],
|
||||
}),
|
||||
"/src/main/index.ts": dedent`
|
||||
import { foo } from '../strings/foo.json';
|
||||
console.log(foo);
|
||||
`,
|
||||
"/src/main/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/solution/project/main/index.ts": dedent`
|
||||
import { foo } from '../strings/foo.json';
|
||||
console.log(foo);
|
||||
`,
|
||||
"/home/src/workspaces/solution/project/main/tsconfig.json": jsonToReadableText({
|
||||
extends: "../tsconfig.json",
|
||||
include: [
|
||||
"./**/*.ts",
|
||||
@@ -179,7 +176,7 @@ describe("unittests:: tsbuild:: with resolveJsonModule option on project importJ
|
||||
path: "../strings/tsconfig.json",
|
||||
}],
|
||||
}),
|
||||
"/src/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/solution/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
target: "es5",
|
||||
module: "commonjs",
|
||||
@@ -195,8 +192,8 @@ describe("unittests:: tsbuild:: with resolveJsonModule option on project importJ
|
||||
],
|
||||
files: [],
|
||||
}),
|
||||
}),
|
||||
commandLineArgs: ["--b", "src/tsconfig.json", "--verbose", "--explainFiles"],
|
||||
}, { currentDirectory: "/home/src/workspaces/solution" }),
|
||||
commandLineArgs: ["--b", "project", "--verbose", "--explainFiles"],
|
||||
edits: noChangeOnlyRuns,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,35 +1,29 @@
|
||||
import { dedent } from "../../_namespaces/Utils.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import { forEachScenarioForRootsFromReferencedProject } from "../helpers/projectRoots.js";
|
||||
import {
|
||||
noChangeRun,
|
||||
verifyTsc,
|
||||
} from "../helpers/tsc.js";
|
||||
import {
|
||||
appendText,
|
||||
loadProjectFromFiles,
|
||||
} from "../helpers/vfs.js";
|
||||
import { verifyTsc } from "../helpers/tsc.js";
|
||||
import { TestServerHost } from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsbuild:: roots::", () => {
|
||||
verifyTsc({
|
||||
scenario: "roots",
|
||||
subScenario: `when two root files are consecutive`,
|
||||
commandLineArgs: ["--b", "/src/tsconfig.json", "-v"],
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/file1.ts": `export const x = "hello";`,
|
||||
"/src/file2.ts": `export const y = "world";`,
|
||||
"/src/tsconfig.json": jsonToReadableText({
|
||||
commandLineArgs: ["--b", "-v"],
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/file1.ts": `export const x = "hello";`,
|
||||
"/home/src/workspaces/project/file2.ts": `export const y = "world";`,
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: { composite: true },
|
||||
include: ["*.ts"],
|
||||
}),
|
||||
}),
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
edits: [{
|
||||
caption: "delete file1",
|
||||
edit: fs => {
|
||||
fs.rimrafSync("/src/file1.ts");
|
||||
fs.rimrafSync("/src/file1.js");
|
||||
fs.rimrafSync("/src/file1.d.ts");
|
||||
edit: sys => {
|
||||
sys.rimrafSync("/home/src/workspaces/project/file1.ts");
|
||||
sys.rimrafSync("/home/src/workspaces/project/file1.js");
|
||||
sys.rimrafSync("/home/src/workspaces/project/file1.d.ts");
|
||||
},
|
||||
}],
|
||||
});
|
||||
@@ -37,24 +31,24 @@ describe("unittests:: tsbuild:: roots::", () => {
|
||||
verifyTsc({
|
||||
scenario: "roots",
|
||||
subScenario: `when multiple root files are consecutive`,
|
||||
commandLineArgs: ["--b", "/src/tsconfig.json", "-v"],
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/file1.ts": `export const x = "hello";`,
|
||||
"/src/file2.ts": `export const y = "world";`,
|
||||
"/src/file3.ts": `export const y = "world";`,
|
||||
"/src/file4.ts": `export const y = "world";`,
|
||||
"/src/tsconfig.json": jsonToReadableText({
|
||||
commandLineArgs: ["--b", "-v"],
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/file1.ts": `export const x = "hello";`,
|
||||
"/home/src/workspaces/project/file2.ts": `export const y = "world";`,
|
||||
"/home/src/workspaces/project/file3.ts": `export const y = "world";`,
|
||||
"/home/src/workspaces/project/file4.ts": `export const y = "world";`,
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: { composite: true },
|
||||
include: ["*.ts"],
|
||||
}),
|
||||
}),
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
edits: [{
|
||||
caption: "delete file1",
|
||||
edit: fs => {
|
||||
fs.rimrafSync("/src/file1.ts");
|
||||
fs.rimrafSync("/src/file1.js");
|
||||
fs.rimrafSync("/src/file1.d.ts");
|
||||
edit: sys => {
|
||||
sys.rimrafSync("/home/src/workspaces/project/file1.ts");
|
||||
sys.rimrafSync("/home/src/workspaces/project/file1.js");
|
||||
sys.rimrafSync("/home/src/workspaces/project/file1.d.ts");
|
||||
},
|
||||
}],
|
||||
});
|
||||
@@ -62,26 +56,26 @@ describe("unittests:: tsbuild:: roots::", () => {
|
||||
verifyTsc({
|
||||
scenario: "roots",
|
||||
subScenario: `when files are not consecutive`,
|
||||
commandLineArgs: ["--b", "/src/tsconfig.json", "-v"],
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/file1.ts": `export const x = "hello";`,
|
||||
"/src/random.d.ts": `export const random = "world";`,
|
||||
"/src/file2.ts": dedent`
|
||||
import { random } from "./random";
|
||||
export const y = "world";
|
||||
`,
|
||||
"/src/tsconfig.json": jsonToReadableText({
|
||||
commandLineArgs: ["--b", "-v"],
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/file1.ts": `export const x = "hello";`,
|
||||
"/home/src/workspaces/project/random.d.ts": `export const random = "world";`,
|
||||
"/home/src/workspaces/project/file2.ts": dedent`
|
||||
import { random } from "./random";
|
||||
export const y = "world";
|
||||
`,
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: { composite: true },
|
||||
include: ["file*.ts"],
|
||||
}),
|
||||
}),
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
edits: [{
|
||||
caption: "delete file1",
|
||||
edit: fs => {
|
||||
fs.rimrafSync("/src/file1.ts");
|
||||
fs.rimrafSync("/src/file1.js");
|
||||
fs.rimrafSync("/src/file1.d.ts");
|
||||
edit: sys => {
|
||||
sys.rimrafSync("/home/src/workspaces/project/file1.ts");
|
||||
sys.rimrafSync("/home/src/workspaces/project/file1.js");
|
||||
sys.rimrafSync("/home/src/workspaces/project/file1.d.ts");
|
||||
},
|
||||
}],
|
||||
});
|
||||
@@ -89,64 +83,55 @@ describe("unittests:: tsbuild:: roots::", () => {
|
||||
verifyTsc({
|
||||
scenario: "roots",
|
||||
subScenario: `when consecutive and non consecutive are mixed`,
|
||||
commandLineArgs: ["--b", "/src/tsconfig.json", "-v"],
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/file1.ts": `export const x = "hello";`,
|
||||
"/src/file2.ts": `export const y = "world";`,
|
||||
"/src/random.d.ts": `export const random = "hello";`,
|
||||
"/src/nonconsecutive.ts": dedent`
|
||||
commandLineArgs: ["--b", "-v"],
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/file1.ts": `export const x = "hello";`,
|
||||
"/home/src/workspaces/project/file2.ts": `export const y = "world";`,
|
||||
"/home/src/workspaces/project/random.d.ts": `export const random = "hello";`,
|
||||
"/home/src/workspaces/project/nonconsecutive.ts": dedent`
|
||||
import { random } from "./random";
|
||||
export const nonConsecutive = "hello";
|
||||
`,
|
||||
"/src/random1.d.ts": `export const random = "hello";`,
|
||||
"/src/asArray1.ts": dedent`
|
||||
"/home/src/workspaces/project/random1.d.ts": `export const random = "hello";`,
|
||||
"/home/src/workspaces/project/asArray1.ts": dedent`
|
||||
import { random } from "./random1";
|
||||
export const x = "hello";
|
||||
`,
|
||||
"/src/asArray2.ts": `export const x = "hello";`,
|
||||
"/src/asArray3.ts": `export const x = "hello";`,
|
||||
"/src/random2.d.ts": `export const random = "hello";`,
|
||||
"/src/anotherNonConsecutive.ts": dedent`
|
||||
"/home/src/workspaces/project/asArray2.ts": `export const x = "hello";`,
|
||||
"/home/src/workspaces/project/asArray3.ts": `export const x = "hello";`,
|
||||
"/home/src/workspaces/project/random2.d.ts": `export const random = "hello";`,
|
||||
"/home/src/workspaces/project/anotherNonConsecutive.ts": dedent`
|
||||
import { random } from "./random2";
|
||||
export const nonConsecutive = "hello";
|
||||
`,
|
||||
"/src/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: { composite: true },
|
||||
include: ["file*.ts", "nonconsecutive*.ts", "asArray*.ts", "anotherNonConsecutive.ts"],
|
||||
}),
|
||||
}),
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
edits: [{
|
||||
caption: "delete file1",
|
||||
edit: fs => {
|
||||
fs.rimrafSync("/src/file1.ts");
|
||||
fs.rimrafSync("/src/file1.js");
|
||||
fs.rimrafSync("/src/file1.d.ts");
|
||||
edit: sys => {
|
||||
sys.rimrafSync("/home/src/workspaces/project/file1.ts");
|
||||
sys.rimrafSync("/home/src/workspaces/project/file1.js");
|
||||
sys.rimrafSync("/home/src/workspaces/project/file1.d.ts");
|
||||
},
|
||||
}],
|
||||
});
|
||||
|
||||
describe("when root file is from referenced project", () => {
|
||||
forEachScenarioForRootsFromReferencedProject((subScenario, getFsContents) => {
|
||||
verifyTsc({
|
||||
scenario: "roots",
|
||||
subScenario,
|
||||
commandLineArgs: ["--b", "projects/server", "-v", "--traceResolution", "--explainFiles"],
|
||||
fs: () => loadProjectFromFiles(getFsContents(), { cwd: "/home/src/workspaces" }),
|
||||
edits: [
|
||||
noChangeRun,
|
||||
{
|
||||
caption: "edit logging file",
|
||||
edit: fs => appendText(fs, "/home/src/workspaces/projects/shared/src/logging.ts", "export const x = 10;"),
|
||||
},
|
||||
noChangeRun,
|
||||
{
|
||||
caption: "delete random file",
|
||||
edit: fs => fs.unlinkSync("/home/src/workspaces/projects/shared/src/random.ts"),
|
||||
},
|
||||
noChangeRun,
|
||||
],
|
||||
});
|
||||
});
|
||||
forEachScenarioForRootsFromReferencedProject(
|
||||
/*forTsserver*/ false,
|
||||
(subScenario, sys, edits) => {
|
||||
verifyTsc({
|
||||
scenario: "roots",
|
||||
subScenario,
|
||||
commandLineArgs: ["--b", "projects/server", "-v", "--traceResolution", "--explainFiles"],
|
||||
sys,
|
||||
edits: edits(),
|
||||
});
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,69 +1,38 @@
|
||||
import * as fakes from "../../_namespaces/fakes.js";
|
||||
import * as Harness from "../../_namespaces/Harness.js";
|
||||
import { Baseline } from "../../_namespaces/Harness.js";
|
||||
import * as ts from "../../_namespaces/ts.js";
|
||||
import * as vfs from "../../_namespaces/vfs.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import { patchHostForBuildInfoReadWrite } from "../helpers/baseline.js";
|
||||
import { getTypeScriptLibTestLocation } from "../helpers/contents.js";
|
||||
import {
|
||||
libContent,
|
||||
libPath,
|
||||
} from "../helpers/contents.js";
|
||||
import {
|
||||
getFsForSampleProjectReferences,
|
||||
getSysForSampleProjectReferences,
|
||||
getSysForSampleProjectReferencesBuilt,
|
||||
} from "../helpers/sampleProjectReferences.js";
|
||||
import { createSolutionBuilderHostForBaseline } from "../helpers/solutionBuilder.js";
|
||||
import {
|
||||
createSolutionBuilderHostForBaseline,
|
||||
verifySolutionBuilderWithDifferentTsVersion,
|
||||
} from "../helpers/solutionBuilder.js";
|
||||
import {
|
||||
noChangeOnlyRuns,
|
||||
noChangeRun,
|
||||
testTscCompileLike,
|
||||
TestTscEdit,
|
||||
TscCompileSystem,
|
||||
verifyTsc,
|
||||
verifyTscCompileLike,
|
||||
} from "../helpers/tsc.js";
|
||||
import {
|
||||
appendText,
|
||||
loadProjectFromFiles,
|
||||
prependText,
|
||||
replaceText,
|
||||
} from "../helpers/vfs.js";
|
||||
import {
|
||||
changeToHostTrackingWrittenFiles,
|
||||
libFile,
|
||||
SerializeOutputOrder,
|
||||
TestServerHost,
|
||||
} from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsbuild:: on 'sample1' project", () => {
|
||||
let projFs: vfs.FileSystem;
|
||||
let projFsWithBuild: vfs.FileSystem;
|
||||
before(() => {
|
||||
projFs = getFsForSampleProjectReferences();
|
||||
});
|
||||
|
||||
after(() => {
|
||||
projFs = undefined!; // Release the contents
|
||||
projFsWithBuild = undefined!;
|
||||
});
|
||||
|
||||
function getSampleFsAfterBuild() {
|
||||
if (projFsWithBuild) return projFsWithBuild;
|
||||
const fs = projFs.shadow();
|
||||
const sys = new fakes.System(fs, { executingFilePath: libFile.path });
|
||||
const host = createSolutionBuilderHostForBaseline(sys as TscCompileSystem);
|
||||
const builder = ts.createSolutionBuilder(host, ["tests"], {});
|
||||
builder.build();
|
||||
fs.makeReadonly();
|
||||
return projFsWithBuild = fs;
|
||||
}
|
||||
|
||||
describe("sanity check of clean build of 'sample1' project", () => {
|
||||
verifyTsc({
|
||||
scenario: "sample1",
|
||||
subScenario: "builds correctly when outDir is specified",
|
||||
fs: () => projFs,
|
||||
sys: getSysForSampleProjectReferences,
|
||||
commandLineArgs: ["--b", "tests"],
|
||||
modifyFs: fs =>
|
||||
fs.writeFileSync(
|
||||
modifySystem: sys =>
|
||||
sys.writeFile(
|
||||
"logic/tsconfig.json",
|
||||
jsonToReadableText({
|
||||
compilerOptions: { composite: true, declaration: true, sourceMap: true, outDir: "outDir" },
|
||||
@@ -75,10 +44,10 @@ describe("unittests:: tsbuild:: on 'sample1' project", () => {
|
||||
verifyTsc({
|
||||
scenario: "sample1",
|
||||
subScenario: "builds correctly when declarationDir is specified",
|
||||
fs: () => projFs,
|
||||
sys: getSysForSampleProjectReferences,
|
||||
commandLineArgs: ["--b", "tests"],
|
||||
modifyFs: fs =>
|
||||
fs.writeFileSync(
|
||||
modifySystem: sys =>
|
||||
sys.writeFile(
|
||||
"logic/tsconfig.json",
|
||||
jsonToReadableText({
|
||||
compilerOptions: { composite: true, declaration: true, sourceMap: true, declarationDir: "out/decls" },
|
||||
@@ -90,9 +59,9 @@ describe("unittests:: tsbuild:: on 'sample1' project", () => {
|
||||
verifyTsc({
|
||||
scenario: "sample1",
|
||||
subScenario: "builds correctly when project is not composite or doesnt have any references",
|
||||
fs: () => projFs,
|
||||
sys: getSysForSampleProjectReferences,
|
||||
commandLineArgs: ["--b", "core", "--verbose"],
|
||||
modifyFs: fs => replaceText(fs, "core/tsconfig.json", `"composite": true,`, ""),
|
||||
modifySystem: sys => sys.replaceFileText("core/tsconfig.json", `"composite": true,`, ""),
|
||||
});
|
||||
});
|
||||
|
||||
@@ -100,7 +69,7 @@ describe("unittests:: tsbuild:: on 'sample1' project", () => {
|
||||
verifyTsc({
|
||||
scenario: "sample1",
|
||||
subScenario: "does not write any files in a dry build",
|
||||
fs: () => projFs,
|
||||
sys: getSysForSampleProjectReferences,
|
||||
commandLineArgs: ["--b", "tests", "--dry"],
|
||||
});
|
||||
});
|
||||
@@ -109,32 +78,34 @@ describe("unittests:: tsbuild:: on 'sample1' project", () => {
|
||||
verifyTsc({
|
||||
scenario: "sample1",
|
||||
subScenario: "removes all files it built",
|
||||
fs: getSampleFsAfterBuild,
|
||||
sys: getSysForSampleProjectReferencesBuilt,
|
||||
commandLineArgs: ["--b", "tests", "--clean"],
|
||||
edits: noChangeOnlyRuns,
|
||||
});
|
||||
|
||||
verifyTscCompileLike(testTscCompileLike, {
|
||||
verifyTsc({
|
||||
scenario: "sample1",
|
||||
subScenario: "cleans till project specified",
|
||||
fs: getSampleFsAfterBuild,
|
||||
sys: getSysForSampleProjectReferencesBuilt,
|
||||
commandLineArgs: ["--b", "logic", "--clean"],
|
||||
compile: sys => {
|
||||
const buildHost = createSolutionBuilderHostForBaseline(sys);
|
||||
const builder = ts.createSolutionBuilder(buildHost, ["third/tsconfig.json"], {});
|
||||
const builder = ts.createSolutionBuilder(buildHost, ["tests"], {});
|
||||
sys.exit(builder.clean("logic"));
|
||||
return buildHost.getPrograms;
|
||||
},
|
||||
});
|
||||
|
||||
verifyTscCompileLike(testTscCompileLike, {
|
||||
verifyTsc({
|
||||
scenario: "sample1",
|
||||
subScenario: "cleaning project in not build order doesnt throw error",
|
||||
fs: getSampleFsAfterBuild,
|
||||
sys: getSysForSampleProjectReferencesBuilt,
|
||||
commandLineArgs: ["--b", "logic2", "--clean"],
|
||||
compile: sys => {
|
||||
const buildHost = createSolutionBuilderHostForBaseline(sys);
|
||||
const builder = ts.createSolutionBuilder(buildHost, ["third/tsconfig.json"], {});
|
||||
const builder = ts.createSolutionBuilder(buildHost, ["tests"], {});
|
||||
sys.exit(builder.clean("logic2"));
|
||||
return buildHost.getPrograms;
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -143,7 +114,7 @@ describe("unittests:: tsbuild:: on 'sample1' project", () => {
|
||||
verifyTsc({
|
||||
scenario: "sample1",
|
||||
subScenario: "always builds under with force option",
|
||||
fs: () => projFs,
|
||||
sys: getSysForSampleProjectReferences,
|
||||
commandLineArgs: ["--b", "tests", "--force"],
|
||||
edits: noChangeOnlyRuns,
|
||||
});
|
||||
@@ -153,25 +124,22 @@ describe("unittests:: tsbuild:: on 'sample1' project", () => {
|
||||
verifyTsc({
|
||||
scenario: "sample1",
|
||||
subScenario: "can detect when and what to rebuild",
|
||||
fs: getSampleFsAfterBuild,
|
||||
sys: getSysForSampleProjectReferencesBuilt,
|
||||
commandLineArgs: ["--b", "tests", "--verbose"],
|
||||
edits: [
|
||||
// Update a file in the leaf node (tests), only it should rebuild the last one
|
||||
{
|
||||
caption: "Only builds the leaf node project",
|
||||
edit: fs => fs.writeFileSync("tests/index.ts", "const m = 10;"),
|
||||
edit: sys => sys.writeFile("tests/index.ts", "const m = 10;"),
|
||||
},
|
||||
// Update a file in the parent (without affecting types), should get fast downstream builds
|
||||
{
|
||||
caption: "Detects type-only changes in upstream projects",
|
||||
edit: fs => replaceText(fs, "core/index.ts", "HELLO WORLD", "WELCOME PLANET"),
|
||||
edit: sys => sys.replaceFileText("core/index.ts", "HELLO WORLD", "WELCOME PLANET"),
|
||||
},
|
||||
{
|
||||
caption: "rebuilds when tsconfig changes",
|
||||
edit: fs => {
|
||||
replaceText(fs, "tests/tsconfig.json", `"composite": true`, `"composite": true, "target": "es2020"`);
|
||||
fs.writeFileSync(libPath("es2020.full"), libContent);
|
||||
},
|
||||
edit: sys => sys.replaceFileText("tests/tsconfig.json", `"composite": true`, `"composite": true, "target": "es2020"`),
|
||||
},
|
||||
],
|
||||
});
|
||||
@@ -179,32 +147,27 @@ describe("unittests:: tsbuild:: on 'sample1' project", () => {
|
||||
verifyTsc({
|
||||
scenario: "sample1",
|
||||
subScenario: "when input file text does not change but its modified time changes",
|
||||
fs: () => projFs,
|
||||
sys: getSysForSampleProjectReferences,
|
||||
commandLineArgs: ["--b", "tests", "--verbose"],
|
||||
edits: [
|
||||
{
|
||||
caption: "upstream project changes without changing file text",
|
||||
edit: fs => {
|
||||
const time = new Date(fs.time());
|
||||
fs.utimesSync("core/index.ts", time, time);
|
||||
},
|
||||
},
|
||||
],
|
||||
edits: [{
|
||||
caption: "upstream project changes without changing file text",
|
||||
edit: sys => sys.setModifiedTime("core/index.ts", sys.now()),
|
||||
}],
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "sample1",
|
||||
subScenario: "when declarationMap changes",
|
||||
fs: () => projFs,
|
||||
sys: getSysForSampleProjectReferences,
|
||||
commandLineArgs: ["--b", "tests", "--verbose"],
|
||||
edits: [
|
||||
{
|
||||
caption: "Disable declarationMap",
|
||||
edit: fs => replaceText(fs, "core/tsconfig.json", `"declarationMap": true,`, `"declarationMap": false,`),
|
||||
edit: sys => sys.replaceFileText("core/tsconfig.json", `"declarationMap": true,`, `"declarationMap": false,`),
|
||||
},
|
||||
{
|
||||
caption: "Enable declarationMap",
|
||||
edit: fs => replaceText(fs, "core/tsconfig.json", `"declarationMap": false,`, `"declarationMap": true,`),
|
||||
edit: sys => sys.replaceFileText("core/tsconfig.json", `"declarationMap": false,`, `"declarationMap": true,`),
|
||||
},
|
||||
],
|
||||
});
|
||||
@@ -212,109 +175,105 @@ describe("unittests:: tsbuild:: on 'sample1' project", () => {
|
||||
verifyTsc({
|
||||
scenario: "sample1",
|
||||
subScenario: "indicates that it would skip builds during a dry build",
|
||||
fs: getSampleFsAfterBuild,
|
||||
sys: getSysForSampleProjectReferencesBuilt,
|
||||
commandLineArgs: ["--b", "tests", "--dry"],
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "sample1",
|
||||
subScenario: "rebuilds from start if force option is set",
|
||||
fs: getSampleFsAfterBuild,
|
||||
sys: getSysForSampleProjectReferencesBuilt,
|
||||
commandLineArgs: ["--b", "tests", "--verbose", "--force"],
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "sample1",
|
||||
subScenario: "tsbuildinfo has error",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/project/main.ts": "export const x = 10;",
|
||||
"/src/project/tsconfig.json": "{}",
|
||||
"/src/project/tsconfig.tsbuildinfo": "Some random string",
|
||||
}),
|
||||
commandLineArgs: ["--b", "src/project", "-i", "-v"],
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/main.ts": "export const x = 10;",
|
||||
"/home/src/workspaces/project/tsconfig.json": "{}",
|
||||
"/home/src/workspaces/project/tsconfig.tsbuildinfo": "Some random string",
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
commandLineArgs: ["--b", "-i", "-v"],
|
||||
edits: [{
|
||||
caption: "tsbuildinfo written has error",
|
||||
edit: fs => prependText(fs, "/src/project/tsconfig.tsbuildinfo", "Some random string"),
|
||||
edit: sys => sys.prependFile("/home/src/workspaces/project/tsconfig.tsbuildinfo", "Some random string"),
|
||||
}],
|
||||
});
|
||||
|
||||
verifyTscCompileLike(testTscCompileLike, {
|
||||
verifySolutionBuilderWithDifferentTsVersion({
|
||||
scenario: "sample1",
|
||||
subScenario: "rebuilds completely when version in tsbuildinfo doesnt match ts version",
|
||||
fs: getSampleFsAfterBuild,
|
||||
sys: getSysForSampleProjectReferencesBuilt,
|
||||
commandLineArgs: ["--b", "tests", "--verbose"],
|
||||
compile: sys => {
|
||||
// Buildinfo will have version which does not match with current ts version
|
||||
const buildHost = createSolutionBuilderHostForBaseline(sys, "FakeTSCurrentVersion");
|
||||
const builder = ts.createSolutionBuilder(buildHost, ["tests"], { verbose: true });
|
||||
sys.exit(builder.build());
|
||||
},
|
||||
});
|
||||
}, ["tests"]);
|
||||
|
||||
verifyTscCompileLike(testTscCompileLike, {
|
||||
verifySolutionBuilderWithDifferentTsVersion({
|
||||
scenario: "sample1",
|
||||
subScenario: "does not rebuild if there is no program and bundle in the ts build info event if version doesnt match ts version",
|
||||
fs: () => {
|
||||
const fs = projFs.shadow();
|
||||
const host = fakes.SolutionBuilderHost.create(fs, /*options*/ undefined, /*setParentNodes*/ undefined, ts.createAbstractBuilder);
|
||||
sys: () => {
|
||||
const sys = getSysForSampleProjectReferences();
|
||||
patchHostForBuildInfoReadWrite(sys);
|
||||
const host = ts.createSolutionBuilderHost(
|
||||
sys,
|
||||
ts.createAbstractBuilder,
|
||||
ts.createDiagnosticReporter(sys, /*pretty*/ true),
|
||||
ts.createBuilderStatusReporter(sys, /*pretty*/ true),
|
||||
);
|
||||
const builder = ts.createSolutionBuilder(host, ["tests"], { verbose: true });
|
||||
builder.build();
|
||||
fs.makeReadonly();
|
||||
return fs;
|
||||
sys.clearOutput();
|
||||
return sys;
|
||||
},
|
||||
commandLineArgs: ["--b", "tests", "--verbose"],
|
||||
compile: sys => {
|
||||
// Buildinfo will have version which does not match with current ts version
|
||||
const buildHost = createSolutionBuilderHostForBaseline(sys, "FakeTSCurrentVersion");
|
||||
const builder = ts.createSolutionBuilder(buildHost, ["tests"], { verbose: true });
|
||||
sys.exit(builder.build());
|
||||
},
|
||||
});
|
||||
}, ["tests"]);
|
||||
|
||||
verifyTsc({
|
||||
scenario: "sample1",
|
||||
subScenario: "rebuilds when extended config file changes",
|
||||
fs: () => projFs,
|
||||
sys: getSysForSampleProjectReferences,
|
||||
commandLineArgs: ["--b", "tests", "--verbose"],
|
||||
modifyFs: fs => {
|
||||
fs.writeFileSync("tests/tsconfig.base.json", jsonToReadableText({ compilerOptions: { target: "es5" } }));
|
||||
replaceText(fs, "tests/tsconfig.json", `"references": [`, `"extends": "./tsconfig.base.json", "references": [`);
|
||||
modifySystem: sys => {
|
||||
sys.writeFile("tests/tsconfig.base.json", jsonToReadableText({ compilerOptions: { target: "es5" } }));
|
||||
sys.replaceFileText("tests/tsconfig.json", `"references": [`, `"extends": "./tsconfig.base.json", "references": [`);
|
||||
},
|
||||
edits: [{
|
||||
caption: "incremental-declaration-changes",
|
||||
edit: fs => fs.writeFileSync("tests/tsconfig.base.json", jsonToReadableText({ compilerOptions: {} })),
|
||||
edit: sys => sys.writeFile("tests/tsconfig.base.json", jsonToReadableText({ compilerOptions: {} })),
|
||||
}],
|
||||
});
|
||||
|
||||
verifyTscCompileLike(testTscCompileLike, {
|
||||
verifyTsc({
|
||||
scenario: "sample1",
|
||||
subScenario: "builds till project specified",
|
||||
fs: () => projFs,
|
||||
sys: getSysForSampleProjectReferences,
|
||||
commandLineArgs: ["--build", "logic/tsconfig.json"],
|
||||
compile: sys => {
|
||||
const buildHost = createSolutionBuilderHostForBaseline(sys);
|
||||
const builder = ts.createSolutionBuilder(buildHost, ["tests"], {});
|
||||
sys.exit(builder.build("logic/tsconfig.json"));
|
||||
return buildHost.getPrograms;
|
||||
},
|
||||
});
|
||||
|
||||
verifyTscCompileLike(testTscCompileLike, {
|
||||
verifyTsc({
|
||||
scenario: "sample1",
|
||||
subScenario: "building project in not build order doesnt throw error",
|
||||
fs: () => projFs,
|
||||
sys: getSysForSampleProjectReferences,
|
||||
commandLineArgs: ["--build", "logic2/tsconfig.json"],
|
||||
compile: sys => {
|
||||
const buildHost = createSolutionBuilderHostForBaseline(sys);
|
||||
const builder = ts.createSolutionBuilder(buildHost, ["tests"], {});
|
||||
sys.exit(builder.build("logic2/tsconfig.json"));
|
||||
return buildHost.getPrograms;
|
||||
},
|
||||
});
|
||||
|
||||
it("building using getNextInvalidatedProject", () => {
|
||||
const baseline: string[] = [];
|
||||
const system = changeToHostTrackingWrittenFiles(
|
||||
fakes.patchHostForBuildInfoReadWrite(
|
||||
patchHostForBuildInfoReadWrite(
|
||||
getSysForSampleProjectReferences(),
|
||||
),
|
||||
);
|
||||
@@ -327,7 +286,7 @@ describe("unittests:: tsbuild:: on 'sample1' project", () => {
|
||||
verifyBuildNextResult(); // logic
|
||||
verifyBuildNextResult(); // tests
|
||||
verifyBuildNextResult(); // All Done
|
||||
Harness.Baseline.runBaseline(`tsbuild/sample1/building-using-getNextInvalidatedProject.js`, baseline.join("\r\n"));
|
||||
Baseline.runBaseline(`tsbuild/sample1/building-using-getNextInvalidatedProject.js`, baseline.join("\r\n"));
|
||||
|
||||
function verifyBuildNextResult() {
|
||||
const project = builder.getNextInvalidatedProject();
|
||||
@@ -337,15 +296,16 @@ describe("unittests:: tsbuild:: on 'sample1' project", () => {
|
||||
}
|
||||
});
|
||||
|
||||
verifyTscCompileLike(testTscCompileLike, {
|
||||
verifyTsc({
|
||||
scenario: "sample1",
|
||||
subScenario: "building using buildReferencedProject",
|
||||
fs: () => projFs,
|
||||
sys: getSysForSampleProjectReferences,
|
||||
commandLineArgs: ["--build", "logic2/tsconfig.json"],
|
||||
compile: sys => {
|
||||
const buildHost = createSolutionBuilderHostForBaseline(sys);
|
||||
const builder = ts.createSolutionBuilder(buildHost, ["tests"], { verbose: true });
|
||||
sys.exit(builder.buildReferences("tests"));
|
||||
return buildHost.getPrograms;
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -354,9 +314,9 @@ describe("unittests:: tsbuild:: on 'sample1' project", () => {
|
||||
verifyTsc({
|
||||
scenario: "sample1",
|
||||
subScenario: "builds downstream projects even if upstream projects have errors",
|
||||
fs: () => projFs,
|
||||
sys: getSysForSampleProjectReferences,
|
||||
commandLineArgs: ["--b", "tests", "--verbose"],
|
||||
modifyFs: fs => replaceText(fs, "logic/index.ts", "c.multiply(10, 15)", `c.muitply()`),
|
||||
modifySystem: sys => sys.replaceFileText("logic/index.ts", "c.multiply(10, 15)", `c.muitply()`),
|
||||
edits: noChangeOnlyRuns,
|
||||
});
|
||||
|
||||
@@ -364,14 +324,14 @@ describe("unittests:: tsbuild:: on 'sample1' project", () => {
|
||||
verifyTsc({
|
||||
scenario: "sample1",
|
||||
subScenario: `skips builds downstream projects if upstream projects have errors with stopBuildOnErrors${skipReferenceCoreFromTest ? " when test does not reference core" : ""}`,
|
||||
fs: () => getFsForSampleProjectReferences(/*withNodeNext*/ undefined, skipReferenceCoreFromTest),
|
||||
sys: () => getSysForSampleProjectReferences(/*withNodeNext*/ undefined, skipReferenceCoreFromTest),
|
||||
commandLineArgs: ["--b", "tests", "--verbose", "--stopBuildOnErrors"],
|
||||
modifyFs: fs => appendText(fs, "core/index.ts", `multiply();`),
|
||||
modifySystem: sys => sys.appendFile("core/index.ts", `multiply();`),
|
||||
edits: [
|
||||
noChangeRun,
|
||||
{
|
||||
caption: "fix error",
|
||||
edit: fs => replaceText(fs, "core/index.ts", "multiply();", ""),
|
||||
edit: sys => sys.replaceFileText("core/index.ts", "multiply();", ""),
|
||||
},
|
||||
],
|
||||
})
|
||||
@@ -382,7 +342,7 @@ describe("unittests:: tsbuild:: on 'sample1' project", () => {
|
||||
it("invalidates projects correctly", () => {
|
||||
const baseline: string[] = [];
|
||||
const system = changeToHostTrackingWrittenFiles(
|
||||
fakes.patchHostForBuildInfoReadWrite(
|
||||
patchHostForBuildInfoReadWrite(
|
||||
getSysForSampleProjectReferences(),
|
||||
),
|
||||
);
|
||||
@@ -403,7 +363,7 @@ describe("unittests:: tsbuild:: on 'sample1' project", () => {
|
||||
// Rebuild this project
|
||||
system.appendFile("logic/index.ts", `export class cNew {}`);
|
||||
verifyInvalidation("Dts change to Logic");
|
||||
Harness.Baseline.runBaseline(`tsbuild/sample1/invalidates-projects-correctly.js`, baseline.join("\r\n"));
|
||||
Baseline.runBaseline(`tsbuild/sample1/invalidates-projects-correctly.js`, baseline.join("\r\n"));
|
||||
|
||||
function verifyInvalidation(heading: string) {
|
||||
// Rebuild this project
|
||||
@@ -426,9 +386,8 @@ describe("unittests:: tsbuild:: on 'sample1' project", () => {
|
||||
const coreChanges: TestTscEdit[] = [
|
||||
{
|
||||
caption: "incremental-declaration-changes",
|
||||
edit: fs =>
|
||||
appendText(
|
||||
fs,
|
||||
edit: sys =>
|
||||
sys.appendFile(
|
||||
"core/index.ts",
|
||||
`
|
||||
export class someClass { }`,
|
||||
@@ -436,9 +395,8 @@ export class someClass { }`,
|
||||
},
|
||||
{
|
||||
caption: "incremental-declaration-doesnt-change",
|
||||
edit: fs =>
|
||||
appendText(
|
||||
fs,
|
||||
edit: sys =>
|
||||
sys.appendFile(
|
||||
"core/index.ts",
|
||||
`
|
||||
class someClass2 { }`,
|
||||
@@ -451,21 +409,21 @@ class someClass2 { }`,
|
||||
verifyTsc({
|
||||
scenario: "sample1",
|
||||
subScenario: "listFiles",
|
||||
fs: () => projFs,
|
||||
sys: getSysForSampleProjectReferences,
|
||||
commandLineArgs: ["--b", "tests", "--listFiles"],
|
||||
edits: coreChanges,
|
||||
});
|
||||
verifyTsc({
|
||||
scenario: "sample1",
|
||||
subScenario: "listEmittedFiles",
|
||||
fs: () => projFs,
|
||||
sys: getSysForSampleProjectReferences,
|
||||
commandLineArgs: ["--b", "tests", "--listEmittedFiles"],
|
||||
edits: coreChanges,
|
||||
});
|
||||
verifyTsc({
|
||||
scenario: "sample1",
|
||||
subScenario: "explainFiles",
|
||||
fs: () => projFs,
|
||||
sys: getSysForSampleProjectReferences,
|
||||
commandLineArgs: ["--b", "tests", "--explainFiles", "--v"],
|
||||
edits: coreChanges,
|
||||
});
|
||||
@@ -474,7 +432,7 @@ class someClass2 { }`,
|
||||
describe("emit output", () => {
|
||||
verifyTsc({
|
||||
subScenario: "sample",
|
||||
fs: () => projFs,
|
||||
sys: getSysForSampleProjectReferences,
|
||||
scenario: "sample1",
|
||||
commandLineArgs: ["--b", "tests", "--verbose"],
|
||||
baselineSourceMap: true,
|
||||
@@ -483,9 +441,8 @@ class someClass2 { }`,
|
||||
...coreChanges,
|
||||
{
|
||||
caption: "when logic config changes declaration dir",
|
||||
edit: fs =>
|
||||
replaceText(
|
||||
fs,
|
||||
edit: sys =>
|
||||
sys.replaceFileText(
|
||||
"logic/tsconfig.json",
|
||||
`"declaration": true,`,
|
||||
`"declaration": true,
|
||||
@@ -499,10 +456,9 @@ class someClass2 { }`,
|
||||
verifyTsc({
|
||||
scenario: "sample1",
|
||||
subScenario: "when logic specifies tsBuildInfoFile",
|
||||
fs: () => projFs,
|
||||
modifyFs: fs =>
|
||||
replaceText(
|
||||
fs,
|
||||
sys: getSysForSampleProjectReferences,
|
||||
modifySystem: sys =>
|
||||
sys.replaceFileText(
|
||||
"logic/tsconfig.json",
|
||||
`"composite": true,`,
|
||||
`"composite": true,
|
||||
@@ -515,11 +471,11 @@ class someClass2 { }`,
|
||||
|
||||
verifyTsc({
|
||||
subScenario: "when declaration option changes",
|
||||
fs: () => projFs,
|
||||
sys: getSysForSampleProjectReferences,
|
||||
scenario: "sample1",
|
||||
commandLineArgs: ["--b", "core", "--verbose"],
|
||||
modifyFs: fs =>
|
||||
fs.writeFileSync(
|
||||
modifySystem: sys =>
|
||||
sys.writeFile(
|
||||
"core/tsconfig.json",
|
||||
jsonToReadableText({
|
||||
compilerOptions: {
|
||||
@@ -530,28 +486,27 @@ class someClass2 { }`,
|
||||
),
|
||||
edits: [{
|
||||
caption: "incremental-declaration-changes",
|
||||
edit: fs => replaceText(fs, "core/tsconfig.json", `"incremental": true,`, `"incremental": true, "declaration": true,`),
|
||||
edit: sys => sys.replaceFileText("core/tsconfig.json", `"incremental": true,`, `"incremental": true, "declaration": true,`),
|
||||
}],
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
subScenario: "when target option changes",
|
||||
fs: () => projFs,
|
||||
sys: getSysForSampleProjectReferences,
|
||||
scenario: "sample1",
|
||||
commandLineArgs: ["--b", "core", "--verbose"],
|
||||
modifyFs: fs => {
|
||||
fs.writeFileSync(
|
||||
libPath("esnext.full"),
|
||||
modifySystem: sys => {
|
||||
sys.writeFile(
|
||||
getTypeScriptLibTestLocation("esnext.full"),
|
||||
`/// <reference no-default-lib="true"/>
|
||||
/// <reference lib="esnext" />`,
|
||||
);
|
||||
fs.writeFileSync(libPath("esnext"), libContent);
|
||||
fs.writeFileSync(
|
||||
sys.writeFile(
|
||||
libFile.path,
|
||||
`/// <reference no-default-lib="true"/>
|
||||
/// <reference lib="esnext" />`,
|
||||
);
|
||||
fs.writeFileSync(
|
||||
sys.writeFile(
|
||||
"core/tsconfig.json",
|
||||
jsonToReadableText({
|
||||
compilerOptions: {
|
||||
@@ -565,17 +520,17 @@ class someClass2 { }`,
|
||||
},
|
||||
edits: [{
|
||||
caption: "incremental-declaration-changes",
|
||||
edit: fs => replaceText(fs, "core/tsconfig.json", "esnext", "es5"),
|
||||
edit: sys => sys.replaceFileText("core/tsconfig.json", "esnext", "es5"),
|
||||
}],
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
subScenario: "when module option changes",
|
||||
fs: () => projFs,
|
||||
sys: getSysForSampleProjectReferences,
|
||||
scenario: "sample1",
|
||||
commandLineArgs: ["--b", "core", "--verbose"],
|
||||
modifyFs: fs =>
|
||||
fs.writeFileSync(
|
||||
modifySystem: sys =>
|
||||
sys.writeFile(
|
||||
"core/tsconfig.json",
|
||||
jsonToReadableText({
|
||||
compilerOptions: {
|
||||
@@ -586,17 +541,17 @@ class someClass2 { }`,
|
||||
),
|
||||
edits: [{
|
||||
caption: "incremental-declaration-changes",
|
||||
edit: fs => replaceText(fs, "core/tsconfig.json", `"module": "commonjs"`, `"module": "amd"`),
|
||||
edit: sys => sys.replaceFileText("core/tsconfig.json", `"module": "commonjs"`, `"module": "amd"`),
|
||||
}],
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
subScenario: "when esModuleInterop option changes",
|
||||
fs: () => projFs,
|
||||
sys: getSysForSampleProjectReferences,
|
||||
scenario: "sample1",
|
||||
commandLineArgs: ["--b", "tests", "--verbose"],
|
||||
modifyFs: fs =>
|
||||
fs.writeFileSync(
|
||||
modifySystem: sys =>
|
||||
sys.writeFile(
|
||||
"tests/tsconfig.json",
|
||||
jsonToReadableText({
|
||||
references: [
|
||||
@@ -615,41 +570,41 @@ class someClass2 { }`,
|
||||
),
|
||||
edits: [{
|
||||
caption: "incremental-declaration-changes",
|
||||
edit: fs => replaceText(fs, "tests/tsconfig.json", `"esModuleInterop": false`, `"esModuleInterop": true`),
|
||||
edit: sys => sys.replaceFileText("tests/tsconfig.json", `"esModuleInterop": false`, `"esModuleInterop": true`),
|
||||
}],
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "sample1",
|
||||
subScenario: "reports error if input file is missing",
|
||||
fs: () => projFs,
|
||||
sys: getSysForSampleProjectReferences,
|
||||
commandLineArgs: ["--b", "tests", "--v"],
|
||||
modifyFs: fs => {
|
||||
fs.writeFileSync(
|
||||
modifySystem: sys => {
|
||||
sys.writeFile(
|
||||
"core/tsconfig.json",
|
||||
jsonToReadableText({
|
||||
compilerOptions: { composite: true },
|
||||
files: ["anotherModule.ts", "index.ts", "some_decl.d.ts"],
|
||||
}),
|
||||
);
|
||||
fs.unlinkSync("core/anotherModule.ts");
|
||||
sys.deleteFile("core/anotherModule.ts");
|
||||
},
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "sample1",
|
||||
subScenario: "reports error if input file is missing with force",
|
||||
fs: () => projFs,
|
||||
sys: getSysForSampleProjectReferences,
|
||||
commandLineArgs: ["--b", "tests", "--v", "--f"],
|
||||
modifyFs: fs => {
|
||||
fs.writeFileSync(
|
||||
modifySystem: sys => {
|
||||
sys.writeFile(
|
||||
"core/tsconfig.json",
|
||||
jsonToReadableText({
|
||||
compilerOptions: { composite: true },
|
||||
files: ["anotherModule.ts", "index.ts", "some_decl.d.ts"],
|
||||
}),
|
||||
);
|
||||
fs.unlinkSync("core/anotherModule.ts");
|
||||
sys.deleteFile("core/anotherModule.ts");
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,32 +1,16 @@
|
||||
import * as vfs from "../../_namespaces/vfs.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import { getFsContentsForTransitiveReferences } from "../helpers/transitiveReferences.js";
|
||||
import { getSysForTransitiveReferences } from "../helpers/transitiveReferences.js";
|
||||
import { verifyTsc } from "../helpers/tsc.js";
|
||||
import { loadProjectFromFiles } from "../helpers/vfs.js";
|
||||
import { libFile } from "../helpers/virtualFileSystemWithWatch.js";
|
||||
import { TestServerHost } from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsbuild:: when project reference is referenced transitively", () => {
|
||||
let projFs: vfs.FileSystem;
|
||||
before(() => {
|
||||
projFs = loadProjectFromFiles(
|
||||
getFsContentsForTransitiveReferences(),
|
||||
{
|
||||
cwd: "/user/username/projects/transitiveReferences",
|
||||
executingFilePath: libFile.path,
|
||||
},
|
||||
);
|
||||
});
|
||||
after(() => {
|
||||
projFs = undefined!; // Release the contents
|
||||
});
|
||||
|
||||
function modifyFsBTsToNonRelativeImport(fs: vfs.FileSystem, moduleResolution: "node" | "classic") {
|
||||
fs.writeFileSync(
|
||||
describe("unittests:: tsbuild:: transitiveReferences:: when project reference is referenced transitively", () => {
|
||||
function modifyFsBTsToNonRelativeImport(sys: TestServerHost, moduleResolution: "node" | "classic") {
|
||||
sys.writeFile(
|
||||
"b.ts",
|
||||
`import {A} from 'a';
|
||||
export const b = new A();`,
|
||||
);
|
||||
fs.writeFileSync(
|
||||
sys.writeFile(
|
||||
"tsconfig.b.json",
|
||||
jsonToReadableText({
|
||||
compilerOptions: {
|
||||
@@ -42,23 +26,23 @@ export const b = new A();`,
|
||||
verifyTsc({
|
||||
scenario: "transitiveReferences",
|
||||
subScenario: "builds correctly",
|
||||
fs: () => projFs,
|
||||
sys: getSysForTransitiveReferences,
|
||||
commandLineArgs: ["--b", "tsconfig.c.json", "--listFiles"],
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "transitiveReferences",
|
||||
subScenario: "builds correctly when the referenced project uses different module resolution",
|
||||
fs: () => projFs,
|
||||
sys: getSysForTransitiveReferences,
|
||||
commandLineArgs: ["--b", "tsconfig.c.json", "--listFiles"],
|
||||
modifyFs: fs => modifyFsBTsToNonRelativeImport(fs, "classic"),
|
||||
modifySystem: sys => modifyFsBTsToNonRelativeImport(sys, "classic"),
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "transitiveReferences",
|
||||
subScenario: "reports error about module not found with node resolution with external module name",
|
||||
fs: () => projFs,
|
||||
sys: getSysForTransitiveReferences,
|
||||
commandLineArgs: ["--b", "tsconfig.c.json", "--listFiles"],
|
||||
modifyFs: fs => modifyFsBTsToNonRelativeImport(fs, "node"),
|
||||
modifySystem: sys => modifyFsBTsToNonRelativeImport(sys, "node"),
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
import { dedent } from "../../_namespaces/Utils.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import { verifyTscWatch } from "../helpers/tscWatch.js";
|
||||
import {
|
||||
createWatchedSystem,
|
||||
libFile,
|
||||
} from "../helpers/virtualFileSystemWithWatch.js";
|
||||
import { TestServerHost } from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsbuildWatch:: watchMode:: configFileErrors:: reports syntax errors in config file", () => {
|
||||
function verify(outFile?: object) {
|
||||
@@ -12,7 +9,7 @@ describe("unittests:: tsbuildWatch:: watchMode:: configFileErrors:: reports synt
|
||||
scenario: "configFileErrors",
|
||||
subScenario: `${outFile ? "outFile" : "multiFile"}/reports syntax errors in config file`,
|
||||
sys: () =>
|
||||
createWatchedSystem(
|
||||
TestServerHost.createWatchedSystem(
|
||||
[
|
||||
{ path: `/user/username/projects/myproject/a.ts`, content: "export function foo() { }" },
|
||||
{ path: `/user/username/projects/myproject/b.ts`, content: "export function bar() { }" },
|
||||
@@ -29,7 +26,6 @@ describe("unittests:: tsbuildWatch:: watchMode:: configFileErrors:: reports synt
|
||||
]
|
||||
}`,
|
||||
},
|
||||
libFile,
|
||||
],
|
||||
{ currentDirectory: "/user/username/projects/myproject" },
|
||||
),
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
} from "../helpers/demoProjectReferences.js";
|
||||
import { verifyTscWatch } from "../helpers/tscWatch.js";
|
||||
|
||||
describe("unittests:: tsbuildWatch:: watchMode:: with demo project", () => {
|
||||
describe("unittests:: tsbuildWatch:: watchMode:: with demo:: project", () => {
|
||||
verifyTscWatch({
|
||||
scenario: "demo",
|
||||
subScenario: "updates with circular reference",
|
||||
|
||||
@@ -1,20 +1,16 @@
|
||||
import {
|
||||
getConfigDirExtendsSys,
|
||||
modifyFirstExtendedConfigOfConfigDirExtendsSys,
|
||||
} from "../helpers/extends.js";
|
||||
import { forConfigDirExtendsSysScenario } from "../helpers/extends.js";
|
||||
import { verifyTscWatch } from "../helpers/tscWatch.js";
|
||||
import { createWatchedSystem } from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsbuildWatch:: watchMode:: extends::", () => {
|
||||
verifyTscWatch({
|
||||
scenario: "extends",
|
||||
subScenario: "configDir template",
|
||||
sys: () => createWatchedSystem(getConfigDirExtendsSys(), { currentDirectory: "/home/src/projects/myproject" }),
|
||||
commandLineArgs: ["-b", "-w", "--extendedDiagnostics", "--explainFiles", "-v"],
|
||||
edits: [{
|
||||
caption: "edit extended config file",
|
||||
edit: modifyFirstExtendedConfigOfConfigDirExtendsSys,
|
||||
timeouts: sys => sys.runQueuedTimeoutCallbacks(),
|
||||
}],
|
||||
});
|
||||
forConfigDirExtendsSysScenario(
|
||||
/*forTsserver*/ false,
|
||||
(subScenario, sys, edits) =>
|
||||
verifyTscWatch({
|
||||
scenario: "extends",
|
||||
subScenario,
|
||||
sys,
|
||||
commandLineArgs: ["-b", "-w", "--extendedDiagnostics", "--explainFiles", "-v"],
|
||||
edits: edits(),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
import { getSysForLibResolution } from "../helpers/libraryResolution.js";
|
||||
import { forEachLibResolutionScenario } from "../helpers/libraryResolution.js";
|
||||
import { verifyTscWatch } from "../helpers/tscWatch.js";
|
||||
|
||||
describe("unittests:: tsbuildWatch:: watchMode:: libraryResolution:: library file resolution", () => {
|
||||
function verify(libRedirection?: true) {
|
||||
verifyTscWatch({
|
||||
scenario: "libraryResolution",
|
||||
subScenario: `with config${libRedirection ? " with redirection" : ""}`,
|
||||
sys: () => getSysForLibResolution(libRedirection),
|
||||
commandLineArgs: ["-b", "-w", "project1", "project2", "project3", "project4", "--verbose", "--explainFiles", "--extendedDiagnostics"],
|
||||
});
|
||||
}
|
||||
verify();
|
||||
verify(/*libRedirection*/ true);
|
||||
forEachLibResolutionScenario(
|
||||
/*forTsserver*/ false,
|
||||
/*withoutConfig*/ undefined,
|
||||
(subScenario, sys) =>
|
||||
verifyTscWatch({
|
||||
scenario: "libraryResolution",
|
||||
subScenario,
|
||||
sys,
|
||||
commandLineArgs: ["-b", "-w", "project1", "project2", "project3", "project4", "--verbose", "--explainFiles", "--extendedDiagnostics"],
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
import { dedent } from "../../_namespaces/Utils.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import { verifyTscWatch } from "../helpers/tscWatch.js";
|
||||
import {
|
||||
createWatchedSystem,
|
||||
libFile,
|
||||
} from "../helpers/virtualFileSystemWithWatch.js";
|
||||
import { TestServerHost } from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsbuildWatch:: watchMode:: moduleResolution", () => {
|
||||
describe("unittests:: tsbuildWatch:: watchMode:: moduleResolution::", () => {
|
||||
verifyTscWatch({
|
||||
scenario: "moduleResolutionCache",
|
||||
subScenario: "handles the cache correctly when two projects use different module resolution settings",
|
||||
sys: () =>
|
||||
createWatchedSystem(
|
||||
TestServerHost.createWatchedSystem(
|
||||
[
|
||||
{ path: `/user/username/projects/myproject/project1/index.ts`, content: `import { foo } from "file";` },
|
||||
{ path: `/user/username/projects/myproject/project1/node_modules/file/index.d.ts`, content: "export const foo = 10;" },
|
||||
@@ -43,7 +40,6 @@ describe("unittests:: tsbuildWatch:: watchMode:: moduleResolution", () => {
|
||||
],
|
||||
}),
|
||||
},
|
||||
libFile,
|
||||
],
|
||||
{ currentDirectory: "/user/username/projects/myproject" },
|
||||
),
|
||||
@@ -61,7 +57,7 @@ describe("unittests:: tsbuildWatch:: watchMode:: moduleResolution", () => {
|
||||
scenario: "moduleResolution",
|
||||
subScenario: `resolves specifier in output declaration file from referenced project correctly with cts and mts extensions`,
|
||||
sys: () =>
|
||||
createWatchedSystem([
|
||||
TestServerHost.createWatchedSystem([
|
||||
{
|
||||
path: `/user/username/projects/myproject/packages/pkg1/package.json`,
|
||||
content: jsonToReadableText({
|
||||
@@ -118,7 +114,6 @@ describe("unittests:: tsbuildWatch:: watchMode:: moduleResolution", () => {
|
||||
path: `/user/username/projects/myproject/node_modules/pkg2`,
|
||||
symLink: `/user/username/projects/myproject/packages/pkg2`,
|
||||
},
|
||||
{ ...libFile, path: `/a/lib/lib.es2022.full.d.ts` },
|
||||
], { currentDirectory: "/user/username/projects/myproject" }),
|
||||
commandLineArgs: ["-b", "packages/pkg1", "-w", "--verbose", "--traceResolution"],
|
||||
edits: [
|
||||
@@ -155,7 +150,7 @@ describe("unittests:: tsbuildWatch:: watchMode:: moduleResolution", () => {
|
||||
scenario: "moduleResolution",
|
||||
subScenario: `build mode watches for changes to package-json main fields`,
|
||||
sys: () =>
|
||||
createWatchedSystem([
|
||||
TestServerHost.createWatchedSystem([
|
||||
{
|
||||
path: `/user/username/projects/myproject/packages/pkg1/package.json`,
|
||||
content: jsonToReadableText({
|
||||
@@ -213,7 +208,6 @@ describe("unittests:: tsbuildWatch:: watchMode:: moduleResolution", () => {
|
||||
path: `/user/username/projects/myproject/node_modules/pkg2`,
|
||||
symLink: `/user/username/projects/myproject/packages/pkg2`,
|
||||
},
|
||||
libFile,
|
||||
], { currentDirectory: "/user/username/projects/myproject" }),
|
||||
commandLineArgs: ["-b", "packages/pkg1", "--verbose", "-w", "--traceResolution"],
|
||||
edits: [
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import { libContent } from "../helpers/contents.js";
|
||||
import { forEachNoEmitTscWatch } from "../helpers/noEmit.js";
|
||||
import { verifyTscWatch } from "../helpers/tscWatch.js";
|
||||
import {
|
||||
createWatchedSystem,
|
||||
libFile,
|
||||
} from "../helpers/virtualFileSystemWithWatch.js";
|
||||
import { TestServerHost } from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsbuildWatch:: watchMode:: with noEmit::", () => {
|
||||
function verify(outFile?: object) {
|
||||
@@ -14,8 +10,7 @@ describe("unittests:: tsbuildWatch:: watchMode:: with noEmit::", () => {
|
||||
subScenario: `${outFile ? "outFile" : "multiFile"}/does not go in loop when watching when no files are emitted`,
|
||||
commandLineArgs: ["-b", "-w", "-verbose"],
|
||||
sys: () =>
|
||||
createWatchedSystem({
|
||||
[libFile.path]: libContent,
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/user/username/projects/myproject/a.js": "",
|
||||
"/user/username/projects/myproject/b.ts": "",
|
||||
"/user/username/projects/myproject/tsconfig.json": jsonToReadableText({
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
import * as ts from "../../_namespaces/ts.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import { FsContents } from "../helpers/contents.js";
|
||||
import { createBaseline } from "../helpers/baseline.js";
|
||||
import {
|
||||
getFsContentsForSampleProjectReferences,
|
||||
getFsContentsForSampleProjectReferencesLogicConfig,
|
||||
getSysForSampleProjectReferences,
|
||||
} from "../helpers/sampleProjectReferences.js";
|
||||
import {
|
||||
commonFile1,
|
||||
commonFile2,
|
||||
createBaseline,
|
||||
createSolutionBuilderWithWatchHostForBaseline,
|
||||
noopChange,
|
||||
runWatchBaseline,
|
||||
@@ -17,12 +13,11 @@ import {
|
||||
verifyTscWatch,
|
||||
} from "../helpers/tscWatch.js";
|
||||
import {
|
||||
createWatchedSystem,
|
||||
File,
|
||||
libFile,
|
||||
TestServerHost,
|
||||
} from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsbuildWatch:: watchMode:: program updates", () => {
|
||||
describe("unittests:: tsbuildWatch:: watchMode:: programUpdates::", () => {
|
||||
verifyTscWatch({
|
||||
scenario: "programUpdates",
|
||||
subScenario: "creates solution in watch mode",
|
||||
@@ -47,7 +42,7 @@ describe("unittests:: tsbuildWatch:: watchMode:: program updates", () => {
|
||||
});
|
||||
|
||||
describe("validates the changes and watched files", () => {
|
||||
function verifyProjectChanges(subScenario: string, allFilesGetter: () => FsContents) {
|
||||
function verifyProjectChanges(subScenario: string, sys: () => TestServerHost) {
|
||||
const buildLogicAndTests: TscWatchCompileChange = {
|
||||
caption: "Build logic and tests",
|
||||
edit: ts.noop,
|
||||
@@ -57,31 +52,27 @@ describe("unittests:: tsbuildWatch:: watchMode:: program updates", () => {
|
||||
verifyTscWatch({
|
||||
scenario: "programUpdates",
|
||||
subScenario: `${subScenario}/change builds changes and reports found errors message`,
|
||||
commandLineArgs: ["-b", "-w", "sample1/tests"],
|
||||
sys: () =>
|
||||
createWatchedSystem(
|
||||
allFilesGetter(),
|
||||
{ currentDirectory: "/user/username/projects" },
|
||||
),
|
||||
commandLineArgs: ["-b", "-w", "tests"],
|
||||
sys,
|
||||
edits: [
|
||||
{
|
||||
caption: "Make change to core",
|
||||
edit: sys => sys.appendFile("sample1/core/index.ts", `\nexport class someClass { }`),
|
||||
edit: sys => sys.appendFile("core/index.ts", `\nexport class someClass { }`),
|
||||
timeouts: sys => sys.runQueuedTimeoutCallbacks(), // Builds core
|
||||
},
|
||||
buildLogicAndTests,
|
||||
// Another change requeues and builds it
|
||||
{
|
||||
caption: "Revert core file",
|
||||
edit: sys => sys.replaceFileText("sample1/core/index.ts", `\nexport class someClass { }`, ""),
|
||||
edit: sys => sys.replaceFileText("core/index.ts", `\nexport class someClass { }`, ""),
|
||||
timeouts: sys => sys.runQueuedTimeoutCallbacks(), // Builds core
|
||||
},
|
||||
buildLogicAndTests,
|
||||
{
|
||||
caption: "Make two changes",
|
||||
edit: sys => {
|
||||
sys.appendFile("sample1/core/index.ts", `\nexport class someClass { }`);
|
||||
sys.appendFile("sample1/core/index.ts", `\nexport class someClass2 { }`);
|
||||
sys.appendFile("core/index.ts", `\nexport class someClass { }`);
|
||||
sys.appendFile("core/index.ts", `\nexport class someClass2 { }`);
|
||||
},
|
||||
timeouts: sys => sys.runQueuedTimeoutCallbacks(), // Builds core
|
||||
},
|
||||
@@ -92,15 +83,11 @@ describe("unittests:: tsbuildWatch:: watchMode:: program updates", () => {
|
||||
verifyTscWatch({
|
||||
scenario: "programUpdates",
|
||||
subScenario: `${subScenario}/non local change does not start build of referencing projects`,
|
||||
commandLineArgs: ["-b", "-w", "sample1/tests"],
|
||||
sys: () =>
|
||||
createWatchedSystem(
|
||||
allFilesGetter(),
|
||||
{ currentDirectory: "/user/username/projects" },
|
||||
),
|
||||
commandLineArgs: ["-b", "-w", "tests"],
|
||||
sys,
|
||||
edits: [{
|
||||
caption: "Make local change to core",
|
||||
edit: sys => sys.appendFile("sample1/core/index.ts", `\nfunction foo() { }`),
|
||||
edit: sys => sys.appendFile("core/index.ts", `\nfunction foo() { }`),
|
||||
timeouts: sys => sys.runQueuedTimeoutCallbacks(), // Builds core
|
||||
}],
|
||||
});
|
||||
@@ -108,22 +95,18 @@ describe("unittests:: tsbuildWatch:: watchMode:: program updates", () => {
|
||||
verifyTscWatch({
|
||||
scenario: "programUpdates",
|
||||
subScenario: `${subScenario}/builds when new file is added, and its subsequent updates`,
|
||||
commandLineArgs: ["-b", "-w", "sample1/tests"],
|
||||
sys: () =>
|
||||
createWatchedSystem(
|
||||
allFilesGetter(),
|
||||
{ currentDirectory: "/user/username/projects" },
|
||||
),
|
||||
commandLineArgs: ["-b", "-w", "tests"],
|
||||
sys,
|
||||
edits: [
|
||||
{
|
||||
caption: "Change to new File and build core",
|
||||
edit: sys => sys.writeFile("sample1/core/newfile.ts", `export const newFileConst = 30;`),
|
||||
edit: sys => sys.writeFile("core/newfile.ts", `export const newFileConst = 30;`),
|
||||
timeouts: sys => sys.runQueuedTimeoutCallbacks(), // Builds core
|
||||
},
|
||||
buildLogicAndTests,
|
||||
{
|
||||
caption: "Change to new File and build core",
|
||||
edit: sys => sys.appendFile("sample1/core/newfile.ts", `\nexport class someClass2 { }`),
|
||||
edit: sys => sys.appendFile("core/newfile.ts", `\nexport class someClass2 { }`),
|
||||
timeouts: sys => sys.runQueuedTimeoutCallbacks(), // Builds core
|
||||
},
|
||||
buildLogicAndTests,
|
||||
@@ -134,20 +117,24 @@ describe("unittests:: tsbuildWatch:: watchMode:: program updates", () => {
|
||||
describe("with simple project reference graph", () => {
|
||||
verifyProjectChanges(
|
||||
"with simple project reference graph",
|
||||
getFsContentsForSampleProjectReferences,
|
||||
getSysForSampleProjectReferences,
|
||||
);
|
||||
});
|
||||
|
||||
describe("with circular project reference", () => {
|
||||
verifyProjectChanges(
|
||||
"with circular project reference",
|
||||
() => ({
|
||||
...getFsContentsForSampleProjectReferences(),
|
||||
"/user/username/projects/sample1/core/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: { composite: true, declaration: true },
|
||||
references: [{ path: "../tests", circular: true }],
|
||||
}),
|
||||
}),
|
||||
() => {
|
||||
const sys = getSysForSampleProjectReferences();
|
||||
sys.writeFile(
|
||||
"core/tsconfig.json",
|
||||
jsonToReadableText({
|
||||
compilerOptions: { composite: true, declaration: true },
|
||||
references: [{ path: "../tests", circular: true }],
|
||||
}),
|
||||
);
|
||||
return sys;
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -181,18 +168,17 @@ describe("unittests:: tsbuildWatch:: watchMode:: program updates", () => {
|
||||
subScenario: "with outFile and non local change",
|
||||
commandLineArgs: ["-b", "-w", "sample1/logic"],
|
||||
sys: () =>
|
||||
createWatchedSystem({
|
||||
[libFile.path]: libFile.content,
|
||||
"/user/username/projects/sample1/core/tsconfig.json": jsonToReadableText({
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/user/username/workspaces/solution/sample1/core/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: { composite: true, declaration: true, outFile: "index.js" },
|
||||
}),
|
||||
"/user/username/projects/sample1/core/index.ts": `function foo() { return 10; }`,
|
||||
"/user/username/projects/sample1/logic/tsconfig.json": jsonToReadableText({
|
||||
"/user/username/workspaces/solution/sample1/core/index.ts": `function foo() { return 10; }`,
|
||||
"/user/username/workspaces/solution/sample1/logic/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: { composite: true, declaration: true, outFile: "index.js" },
|
||||
references: [{ path: "../core" }],
|
||||
}),
|
||||
"/user/username/projects/sample1/logic/index.ts": `function bar() { return foo() + 1 };`,
|
||||
}, { currentDirectory: "/user/username/projects" }),
|
||||
"/user/username/workspaces/solution/sample1/logic/index.ts": `function bar() { return foo() + 1 };`,
|
||||
}, { currentDirectory: "/user/username/workspaces/solution" }),
|
||||
edits: [
|
||||
{
|
||||
caption: "Make non local change and build core",
|
||||
@@ -256,8 +242,8 @@ createSomeObject().message;`,
|
||||
content: jsonToReadableText({ references: [{ path: "../Library" }] }),
|
||||
};
|
||||
|
||||
const files = [libFile, libraryTs, libraryTsconfig, appTs, appTsconfig];
|
||||
return createWatchedSystem(files, { currentDirectory: `${"/user/username/projects"}/sample1` });
|
||||
const files = [libraryTs, libraryTsconfig, appTs, appTsconfig];
|
||||
return TestServerHost.createWatchedSystem(files, { currentDirectory: `${"/user/username/projects"}/sample1` });
|
||||
},
|
||||
edits: [
|
||||
{
|
||||
@@ -381,8 +367,8 @@ createSomeObject().message;`,
|
||||
subScenario: "reportErrors/declarationEmitErrors/when fixing error files all files are emitted",
|
||||
commandLineArgs: ["-b", "-w", subProject],
|
||||
sys: () =>
|
||||
createWatchedSystem(
|
||||
[libFile, fileWithError, fileWithoutError, tsconfig],
|
||||
TestServerHost.createWatchedSystem(
|
||||
[fileWithError, fileWithoutError, tsconfig],
|
||||
{ currentDirectory: `${"/user/username/projects"}/${solution}` },
|
||||
),
|
||||
edits: [
|
||||
@@ -395,8 +381,8 @@ createSomeObject().message;`,
|
||||
subScenario: "reportErrors/declarationEmitErrors/when file with no error changes",
|
||||
commandLineArgs: ["-b", "-w", subProject],
|
||||
sys: () =>
|
||||
createWatchedSystem(
|
||||
[libFile, fileWithError, fileWithoutError, tsconfig],
|
||||
TestServerHost.createWatchedSystem(
|
||||
[fileWithError, fileWithoutError, tsconfig],
|
||||
{ currentDirectory: `${"/user/username/projects"}/${solution}` },
|
||||
),
|
||||
edits: [
|
||||
@@ -416,8 +402,8 @@ createSomeObject().message;`,
|
||||
subScenario: "reportErrors/declarationEmitErrors/introduceError/when fixing errors only changed file is emitted",
|
||||
commandLineArgs: ["-b", "-w", subProject],
|
||||
sys: () =>
|
||||
createWatchedSystem(
|
||||
[libFile, fileWithFixedError, fileWithoutError, tsconfig],
|
||||
TestServerHost.createWatchedSystem(
|
||||
[fileWithFixedError, fileWithoutError, tsconfig],
|
||||
{ currentDirectory: `${"/user/username/projects"}/${solution}` },
|
||||
),
|
||||
edits: [
|
||||
@@ -431,8 +417,8 @@ createSomeObject().message;`,
|
||||
subScenario: "reportErrors/declarationEmitErrors/introduceError/when file with no error changes",
|
||||
commandLineArgs: ["-b", "-w", subProject],
|
||||
sys: () =>
|
||||
createWatchedSystem(
|
||||
[libFile, fileWithFixedError, fileWithoutError, tsconfig],
|
||||
TestServerHost.createWatchedSystem(
|
||||
[fileWithFixedError, fileWithoutError, tsconfig],
|
||||
{ currentDirectory: `${"/user/username/projects"}/${solution}` },
|
||||
),
|
||||
edits: [
|
||||
@@ -483,7 +469,7 @@ createSomeObject().message;`,
|
||||
},
|
||||
}),
|
||||
};
|
||||
return createWatchedSystem([index, configFile, libFile], { currentDirectory: "/user/username/projects/myproject" });
|
||||
return TestServerHost.createWatchedSystem([index, configFile], { currentDirectory: "/user/username/projects/myproject" });
|
||||
},
|
||||
edits: [
|
||||
{
|
||||
@@ -521,19 +507,22 @@ createSomeObject().message;`,
|
||||
verifyTscWatch({
|
||||
scenario: "programUpdates",
|
||||
subScenario: "should not trigger recompilation because of program emit with outDir specified",
|
||||
commandLineArgs: ["-b", "-w", "sample1/core", "-verbose"],
|
||||
sys: () =>
|
||||
createWatchedSystem({
|
||||
...getFsContentsForSampleProjectReferences(),
|
||||
"/user/username/projects/sample1/core/tsconfig.json": jsonToReadableText({
|
||||
commandLineArgs: ["-b", "-w", "core", "-verbose"],
|
||||
sys: () => {
|
||||
const sys = getSysForSampleProjectReferences();
|
||||
sys.writeFile(
|
||||
"core/tsconfig.json",
|
||||
jsonToReadableText({
|
||||
compilerOptions: { composite: true, outDir: "outDir" },
|
||||
}),
|
||||
}, { currentDirectory: "/user/username/projects" }),
|
||||
);
|
||||
return sys;
|
||||
},
|
||||
edits: [
|
||||
noopChange,
|
||||
{
|
||||
caption: "Add new file",
|
||||
edit: sys => sys.writeFile("sample1/core/file3.ts", `export const y = 10;`),
|
||||
edit: sys => sys.writeFile("core/file3.ts", `export const y = 10;`),
|
||||
timeouts: sys => sys.runQueuedTimeoutCallbacks(),
|
||||
},
|
||||
noopChange,
|
||||
@@ -545,12 +534,20 @@ createSomeObject().message;`,
|
||||
subScenario: "works with extended source files",
|
||||
commandLineArgs: ["-b", "-w", "-v", "project1.tsconfig.json", "project2.tsconfig.json", "project3.tsconfig.json"],
|
||||
sys: () => {
|
||||
const commonFile1: File = {
|
||||
path: "/user/username/projects/project/commonFile1.ts",
|
||||
content: "let x = 1",
|
||||
};
|
||||
const commonFile2: File = {
|
||||
path: "/user/username/projects/project/commonFile2.ts",
|
||||
content: "let y = 1",
|
||||
};
|
||||
const alphaExtendedConfigFile: File = {
|
||||
path: "/a/b/alpha.tsconfig.json",
|
||||
path: "/user/username/projects/project/alpha.tsconfig.json",
|
||||
content: "{}",
|
||||
};
|
||||
const project1Config: File = {
|
||||
path: "/a/b/project1.tsconfig.json",
|
||||
path: "/user/username/projects/project/project1.tsconfig.json",
|
||||
content: jsonToReadableText({
|
||||
extends: "./alpha.tsconfig.json",
|
||||
compilerOptions: {
|
||||
@@ -560,17 +557,17 @@ createSomeObject().message;`,
|
||||
}),
|
||||
};
|
||||
const bravoExtendedConfigFile: File = {
|
||||
path: "/a/b/bravo.tsconfig.json",
|
||||
path: "/user/username/projects/project/bravo.tsconfig.json",
|
||||
content: jsonToReadableText({
|
||||
extends: "./alpha.tsconfig.json",
|
||||
}),
|
||||
};
|
||||
const otherFile: File = {
|
||||
path: "/a/b/other.ts",
|
||||
path: "/user/username/projects/project/other.ts",
|
||||
content: "let z = 0;",
|
||||
};
|
||||
const project2Config: File = {
|
||||
path: "/a/b/project2.tsconfig.json",
|
||||
path: "/user/username/projects/project/project2.tsconfig.json",
|
||||
content: jsonToReadableText({
|
||||
extends: "./bravo.tsconfig.json",
|
||||
compilerOptions: {
|
||||
@@ -580,11 +577,11 @@ createSomeObject().message;`,
|
||||
}),
|
||||
};
|
||||
const otherFile2: File = {
|
||||
path: "/a/b/other2.ts",
|
||||
path: "/user/username/projects/project/other2.ts",
|
||||
content: "let k = 0;",
|
||||
};
|
||||
const extendsConfigFile1: File = {
|
||||
path: "/a/b/extendsConfig1.tsconfig.json",
|
||||
path: "/user/username/projects/project/extendsConfig1.tsconfig.json",
|
||||
content: jsonToReadableText({
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
@@ -592,7 +589,7 @@ createSomeObject().message;`,
|
||||
}),
|
||||
};
|
||||
const extendsConfigFile2: File = {
|
||||
path: "/a/b/extendsConfig2.tsconfig.json",
|
||||
path: "/user/username/projects/project/extendsConfig2.tsconfig.json",
|
||||
content: jsonToReadableText({
|
||||
compilerOptions: {
|
||||
strictNullChecks: false,
|
||||
@@ -600,7 +597,7 @@ createSomeObject().message;`,
|
||||
}),
|
||||
};
|
||||
const extendsConfigFile3: File = {
|
||||
path: "/a/b/extendsConfig3.tsconfig.json",
|
||||
path: "/user/username/projects/project/extendsConfig3.tsconfig.json",
|
||||
content: jsonToReadableText({
|
||||
compilerOptions: {
|
||||
noImplicitAny: true,
|
||||
@@ -608,17 +605,20 @@ createSomeObject().message;`,
|
||||
}),
|
||||
};
|
||||
const project3Config: File = {
|
||||
path: "/a/b/project3.tsconfig.json",
|
||||
path: "/user/username/projects/project/project3.tsconfig.json",
|
||||
content: jsonToReadableText({
|
||||
extends: ["./extendsConfig1.tsconfig.json", "./extendsConfig2.tsconfig.json", "./extendsConfig3.tsconfig.json"],
|
||||
extends: [
|
||||
"./extendsConfig1.tsconfig.json",
|
||||
"./extendsConfig2.tsconfig.json",
|
||||
"./extendsConfig3.tsconfig.json",
|
||||
],
|
||||
compilerOptions: {
|
||||
composite: false,
|
||||
},
|
||||
files: [otherFile2.path],
|
||||
}),
|
||||
};
|
||||
return createWatchedSystem([
|
||||
libFile,
|
||||
return TestServerHost.createWatchedSystem([
|
||||
alphaExtendedConfigFile,
|
||||
project1Config,
|
||||
commonFile1,
|
||||
@@ -631,14 +631,14 @@ createSomeObject().message;`,
|
||||
extendsConfigFile2,
|
||||
extendsConfigFile3,
|
||||
project3Config,
|
||||
], { currentDirectory: "/a/b" });
|
||||
], { currentDirectory: "/user/username/projects/project" });
|
||||
},
|
||||
edits: [
|
||||
{
|
||||
caption: "Modify alpha config",
|
||||
edit: sys =>
|
||||
sys.writeFile(
|
||||
"/a/b/alpha.tsconfig.json",
|
||||
"/user/username/projects/project/alpha.tsconfig.json",
|
||||
jsonToReadableText({
|
||||
compilerOptions: { strict: true },
|
||||
}),
|
||||
@@ -654,7 +654,7 @@ createSomeObject().message;`,
|
||||
caption: "change bravo config",
|
||||
edit: sys =>
|
||||
sys.writeFile(
|
||||
"/a/b/bravo.tsconfig.json",
|
||||
"/user/username/projects/project/bravo.tsconfig.json",
|
||||
jsonToReadableText({
|
||||
extends: "./alpha.tsconfig.json",
|
||||
compilerOptions: { strict: false },
|
||||
@@ -666,7 +666,7 @@ createSomeObject().message;`,
|
||||
caption: "project 2 extends alpha",
|
||||
edit: sys =>
|
||||
sys.writeFile(
|
||||
"/a/b/project2.tsconfig.json",
|
||||
"/user/username/projects/project/project2.tsconfig.json",
|
||||
jsonToReadableText({
|
||||
extends: "./alpha.tsconfig.json",
|
||||
}),
|
||||
@@ -675,7 +675,7 @@ createSomeObject().message;`,
|
||||
},
|
||||
{
|
||||
caption: "update aplha config",
|
||||
edit: sys => sys.writeFile("/a/b/alpha.tsconfig.json", "{}"),
|
||||
edit: sys => sys.writeFile("/user/username/projects/project/alpha.tsconfig.json", "{}"),
|
||||
timeouts: sys => sys.runQueuedTimeoutCallbacks(), // build project1
|
||||
},
|
||||
{
|
||||
@@ -687,7 +687,7 @@ createSomeObject().message;`,
|
||||
caption: "Modify extendsConfigFile2",
|
||||
edit: sys =>
|
||||
sys.writeFile(
|
||||
"/a/b/extendsConfig2.tsconfig.json",
|
||||
"/user/username/projects/project/extendsConfig2.tsconfig.json",
|
||||
jsonToReadableText({
|
||||
compilerOptions: { strictNullChecks: true },
|
||||
}),
|
||||
@@ -698,11 +698,11 @@ createSomeObject().message;`,
|
||||
caption: "Modify project 3",
|
||||
edit: sys =>
|
||||
sys.writeFile(
|
||||
"/a/b/project3.tsconfig.json",
|
||||
"/user/username/projects/project/project3.tsconfig.json",
|
||||
jsonToReadableText({
|
||||
extends: ["./extendsConfig1.tsconfig.json", "./extendsConfig2.tsconfig.json"],
|
||||
compilerOptions: { composite: false },
|
||||
files: ["/a/b/other2.ts"],
|
||||
files: ["/user/username/projects/project/other2.ts"],
|
||||
}),
|
||||
),
|
||||
timeouts: sys => sys.runQueuedTimeoutCallbacks(), // Build project3
|
||||
@@ -720,8 +720,16 @@ createSomeObject().message;`,
|
||||
subScenario: "works correctly when project with extended config is removed",
|
||||
commandLineArgs: ["-b", "-w", "-v"],
|
||||
sys: () => {
|
||||
const commonFile1: File = {
|
||||
path: "/user/username/projects/project/commonFile1.ts",
|
||||
content: "let x = 1",
|
||||
};
|
||||
const commonFile2: File = {
|
||||
path: "/user/username/projects/project/commonFile2.ts",
|
||||
content: "let y = 1",
|
||||
};
|
||||
const alphaExtendedConfigFile: File = {
|
||||
path: "/a/b/alpha.tsconfig.json",
|
||||
path: "/user/username/projects/project/alpha.tsconfig.json",
|
||||
content: jsonToReadableText({
|
||||
compilerOptions: {
|
||||
strict: true,
|
||||
@@ -729,7 +737,7 @@ createSomeObject().message;`,
|
||||
}),
|
||||
};
|
||||
const project1Config: File = {
|
||||
path: "/a/b/project1.tsconfig.json",
|
||||
path: "/user/username/projects/project/project1.tsconfig.json",
|
||||
content: jsonToReadableText({
|
||||
extends: "./alpha.tsconfig.json",
|
||||
compilerOptions: {
|
||||
@@ -739,7 +747,7 @@ createSomeObject().message;`,
|
||||
}),
|
||||
};
|
||||
const bravoExtendedConfigFile: File = {
|
||||
path: "/a/b/bravo.tsconfig.json",
|
||||
path: "/user/username/projects/project/bravo.tsconfig.json",
|
||||
content: jsonToReadableText({
|
||||
compilerOptions: {
|
||||
strict: true,
|
||||
@@ -747,11 +755,11 @@ createSomeObject().message;`,
|
||||
}),
|
||||
};
|
||||
const otherFile: File = {
|
||||
path: "/a/b/other.ts",
|
||||
path: "/user/username/projects/project/other.ts",
|
||||
content: "let z = 0;",
|
||||
};
|
||||
const project2Config: File = {
|
||||
path: "/a/b/project2.tsconfig.json",
|
||||
path: "/user/username/projects/project/project2.tsconfig.json",
|
||||
content: jsonToReadableText({
|
||||
extends: "./bravo.tsconfig.json",
|
||||
compilerOptions: {
|
||||
@@ -761,7 +769,7 @@ createSomeObject().message;`,
|
||||
}),
|
||||
};
|
||||
const configFile: File = {
|
||||
path: "/a/b/tsconfig.json",
|
||||
path: "/user/username/projects/project/tsconfig.json",
|
||||
content: jsonToReadableText({
|
||||
references: [
|
||||
{
|
||||
@@ -774,8 +782,7 @@ createSomeObject().message;`,
|
||||
files: [],
|
||||
}),
|
||||
};
|
||||
return createWatchedSystem([
|
||||
libFile,
|
||||
return TestServerHost.createWatchedSystem([
|
||||
configFile,
|
||||
alphaExtendedConfigFile,
|
||||
project1Config,
|
||||
@@ -784,14 +791,14 @@ createSomeObject().message;`,
|
||||
bravoExtendedConfigFile,
|
||||
project2Config,
|
||||
otherFile,
|
||||
], { currentDirectory: "/a/b" });
|
||||
], { currentDirectory: "/user/username/projects/project" });
|
||||
},
|
||||
edits: [
|
||||
{
|
||||
caption: "Remove project2 from base config",
|
||||
edit: sys =>
|
||||
sys.modifyFile(
|
||||
"/a/b/tsconfig.json",
|
||||
"/user/username/projects/project/tsconfig.json",
|
||||
jsonToReadableText({
|
||||
references: [
|
||||
{
|
||||
@@ -810,12 +817,11 @@ createSomeObject().message;`,
|
||||
scenario: "programUpdates",
|
||||
subScenario: "tsbuildinfo has error",
|
||||
sys: () =>
|
||||
createWatchedSystem({
|
||||
"/src/project/main.ts": "export const x = 10;",
|
||||
"/src/project/tsconfig.json": "{}",
|
||||
"/src/project/tsconfig.tsbuildinfo": "Some random string",
|
||||
[libFile.path]: libFile.content,
|
||||
}),
|
||||
commandLineArgs: ["--b", "src/project", "-i", "-w"],
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/user/username/projects/project/main.ts": "export const x = 10;",
|
||||
"/user/username/projects/project/tsconfig.json": "{}",
|
||||
"/user/username/projects/project/tsconfig.tsbuildinfo": "Some random string",
|
||||
}, { currentDirectory: "/user/username/projects/project" }),
|
||||
commandLineArgs: ["--b", "-i", "-w"],
|
||||
});
|
||||
});
|
||||
|
||||
@@ -6,12 +6,11 @@ import {
|
||||
verifyTscWatch,
|
||||
} from "../helpers/tscWatch.js";
|
||||
import {
|
||||
createWatchedSystem,
|
||||
File,
|
||||
libFile,
|
||||
TestServerHost,
|
||||
} from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsbuildWatch:: watchMode:: projectsBuilding", () => {
|
||||
describe("unittests:: tsbuildWatch:: watchMode:: projectsBuilding::", () => {
|
||||
function pkgs<T>(cb: (index: number) => T, count: number, startIndex?: number): T[] {
|
||||
const result: T[] = [];
|
||||
for (let index = startIndex || 0; count > 0; index++, count--) {
|
||||
@@ -60,8 +59,8 @@ describe("unittests:: tsbuildWatch:: watchMode:: projectsBuilding", () => {
|
||||
subScenario: `when there are 3 projects in a solution`,
|
||||
commandLineArgs: ["-b", "-w", "-v"],
|
||||
sys: () =>
|
||||
createWatchedSystem(
|
||||
[libFile, ...ts.flatMap(pkgs(pkgFiles, 3), ts.identity), solution(3)],
|
||||
TestServerHost.createWatchedSystem(
|
||||
[...ts.flatMap(pkgs(pkgFiles, 3), ts.identity), solution(3)],
|
||||
{ currentDirectory: "/user/username/projects/myproject" },
|
||||
),
|
||||
edits: [
|
||||
@@ -85,8 +84,8 @@ describe("unittests:: tsbuildWatch:: watchMode:: projectsBuilding", () => {
|
||||
subScenario: `when there are 5 projects in a solution`,
|
||||
commandLineArgs: ["-b", "-w", "-v"],
|
||||
sys: () =>
|
||||
createWatchedSystem(
|
||||
[libFile, ...ts.flatMap(pkgs(pkgFiles, 5), ts.identity), solution(5)],
|
||||
TestServerHost.createWatchedSystem(
|
||||
[...ts.flatMap(pkgs(pkgFiles, 5), ts.identity), solution(5)],
|
||||
{ currentDirectory: "/user/username/projects/myproject" },
|
||||
),
|
||||
edits: [
|
||||
@@ -110,8 +109,8 @@ describe("unittests:: tsbuildWatch:: watchMode:: projectsBuilding", () => {
|
||||
subScenario: `when there are 8 projects in a solution`,
|
||||
commandLineArgs: ["-b", "-w", "-v"],
|
||||
sys: () =>
|
||||
createWatchedSystem(
|
||||
[libFile, ...ts.flatMap(pkgs(pkgFiles, 8), ts.identity), solution(8)],
|
||||
TestServerHost.createWatchedSystem(
|
||||
[...ts.flatMap(pkgs(pkgFiles, 8), ts.identity), solution(8)],
|
||||
{ currentDirectory: "/user/username/projects/myproject" },
|
||||
),
|
||||
edits: [
|
||||
@@ -149,8 +148,8 @@ describe("unittests:: tsbuildWatch:: watchMode:: projectsBuilding", () => {
|
||||
subScenario: `when there are 23 projects in a solution`,
|
||||
commandLineArgs: ["-b", "-w", "-v"],
|
||||
sys: () =>
|
||||
createWatchedSystem(
|
||||
[libFile, ...ts.flatMap(pkgs(pkgFiles, 23), ts.identity), solution(23)],
|
||||
TestServerHost.createWatchedSystem(
|
||||
[...ts.flatMap(pkgs(pkgFiles, 23), ts.identity), solution(23)],
|
||||
{ currentDirectory: "/user/username/projects/myproject" },
|
||||
),
|
||||
edits: [
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
import * as ts from "../../_namespaces/ts.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import { createBaseline } from "../helpers/baseline.js";
|
||||
import {
|
||||
createBaseline,
|
||||
createSolutionBuilderWithWatchHostForBaseline,
|
||||
runWatchBaseline,
|
||||
} from "../helpers/tscWatch.js";
|
||||
import {
|
||||
createWatchedSystem,
|
||||
File,
|
||||
libFile,
|
||||
TestServerHost,
|
||||
} from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
it("unittests:: tsbuildWatch:: watchMode:: Public API with custom transformers", () => {
|
||||
it("unittests:: tsbuildWatch:: watchMode:: publicAPI:: Public API with custom transformers", () => {
|
||||
const solution: File = {
|
||||
path: `/user/username/projects/myproject/tsconfig.json`,
|
||||
content: jsonToReadableText({
|
||||
@@ -52,7 +51,10 @@ export enum e2 { }
|
||||
export function f22() { } // trailing`,
|
||||
};
|
||||
const commandLineArgs = ["--b", "--w"];
|
||||
const { sys, baseline, cb, getPrograms } = createBaseline(createWatchedSystem([libFile, solution, sharedConfig, sharedIndex, webpackConfig, webpackIndex], { currentDirectory: "/user/username/projects/myproject" }));
|
||||
const { sys, baseline, cb, getPrograms } = createBaseline(TestServerHost.createWatchedSystem(
|
||||
[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 });
|
||||
|
||||
@@ -1,19 +1,15 @@
|
||||
import { dedent } from "../../_namespaces/Utils.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import { libContent } from "../helpers/contents.js";
|
||||
import { verifyTscWatch } from "../helpers/tscWatch.js";
|
||||
import {
|
||||
createWatchedSystem,
|
||||
libFile,
|
||||
} from "../helpers/virtualFileSystemWithWatch.js";
|
||||
import { TestServerHost } from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsbuildWatch:: watchMode:: with reexport when referenced project reexports definitions from another file", () => {
|
||||
describe("unittests:: tsbuildWatch:: watchMode:: reexport:: with reexport when referenced project reexports definitions from another file", () => {
|
||||
verifyTscWatch({
|
||||
scenario: "reexport",
|
||||
subScenario: "Reports errors correctly",
|
||||
commandLineArgs: ["-b", "-w", "-verbose", "src"],
|
||||
sys: () =>
|
||||
createWatchedSystem({
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/user/username/projects/reexport/src/tsconfig.json": jsonToReadableText({
|
||||
files: [],
|
||||
include: [],
|
||||
@@ -49,7 +45,6 @@ describe("unittests:: tsbuildWatch:: watchMode:: with reexport when referenced p
|
||||
// bar: number;
|
||||
}
|
||||
`,
|
||||
[libFile.path]: libContent,
|
||||
}, { currentDirectory: `/user/username/projects/reexport` }),
|
||||
edits: [
|
||||
{
|
||||
|
||||
@@ -1,40 +1,18 @@
|
||||
import { forEachScenarioForRootsFromReferencedProject } from "../helpers/projectRoots.js";
|
||||
import {
|
||||
noopChange,
|
||||
verifyTscWatch,
|
||||
} from "../helpers/tscWatch.js";
|
||||
import { createWatchedSystem } from "../helpers/virtualFileSystemWithWatch.js";
|
||||
import { verifyTscWatch } from "../helpers/tscWatch.js";
|
||||
|
||||
describe("unittests:: tsbuildWatch:: watchMode:: roots::", () => {
|
||||
describe("when root file is from referenced project", () => {
|
||||
forEachScenarioForRootsFromReferencedProject((subScenario, getFsContents) => {
|
||||
verifyTscWatch({
|
||||
scenario: "roots",
|
||||
subScenario,
|
||||
commandLineArgs: ["--b", "projects/server", "-w", "-v", "--traceResolution", "--explainFiles"],
|
||||
sys: () => createWatchedSystem(getFsContents(), { currentDirectory: "/home/src/workspaces" }),
|
||||
edits: [
|
||||
noopChange,
|
||||
{
|
||||
caption: "edit logging file",
|
||||
edit: sys => sys.appendFile("/home/src/workspaces/projects/shared/src/logging.ts", "export const x = 10;"),
|
||||
timeouts: sys => {
|
||||
sys.runQueuedTimeoutCallbacks(); // build shared
|
||||
sys.runQueuedTimeoutCallbacks(); // build server
|
||||
},
|
||||
},
|
||||
noopChange,
|
||||
{
|
||||
caption: "delete random file",
|
||||
edit: sys => sys.deleteFile("/home/src/workspaces/projects/shared/src/random.ts"),
|
||||
timeouts: sys => {
|
||||
sys.runQueuedTimeoutCallbacks(); // build shared
|
||||
sys.runQueuedTimeoutCallbacks(); // build server
|
||||
},
|
||||
},
|
||||
noopChange,
|
||||
],
|
||||
});
|
||||
});
|
||||
forEachScenarioForRootsFromReferencedProject(
|
||||
/*forTsserver*/ false,
|
||||
(subScenario, sys, edits) =>
|
||||
verifyTscWatch({
|
||||
scenario: "roots",
|
||||
subScenario,
|
||||
commandLineArgs: ["--b", "projects/server", "-w", "-v", "--traceResolution", "--explainFiles"],
|
||||
sys,
|
||||
edits: edits(),
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
import * as ts from "../../_namespaces/ts.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import { createBaseline } from "../helpers/baseline.js";
|
||||
import {
|
||||
createBaseline,
|
||||
createSolutionBuilderWithWatchHostForBaseline,
|
||||
runWatchBaseline,
|
||||
} from "../helpers/tscWatch.js";
|
||||
import {
|
||||
createWatchedSystem,
|
||||
File,
|
||||
libFile,
|
||||
TestServerHost,
|
||||
} from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
@@ -23,7 +21,7 @@ describe("unittests:: tsbuildWatch:: watchEnvironment:: tsbuild:: watchMode:: wi
|
||||
};
|
||||
|
||||
const allPkgFiles = pkgs(pkgFiles);
|
||||
const system = createWatchedSystem([libFile, typing, ...flatArray(allPkgFiles)], { currentDirectory: project });
|
||||
const system = TestServerHost.createWatchedSystem([typing, ...flatArray(allPkgFiles)], { currentDirectory: project });
|
||||
writePkgReferences(system);
|
||||
const { sys, baseline, cb, getPrograms } = createBaseline(system);
|
||||
const host = createSolutionBuilderWithWatchHostForBaseline(sys, cb);
|
||||
|
||||
@@ -1,20 +1,17 @@
|
||||
import * as Harness from "../../_namespaces/Harness.js";
|
||||
import { Baseline } from "../../_namespaces/Harness.js";
|
||||
import * as ts from "../../_namespaces/ts.js";
|
||||
import * as Utils from "../../_namespaces/Utils.js";
|
||||
import { dedent } from "../../_namespaces/Utils.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import {
|
||||
applyEdit,
|
||||
baselineBuildInfo,
|
||||
CommandLineProgram,
|
||||
} from "../helpers/baseline.js";
|
||||
import {
|
||||
applyEdit,
|
||||
createBaseline,
|
||||
watchBaseline,
|
||||
} from "../helpers/tscWatch.js";
|
||||
} from "../helpers/baseline.js";
|
||||
import { watchBaseline } from "../helpers/tscWatch.js";
|
||||
import {
|
||||
createWatchedSystem,
|
||||
File,
|
||||
libFile,
|
||||
TestServerHost,
|
||||
} from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsc:: builder cancellationToken::", () => {
|
||||
@@ -24,7 +21,7 @@ describe("unittests:: tsc:: builder cancellationToken::", () => {
|
||||
it(scenario, () => {
|
||||
const aFile: File = {
|
||||
path: `/user/username/projects/myproject/a.ts`,
|
||||
content: Utils.dedent`
|
||||
content: dedent`
|
||||
import {B} from './b';
|
||||
declare var console: any;
|
||||
let b = new B();
|
||||
@@ -32,7 +29,7 @@ describe("unittests:: tsc:: builder cancellationToken::", () => {
|
||||
};
|
||||
const bFile: File = {
|
||||
path: `/user/username/projects/myproject/b.ts`,
|
||||
content: Utils.dedent`
|
||||
content: dedent`
|
||||
import {C} from './c';
|
||||
export class B {
|
||||
c = new C();
|
||||
@@ -40,7 +37,7 @@ describe("unittests:: tsc:: builder cancellationToken::", () => {
|
||||
};
|
||||
const cFile: File = {
|
||||
path: `/user/username/projects/myproject/c.ts`,
|
||||
content: Utils.dedent`
|
||||
content: dedent`
|
||||
export var C = class CReal {
|
||||
d = 1;
|
||||
};`,
|
||||
@@ -53,8 +50,8 @@ describe("unittests:: tsc:: builder cancellationToken::", () => {
|
||||
path: `/user/username/projects/myproject/tsconfig.json`,
|
||||
content: jsonToReadableText({ compilerOptions: { incremental: true, declaration: true } }),
|
||||
};
|
||||
const { sys, baseline } = createBaseline(createWatchedSystem(
|
||||
[aFile, bFile, cFile, dFile, config, libFile],
|
||||
const { sys, baseline } = createBaseline(TestServerHost.createWatchedSystem(
|
||||
[aFile, bFile, cFile, dFile, config],
|
||||
{ currentDirectory: "/user/username/projects/myproject" },
|
||||
));
|
||||
sys.exit = exitCode => sys.exitCode = exitCode;
|
||||
@@ -121,7 +118,7 @@ describe("unittests:: tsc:: builder cancellationToken::", () => {
|
||||
noChange("Clean build");
|
||||
baselineCleanBuild();
|
||||
|
||||
Harness.Baseline.runBaseline(`tsc/cancellationToken/${scenario.split(" ").join("-")}.js`, baseline.join("\r\n"));
|
||||
Baseline.runBaseline(`tsc/cancellationToken/${scenario.split(" ").join("-")}.js`, baseline.join("\r\n"));
|
||||
|
||||
function noChange(caption: string) {
|
||||
applyEdit(sys, baseline, ts.noop, caption);
|
||||
|
||||
@@ -1,116 +1,110 @@
|
||||
import * as Utils from "../../_namespaces/Utils.js";
|
||||
import { emptyArray } from "../../_namespaces/ts.js";
|
||||
import { dedent } from "../../_namespaces/Utils.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import { verifyTsc } from "../helpers/tsc.js";
|
||||
import {
|
||||
loadProjectFromFiles,
|
||||
replaceText,
|
||||
} from "../helpers/vfs.js";
|
||||
import { TestServerHost } from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsc:: composite::", () => {
|
||||
verifyTsc({
|
||||
scenario: "composite",
|
||||
subScenario: "when setting composite false on command line",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/project/src/main.ts": "export const x = 10;",
|
||||
"/src/project/tsconfig.json": Utils.dedent`
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"module": "commonjs",
|
||||
"composite": true,
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts"
|
||||
]
|
||||
}`,
|
||||
}),
|
||||
commandLineArgs: ["--composite", "false", "--p", "src/project"],
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/src/main.ts": "export const x = 10;",
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
target: "es5",
|
||||
module: "commonjs",
|
||||
composite: true,
|
||||
},
|
||||
include: [
|
||||
"src/**/*.ts",
|
||||
],
|
||||
}),
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
commandLineArgs: ["--composite", "false"],
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "composite",
|
||||
subScenario: "when setting composite null on command line",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/project/src/main.ts": "export const x = 10;",
|
||||
"/src/project/tsconfig.json": Utils.dedent`
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"module": "commonjs",
|
||||
"composite": true,
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts"
|
||||
]
|
||||
}`,
|
||||
}),
|
||||
commandLineArgs: ["--composite", "null", "--p", "src/project"],
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/src/main.ts": "export const x = 10;",
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
target: "es5",
|
||||
module: "commonjs",
|
||||
composite: true,
|
||||
},
|
||||
include: [
|
||||
"src/**/*.ts",
|
||||
],
|
||||
}),
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
commandLineArgs: ["--composite", "null"],
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "composite",
|
||||
subScenario: "when setting composite false on command line but has tsbuild info in config",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/project/src/main.ts": "export const x = 10;",
|
||||
"/src/project/tsconfig.json": Utils.dedent`
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"module": "commonjs",
|
||||
"composite": true,
|
||||
"tsBuildInfoFile": "tsconfig.json.tsbuildinfo"
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts"
|
||||
]
|
||||
}`,
|
||||
}),
|
||||
commandLineArgs: ["--composite", "false", "--p", "src/project"],
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/src/main.ts": "export const x = 10;",
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
target: "es5",
|
||||
module: "commonjs",
|
||||
composite: true,
|
||||
tsBuildInfoFile: "tsconfig.json.tsbuildinfo",
|
||||
},
|
||||
include: [
|
||||
"src/**/*.ts",
|
||||
],
|
||||
}),
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
commandLineArgs: ["--composite", "false"],
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "composite",
|
||||
subScenario: "when setting composite false and tsbuildinfo as null on command line but has tsbuild info in config",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/project/src/main.ts": "export const x = 10;",
|
||||
"/src/project/tsconfig.json": Utils.dedent`
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"module": "commonjs",
|
||||
"composite": true,
|
||||
"tsBuildInfoFile": "tsconfig.json.tsbuildinfo"
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts"
|
||||
]
|
||||
}`,
|
||||
}),
|
||||
commandLineArgs: ["--composite", "false", "--p", "src/project", "--tsBuildInfoFile", "null"],
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/src/main.ts": "export const x = 10;",
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
target: "es5",
|
||||
module: "commonjs",
|
||||
composite: true,
|
||||
tsBuildInfoFile: "tsconfig.json.tsbuildinfo",
|
||||
},
|
||||
include: [
|
||||
"src/**/*.ts",
|
||||
],
|
||||
}),
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
commandLineArgs: ["--composite", "false", "--tsBuildInfoFile", "null"],
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "composite",
|
||||
subScenario: "converting to modules",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/project/src/main.ts": "const x = 10;",
|
||||
"/src/project/tsconfig.json": jsonToReadableText({
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/src/main.ts": "const x = 10;",
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
module: "none",
|
||||
composite: true,
|
||||
},
|
||||
}),
|
||||
}),
|
||||
commandLineArgs: ["-p", "/src/project"],
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
commandLineArgs: [],
|
||||
edits: [
|
||||
{
|
||||
caption: "convert to modules",
|
||||
edit: fs => replaceText(fs, "/src/project/tsconfig.json", "none", "es2015"),
|
||||
edit: sys => sys.replaceFileText("/home/src/workspaces/project/tsconfig.json", "none", "es2015"),
|
||||
},
|
||||
],
|
||||
});
|
||||
@@ -118,10 +112,10 @@ describe("unittests:: tsc:: composite::", () => {
|
||||
verifyTsc({
|
||||
scenario: "composite",
|
||||
subScenario: "synthetic jsx import of ESM module from CJS module no crash no jsx element",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/main.ts": "export default 42;",
|
||||
"/tsconfig.json": jsonToReadableText({
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/projects/project/src/main.ts": "export default 42;",
|
||||
"/home/src/projects/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
module: "Node16",
|
||||
@@ -129,26 +123,26 @@ describe("unittests:: tsc:: composite::", () => {
|
||||
jsxImportSource: "solid-js",
|
||||
},
|
||||
}),
|
||||
"/node_modules/solid-js/package.json": jsonToReadableText({
|
||||
"/home/src/projects/project/node_modules/solid-js/package.json": jsonToReadableText({
|
||||
name: "solid-js",
|
||||
type: "module",
|
||||
}),
|
||||
"/node_modules/solid-js/jsx-runtime.d.ts": Utils.dedent`
|
||||
"/home/src/projects/project/node_modules/solid-js/jsx-runtime.d.ts": dedent`
|
||||
export namespace JSX {
|
||||
type IntrinsicElements = { div: {}; };
|
||||
}
|
||||
`,
|
||||
}),
|
||||
commandLineArgs: [],
|
||||
}, { currentDirectory: "/home/src/projects/project" }),
|
||||
commandLineArgs: emptyArray,
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "composite",
|
||||
subScenario: "synthetic jsx import of ESM module from CJS module error on jsx element",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/main.tsx": "export default <div/>;",
|
||||
"/tsconfig.json": jsonToReadableText({
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/projects/project/src/main.tsx": "export default <div/>;",
|
||||
"/home/src/projects/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
module: "Node16",
|
||||
@@ -156,16 +150,16 @@ describe("unittests:: tsc:: composite::", () => {
|
||||
jsxImportSource: "solid-js",
|
||||
},
|
||||
}),
|
||||
"/node_modules/solid-js/package.json": jsonToReadableText({
|
||||
"/home/src/projects/project/node_modules/solid-js/package.json": jsonToReadableText({
|
||||
name: "solid-js",
|
||||
type: "module",
|
||||
}),
|
||||
"/node_modules/solid-js/jsx-runtime.d.ts": Utils.dedent`
|
||||
"/home/src/projects/project/node_modules/solid-js/jsx-runtime.d.ts": dedent`
|
||||
export namespace JSX {
|
||||
type IntrinsicElements = { div: {}; };
|
||||
}
|
||||
`,
|
||||
}),
|
||||
commandLineArgs: [],
|
||||
}, { currentDirectory: "/home/src/projects/project" }),
|
||||
commandLineArgs: emptyArray,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
import * as Utils from "../../_namespaces/Utils.js";
|
||||
import { dedent } from "../../_namespaces/Utils.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import { forEachDeclarationEmitWithErrorsScenario } from "../helpers/declarationEmit.js";
|
||||
import {
|
||||
noChangeRun,
|
||||
verifyTsc,
|
||||
} from "../helpers/tsc.js";
|
||||
import { verifyTscWatch } from "../helpers/tscWatch.js";
|
||||
import {
|
||||
createWatchedSystem,
|
||||
FileOrFolderOrSymLink,
|
||||
isSymLink,
|
||||
libFile,
|
||||
TestServerHost,
|
||||
} from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsc:: declarationEmit::", () => {
|
||||
@@ -30,21 +28,21 @@ describe("unittests:: tsc:: declarationEmit::", () => {
|
||||
|
||||
function verifyDeclarationEmit({ subScenario, files, rootProject, changeCaseFileTestPath }: VerifyDeclarationEmitInput) {
|
||||
describe(subScenario, () => {
|
||||
verifyTscWatch({
|
||||
verifyTsc({
|
||||
scenario: "declarationEmit",
|
||||
subScenario,
|
||||
sys: () => createWatchedSystem(files, { currentDirectory: "/user/username/projects/myproject" }),
|
||||
sys: () => TestServerHost.createWatchedSystem(files, { currentDirectory: "/user/username/projects/myproject" }),
|
||||
commandLineArgs: ["-p", rootProject, "--explainFiles"],
|
||||
});
|
||||
});
|
||||
|
||||
const caseChangeScenario = `${subScenario} moduleCaseChange`;
|
||||
describe(caseChangeScenario, () => {
|
||||
verifyTscWatch({
|
||||
verifyTsc({
|
||||
scenario: "declarationEmit",
|
||||
subScenario: caseChangeScenario,
|
||||
sys: () =>
|
||||
createWatchedSystem(
|
||||
TestServerHost.createWatchedSystem(
|
||||
files.map(f => changeCaseFile(f, changeCaseFileTestPath, str => str.replace("myproject", "myProject"))),
|
||||
{ currentDirectory: "/user/username/projects/myproject" },
|
||||
),
|
||||
@@ -67,14 +65,14 @@ describe("unittests:: tsc:: declarationEmit::", () => {
|
||||
return `import pluginTwo from "plugin-two"; // include this to add reference to symlink`;
|
||||
}
|
||||
function pluginOneAction() {
|
||||
return Utils.dedent`
|
||||
return dedent`
|
||||
import { actionCreatorFactory } from "typescript-fsa"; // Include version of shared lib
|
||||
const action = actionCreatorFactory("somekey");
|
||||
const featureOne = action<{ route: string }>("feature-one");
|
||||
export const actions = { featureOne };`;
|
||||
}
|
||||
function pluginTwoDts() {
|
||||
return Utils.dedent`
|
||||
return dedent`
|
||||
declare const _default: {
|
||||
features: {
|
||||
featureOne: {
|
||||
@@ -104,7 +102,7 @@ describe("unittests:: tsc:: declarationEmit::", () => {
|
||||
});
|
||||
}
|
||||
function fsaIndex() {
|
||||
return Utils.dedent`
|
||||
return dedent`
|
||||
export interface Action<Payload> {
|
||||
type: string;
|
||||
payload: Payload;
|
||||
@@ -133,7 +131,6 @@ describe("unittests:: tsc:: declarationEmit::", () => {
|
||||
{ path: `/user/username/projects/myproject/plugin-one/node_modules/typescript-fsa/package.json`, content: fsaPackageJson() },
|
||||
{ path: `/user/username/projects/myproject/plugin-one/node_modules/typescript-fsa/index.d.ts`, content: fsaIndex() },
|
||||
{ path: `/user/username/projects/myproject/plugin-one/node_modules/plugin-two`, symLink: `/user/username/projects/myproject/plugin-two` },
|
||||
libFile,
|
||||
],
|
||||
changeCaseFileTestPath: str => str.includes("/plugin-two"),
|
||||
});
|
||||
@@ -163,7 +160,6 @@ ${pluginOneAction()}`,
|
||||
{ path: `/user/username/projects/myproject/plugin-one/node_modules/typescript-fsa/index.d.ts`, content: fsaIndex() },
|
||||
{ path: `/temp/yarn/data/link/plugin-two`, symLink: `/user/username/projects/myproject/plugin-two` },
|
||||
{ path: `/user/username/projects/myproject/plugin-one/node_modules/plugin-two`, symLink: `/temp/yarn/data/link/plugin-two` },
|
||||
libFile,
|
||||
],
|
||||
changeCaseFileTestPath: str => str.includes("/plugin-two"),
|
||||
});
|
||||
@@ -175,12 +171,12 @@ ${pluginOneAction()}`,
|
||||
files: [
|
||||
{
|
||||
path: `/user/username/projects/myproject/pkg1/dist/index.d.ts`,
|
||||
content: Utils.dedent`
|
||||
content: dedent`
|
||||
export * from './types';`,
|
||||
},
|
||||
{
|
||||
path: `/user/username/projects/myproject/pkg1/dist/types.d.ts`,
|
||||
content: Utils.dedent`
|
||||
content: dedent`
|
||||
export declare type A = {
|
||||
id: string;
|
||||
};
|
||||
@@ -206,12 +202,12 @@ ${pluginOneAction()}`,
|
||||
},
|
||||
{
|
||||
path: `/user/username/projects/myproject/pkg2/dist/index.d.ts`,
|
||||
content: Utils.dedent`
|
||||
content: dedent`
|
||||
export * from './types';`,
|
||||
},
|
||||
{
|
||||
path: `/user/username/projects/myproject/pkg2/dist/types.d.ts`,
|
||||
content: Utils.dedent`
|
||||
content: dedent`
|
||||
export {MetadataAccessor} from '@raymondfeng/pkg1';`,
|
||||
},
|
||||
{
|
||||
@@ -225,12 +221,12 @@ ${pluginOneAction()}`,
|
||||
},
|
||||
{
|
||||
path: `/user/username/projects/myproject/pkg3/src/index.ts`,
|
||||
content: Utils.dedent`
|
||||
content: dedent`
|
||||
export * from './keys';`,
|
||||
},
|
||||
{
|
||||
path: `/user/username/projects/myproject/pkg3/src/keys.ts`,
|
||||
content: Utils.dedent`
|
||||
content: dedent`
|
||||
import {MetadataAccessor} from "@raymondfeng/pkg2";
|
||||
export const ADMIN = MetadataAccessor.create<boolean>('1');`,
|
||||
},
|
||||
@@ -256,17 +252,16 @@ ${pluginOneAction()}`,
|
||||
path: `/user/username/projects/myproject/pkg3/node_modules/@raymondfeng/pkg2`,
|
||||
symLink: `/user/username/projects/myproject/pkg2`,
|
||||
},
|
||||
libFile,
|
||||
],
|
||||
changeCaseFileTestPath: str => str.includes("/pkg1"),
|
||||
});
|
||||
});
|
||||
|
||||
verifyTscWatch({
|
||||
verifyTsc({
|
||||
scenario: "declarationEmit",
|
||||
subScenario: "when using Windows paths and uppercase letters",
|
||||
sys: () =>
|
||||
createWatchedSystem([
|
||||
TestServerHost.createWatchedSystem([
|
||||
{
|
||||
path: `D:\\Work\\pkg1\\package.json`,
|
||||
content: jsonToReadableText({
|
||||
@@ -315,7 +310,7 @@ ${pluginOneAction()}`,
|
||||
},
|
||||
{
|
||||
path: `D:\\Work\\pkg1\\src\\main.ts`,
|
||||
content: Utils.dedent`
|
||||
content: dedent`
|
||||
import { PartialType } from './utils';
|
||||
|
||||
class Common {}
|
||||
@@ -327,7 +322,7 @@ ${pluginOneAction()}`,
|
||||
},
|
||||
{
|
||||
path: `D:\\Work\\pkg1\\src\\utils\\index.ts`,
|
||||
content: Utils.dedent`
|
||||
content: dedent`
|
||||
import { MyType, MyReturnType } from './type-helpers';
|
||||
|
||||
export function PartialType<T>(classRef: MyType<T>) {
|
||||
@@ -341,7 +336,7 @@ ${pluginOneAction()}`,
|
||||
},
|
||||
{
|
||||
path: `D:\\Work\\pkg1\\src\\utils\\type-helpers.ts`,
|
||||
content: Utils.dedent`
|
||||
content: dedent`
|
||||
export type MyReturnType = {
|
||||
new (...args: any[]): any;
|
||||
};
|
||||
@@ -351,22 +346,21 @@ ${pluginOneAction()}`,
|
||||
}
|
||||
`,
|
||||
},
|
||||
libFile,
|
||||
], { currentDirectory: "D:\\Work\\pkg1", windowsStyleRoot: "D:/" }),
|
||||
commandLineArgs: ["-p", "D:\\Work\\pkg1", "--explainFiles"],
|
||||
});
|
||||
|
||||
forEachDeclarationEmitWithErrorsScenario((scenarioName, fs) => {
|
||||
forEachDeclarationEmitWithErrorsScenario((scenarioName, sys) => {
|
||||
verifyTsc({
|
||||
scenario: "declarationEmit",
|
||||
subScenario: scenarioName("reports dts generation errors"),
|
||||
commandLineArgs: ["-p", `/src/project`, "--explainFiles", "--listEmittedFiles"],
|
||||
fs,
|
||||
commandLineArgs: ["--explainFiles", "--listEmittedFiles"],
|
||||
sys,
|
||||
edits: [
|
||||
noChangeRun,
|
||||
{
|
||||
...noChangeRun,
|
||||
commandLineArgs: ["-b", `/src/project`, "--explainFiles", "--listEmittedFiles", "-v"],
|
||||
commandLineArgs: ["-b", "--explainFiles", "--listEmittedFiles", "-v"],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
@@ -3,11 +3,9 @@ import {
|
||||
getSymlinkedExtendsSys,
|
||||
} from "../helpers/extends.js";
|
||||
import { verifyTsc } from "../helpers/tsc.js";
|
||||
import { verifyTscWatch } from "../helpers/tscWatch.js";
|
||||
import { loadProjectFromFiles } from "../helpers/vfs.js";
|
||||
|
||||
describe("unittests:: tsc:: extends::", () => {
|
||||
verifyTscWatch({
|
||||
verifyTsc({
|
||||
scenario: "extends",
|
||||
subScenario: "resolves the symlink path",
|
||||
sys: getSymlinkedExtendsSys,
|
||||
@@ -17,21 +15,21 @@ describe("unittests:: tsc:: extends::", () => {
|
||||
verifyTsc({
|
||||
scenario: "extends",
|
||||
subScenario: "configDir template",
|
||||
fs: () => loadProjectFromFiles(getConfigDirExtendsSys(), { cwd: "/home/src/projects/myproject" }),
|
||||
commandLineArgs: ["-p", "/home/src/projects/myproject", "--explainFiles"],
|
||||
sys: getConfigDirExtendsSys,
|
||||
commandLineArgs: ["--explainFiles"],
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "extends",
|
||||
subScenario: "configDir template showConfig",
|
||||
fs: () => loadProjectFromFiles(getConfigDirExtendsSys(), { cwd: "/home/src/projects/myproject" }),
|
||||
commandLineArgs: ["-p", "/home/src/projects/myproject", "--showConfig"],
|
||||
sys: getConfigDirExtendsSys,
|
||||
commandLineArgs: ["--showConfig"],
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "extends",
|
||||
subScenario: "configDir template with commandline",
|
||||
fs: () => loadProjectFromFiles(getConfigDirExtendsSys(), { cwd: "/home/src/projects/myproject" }),
|
||||
commandLineArgs: ["-p", "/home/src/projects/myproject", "--explainFiles", "--outDir", "${configDir}/outDir"], // eslint-disable-line no-template-curly-in-string
|
||||
sys: getConfigDirExtendsSys,
|
||||
commandLineArgs: ["--explainFiles", "--outDir", "${configDir}/outDir"], // eslint-disable-line no-template-curly-in-string
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,44 +1,44 @@
|
||||
import { dedent } from "../../_namespaces/Utils.js";
|
||||
import { getFsContentsForMultipleErrorsForceConsistentCasingInFileNames } from "../helpers/forceConsistentCasingInFileNames.js";
|
||||
import { getSysForMultipleErrorsForceConsistentCasingInFileNames } from "../helpers/forceConsistentCasingInFileNames.js";
|
||||
import { verifyTsc } from "../helpers/tsc.js";
|
||||
import { loadProjectFromFiles } from "../helpers/vfs.js";
|
||||
import { TestServerHost } from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsc:: forceConsistentCasingInFileNames::", () => {
|
||||
verifyTsc({
|
||||
scenario: "forceConsistentCasingInFileNames",
|
||||
subScenario: "with relative and non relative file resolutions",
|
||||
commandLineArgs: ["/src/project/src/struct.d.ts", "--forceConsistentCasingInFileNames", "--explainFiles"],
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/project/src/struct.d.ts": dedent`
|
||||
commandLineArgs: ["/user/username/projects/myproject/src/struct.d.ts", "--forceConsistentCasingInFileNames", "--explainFiles"],
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/user/username/projects/myproject/src/struct.d.ts": dedent`
|
||||
import * as xs1 from "fp-ts/lib/Struct";
|
||||
import * as xs2 from "fp-ts/lib/struct";
|
||||
import * as xs3 from "./Struct";
|
||||
import * as xs4 from "./struct";
|
||||
`,
|
||||
"/src/project/node_modules/fp-ts/lib/struct.d.ts": `export function foo(): void`,
|
||||
}),
|
||||
"/user/username/projects/myproject/node_modules/fp-ts/lib/struct.d.ts": `export function foo(): void`,
|
||||
}, { currentDirectory: "/user/username/projects/myproject" }),
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "forceConsistentCasingInFileNames",
|
||||
subScenario: "when file is included from multiple places with different casing",
|
||||
commandLineArgs: ["-p", "/home/src/projects/project/tsconfig.json", "--explainFiles"],
|
||||
fs: () => loadProjectFromFiles(getFsContentsForMultipleErrorsForceConsistentCasingInFileNames()),
|
||||
commandLineArgs: ["--explainFiles"],
|
||||
sys: getSysForMultipleErrorsForceConsistentCasingInFileNames,
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "forceConsistentCasingInFileNames",
|
||||
subScenario: "with type ref from file",
|
||||
commandLineArgs: ["-p", "/src/project/src", "--explainFiles", "--traceResolution"],
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/project/src/fileOne.d.ts": `declare class c { }`,
|
||||
"/src/project/src/file2.d.ts": dedent`
|
||||
commandLineArgs: ["-p", "/user/username/projects/myproject", "--explainFiles", "--traceResolution"],
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/user/username/projects/myproject/src/fileOne.d.ts": `declare class c { }`,
|
||||
"/user/username/projects/myproject/src/file2.d.ts": dedent`
|
||||
/// <reference types="./fileOne.d.ts"/>
|
||||
declare const y: c;
|
||||
`,
|
||||
"/src/project/src/tsconfig.json": "{ }",
|
||||
}),
|
||||
"/user/username/projects/myproject/tsconfig.json": "{ }",
|
||||
}, { currentDirectory: "/user/username/projects/myproject" }),
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
import * as ts from "../../_namespaces/ts.js";
|
||||
import { dedent } from "../../_namespaces/Utils.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import {
|
||||
compilerOptionsToConfigJson,
|
||||
libContent,
|
||||
} from "../helpers/contents.js";
|
||||
import { compilerOptionsToConfigJson } from "../helpers/contents.js";
|
||||
import {
|
||||
noChangeOnlyRuns,
|
||||
noChangeRun,
|
||||
@@ -12,67 +9,63 @@ import {
|
||||
verifyTsc,
|
||||
} from "../helpers/tsc.js";
|
||||
import {
|
||||
appendText,
|
||||
loadProjectFromFiles,
|
||||
prependText,
|
||||
replaceText,
|
||||
} from "../helpers/vfs.js";
|
||||
libFile,
|
||||
TestServerHost,
|
||||
} from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsc:: incremental::", () => {
|
||||
verifyTsc({
|
||||
scenario: "incremental",
|
||||
subScenario: "when passing filename for buildinfo on commandline",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/project/src/main.ts": "export const x = 10;",
|
||||
"/src/project/tsconfig.json": dedent`
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"module": "commonjs",
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts"
|
||||
]
|
||||
}`,
|
||||
}),
|
||||
commandLineArgs: ["--incremental", "--p", "src/project", "--tsBuildInfoFile", "src/project/.tsbuildinfo", "--explainFiles"],
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/src/main.ts": "export const x = 10;",
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
target: "es5",
|
||||
module: "commonjs",
|
||||
},
|
||||
include: [
|
||||
"src/**/*.ts",
|
||||
],
|
||||
}),
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
commandLineArgs: ["--incremental", "--tsBuildInfoFile", ".tsbuildinfo", "--explainFiles"],
|
||||
edits: noChangeOnlyRuns,
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "incremental",
|
||||
subScenario: "when passing rootDir from commandline",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/project/src/main.ts": "export const x = 10;",
|
||||
"/src/project/tsconfig.json": dedent`
|
||||
{
|
||||
"compilerOptions": {
|
||||
"incremental": true,
|
||||
"outDir": "dist",
|
||||
},
|
||||
}`,
|
||||
}),
|
||||
commandLineArgs: ["--p", "src/project", "--rootDir", "src/project/src"],
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/src/main.ts": "export const x = 10;",
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
incremental: true,
|
||||
outDir: "dist",
|
||||
},
|
||||
}),
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
commandLineArgs: ["--rootDir", "src"],
|
||||
edits: noChangeOnlyRuns,
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "incremental",
|
||||
subScenario: "with only dts files",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/project/src/main.d.ts": "export const x = 10;",
|
||||
"/src/project/src/another.d.ts": "export const y = 10;",
|
||||
"/src/project/tsconfig.json": "{}",
|
||||
}),
|
||||
commandLineArgs: ["--incremental", "--p", "src/project"],
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/src/main.d.ts": "export const x = 10;",
|
||||
"/home/src/workspaces/project/src/another.d.ts": "export const y = 10;",
|
||||
"/home/src/workspaces/project/tsconfig.json": "{}",
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
commandLineArgs: ["--incremental"],
|
||||
edits: [
|
||||
noChangeRun,
|
||||
{
|
||||
caption: "incremental-declaration-doesnt-change",
|
||||
edit: fs => appendText(fs, "/src/project/src/main.d.ts", "export const xy = 100;"),
|
||||
edit: sys => sys.appendFile("/home/src/workspaces/project/src/main.d.ts", "export const xy = 100;"),
|
||||
},
|
||||
],
|
||||
});
|
||||
@@ -80,90 +73,88 @@ describe("unittests:: tsc:: incremental::", () => {
|
||||
verifyTsc({
|
||||
scenario: "incremental",
|
||||
subScenario: "when passing rootDir is in the tsconfig",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/project/src/main.ts": "export const x = 10;",
|
||||
"/src/project/tsconfig.json": dedent`
|
||||
{
|
||||
"compilerOptions": {
|
||||
"incremental": true,
|
||||
"outDir": "./built",
|
||||
"rootDir": "./"
|
||||
},
|
||||
}`,
|
||||
}),
|
||||
commandLineArgs: ["--p", "src/project"],
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/src/main.ts": "export const x = 10;",
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
incremental: true,
|
||||
outDir: "./built",
|
||||
rootDir: "./",
|
||||
},
|
||||
}),
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
commandLineArgs: ts.emptyArray,
|
||||
edits: noChangeOnlyRuns,
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "incremental",
|
||||
subScenario: "tsbuildinfo has error",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/project/main.ts": "export const x = 10;",
|
||||
"/src/project/tsconfig.json": "{}",
|
||||
"/src/project/tsconfig.tsbuildinfo": "Some random string",
|
||||
}),
|
||||
commandLineArgs: ["--p", "src/project", "-i"],
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/main.ts": "export const x = 10;",
|
||||
"/home/src/workspaces/project/tsconfig.json": "{}",
|
||||
"/home/src/workspaces/project/tsconfig.tsbuildinfo": "Some random string",
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
commandLineArgs: ["-i"],
|
||||
edits: [{
|
||||
caption: "tsbuildinfo written has error",
|
||||
edit: fs => prependText(fs, "/src/project/tsconfig.tsbuildinfo", "Some random string"),
|
||||
edit: sys => sys.prependFile("/home/src/workspaces/project/tsconfig.tsbuildinfo", "Some random string"),
|
||||
}],
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "incremental",
|
||||
subScenario: `when global file is added, the signatures are updated`,
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/project/src/main.ts": dedent`
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/src/main.ts": dedent`
|
||||
/// <reference path="./filePresent.ts"/>
|
||||
/// <reference path="./fileNotFound.ts"/>
|
||||
function main() { }
|
||||
`,
|
||||
"/src/project/src/anotherFileWithSameReferenes.ts": dedent`
|
||||
"/home/src/workspaces/project/src/anotherFileWithSameReferenes.ts": dedent`
|
||||
/// <reference path="./filePresent.ts"/>
|
||||
/// <reference path="./fileNotFound.ts"/>
|
||||
function anotherFileWithSameReferenes() { }
|
||||
`,
|
||||
"/src/project/src/filePresent.ts": `function something() { return 10; }`,
|
||||
"/src/project/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/project/src/filePresent.ts": `function something() { return 10; }`,
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: { composite: true },
|
||||
include: ["src/**/*.ts"],
|
||||
}),
|
||||
}),
|
||||
commandLineArgs: ["--p", "src/project"],
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
commandLineArgs: ts.emptyArray,
|
||||
edits: [
|
||||
noChangeRun,
|
||||
{
|
||||
caption: "Modify main file",
|
||||
edit: fs => appendText(fs, `/src/project/src/main.ts`, `something();`),
|
||||
edit: sys => sys.appendFile(`/home/src/workspaces/project/src/main.ts`, `something();`),
|
||||
},
|
||||
{
|
||||
caption: "Modify main file again",
|
||||
edit: fs => appendText(fs, `/src/project/src/main.ts`, `something();`),
|
||||
edit: sys => sys.appendFile(`/home/src/workspaces/project/src/main.ts`, `something();`),
|
||||
},
|
||||
{
|
||||
caption: "Add new file and update main file",
|
||||
edit: fs => {
|
||||
fs.writeFileSync(`/src/project/src/newFile.ts`, "function foo() { return 20; }");
|
||||
prependText(
|
||||
fs,
|
||||
`/src/project/src/main.ts`,
|
||||
edit: sys => {
|
||||
sys.writeFile(`/home/src/workspaces/project/src/newFile.ts`, "function foo() { return 20; }");
|
||||
sys.prependFile(
|
||||
`/home/src/workspaces/project/src/main.ts`,
|
||||
`/// <reference path="./newFile.ts"/>
|
||||
`,
|
||||
);
|
||||
appendText(fs, `/src/project/src/main.ts`, `foo();`);
|
||||
sys.appendFile(`/home/src/workspaces/project/src/main.ts`, `foo();`);
|
||||
},
|
||||
},
|
||||
{
|
||||
caption: "Write file that could not be resolved",
|
||||
edit: fs => fs.writeFileSync(`/src/project/src/fileNotFound.ts`, "function something2() { return 20; }"),
|
||||
edit: sys => sys.writeFile(`/home/src/workspaces/project/src/fileNotFound.ts`, "function something2() { return 20; }"),
|
||||
},
|
||||
{
|
||||
caption: "Modify main file",
|
||||
edit: fs => appendText(fs, `/src/project/src/main.ts`, `something();`),
|
||||
edit: sys => sys.appendFile(`/home/src/workspaces/project/src/main.ts`, `something();`),
|
||||
},
|
||||
],
|
||||
baselinePrograms: true,
|
||||
@@ -186,48 +177,48 @@ declare global {
|
||||
}
|
||||
|
||||
verifyTsc({
|
||||
scenario: "react-jsx-emit-mode",
|
||||
subScenario: "with no backing types found doesn't crash",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/project/node_modules/react/jsx-runtime.js": "export {}", // js needs to be present so there's a resolution result
|
||||
"/src/project/node_modules/@types/react/index.d.ts": getJsxLibraryContent(), // doesn't contain a jsx-runtime definition
|
||||
"/src/project/src/index.tsx": `export const App = () => <div propA={true}></div>;`,
|
||||
"/src/project/tsconfig.json": jsonToReadableText({ compilerOptions: { module: "commonjs", jsx: "react-jsx", incremental: true, jsxImportSource: "react" } }),
|
||||
}),
|
||||
commandLineArgs: ["--p", "src/project"],
|
||||
scenario: "incremental",
|
||||
subScenario: "react-jsx-emit-mode with no backing types found doesn't crash",
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/node_modules/react/jsx-runtime.js": "export {}", // js needs to be present so there's a resolution result
|
||||
"/home/src/workspaces/project/node_modules/@types/react/index.d.ts": getJsxLibraryContent(), // doesn't contain a jsx-runtime definition
|
||||
"/home/src/workspaces/project/src/index.tsx": `export const App = () => <div propA={true}></div>;`,
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({ compilerOptions: { module: "commonjs", jsx: "react-jsx", incremental: true, jsxImportSource: "react" } }),
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
commandLineArgs: ts.emptyArray,
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "react-jsx-emit-mode",
|
||||
subScenario: "with no backing types found doesn't crash under --strict",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/project/node_modules/react/jsx-runtime.js": "export {}", // js needs to be present so there's a resolution result
|
||||
"/src/project/node_modules/@types/react/index.d.ts": getJsxLibraryContent(), // doesn't contain a jsx-runtime definition
|
||||
"/src/project/src/index.tsx": `export const App = () => <div propA={true}></div>;`,
|
||||
"/src/project/tsconfig.json": jsonToReadableText({ compilerOptions: { module: "commonjs", jsx: "react-jsx", incremental: true, jsxImportSource: "react" } }),
|
||||
}),
|
||||
commandLineArgs: ["--p", "src/project", "--strict"],
|
||||
scenario: "incremental",
|
||||
subScenario: "react-jsx-emit-mode with no backing types found doesn't crash under --strict",
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/node_modules/react/jsx-runtime.js": "export {}", // js needs to be present so there's a resolution result
|
||||
"/home/src/workspaces/project/node_modules/@types/react/index.d.ts": getJsxLibraryContent(), // doesn't contain a jsx-runtime definition
|
||||
"/home/src/workspaces/project/src/index.tsx": `export const App = () => <div propA={true}></div>;`,
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({ compilerOptions: { module: "commonjs", jsx: "react-jsx", incremental: true, jsxImportSource: "react" } }),
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
commandLineArgs: ["--strict"],
|
||||
});
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "incremental",
|
||||
subScenario: "when new file is added to the referenced project",
|
||||
commandLineArgs: ["-i", "-p", `src/projects/project2`],
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/projects/project1/tsconfig.json": jsonToReadableText({
|
||||
commandLineArgs: ["-i", "-p", "project2"],
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/projects/project1/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
module: "none",
|
||||
composite: true,
|
||||
},
|
||||
exclude: ["temp"],
|
||||
}),
|
||||
"/src/projects/project1/class1.ts": `class class1 {}`,
|
||||
"/src/projects/project1/class1.d.ts": `declare class class1 {}`,
|
||||
"/src/projects/project2/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/projects/project1/class1.ts": `class class1 {}`,
|
||||
"/home/src/workspaces/projects/project1/class1.d.ts": `declare class class1 {}`,
|
||||
"/home/src/workspaces/projects/project2/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
module: "none",
|
||||
composite: true,
|
||||
@@ -236,12 +227,12 @@ declare global {
|
||||
{ path: "../project1" },
|
||||
],
|
||||
}),
|
||||
"/src/projects/project2/class2.ts": `class class2 {}`,
|
||||
}),
|
||||
"/home/src/workspaces/projects/project2/class2.ts": `class class2 {}`,
|
||||
}, { currentDirectory: "/home/src/workspaces/projects" }),
|
||||
edits: [
|
||||
{
|
||||
caption: "Add class3 to project1 and build it",
|
||||
edit: fs => fs.writeFileSync("/src/projects/project1/class3.ts", `class class3 {}`, "utf-8"),
|
||||
edit: sys => sys.writeFile("/home/src/workspaces/projects/project1/class3.ts", `class class3 {}`),
|
||||
discrepancyExplanation: () => [
|
||||
"Ts buildinfo will not be updated in incremental build so it will have semantic diagnostics cached from previous build",
|
||||
"But in clean build because of global diagnostics, semantic diagnostics are not queried so not cached in tsbuildinfo",
|
||||
@@ -249,22 +240,22 @@ declare global {
|
||||
},
|
||||
{
|
||||
caption: "Add output of class3",
|
||||
edit: fs => fs.writeFileSync("/src/projects/project1/class3.d.ts", `declare class class3 {}`, "utf-8"),
|
||||
edit: sys => sys.writeFile("/home/src/workspaces/projects/project1/class3.d.ts", `declare class class3 {}`),
|
||||
},
|
||||
{
|
||||
caption: "Add excluded file to project1",
|
||||
edit: fs => {
|
||||
fs.mkdirSync("/src/projects/project1/temp");
|
||||
fs.writeFileSync("/src/projects/project1/temp/file.d.ts", `declare class file {}`, "utf-8");
|
||||
edit: sys => {
|
||||
sys.ensureFileOrFolder({ path: "/home/src/workspaces/projects/project1/temp" });
|
||||
sys.writeFile("/home/src/workspaces/projects/project1/temp/file.d.ts", `declare class file {}`);
|
||||
},
|
||||
},
|
||||
{
|
||||
caption: "Delete output for class3",
|
||||
edit: fs => fs.unlinkSync("/src/projects/project1/class3.d.ts"),
|
||||
edit: sys => sys.deleteFile("/home/src/workspaces/projects/project1/class3.d.ts"),
|
||||
},
|
||||
{
|
||||
caption: "Create output for class3",
|
||||
edit: fs => fs.writeFileSync("/src/projects/project1/class3.d.ts", `declare class class3 {}`, "utf-8"),
|
||||
edit: sys => sys.writeFile("/home/src/workspaces/projects/project1/class3.d.ts", `declare class class3 {}`),
|
||||
},
|
||||
],
|
||||
});
|
||||
@@ -272,10 +263,10 @@ declare global {
|
||||
verifyTsc({
|
||||
scenario: "incremental",
|
||||
subScenario: "serializing error chains",
|
||||
commandLineArgs: ["-p", `src/project`],
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/project/tsconfig.json": jsonToReadableText({
|
||||
commandLineArgs: ts.emptyArray,
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
incremental: true,
|
||||
strict: true,
|
||||
@@ -283,7 +274,7 @@ declare global {
|
||||
module: "esnext",
|
||||
},
|
||||
}),
|
||||
"/src/project/index.tsx": dedent`
|
||||
"/home/src/workspaces/project/index.tsx": dedent`
|
||||
declare namespace JSX {
|
||||
interface ElementChildrenAttribute { children: {}; }
|
||||
interface IntrinsicElements { div: {} }
|
||||
@@ -297,16 +288,17 @@ declare global {
|
||||
<div />
|
||||
<div />
|
||||
</Component>)`,
|
||||
}, `\ninterface ReadonlyArray<T> { readonly length: number }`),
|
||||
[libFile.path]: `${libFile.content}\ninterface ReadonlyArray<T> { readonly length: number }`,
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
edits: noChangeOnlyRuns,
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "incremental",
|
||||
subScenario: "ts file with no-default-lib that augments the global scope",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/project/src/main.ts": dedent`
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/src/main.ts": dedent`
|
||||
/// <reference no-default-lib="true"/>
|
||||
/// <reference lib="esnext" />
|
||||
|
||||
@@ -317,56 +309,52 @@ declare global {
|
||||
|
||||
export {};
|
||||
`,
|
||||
"/src/project/tsconfig.json": dedent`
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"module": "ESNext",
|
||||
"incremental": true,
|
||||
"outDir": "dist",
|
||||
},
|
||||
}`,
|
||||
}),
|
||||
commandLineArgs: ["--p", "src/project", "--rootDir", "src/project/src"],
|
||||
modifyFs: fs => {
|
||||
fs.writeFileSync("/lib/lib.esnext.d.ts", libContent);
|
||||
},
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
target: "ESNext",
|
||||
module: "ESNext",
|
||||
incremental: true,
|
||||
outDir: "dist",
|
||||
},
|
||||
}),
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
commandLineArgs: ["--rootDir", "src"],
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "incremental",
|
||||
subScenario: "change to type that gets used as global through export in another file",
|
||||
commandLineArgs: ["-p", `src/project`],
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/project/tsconfig.json": jsonToReadableText({ compilerOptions: { composite: true } }),
|
||||
"/src/project/class1.ts": `const a: MagicNumber = 1;
|
||||
commandLineArgs: ts.emptyArray,
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({ compilerOptions: { composite: true } }),
|
||||
"/home/src/workspaces/project/class1.ts": `const a: MagicNumber = 1;
|
||||
console.log(a);`,
|
||||
"/src/project/constants.ts": "export default 1;",
|
||||
"/src/project/types.d.ts": `type MagicNumber = typeof import('./constants').default`,
|
||||
}),
|
||||
"/home/src/workspaces/project/constants.ts": "export default 1;",
|
||||
"/home/src/workspaces/project/types.d.ts": `type MagicNumber = typeof import('./constants').default`,
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
edits: [{
|
||||
caption: "Modify imports used in global file",
|
||||
edit: fs => fs.writeFileSync("/src/project/constants.ts", "export default 2;"),
|
||||
edit: sys => sys.writeFile("/home/src/workspaces/project/constants.ts", "export default 2;"),
|
||||
}],
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "incremental",
|
||||
subScenario: "change to type that gets used as global through export in another file through indirect import",
|
||||
commandLineArgs: ["-p", `src/project`],
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/project/tsconfig.json": jsonToReadableText({ compilerOptions: { composite: true } }),
|
||||
"/src/project/class1.ts": `const a: MagicNumber = 1;
|
||||
commandLineArgs: ts.emptyArray,
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({ compilerOptions: { composite: true } }),
|
||||
"/home/src/workspaces/project/class1.ts": `const a: MagicNumber = 1;
|
||||
console.log(a);`,
|
||||
"/src/project/constants.ts": "export default 1;",
|
||||
"/src/project/reexport.ts": `export { default as ConstantNumber } from "./constants"`,
|
||||
"/src/project/types.d.ts": `type MagicNumber = typeof import('./reexport').ConstantNumber`,
|
||||
}),
|
||||
"/home/src/workspaces/project/constants.ts": "export default 1;",
|
||||
"/home/src/workspaces/project/reexport.ts": `export { default as ConstantNumber } from "./constants"`,
|
||||
"/home/src/workspaces/project/types.d.ts": `type MagicNumber = typeof import('./reexport').ConstantNumber`,
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
edits: [{
|
||||
caption: "Modify imports used in global file",
|
||||
edit: fs => fs.writeFileSync("/src/project/constants.ts", "export default 2;"),
|
||||
edit: sys => sys.writeFile("/home/src/workspaces/project/constants.ts", "export default 2;"),
|
||||
}],
|
||||
});
|
||||
|
||||
@@ -374,16 +362,16 @@ console.log(a);`,
|
||||
verifyTsc({
|
||||
scenario: "incremental",
|
||||
subScenario: `change to modifier of class expression field${declaration ? " with declaration emit enabled" : ""}`,
|
||||
commandLineArgs: ["-p", "src/project", "--incremental"],
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/project/tsconfig.json": jsonToReadableText({ compilerOptions: { declaration } }),
|
||||
"/src/project/main.ts": dedent`
|
||||
commandLineArgs: ["--incremental"],
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({ compilerOptions: { declaration } }),
|
||||
"/home/src/workspaces/project/main.ts": dedent`
|
||||
import MessageablePerson from './MessageablePerson.js';
|
||||
function logMessage( person: MessageablePerson ) {
|
||||
console.log( person.message );
|
||||
}`,
|
||||
"/src/project/MessageablePerson.ts": dedent`
|
||||
"/home/src/workspaces/project/MessageablePerson.ts": dedent`
|
||||
const Messageable = () => {
|
||||
return class MessageableClass {
|
||||
public message = 'hello';
|
||||
@@ -392,11 +380,10 @@ console.log(a);`,
|
||||
const wrapper = () => Messageable();
|
||||
type MessageablePerson = InstanceType<ReturnType<typeof wrapper>>;
|
||||
export default MessageablePerson;`,
|
||||
}),
|
||||
modifyFs: fs =>
|
||||
appendText(
|
||||
fs,
|
||||
"/lib/lib.d.ts",
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
modifySystem: sys =>
|
||||
sys.appendFile(
|
||||
libFile.path,
|
||||
dedent`
|
||||
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;
|
||||
type InstanceType<T extends abstract new (...args: any) => any> = T extends abstract new (...args: any) => infer R ? R : any;`,
|
||||
@@ -405,12 +392,12 @@ console.log(a);`,
|
||||
noChangeRun,
|
||||
{
|
||||
caption: "modify public to protected",
|
||||
edit: fs => replaceText(fs, "/src/project/MessageablePerson.ts", "public", "protected"),
|
||||
edit: sys => sys.replaceFileText("/home/src/workspaces/project/MessageablePerson.ts", "public", "protected"),
|
||||
},
|
||||
noChangeRun,
|
||||
{
|
||||
caption: "modify protected to public",
|
||||
edit: fs => replaceText(fs, "/src/project/MessageablePerson.ts", "protected", "public"),
|
||||
edit: sys => sys.replaceFileText("/home/src/workspaces/project/MessageablePerson.ts", "protected", "public"),
|
||||
},
|
||||
noChangeRun,
|
||||
],
|
||||
@@ -424,7 +411,7 @@ console.log(a);`,
|
||||
return {
|
||||
caption,
|
||||
edit: ts.noop,
|
||||
commandLineArgs: ["--p", "/src/project", ...options],
|
||||
commandLineArgs: [...options],
|
||||
};
|
||||
}
|
||||
function noChangeWithSubscenario(caption: string): TestTscEdit {
|
||||
@@ -451,25 +438,25 @@ console.log(a);`,
|
||||
function localChange(): TestTscEdit {
|
||||
return {
|
||||
caption: "local change",
|
||||
edit: fs => replaceText(fs, "/src/project/a.ts", "Local = 1", "Local = 10"),
|
||||
edit: sys => sys.replaceFileText("/home/src/workspaces/project/a.ts", "Local = 1", "Local = 10"),
|
||||
};
|
||||
}
|
||||
function fs(options: ts.CompilerOptions) {
|
||||
return loadProjectFromFiles({
|
||||
"/src/project/tsconfig.json": jsonToReadableText({ compilerOptions: compilerOptionsToConfigJson(options) }),
|
||||
"/src/project/a.ts": `export const a = 10;const aLocal = 10;`,
|
||||
"/src/project/b.ts": `export const b = 10;const bLocal = 10;`,
|
||||
"/src/project/c.ts": `import { a } from "./a";export const c = a;`,
|
||||
"/src/project/d.ts": `import { b } from "./b";export const d = b;`,
|
||||
});
|
||||
function sys(options: ts.CompilerOptions) {
|
||||
return TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({ compilerOptions: compilerOptionsToConfigJson(options) }),
|
||||
"/home/src/workspaces/project/a.ts": `export const a = 10;const aLocal = 10;`,
|
||||
"/home/src/workspaces/project/b.ts": `export const b = 10;const bLocal = 10;`,
|
||||
"/home/src/workspaces/project/c.ts": `import { a } from "./a";export const c = a;`,
|
||||
"/home/src/workspaces/project/d.ts": `import { b } from "./b";export const d = b;`,
|
||||
}, { currentDirectory: "/home/src/workspaces/project" });
|
||||
}
|
||||
function enableDeclarationMap(): TestTscEdit {
|
||||
return {
|
||||
caption: "declarationMap enabling",
|
||||
edit: fs => {
|
||||
const config = JSON.parse(fs.readFileSync("/src/project/tsconfig.json", "utf-8"));
|
||||
edit: sys => {
|
||||
const config = JSON.parse(sys.readFile("/home/src/workspaces/project/tsconfig.json")!);
|
||||
config.compilerOptions.declarationMap = true;
|
||||
fs.writeFileSync("/src/project/tsconfig.json", jsonToReadableText(config));
|
||||
sys.writeFile("/home/src/workspaces/project/tsconfig.json", jsonToReadableText(config));
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -480,8 +467,8 @@ console.log(a);`,
|
||||
verifyTsc({
|
||||
scenario: "incremental",
|
||||
subScenario: scenarioName("different options"),
|
||||
fs: () => fs({ composite: true, ...options }),
|
||||
commandLineArgs: ["--p", "/src/project"],
|
||||
sys: () => sys({ composite: true, ...options }),
|
||||
commandLineArgs: ts.emptyArray,
|
||||
edits: [
|
||||
withOptionChange("with sourceMap", "--sourceMap"),
|
||||
noChangeWithSubscenario("should re-emit only js so they dont contain sourcemap"),
|
||||
@@ -503,8 +490,8 @@ console.log(a);`,
|
||||
verifyTsc({
|
||||
scenario: "incremental",
|
||||
subScenario: scenarioName("different options with incremental"),
|
||||
fs: () => fs({ incremental: true, ...options }),
|
||||
commandLineArgs: ["--p", "/src/project"],
|
||||
sys: () => sys({ incremental: true, ...options }),
|
||||
commandLineArgs: ts.emptyArray,
|
||||
edits: [
|
||||
withOptionChange("with sourceMap", "--sourceMap"),
|
||||
noChangeWithSubscenario("should re-emit only js so they dont contain sourcemap"),
|
||||
@@ -531,22 +518,22 @@ console.log(a);`,
|
||||
verifyTsc({
|
||||
scenario: "incremental",
|
||||
subScenario: "when file is deleted",
|
||||
commandLineArgs: ["-p", `/src/project`],
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/project/tsconfig.json": jsonToReadableText({
|
||||
commandLineArgs: ts.emptyArray,
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
outDir: "outDir",
|
||||
},
|
||||
}),
|
||||
"/src/project/file1.ts": `export class C { }`,
|
||||
"/src/project/file2.ts": `export class D { }`,
|
||||
}),
|
||||
"/home/src/workspaces/project/file1.ts": `export class C { }`,
|
||||
"/home/src/workspaces/project/file2.ts": `export class D { }`,
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
edits: [
|
||||
{
|
||||
caption: "delete file with imports",
|
||||
edit: fs => fs.unlinkSync("/src/project/file2.ts"),
|
||||
edit: sys => sys.deleteFile("/home/src/workspaces/project/file2.ts"),
|
||||
},
|
||||
],
|
||||
});
|
||||
@@ -554,10 +541,10 @@ console.log(a);`,
|
||||
verifyTsc({
|
||||
scenario: "incremental",
|
||||
subScenario: "generates typerefs correctly",
|
||||
commandLineArgs: ["-p", `/src/project`],
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/project/tsconfig.json": jsonToReadableText({
|
||||
commandLineArgs: ts.emptyArray,
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
outDir: "outDir",
|
||||
@@ -565,12 +552,12 @@ console.log(a);`,
|
||||
},
|
||||
include: ["src"],
|
||||
}),
|
||||
"/src/project/src/box.ts": dedent`
|
||||
"/home/src/workspaces/project/src/box.ts": dedent`
|
||||
export interface Box<T> {
|
||||
unbox(): T
|
||||
}
|
||||
`,
|
||||
"/src/project/src/bug.js": dedent`
|
||||
"/home/src/workspaces/project/src/bug.js": dedent`
|
||||
import * as B from "./box.js"
|
||||
import * as W from "./wrap.js"
|
||||
|
||||
@@ -590,15 +577,15 @@ console.log(a);`,
|
||||
|
||||
export const bug = wrap({ n: box(1) });
|
||||
`,
|
||||
"/src/project/src/wrap.ts": dedent`
|
||||
"/home/src/workspaces/project/src/wrap.ts": dedent`
|
||||
export type Wrap<C> = {
|
||||
[K in keyof C]: { wrapped: C[K] }
|
||||
}
|
||||
`,
|
||||
}),
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
edits: [{
|
||||
caption: "modify js file",
|
||||
edit: fs => appendText(fs, "/src/project/src/bug.js", `export const something = 1;`),
|
||||
edit: sys => sys.appendFile("/home/src/workspaces/project/src/bug.js", `export const something = 1;`),
|
||||
}],
|
||||
});
|
||||
|
||||
@@ -609,20 +596,20 @@ console.log(a);`,
|
||||
DifferentFile = "aliased in different file ",
|
||||
}
|
||||
function fileWithEnum(withAlias: AliasType) {
|
||||
return withAlias !== AliasType.DifferentFile ? "/src/project/b.d.ts" : "/src/project/worker.d.ts";
|
||||
return withAlias !== AliasType.DifferentFile ? "/home/src/workspaces/project/b.d.ts" : "/home/src/workspaces/project/worker.d.ts";
|
||||
}
|
||||
function verify(withAlias: AliasType, preserveConstEnums: boolean) {
|
||||
verifyTsc({
|
||||
scenario: "incremental",
|
||||
subScenario: `with ${withAlias}const enums${preserveConstEnums ? " with preserveConstEnums" : ""}`,
|
||||
commandLineArgs: ["-i", `/src/project/a.ts`, "--tsbuildinfofile", "/src/project/a.tsbuildinfo", ...preserveConstEnums ? ["--preserveConstEnums"] : []],
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/project/a.ts": dedent`
|
||||
commandLineArgs: ["-i", `a.ts`, "--tsbuildinfofile", "a.tsbuildinfo", ...preserveConstEnums ? ["--preserveConstEnums"] : []],
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/a.ts": dedent`
|
||||
import {A} from "./c"
|
||||
let a = A.ONE
|
||||
`,
|
||||
"/src/project/b.d.ts": withAlias === AliasType.SameFile ?
|
||||
"/home/src/workspaces/project/b.d.ts": withAlias === AliasType.SameFile ?
|
||||
dedent`
|
||||
declare const enum AWorker {
|
||||
ONE = 1
|
||||
@@ -638,33 +625,33 @@ console.log(a);`,
|
||||
ONE = 1
|
||||
}
|
||||
`,
|
||||
"/src/project/c.ts": dedent`
|
||||
"/home/src/workspaces/project/c.ts": dedent`
|
||||
import {A} from "./b"
|
||||
let b = A.ONE
|
||||
export {A}
|
||||
`,
|
||||
"/src/project/worker.d.ts": dedent`
|
||||
"/home/src/workspaces/project/worker.d.ts": dedent`
|
||||
export const enum AWorker {
|
||||
ONE = 1
|
||||
}
|
||||
`,
|
||||
}),
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
edits: [
|
||||
{
|
||||
caption: "change enum value",
|
||||
edit: fs => replaceText(fs, fileWithEnum(withAlias), "1", "2"),
|
||||
edit: sys => sys.replaceFileText(fileWithEnum(withAlias), "1", "2"),
|
||||
},
|
||||
{
|
||||
caption: "change enum value again",
|
||||
edit: fs => replaceText(fs, fileWithEnum(withAlias), "2", "3"),
|
||||
edit: sys => sys.replaceFileText(fileWithEnum(withAlias), "2", "3"),
|
||||
},
|
||||
{
|
||||
caption: "something else changes in b.d.ts",
|
||||
edit: fs => appendText(fs, "/src/project/b.d.ts", "export const randomThing = 10;"),
|
||||
edit: sys => sys.appendFile("/home/src/workspaces/project/b.d.ts", "export const randomThing = 10;"),
|
||||
},
|
||||
{
|
||||
caption: "something else changes in b.d.ts again",
|
||||
edit: fs => appendText(fs, "/src/project/b.d.ts", "export const randomThing2 = 10;"),
|
||||
edit: sys => sys.appendFile("/home/src/workspaces/project/b.d.ts", "export const randomThing2 = 10;"),
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
@@ -1,36 +1,35 @@
|
||||
import { emptyArray } from "../../_namespaces/ts.js";
|
||||
import { dedent } from "../../_namespaces/Utils.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import { libContent } from "../helpers/contents.js";
|
||||
import {
|
||||
forEachLibResolutionScenario,
|
||||
getCommandLineArgsForLibResolution,
|
||||
getFsForLibResolution,
|
||||
getFsForLibResolutionUnknown,
|
||||
getSysForLibResolutionUnknown,
|
||||
} from "../helpers/libraryResolution.js";
|
||||
import {
|
||||
noChangeRun,
|
||||
verifyTsc,
|
||||
} from "../helpers/tsc.js";
|
||||
import { loadProjectFromFiles } from "../helpers/vfs.js";
|
||||
import { TestServerHost } from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsc:: libraryResolution:: library file resolution", () => {
|
||||
function verify(libRedirection?: true, withoutConfig?: true) {
|
||||
verifyTsc({
|
||||
scenario: "libraryResolution",
|
||||
subScenario: `${withoutConfig ? "without" : "with"} config${libRedirection ? " with redirection" : ""}`,
|
||||
fs: () => getFsForLibResolution(libRedirection),
|
||||
commandLineArgs: getCommandLineArgsForLibResolution(withoutConfig),
|
||||
baselinePrograms: true,
|
||||
});
|
||||
function verify(withoutConfig?: true) {
|
||||
forEachLibResolutionScenario(/*forTsserver*/ false, withoutConfig, (subScenario, sys) =>
|
||||
verifyTsc({
|
||||
scenario: "libraryResolution",
|
||||
subScenario,
|
||||
sys,
|
||||
commandLineArgs: getCommandLineArgsForLibResolution(withoutConfig),
|
||||
baselinePrograms: true,
|
||||
}));
|
||||
}
|
||||
verify();
|
||||
verify(/*libRedirection*/ true);
|
||||
verify(/*libRedirection*/ undefined, /*withoutConfig*/ true);
|
||||
verify(/*libRedirection*/ true, /*withoutConfig*/ true);
|
||||
verify(/*withoutConfig*/ true);
|
||||
|
||||
verifyTsc({
|
||||
scenario: "libraryResolution",
|
||||
subScenario: "unknown lib",
|
||||
fs: () => getFsForLibResolutionUnknown(),
|
||||
sys: getSysForLibResolutionUnknown,
|
||||
commandLineArgs: getCommandLineArgsForLibResolution(/*withoutConfig*/ undefined),
|
||||
baselinePrograms: true,
|
||||
});
|
||||
@@ -38,24 +37,23 @@ describe("unittests:: tsc:: libraryResolution:: library file resolution", () =>
|
||||
verifyTsc({
|
||||
scenario: "libraryResolution",
|
||||
subScenario: "when noLib toggles",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/a.d.ts": `declare const a = "hello";`,
|
||||
"/src/b.ts": `const b = 10;`,
|
||||
"/src/tsconfig.json": jsonToReadableText({
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/a.d.ts": `declare const a = "hello";`,
|
||||
"/home/src/workspaces/project/b.ts": `const b = 10;`,
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
declaration: true,
|
||||
incremental: true,
|
||||
lib: ["es6"],
|
||||
},
|
||||
}),
|
||||
"/lib/lib.es2015.d.ts": libContent,
|
||||
}),
|
||||
commandLineArgs: ["-p", "/src/tsconfig.json"],
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
commandLineArgs: emptyArray,
|
||||
edits: [
|
||||
{
|
||||
...noChangeRun,
|
||||
commandLineArgs: ["-p", "/src/tsconfig.json", "--noLib"],
|
||||
commandLineArgs: ["--noLib"],
|
||||
},
|
||||
],
|
||||
baselinePrograms: true,
|
||||
@@ -64,22 +62,21 @@ describe("unittests:: tsc:: libraryResolution:: library file resolution", () =>
|
||||
verifyTsc({
|
||||
scenario: "libraryResolution",
|
||||
subScenario: "when one of the file skips default lib inclusion",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/a.d.ts": dedent`
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/a.d.ts": dedent`
|
||||
/// <reference no-default-lib="true"/>
|
||||
/// <reference lib="es6"/>
|
||||
declare const a = "hello";
|
||||
`,
|
||||
"/src/b.d.ts": `export const b = 10;`,
|
||||
"/src/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/project/b.d.ts": `export const b = 10;`,
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
lib: ["es6", "dom"],
|
||||
},
|
||||
}),
|
||||
"/lib/lib.es2015.d.ts": libContent,
|
||||
}),
|
||||
commandLineArgs: ["-p", "/src/tsconfig.json", "-i", "--explainFiles"],
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
commandLineArgs: ["-i", "--explainFiles"],
|
||||
baselinePrograms: true,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,51 +1,38 @@
|
||||
import * as Utils from "../../_namespaces/Utils.js";
|
||||
import {
|
||||
noChangeRun,
|
||||
verifyTsc,
|
||||
} from "../helpers/tsc.js";
|
||||
import { loadProjectFromFiles } from "../helpers/vfs.js";
|
||||
import { TestServerHost } from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsc:: listFilesOnly::", () => {
|
||||
verifyTsc({
|
||||
scenario: "listFilesOnly",
|
||||
subScenario: "combined with watch",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/test.ts": Utils.dedent`
|
||||
export const x = 1;`,
|
||||
}),
|
||||
commandLineArgs: ["/src/test.ts", "--watch", "--listFilesOnly"],
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "listFilesOnly",
|
||||
subScenario: "loose file",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/test.ts": Utils.dedent`
|
||||
export const x = 1;`,
|
||||
}),
|
||||
commandLineArgs: ["/src/test.ts", "--listFilesOnly"],
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/test.ts": "export const x = 1;",
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
commandLineArgs: ["test.ts", "--listFilesOnly"],
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "listFilesOnly",
|
||||
subScenario: "combined with incremental",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/test.ts": `export const x = 1;`,
|
||||
"/src/tsconfig.json": "{}",
|
||||
}),
|
||||
commandLineArgs: ["-p", "/src", "--incremental", "--listFilesOnly"],
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/test.ts": "export const x = 1;",
|
||||
"/home/src/workspaces/project/tsconfig.json": "{}",
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
commandLineArgs: ["--incremental", "--listFilesOnly"],
|
||||
edits: [
|
||||
{
|
||||
...noChangeRun,
|
||||
commandLineArgs: ["-p", "/src", "--incremental"],
|
||||
commandLineArgs: ["--incremental"],
|
||||
},
|
||||
noChangeRun,
|
||||
{
|
||||
...noChangeRun,
|
||||
commandLineArgs: ["-p", "/src", "--incremental"],
|
||||
commandLineArgs: ["--incremental"],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
@@ -1,91 +1,34 @@
|
||||
import {
|
||||
emptyArray,
|
||||
ModuleKind,
|
||||
ScriptTarget,
|
||||
} from "../../_namespaces/ts.js";
|
||||
import { dedent } from "../../_namespaces/Utils.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import {
|
||||
getFsConentsForAlternateResultAtTypesPackageJson,
|
||||
getFsContentsForAlternateResult,
|
||||
getFsContentsForAlternateResultDts,
|
||||
getFsContentsForAlternateResultPackageJson,
|
||||
} from "../helpers/alternateResult.js";
|
||||
import {
|
||||
compilerOptionsToConfigJson,
|
||||
libContent,
|
||||
} from "../helpers/contents.js";
|
||||
import { verifyAlternateResultScenario } from "../helpers/alternateResult.js";
|
||||
import { compilerOptionsToConfigJson } from "../helpers/contents.js";
|
||||
import { verifyTsc } from "../helpers/tsc.js";
|
||||
import { verifyTscWatch } from "../helpers/tscWatch.js";
|
||||
import { loadProjectFromFiles } from "../helpers/vfs.js";
|
||||
import {
|
||||
createWatchedSystem,
|
||||
libFile,
|
||||
} from "../helpers/virtualFileSystemWithWatch.js";
|
||||
import { TestServerHost } from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsc:: moduleResolution::", () => {
|
||||
verifyTsc({
|
||||
scenario: "moduleResolution",
|
||||
subScenario: "alternateResult",
|
||||
fs: () => loadProjectFromFiles(getFsContentsForAlternateResult()),
|
||||
commandLineArgs: ["-p", "/home/src/projects/project"],
|
||||
baselinePrograms: true,
|
||||
edits: [
|
||||
{
|
||||
caption: "delete the alternateResult in @types",
|
||||
edit: fs => fs.unlinkSync("/home/src/projects/project/node_modules/@types/bar/index.d.ts"),
|
||||
},
|
||||
{
|
||||
caption: "delete the ndoe10Result in package/types",
|
||||
edit: fs => fs.unlinkSync("/home/src/projects/project/node_modules/foo/index.d.ts"),
|
||||
},
|
||||
{
|
||||
caption: "add the alternateResult in @types",
|
||||
edit: fs => fs.writeFileSync("/home/src/projects/project/node_modules/@types/bar/index.d.ts", getFsContentsForAlternateResultDts("bar")),
|
||||
},
|
||||
{
|
||||
caption: "add the ndoe10Result in package/types",
|
||||
edit: fs => fs.writeFileSync("/home/src/projects/project/node_modules/foo/index.d.ts", getFsContentsForAlternateResultDts("foo")),
|
||||
},
|
||||
{
|
||||
caption: "update package.json from @types so error is fixed",
|
||||
edit: fs => fs.writeFileSync("/home/src/projects/project/node_modules/@types/bar/package.json", getFsConentsForAlternateResultAtTypesPackageJson("bar", /*addTypesCondition*/ true)),
|
||||
},
|
||||
{
|
||||
caption: "update package.json so error is fixed",
|
||||
edit: fs => fs.writeFileSync("/home/src/projects/project/node_modules/foo/package.json", getFsContentsForAlternateResultPackageJson("foo", /*addTypes*/ true, /*addTypesCondition*/ true)),
|
||||
},
|
||||
{
|
||||
caption: "update package.json from @types so error is introduced",
|
||||
edit: fs => fs.writeFileSync("/home/src/projects/project/node_modules/@types/bar2/package.json", getFsConentsForAlternateResultAtTypesPackageJson("bar2", /*addTypesCondition*/ false)),
|
||||
},
|
||||
{
|
||||
caption: "update package.json so error is introduced",
|
||||
edit: fs => fs.writeFileSync("/home/src/projects/project/node_modules/foo2/package.json", getFsContentsForAlternateResultPackageJson("foo2", /*addTypes*/ true, /*addTypesCondition*/ false)),
|
||||
},
|
||||
{
|
||||
caption: "delete the alternateResult in @types",
|
||||
edit: fs => fs.unlinkSync("/home/src/projects/project/node_modules/@types/bar2/index.d.ts"),
|
||||
},
|
||||
{
|
||||
caption: "delete the ndoe10Result in package/types",
|
||||
edit: fs => fs.unlinkSync("/home/src/projects/project/node_modules/foo2/index.d.ts"),
|
||||
},
|
||||
{
|
||||
caption: "add the alternateResult in @types",
|
||||
edit: fs => fs.writeFileSync("/home/src/projects/project/node_modules/@types/bar2/index.d.ts", getFsContentsForAlternateResultDts("bar2")),
|
||||
},
|
||||
{
|
||||
caption: "add the ndoe10Result in package/types",
|
||||
edit: fs => fs.writeFileSync("/home/src/projects/project/node_modules/foo2/index.d.ts", getFsContentsForAlternateResultDts("foo2")),
|
||||
},
|
||||
],
|
||||
});
|
||||
verifyAlternateResultScenario(
|
||||
/*forTsserver*/ false,
|
||||
(subScenario, sys, edits) =>
|
||||
verifyTsc({
|
||||
scenario: "moduleResolution",
|
||||
subScenario,
|
||||
sys,
|
||||
commandLineArgs: emptyArray,
|
||||
baselinePrograms: true,
|
||||
edits: edits(),
|
||||
}),
|
||||
);
|
||||
|
||||
verifyTscWatch({
|
||||
verifyTsc({
|
||||
scenario: "moduleResolution",
|
||||
subScenario: "pnpm style layout",
|
||||
sys: () =>
|
||||
createWatchedSystem({
|
||||
TestServerHost.createWatchedSystem({
|
||||
// button@0.0.1
|
||||
"/home/src/projects/component-type-checker/node_modules/.pnpm/@component-type-checker+button@0.0.1/node_modules/@component-type-checker/button/src/index.ts": dedent`
|
||||
export interface Button {
|
||||
@@ -219,75 +162,16 @@ describe("unittests:: tsc:: moduleResolution::", () => {
|
||||
"/home/src/projects/component-type-checker/packages/app/node_modules/@component-type-checker/sdk": {
|
||||
symLink: "/home/src/projects/component-type-checker/packages/sdk",
|
||||
},
|
||||
"/a/lib/lib.es5.d.ts": libContent,
|
||||
}, { currentDirectory: "/home/src/projects/component-type-checker/packages/app" }),
|
||||
commandLineArgs: ["--traceResolution", "--explainFiles"],
|
||||
});
|
||||
|
||||
verifyTscWatch({
|
||||
scenario: "moduleResolution",
|
||||
subScenario: "late discovered dependency symlink",
|
||||
sys: () =>
|
||||
createWatchedSystem({
|
||||
"/workspace/packageA/index.d.ts": dedent`
|
||||
export declare class Foo {
|
||||
private f: any;
|
||||
}`,
|
||||
"/workspace/packageB/package.json": dedent`
|
||||
{
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"package-a": "file:../packageA"
|
||||
}
|
||||
}`,
|
||||
"/workspace/packageB/index.d.ts": dedent`
|
||||
import { Foo } from "package-a";
|
||||
export declare function invoke(): Foo;`,
|
||||
"/workspace/packageC/package.json": dedent`
|
||||
{
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"package-b": "file:../packageB",
|
||||
"package-a": "file:../packageA"
|
||||
}
|
||||
}`,
|
||||
"/workspace/packageC/index.ts": dedent`
|
||||
import * as pkg from "package-b";
|
||||
|
||||
export const a = pkg.invoke();`,
|
||||
"/workspace/packageC/node_modules/package-a": { symLink: "/workspace/packageA" },
|
||||
"/workspace/packageB/node_modules/package-a": { symLink: "/workspace/packageA" },
|
||||
"/workspace/packageC/node_modules/package-b": { symLink: "/workspace/packageB" },
|
||||
"/a/lib/lib.d.ts": libContent,
|
||||
"/workspace/packageC/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
declaration: true,
|
||||
},
|
||||
}),
|
||||
}, { currentDirectory: "/workspace/packageC" }),
|
||||
commandLineArgs: ["--traceResolution", "--explainFiles", "--watch"],
|
||||
edits: [
|
||||
{
|
||||
caption: "change index.ts",
|
||||
edit: fs =>
|
||||
fs.writeFile(
|
||||
"/workspace/packageC/index.ts",
|
||||
dedent`
|
||||
import * as pkg from "package-b";
|
||||
|
||||
export const aa = pkg.invoke();`,
|
||||
),
|
||||
timeouts: sys => sys.runQueuedTimeoutCallbacks(),
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "moduleResolution",
|
||||
subScenario: "package json scope",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/projects/project/src/tsconfig.json": jsonToReadableText({
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/src/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: compilerOptionsToConfigJson({
|
||||
target: ScriptTarget.ES2016,
|
||||
composite: true,
|
||||
@@ -300,20 +184,19 @@ describe("unittests:: tsc:: moduleResolution::", () => {
|
||||
"fileB.mts",
|
||||
],
|
||||
}),
|
||||
"/src/projects/project/src/main.ts": "export const x = 10;",
|
||||
"/src/projects/project/src/fileA.ts": dedent`
|
||||
"/home/src/workspaces/project/src/main.ts": "export const x = 10;",
|
||||
"/home/src/workspaces/project/src/fileA.ts": dedent`
|
||||
import { foo } from "./fileB.mjs";
|
||||
foo();
|
||||
`,
|
||||
"/src/projects/project/src/fileB.mts": "export function foo() {}",
|
||||
"/src/projects/project/package.json": jsonToReadableText({ name: "app", version: "1.0.0" }),
|
||||
"/lib/lib.es2016.full.d.ts": libFile.content,
|
||||
}, { cwd: "/src/projects/project" }),
|
||||
"/home/src/workspaces/project/src/fileB.mts": "export function foo() {}",
|
||||
"/home/src/workspaces/project/package.json": jsonToReadableText({ name: "app", version: "1.0.0" }),
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
commandLineArgs: ["-p", "src", "--explainFiles", "--extendedDiagnostics"],
|
||||
edits: [
|
||||
{
|
||||
caption: "Delete package.json",
|
||||
edit: fs => fs.unlinkSync(`/src/projects/project/package.json`),
|
||||
edit: sys => sys.deleteFile("/home/src/workspaces/project/package.json"),
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
noChangeOnlyRuns,
|
||||
verifyTsc,
|
||||
} from "../helpers/tsc.js";
|
||||
import { loadProjectFromFiles } from "../helpers/vfs.js";
|
||||
import { TestServerHost } from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsc:: noEmit::", () => {
|
||||
forEachNoEmitChanges(["--p"]);
|
||||
@@ -16,17 +16,17 @@ describe("unittests:: tsc:: noEmit::", () => {
|
||||
verifyTsc({
|
||||
scenario: "noEmit",
|
||||
subScenario: "when project has strict true",
|
||||
commandLineArgs: ["-noEmit", "-p", `src/project`],
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/project/tsconfig.json": jsonToReadableText({
|
||||
commandLineArgs: ["-noEmit"],
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
incremental: true,
|
||||
strict: true,
|
||||
},
|
||||
}),
|
||||
"/src/project/class1.ts": `export class class1 {}`,
|
||||
}),
|
||||
"/home/src/workspaces/project/class1.ts": `export class class1 {}`,
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
edits: noChangeOnlyRuns,
|
||||
baselinePrograms: true,
|
||||
});
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import { emptyArray } from "../../_namespaces/ts.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import { forEachNoEmitOnErrorScenarioTsc } from "../helpers/noEmitOnError.js";
|
||||
import { verifyTsc } from "../helpers/tsc.js";
|
||||
import {
|
||||
loadProjectFromFiles,
|
||||
replaceText,
|
||||
} from "../helpers/vfs.js";
|
||||
import { TestServerHost } from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsc:: noEmitOnError::", () => {
|
||||
forEachNoEmitOnErrorScenarioTsc([]);
|
||||
@@ -12,24 +10,24 @@ describe("unittests:: tsc:: noEmitOnError::", () => {
|
||||
verifyTsc({
|
||||
scenario: "noEmitOnError",
|
||||
subScenario: `multiFile/when declarationMap changes`,
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/project/tsconfig.json": jsonToReadableText({
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
noEmitOnError: true,
|
||||
declaration: true,
|
||||
composite: true,
|
||||
},
|
||||
}),
|
||||
"/src/project/a.ts": "const x = 10;",
|
||||
"/src/project/b.ts": "const y = 10;",
|
||||
}),
|
||||
commandLineArgs: ["--p", "/src/project"],
|
||||
"/home/src/workspaces/project/a.ts": "const x = 10;",
|
||||
"/home/src/workspaces/project/b.ts": "const y = 10;",
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
commandLineArgs: emptyArray,
|
||||
edits: [
|
||||
{
|
||||
caption: "error and enable declarationMap",
|
||||
edit: fs => replaceText(fs, "/src/project/a.ts", "x", "x: 20"),
|
||||
commandLineArgs: ["--p", "/src/project", "--declarationMap"],
|
||||
edit: sys => sys.replaceFileText("/home/src/workspaces/project/a.ts", "x", "x: 20"),
|
||||
commandLineArgs: ["--declarationMap"],
|
||||
discrepancyExplanation: () => [
|
||||
`Clean build does not emit any file so will have emitSignatures with all files since they are not emitted`,
|
||||
`Incremental build has emitSignatures from before, so it will have a.ts with signature since file.version isnt same`,
|
||||
@@ -38,8 +36,8 @@ describe("unittests:: tsc:: noEmitOnError::", () => {
|
||||
},
|
||||
{
|
||||
caption: "fix error declarationMap",
|
||||
edit: fs => replaceText(fs, "/src/project/a.ts", "x: 20", "x"),
|
||||
commandLineArgs: ["--p", "/src/project", "--declarationMap"],
|
||||
edit: sys => sys.replaceFileText("/home/src/workspaces/project/a.ts", "x: 20", "x"),
|
||||
commandLineArgs: ["--declarationMap"],
|
||||
},
|
||||
],
|
||||
});
|
||||
@@ -47,9 +45,9 @@ describe("unittests:: tsc:: noEmitOnError::", () => {
|
||||
verifyTsc({
|
||||
scenario: "noEmitOnError",
|
||||
subScenario: `outFile/when declarationMap changes`,
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/project/tsconfig.json": jsonToReadableText({
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
noEmitOnError: true,
|
||||
declaration: true,
|
||||
@@ -57,15 +55,15 @@ describe("unittests:: tsc:: noEmitOnError::", () => {
|
||||
outFile: "../outFile.js",
|
||||
},
|
||||
}),
|
||||
"/src/project/a.ts": "const x = 10;",
|
||||
"/src/project/b.ts": "const y = 10;",
|
||||
}),
|
||||
commandLineArgs: ["--p", "/src/project"],
|
||||
"/home/src/workspaces/project/a.ts": "const x = 10;",
|
||||
"/home/src/workspaces/project/b.ts": "const y = 10;",
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
commandLineArgs: emptyArray,
|
||||
edits: [
|
||||
{
|
||||
caption: "error and enable declarationMap",
|
||||
edit: fs => replaceText(fs, "/src/project/a.ts", "x", "x: 20"),
|
||||
commandLineArgs: ["--p", "/src/project", "--declarationMap"],
|
||||
edit: sys => sys.replaceFileText("/home/src/workspaces/project/a.ts", "x", "x: 20"),
|
||||
commandLineArgs: ["--declarationMap"],
|
||||
discrepancyExplanation: () => [
|
||||
`Clean build does not emit any file so will not have outSignature`,
|
||||
`Incremental build has outSignature from before`,
|
||||
@@ -73,8 +71,8 @@ describe("unittests:: tsc:: noEmitOnError::", () => {
|
||||
},
|
||||
{
|
||||
caption: "fix error declarationMap",
|
||||
edit: fs => replaceText(fs, "/src/project/a.ts", "x: 20", "x"),
|
||||
commandLineArgs: ["--p", "/src/project", "--declarationMap"],
|
||||
edit: sys => sys.replaceFileText("/home/src/workspaces/project/a.ts", "x: 20", "x"),
|
||||
commandLineArgs: ["--declarationMap"],
|
||||
},
|
||||
],
|
||||
});
|
||||
@@ -82,21 +80,21 @@ describe("unittests:: tsc:: noEmitOnError::", () => {
|
||||
verifyTsc({
|
||||
scenario: "noEmitOnError",
|
||||
subScenario: "multiFile/file deleted before fixing error with noEmitOnError",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/project/tsconfig.json": jsonToReadableText({
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
outDir: "outDir",
|
||||
noEmitOnError: true,
|
||||
},
|
||||
}),
|
||||
"/src/project/file1.ts": `export const x: 30 = "hello";`,
|
||||
"/src/project/file2.ts": `export class D { }`,
|
||||
}),
|
||||
commandLineArgs: ["--p", "/src/project", "-i"],
|
||||
"/home/src/workspaces/project/file1.ts": `export const x: 30 = "hello";`,
|
||||
"/home/src/workspaces/project/file2.ts": `export class D { }`,
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
commandLineArgs: ["-i"],
|
||||
edits: [{
|
||||
caption: "delete file without error",
|
||||
edit: fs => fs.unlinkSync("/src/project/file2.ts"),
|
||||
edit: sys => sys.deleteFile("/home/src/workspaces/project/file2.ts"),
|
||||
}],
|
||||
baselinePrograms: true,
|
||||
});
|
||||
@@ -104,22 +102,22 @@ describe("unittests:: tsc:: noEmitOnError::", () => {
|
||||
verifyTsc({
|
||||
scenario: "noEmitOnError",
|
||||
subScenario: "outFile/file deleted before fixing error with noEmitOnError",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/project/tsconfig.json": jsonToReadableText({
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
outFile: "../outFile.js",
|
||||
module: "amd",
|
||||
noEmitOnError: true,
|
||||
},
|
||||
}),
|
||||
"/src/project/file1.ts": `export const x: 30 = "hello";`,
|
||||
"/src/project/file2.ts": `export class D { }`,
|
||||
}),
|
||||
commandLineArgs: ["--p", "/src/project", "-i"],
|
||||
"/home/src/workspaces/project/file1.ts": `export const x: 30 = "hello";`,
|
||||
"/home/src/workspaces/project/file2.ts": `export class D { }`,
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
commandLineArgs: ["-i"],
|
||||
edits: [{
|
||||
caption: "delete file without error",
|
||||
edit: fs => fs.unlinkSync("/src/project/file2.ts"),
|
||||
edit: sys => sys.deleteFile("/home/src/workspaces/project/file2.ts"),
|
||||
}],
|
||||
baselinePrograms: true,
|
||||
});
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
import { emptyArray } from "../../_namespaces/ts.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import { verifyTsc } from "../helpers/tsc.js";
|
||||
import { loadProjectFromFiles } from "../helpers/vfs.js";
|
||||
import { TestServerHost } from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsc:: projectReferences::", () => {
|
||||
verifyTsc({
|
||||
scenario: "projectReferences",
|
||||
subScenario: "when project contains invalid project reference",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/project/src/main.ts": "export const x = 10;",
|
||||
"/src/project/tsconfig.json": jsonToReadableText({
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/src/main.ts": "export const x = 10;",
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
module: "amd",
|
||||
outFile: "theApp.js",
|
||||
@@ -18,42 +19,42 @@ describe("unittests:: tsc:: projectReferences::", () => {
|
||||
{ path: "../Util/Dates" },
|
||||
],
|
||||
}),
|
||||
}),
|
||||
commandLineArgs: ["--p", "src/project"],
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
commandLineArgs: emptyArray,
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "projectReferences",
|
||||
subScenario: "when project references composite project with noEmit",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/utils/index.ts": "export const x = 10;",
|
||||
"/src/utils/tsconfig.json": jsonToReadableText({
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/solution/src/utils/index.ts": "export const x = 10;",
|
||||
"/home/src/workspaces/solution/src/utils/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
noEmit: true,
|
||||
},
|
||||
}),
|
||||
"/src/project/index.ts": `import { x } from "../utils";`,
|
||||
"/src/project/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/solution/project/index.ts": `import { x } from "../utils";`,
|
||||
"/home/src/workspaces/solution/project/tsconfig.json": jsonToReadableText({
|
||||
references: [
|
||||
{ path: "../utils" },
|
||||
],
|
||||
}),
|
||||
}),
|
||||
commandLineArgs: ["--p", "src/project"],
|
||||
}, { currentDirectory: "/home/src/workspaces/solution" }),
|
||||
commandLineArgs: ["--p", "project"],
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "projectReferences",
|
||||
subScenario: "default import interop uses referenced project settings",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/node_modules/ambiguous-package/package.json": `{ "name": "ambiguous-package" }`,
|
||||
"/node_modules/ambiguous-package/index.d.ts": "export declare const ambiguous: number;",
|
||||
"/node_modules/esm-package/package.json": `{ "name": "esm-package", "type": "module" }`,
|
||||
"/node_modules/esm-package/index.d.ts": "export declare const esm: number;",
|
||||
"/lib/tsconfig.json": jsonToReadableText({
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/node_modules/ambiguous-package/package.json": jsonToReadableText({ name: "ambiguous-package" }),
|
||||
"/home/src/workspaces/project/node_modules/ambiguous-package/index.d.ts": "export declare const ambiguous: number;",
|
||||
"/home/src/workspaces/project/node_modules/esm-package/package.json": jsonToReadableText({ name: "esm-package", type: "module" }),
|
||||
"/home/src/workspaces/project/node_modules/esm-package/index.d.ts": "export declare const esm: number;",
|
||||
"/home/src/workspaces/project/lib/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
declaration: true,
|
||||
@@ -64,9 +65,9 @@ describe("unittests:: tsc:: projectReferences::", () => {
|
||||
},
|
||||
include: ["src"],
|
||||
}),
|
||||
"/lib/src/a.ts": "export const a = 0;",
|
||||
"/lib/dist/a.d.ts": "export declare const a = 0;",
|
||||
"/app/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/project/lib/src/a.ts": "export const a = 0;",
|
||||
"/home/src/workspaces/project/lib/dist/a.d.ts": "export declare const a = 0;",
|
||||
"/home/src/workspaces/project/app/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
module: "esnext",
|
||||
moduleResolution: "bundler",
|
||||
@@ -78,33 +79,33 @@ describe("unittests:: tsc:: projectReferences::", () => {
|
||||
{ path: "../lib" },
|
||||
],
|
||||
}),
|
||||
"/app/src/local.ts": "export const local = 0;",
|
||||
"/app/src/index.ts": `
|
||||
"/home/src/workspaces/project/app/src/local.ts": "export const local = 0;",
|
||||
"/home/src/workspaces/project/app/src/index.ts": `
|
||||
import local from "./local"; // Error
|
||||
import esm from "esm-package"; // Error
|
||||
import referencedSource from "../../lib/src/a"; // Error
|
||||
import referencedDeclaration from "../../lib/dist/a"; // Error
|
||||
import ambiguous from "ambiguous-package"; // Ok`,
|
||||
}),
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
commandLineArgs: ["--p", "app", "--pretty", "false"],
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "projectReferences",
|
||||
subScenario: "referencing ambient const enum from referenced project with preserveConstEnums",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/utils/index.ts": "export const enum E { A = 1 }",
|
||||
"/src/utils/index.d.ts": "export declare const enum E { A = 1 }",
|
||||
"/src/utils/tsconfig.json": jsonToReadableText({
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/solution/utils/index.ts": "export const enum E { A = 1 }",
|
||||
"/home/src/workspaces/solution/utils/index.d.ts": "export declare const enum E { A = 1 }",
|
||||
"/home/src/workspaces/solution/utils/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
declaration: true,
|
||||
preserveConstEnums: true,
|
||||
},
|
||||
}),
|
||||
"/src/project/index.ts": `import { E } from "../utils"; E.A;`,
|
||||
"/src/project/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/solution/project/index.ts": `import { E } from "../utils"; E.A;`,
|
||||
"/home/src/workspaces/solution/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
isolatedModules: true,
|
||||
},
|
||||
@@ -112,35 +113,35 @@ describe("unittests:: tsc:: projectReferences::", () => {
|
||||
{ path: "../utils" },
|
||||
],
|
||||
}),
|
||||
}),
|
||||
commandLineArgs: ["--p", "src/project"],
|
||||
}, { currentDirectory: "/home/src/workspaces/solution" }),
|
||||
commandLineArgs: ["--p", "project"],
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "projectReferences",
|
||||
subScenario: "importing const enum from referenced project with preserveConstEnums and verbatimModuleSyntax",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/preserve/index.ts": "export const enum E { A = 1 }",
|
||||
"/src/preserve/index.d.ts": "export declare const enum E { A = 1 }",
|
||||
"/src/preserve/tsconfig.json": jsonToReadableText({
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/solution/preserve/index.ts": "export const enum E { A = 1 }",
|
||||
"/home/src/workspaces/solution/preserve/index.d.ts": "export declare const enum E { A = 1 }",
|
||||
"/home/src/workspaces/solution/preserve/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
declaration: true,
|
||||
preserveConstEnums: true,
|
||||
},
|
||||
}),
|
||||
"/src/no-preserve/index.ts": "export const enum E { A = 1 }",
|
||||
"/src/no-preserve/index.d.ts": "export declare const enum F { A = 1 }",
|
||||
"/src/no-preserve/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/solution/no-preserve/index.ts": "export const enum E { A = 1 }",
|
||||
"/home/src/workspaces/solution/no-preserve/index.d.ts": "export declare const enum F { A = 1 }",
|
||||
"/home/src/workspaces/solution/no-preserve/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
declaration: true,
|
||||
preserveConstEnums: false,
|
||||
},
|
||||
}),
|
||||
"/src/project/index.ts": `import { E } from "../preserve";\nimport { F } from "../no-preserve";\nE.A; F.A;`,
|
||||
"/src/project/tsconfig.json": jsonToReadableText({
|
||||
"/home/src/workspaces/solution/project/index.ts": `import { E } from "../preserve";\nimport { F } from "../no-preserve";\nE.A; F.A;`,
|
||||
"/home/src/workspaces/solution/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
module: "preserve",
|
||||
verbatimModuleSyntax: true,
|
||||
@@ -150,7 +151,7 @@ describe("unittests:: tsc:: projectReferences::", () => {
|
||||
{ path: "../no-preserve" },
|
||||
],
|
||||
}),
|
||||
}),
|
||||
commandLineArgs: ["--p", "src/project", "--pretty", "false"],
|
||||
}, { currentDirectory: "/home/src/workspaces/solution" }),
|
||||
commandLineArgs: ["--p", "project", "--pretty", "false"],
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as ts from "../../_namespaces/ts.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import { verifyTsc } from "../helpers/tsc.js";
|
||||
import { loadProjectFromFiles } from "../helpers/vfs.js";
|
||||
import { TestServerHost } from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
function emptyModule() {
|
||||
return "export { };";
|
||||
@@ -36,201 +36,201 @@ function getConfig({ references, options, config }: {
|
||||
});
|
||||
}
|
||||
|
||||
describe("unittests:: config:: project-references meta check", () => {
|
||||
describe("unittests:: tsc:: projectReferencesConfig:: project-references meta check", () => {
|
||||
verifyTsc({
|
||||
scenario: "projectReferencesConfig",
|
||||
subScenario: "default setup was created correctly",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/primary/tsconfig.json": getConfig(),
|
||||
"/primary/a.ts": emptyModule(),
|
||||
"/secondary/tsconfig.json": getConfig({
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/primary/tsconfig.json": getConfig(),
|
||||
"/home/src/workspaces/project/primary/a.ts": emptyModule(),
|
||||
"/home/src/workspaces/project/secondary/tsconfig.json": getConfig({
|
||||
references: ["../primary"],
|
||||
}),
|
||||
"/secondary/b.ts": moduleImporting("../primary/a"),
|
||||
}),
|
||||
commandLineArgs: ["--p", "/primary/tsconfig.json"],
|
||||
"/home/src/workspaces/project/secondary/b.ts": moduleImporting("../primary/a"),
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
commandLineArgs: ["--p", "primary/tsconfig.json"],
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Validate that we enforce the basic settings constraints for referenced projects
|
||||
*/
|
||||
describe("unittests:: config:: project-references constraint checking for settings", () => {
|
||||
describe("unittests:: tsc:: projectReferencesConfig:: project-references constraint checking for settings", () => {
|
||||
verifyTsc({
|
||||
scenario: "projectReferencesConfig",
|
||||
subScenario: "errors when declaration = false",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/primary/tsconfig.json": getConfig({
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/primary/tsconfig.json": getConfig({
|
||||
options: {
|
||||
declaration: false,
|
||||
},
|
||||
}),
|
||||
"/primary/a.ts": emptyModule(),
|
||||
}),
|
||||
commandLineArgs: ["--p", "/primary/tsconfig.json"],
|
||||
"/home/src/workspaces/project/primary/a.ts": emptyModule(),
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
commandLineArgs: ["--p", "primary/tsconfig.json"],
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "projectReferencesConfig",
|
||||
subScenario: "errors when the referenced project doesnt have composite",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/primary/tsconfig.json": getConfig({
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/primary/tsconfig.json": getConfig({
|
||||
options: {
|
||||
composite: false,
|
||||
},
|
||||
}),
|
||||
"/primary/a.ts": emptyModule(),
|
||||
"/reference/tsconfig.json": getConfig({
|
||||
"/home/src/workspaces/project/primary/a.ts": emptyModule(),
|
||||
"/home/src/workspaces/project/reference/tsconfig.json": getConfig({
|
||||
references: ["../primary"],
|
||||
config: {
|
||||
files: ["b.ts"],
|
||||
},
|
||||
}),
|
||||
"/reference/b.ts": moduleImporting("../primary/a"),
|
||||
}),
|
||||
commandLineArgs: ["--p", "/reference/tsconfig.json"],
|
||||
"/home/src/workspaces/project/reference/b.ts": moduleImporting("../primary/a"),
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
commandLineArgs: ["--p", "reference/tsconfig.json"],
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "projectReferencesConfig",
|
||||
subScenario: "does not error when the referenced project doesnt have composite if its a container project",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/primary/tsconfig.json": getConfig({
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/primary/tsconfig.json": getConfig({
|
||||
options: {
|
||||
composite: false,
|
||||
},
|
||||
}),
|
||||
"/primary/a.ts": emptyModule(),
|
||||
"/reference/tsconfig.json": getConfig({
|
||||
"/home/src/workspaces/project/primary/a.ts": emptyModule(),
|
||||
"/home/src/workspaces/project/reference/tsconfig.json": getConfig({
|
||||
references: ["../primary"],
|
||||
config: {
|
||||
files: [],
|
||||
},
|
||||
}),
|
||||
"/reference/b.ts": moduleImporting("../primary/a"),
|
||||
}),
|
||||
commandLineArgs: ["--p", "/reference/tsconfig.json"],
|
||||
"/home/src/workspaces/project/reference/b.ts": moduleImporting("../primary/a"),
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
commandLineArgs: ["--p", "reference/tsconfig.json"],
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "projectReferencesConfig",
|
||||
subScenario: "errors when the file list is not exhaustive",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/primary/tsconfig.json": getConfig({
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/primary/tsconfig.json": getConfig({
|
||||
config: {
|
||||
files: ["a.ts"],
|
||||
},
|
||||
}),
|
||||
"/primary/a.ts": "import * as b from './b'",
|
||||
"/primary/b.ts": "export {}",
|
||||
}),
|
||||
commandLineArgs: ["--p", "/primary/tsconfig.json"],
|
||||
"/home/src/workspaces/project/primary/a.ts": "import * as b from './b'",
|
||||
"/home/src/workspaces/project/primary/b.ts": "export {}",
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
commandLineArgs: ["--p", "primary/tsconfig.json"],
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "projectReferencesConfig",
|
||||
subScenario: "errors when the referenced project doesnt exist",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/primary/tsconfig.json": getConfig({
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/primary/tsconfig.json": getConfig({
|
||||
references: ["../foo"],
|
||||
}),
|
||||
"/primary/a.ts": emptyModule(),
|
||||
}),
|
||||
commandLineArgs: ["--p", "/primary/tsconfig.json"],
|
||||
"/home/src/workspaces/project/primary/a.ts": emptyModule(),
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
commandLineArgs: ["--p", "primary/tsconfig.json"],
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Path mapping behavior
|
||||
*/
|
||||
describe("unittests:: config:: project-references path mapping", () => {
|
||||
describe("unittests:: tsc:: projectReferencesConfig:: project-references path mapping", () => {
|
||||
verifyTsc({
|
||||
scenario: "projectReferencesConfig",
|
||||
subScenario: "redirects to the output dts file",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/alpha/tsconfig.json": getConfig(),
|
||||
"/alpha/a.ts": "export const m: number = 3;",
|
||||
"/alpha/bin/a.d.ts": emptyModule(),
|
||||
"/beta/tsconfig.json": getConfig({
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/alpha/tsconfig.json": getConfig(),
|
||||
"/home/src/workspaces/project/alpha/a.ts": "export const m: number = 3;",
|
||||
"/home/src/workspaces/project/alpha/bin/a.d.ts": emptyModule(),
|
||||
"/home/src/workspaces/project/beta/tsconfig.json": getConfig({
|
||||
references: ["../alpha"],
|
||||
}),
|
||||
"/beta/b.ts": "import { m } from '../alpha/a'",
|
||||
}),
|
||||
commandLineArgs: ["--p", "/beta/tsconfig.json", "--explainFiles"],
|
||||
"/home/src/workspaces/project/beta/b.ts": "import { m } from '../alpha/a'",
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
commandLineArgs: ["--p", "beta/tsconfig.json", "--explainFiles"],
|
||||
});
|
||||
});
|
||||
|
||||
describe("unittests:: config:: project-references nice-behavior", () => {
|
||||
describe("unittests:: tsc:: projectReferencesConfig:: project-references nice-behavior", () => {
|
||||
verifyTsc({
|
||||
scenario: "projectReferencesConfig",
|
||||
subScenario: "issues a nice error when the input file is missing",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/alpha/tsconfig.json": getConfig(),
|
||||
"/alpha/a.ts": "export const m: number = 3;",
|
||||
"/beta/tsconfig.json": getConfig({
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/alpha/tsconfig.json": getConfig(),
|
||||
"/home/src/workspaces/project/alpha/a.ts": "export const m: number = 3;",
|
||||
"/home/src/workspaces/project/beta/tsconfig.json": getConfig({
|
||||
references: ["../alpha"],
|
||||
}),
|
||||
"/beta/b.ts": "import { m } from '../alpha/a'",
|
||||
}),
|
||||
commandLineArgs: ["--p", "/beta/tsconfig.json"],
|
||||
"/home/src/workspaces/project/beta/b.ts": "import { m } from '../alpha/a'",
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
commandLineArgs: ["--p", "beta/tsconfig.json"],
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "projectReferencesConfig",
|
||||
subScenario: "issues a nice error when the input file is missing when module reference is not relative",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/alpha/tsconfig.json": getConfig(),
|
||||
"/alpha/a.ts": "export const m: number = 3;",
|
||||
"/beta/tsconfig.json": getConfig({
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/alpha/tsconfig.json": getConfig(),
|
||||
"/home/src/workspaces/project/alpha/a.ts": "export const m: number = 3;",
|
||||
"/home/src/workspaces/project/beta/tsconfig.json": getConfig({
|
||||
references: ["../alpha"],
|
||||
options: {
|
||||
baseUrl: "./",
|
||||
paths: {
|
||||
"@alpha/*": ["/alpha/*"],
|
||||
"@alpha/*": ["/home/src/workspaces/project/alpha/*"],
|
||||
},
|
||||
},
|
||||
}),
|
||||
"/beta/b.ts": "import { m } from '@alpha/a'",
|
||||
}),
|
||||
commandLineArgs: ["--p", "/beta/tsconfig.json"],
|
||||
"/home/src/workspaces/project/beta/b.ts": "import { m } from '@alpha/a'",
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
commandLineArgs: ["--p", "beta/tsconfig.json"],
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* 'composite' behavior
|
||||
*/
|
||||
describe("unittests:: config:: project-references behavior changes under composite: true", () => {
|
||||
describe("unittests:: tsc:: projectReferencesConfig:: project-references behavior changes under composite: true", () => {
|
||||
verifyTsc({
|
||||
scenario: "projectReferencesConfig",
|
||||
subScenario: "doesnt infer the rootDir from source paths",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/alpha/tsconfig.json": getConfig(),
|
||||
"/alpha/src/a.ts": "export const m: number = 3;",
|
||||
}),
|
||||
commandLineArgs: ["--p", "/alpha/tsconfig.json"],
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/alpha/tsconfig.json": getConfig(),
|
||||
"/home/src/workspaces/project/alpha/src/a.ts": "export const m: number = 3;",
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
commandLineArgs: ["--p", "alpha/tsconfig.json"],
|
||||
});
|
||||
});
|
||||
|
||||
describe("unittests:: config:: project-references errors when a file in a composite project occurs outside the root", () => {
|
||||
describe("unittests:: tsc:: projectReferencesConfig:: project-references errors when a file in a composite project occurs outside the root", () => {
|
||||
verifyTsc({
|
||||
scenario: "projectReferencesConfig",
|
||||
subScenario: "errors when a file is outside the rootdir",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/alpha/tsconfig.json": getConfig(),
|
||||
"/alpha/src/a.ts": "import * as b from '../../beta/b'",
|
||||
"/beta/b.ts": "export { }",
|
||||
}),
|
||||
commandLineArgs: ["--p", "/alpha/tsconfig.json"],
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/alpha/tsconfig.json": getConfig(),
|
||||
"/home/src/workspaces/project/alpha/src/a.ts": "import * as b from '../../beta/b'",
|
||||
"/home/src/workspaces/project/beta/b.ts": "export { }",
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
commandLineArgs: ["--p", "alpha/tsconfig.json"],
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import { emptyArray } from "../../_namespaces/ts.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import { verifyTsc } from "../helpers/tsc.js";
|
||||
import { loadProjectFromFiles } from "../helpers/vfs.js";
|
||||
import { TestServerHost } from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsc:: redirect::", () => {
|
||||
verifyTsc({
|
||||
scenario: "redirect",
|
||||
subScenario: "when redirecting ts file",
|
||||
fs: () =>
|
||||
loadProjectFromFiles({
|
||||
"/src/project/tsconfig.json": jsonToReadableText({
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/workspaces/project/tsconfig.json": jsonToReadableText({
|
||||
compilerOptions: {
|
||||
outDir: "out",
|
||||
},
|
||||
@@ -17,21 +18,21 @@ describe("unittests:: tsc:: redirect::", () => {
|
||||
"copy2/node_modules/target/*",
|
||||
],
|
||||
}),
|
||||
"/src/project/copy1/node_modules/target/index.ts": "export const a = 1;",
|
||||
"/src/project/copy1/node_modules/target/import.ts": `import {} from "./";`,
|
||||
"/src/project/copy1/node_modules/target/package.json": jsonToReadableText({
|
||||
"/home/src/workspaces/project/copy1/node_modules/target/index.ts": "export const a = 1;",
|
||||
"/home/src/workspaces/project/copy1/node_modules/target/import.ts": `import {} from "./";`,
|
||||
"/home/src/workspaces/project/copy1/node_modules/target/package.json": jsonToReadableText({
|
||||
name: "target",
|
||||
version: "1.0.0",
|
||||
main: "index.js",
|
||||
}),
|
||||
"/src/project/copy2/node_modules/target/index.ts": "export const a = 1;",
|
||||
"/src/project/copy2/node_modules/target/import.ts": `import {} from "./";`,
|
||||
"/src/project/copy2/node_modules/target/package.json": jsonToReadableText({
|
||||
"/home/src/workspaces/project/copy2/node_modules/target/index.ts": "export const a = 1;",
|
||||
"/home/src/workspaces/project/copy2/node_modules/target/import.ts": `import {} from "./";`,
|
||||
"/home/src/workspaces/project/copy2/node_modules/target/package.json": jsonToReadableText({
|
||||
name: "target",
|
||||
version: "1.0.0",
|
||||
main: "index.js",
|
||||
}),
|
||||
}),
|
||||
commandLineArgs: ["-p", "src/project"],
|
||||
}, { currentDirectory: "/home/src/workspaces/project" }),
|
||||
commandLineArgs: emptyArray,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,27 +1,37 @@
|
||||
import { emptyArray } from "../../_namespaces/ts.js";
|
||||
import { verifyTsc } from "../helpers/tsc.js";
|
||||
import { loadProjectFromFiles } from "../helpers/vfs.js";
|
||||
import { TestServerHost } from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsc:: runWithoutArgs::", () => {
|
||||
verifyTsc({
|
||||
scenario: "runWithoutArgs",
|
||||
subScenario: "show help with ExitStatus.DiagnosticsPresent_OutputsSkipped",
|
||||
fs: () => loadProjectFromFiles({}),
|
||||
commandLineArgs: [],
|
||||
environmentVariables: { TS_TEST_TERMINAL_WIDTH: "120" },
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem(emptyArray, {
|
||||
currentDirectory: "/home/src/workspaces/project",
|
||||
environmentVariables: new Map([["TS_TEST_TERMINAL_WIDTH", "120"]]),
|
||||
}),
|
||||
commandLineArgs: emptyArray,
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "runWithoutArgs",
|
||||
subScenario: "show help with ExitStatus.DiagnosticsPresent_OutputsSkipped when host can't provide terminal width",
|
||||
fs: () => loadProjectFromFiles({}),
|
||||
commandLineArgs: [],
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem(emptyArray, {
|
||||
currentDirectory: "/home/src/workspaces/project",
|
||||
}),
|
||||
commandLineArgs: emptyArray,
|
||||
});
|
||||
|
||||
verifyTsc({
|
||||
scenario: "runWithoutArgs",
|
||||
subScenario: "does not add color when NO_COLOR is set",
|
||||
fs: () => loadProjectFromFiles({}),
|
||||
commandLineArgs: [],
|
||||
environmentVariables: { NO_COLOR: "true" },
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem(emptyArray, {
|
||||
currentDirectory: "/home/src/workspaces/project",
|
||||
environmentVariables: new Map([["NO_COLOR", "true"]]),
|
||||
}),
|
||||
commandLineArgs: emptyArray,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,22 +1,21 @@
|
||||
import * as ts from "../../_namespaces/ts.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import { createBaseline } from "../helpers/baseline.js";
|
||||
import {
|
||||
createBaseline,
|
||||
createWatchCompilerHostOfConfigFileForBaseline,
|
||||
runWatchBaseline,
|
||||
TscWatchCompileChange,
|
||||
verifyTscWatch,
|
||||
} from "../helpers/tscWatch.js";
|
||||
import {
|
||||
createWatchedSystem,
|
||||
File,
|
||||
libFile,
|
||||
TestServerHost,
|
||||
} from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsc-watch:: console clearing", () => {
|
||||
describe("unittests:: tscWatch:: consoleClearing::", () => {
|
||||
const scenario = "consoleClearing";
|
||||
const file: File = {
|
||||
path: "/f.ts",
|
||||
path: "/user/username/projects/myproject/f.ts",
|
||||
content: "",
|
||||
};
|
||||
|
||||
@@ -31,7 +30,7 @@ describe("unittests:: tsc-watch:: console clearing", () => {
|
||||
scenario,
|
||||
subScenario,
|
||||
commandLineArgs: ["--w", file.path, ...commandLineOptions || ts.emptyArray],
|
||||
sys: () => createWatchedSystem([file, libFile]),
|
||||
sys: () => TestServerHost.createWatchedSystem([file], { currentDirectory: ts.getDirectoryPath(file.path) }),
|
||||
edits: makeChangeToFile,
|
||||
});
|
||||
}
|
||||
@@ -46,12 +45,11 @@ describe("unittests:: tsc-watch:: console clearing", () => {
|
||||
preserveWatchOutput: true,
|
||||
};
|
||||
const configFile: File = {
|
||||
path: "/tsconfig.json",
|
||||
path: "/user/username/projects/myproject/tsconfig.json",
|
||||
content: jsonToReadableText({ compilerOptions }),
|
||||
};
|
||||
const files = [file, configFile, libFile];
|
||||
it("using createWatchOfConfigFile ", () => {
|
||||
const baseline = createBaseline(createWatchedSystem(files));
|
||||
const baseline = createBaseline(sys());
|
||||
const watch = ts.createWatchProgram(createWatchCompilerHostOfConfigFileForBaseline({
|
||||
system: baseline.sys,
|
||||
cb: baseline.cb,
|
||||
@@ -72,8 +70,15 @@ describe("unittests:: tsc-watch:: console clearing", () => {
|
||||
scenario,
|
||||
subScenario: "when preserveWatchOutput is true in config file/when createWatchProgram is invoked with configFileParseResult on WatchCompilerHostOfConfigFile",
|
||||
commandLineArgs: ["--w", "-p", configFile.path],
|
||||
sys: () => createWatchedSystem(files),
|
||||
sys,
|
||||
edits: makeChangeToFile,
|
||||
});
|
||||
|
||||
function sys() {
|
||||
return TestServerHost.createWatchedSystem(
|
||||
[file, configFile],
|
||||
{ currentDirectory: ts.getDirectoryPath(configFile.path) },
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,68 +5,65 @@ import {
|
||||
verifyTscWatch,
|
||||
} from "../helpers/tscWatch.js";
|
||||
import {
|
||||
createWatchedSystem,
|
||||
File,
|
||||
libFile,
|
||||
TestServerHost,
|
||||
} from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
const scenario = "emit";
|
||||
describe("unittests:: tsc-watch:: emit with outFile or out setting", () => {
|
||||
describe("unittests:: tscWatch:: emit:: with outFile or out setting", () => {
|
||||
function verifyOutAndOutFileSetting(subScenario: string, out?: string, outFile?: string) {
|
||||
verifyTscWatch({
|
||||
scenario,
|
||||
subScenario: `emit with outFile or out setting/${subScenario}`,
|
||||
commandLineArgs: ["--w", "-p", "/a/tsconfig.json"],
|
||||
commandLineArgs: ["--w", "-p", "/home/src/projects/a/tsconfig.json"],
|
||||
sys: () =>
|
||||
createWatchedSystem({
|
||||
"/a/a.ts": "let x = 1",
|
||||
"/a/b.ts": "let y = 1",
|
||||
"/a/tsconfig.json": jsonToReadableText({ compilerOptions: { out, outFile } }),
|
||||
[libFile.path]: libFile.content,
|
||||
}),
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/projects/a/a.ts": "let x = 1",
|
||||
"/home/src/projects/a/b.ts": "let y = 1",
|
||||
"/home/src/projects/a/tsconfig.json": jsonToReadableText({ compilerOptions: { out, outFile } }),
|
||||
}, { currentDirectory: "/home/src/projects/a" }),
|
||||
edits: [
|
||||
{
|
||||
caption: "Make change in the file",
|
||||
edit: sys => sys.writeFile("/a/a.ts", "let x = 11"),
|
||||
edit: sys => sys.writeFile("/home/src/projects/a/a.ts", "let x = 11"),
|
||||
timeouts: sys => sys.runQueuedTimeoutCallbacks(),
|
||||
},
|
||||
{
|
||||
caption: "Make change in the file again",
|
||||
edit: sys => sys.writeFile("/a/a.ts", "let xy = 11"),
|
||||
edit: sys => sys.writeFile("/home/src/projects/a/a.ts", "let xy = 11"),
|
||||
timeouts: sys => sys.runQueuedTimeoutCallbacks(),
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
verifyOutAndOutFileSetting("config does not have out or outFile");
|
||||
verifyOutAndOutFileSetting("config has out", "/a/out.js");
|
||||
verifyOutAndOutFileSetting("config has outFile", /*out*/ undefined, "/a/out.js");
|
||||
verifyOutAndOutFileSetting("config has out", "/home/src/projects/a/out.js");
|
||||
verifyOutAndOutFileSetting("config has outFile", /*out*/ undefined, "/home/src/projects/a/out.js");
|
||||
|
||||
function verifyFilesEmittedOnce(subScenario: string, useOutFile: boolean) {
|
||||
verifyTscWatch({
|
||||
scenario,
|
||||
subScenario: `emit with outFile or out setting/${subScenario}`,
|
||||
commandLineArgs: ["--w", "-p", "/a/b/project/tsconfig.json"],
|
||||
commandLineArgs: ["--w"],
|
||||
sys: () => {
|
||||
const file1: File = {
|
||||
path: "/a/b/output/AnotherDependency/file1.d.ts",
|
||||
path: "/home/src/projects/a/b/output/AnotherDependency/file1.d.ts",
|
||||
content: "declare namespace Common.SomeComponent.DynamicMenu { enum Z { Full = 0, Min = 1, Average = 2, } }",
|
||||
};
|
||||
const file2: File = {
|
||||
path: "/a/b/dependencies/file2.d.ts",
|
||||
path: "/home/src/projects/a/b/dependencies/file2.d.ts",
|
||||
content: "declare namespace Dependencies.SomeComponent { export class SomeClass { version: string; } }",
|
||||
};
|
||||
const file3: File = {
|
||||
path: "/a/b/project/src/main.ts",
|
||||
path: "/home/src/projects/a/b/project/src/main.ts",
|
||||
content: "namespace Main { export function fooBar() {} }",
|
||||
};
|
||||
const file4: File = {
|
||||
path: "/a/b/project/src/main2.ts",
|
||||
path: "/home/src/projects/a/b/project/src/main2.ts",
|
||||
content: "namespace main.file4 { import DynamicMenu = Common.SomeComponent.DynamicMenu; export function foo(a: DynamicMenu.z) { } }",
|
||||
};
|
||||
const configFile: File = {
|
||||
path: "/a/b/project/tsconfig.json",
|
||||
path: "/home/src/projects/a/b/project/tsconfig.json",
|
||||
content: jsonToReadableText({
|
||||
compilerOptions: useOutFile ?
|
||||
{ outFile: "../output/common.js", target: "es5" } :
|
||||
@@ -74,7 +71,10 @@ describe("unittests:: tsc-watch:: emit with outFile or out setting", () => {
|
||||
files: [file1.path, file2.path, file3.path, file4.path],
|
||||
}),
|
||||
};
|
||||
return createWatchedSystem([file1, file2, file3, file4, libFile, configFile]);
|
||||
return TestServerHost.createWatchedSystem(
|
||||
[file1, file2, file3, file4, configFile],
|
||||
{ currentDirectory: "/home/src/projects/a/b/project" },
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -82,13 +82,13 @@ describe("unittests:: tsc-watch:: emit with outFile or out setting", () => {
|
||||
verifyFilesEmittedOnce("without --outFile and multiple declaration files in the program", /*useOutFile*/ false);
|
||||
});
|
||||
|
||||
describe("unittests:: tsc-watch:: emit for configured projects", () => {
|
||||
const file1Consumer1Path = "/a/b/file1Consumer1.ts";
|
||||
const file1Consumer2Path = "/a/b/file1Consumer2.ts";
|
||||
const moduleFile1Path = "/a/b/moduleFile1.ts";
|
||||
const moduleFile2Path = "/a/b/moduleFile2.ts";
|
||||
const globalFilePath = "/a/b/globalFile3.ts";
|
||||
const configFilePath = "/a/b/tsconfig.json";
|
||||
describe("unittests:: tscWatch:: emit:: for configured projects", () => {
|
||||
const file1Consumer1Path = "/home/src/projects/a/b/file1Consumer1.ts";
|
||||
const file1Consumer2Path = "/home/src/projects/a/b/file1Consumer2.ts";
|
||||
const moduleFile1Path = "/home/src/projects/a/b/moduleFile1.ts";
|
||||
const moduleFile2Path = "/home/src/projects/a/b/moduleFile2.ts";
|
||||
const globalFilePath = "/home/src/projects/a/b/globalFile3.ts";
|
||||
const configFilePath = "/home/src/projects/a/b/tsconfig.json";
|
||||
interface VerifyTscWatchEmit {
|
||||
subScenario: string;
|
||||
/** custom config file options */
|
||||
@@ -109,7 +109,7 @@ describe("unittests:: tsc-watch:: emit for configured projects", () => {
|
||||
verifyTscWatch({
|
||||
scenario,
|
||||
subScenario: `emit for configured projects/${subScenario}`,
|
||||
commandLineArgs: ["--w", "-p", configFilePath],
|
||||
commandLineArgs: ["--w"],
|
||||
sys: () => {
|
||||
const moduleFile1: File = {
|
||||
path: moduleFile1Path,
|
||||
@@ -140,11 +140,12 @@ describe("unittests:: tsc-watch:: emit for configured projects", () => {
|
||||
content: jsonToReadableText(configObj || {}),
|
||||
};
|
||||
const additionalFiles = getAdditionalFileOrFolder?.() || ts.emptyArray;
|
||||
const files = [moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, libFile, ...additionalFiles];
|
||||
return createWatchedSystem(
|
||||
const files = [moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, ...additionalFiles];
|
||||
return TestServerHost.createWatchedSystem(
|
||||
firstReloadFileList ?
|
||||
ts.map(firstReloadFileList, fileName => ts.find(files, file => file.path === fileName)!) :
|
||||
files,
|
||||
{ currentDirectory: ts.getDirectoryPath(configFilePath) },
|
||||
);
|
||||
},
|
||||
edits: changes,
|
||||
@@ -224,7 +225,7 @@ describe("unittests:: tsc-watch:: emit for configured projects", () => {
|
||||
{
|
||||
caption: "change moduleFile1 shape and create file1Consumer3",
|
||||
edit: sys => {
|
||||
sys.writeFile("/a/b/file1Consumer3.ts", `import {Foo} from "./moduleFile1"; let y = Foo();`);
|
||||
sys.writeFile("/home/src/projects/a/b/file1Consumer3.ts", `import {Foo} from "./moduleFile1"; let y = Foo();`);
|
||||
modifyModuleFile1Shape(sys);
|
||||
},
|
||||
timeouts: sys => sys.runQueuedTimeoutCallbacks(),
|
||||
@@ -266,7 +267,7 @@ describe("unittests:: tsc-watch:: emit for configured projects", () => {
|
||||
|
||||
verifyTscWatchEmit({
|
||||
subScenario: "should always return the file itself if '--out' or '--outFile' is specified",
|
||||
configObj: { compilerOptions: { module: "system", outFile: "/a/b/out.js" } },
|
||||
configObj: { compilerOptions: { module: "system", outFile: "/home/src/projects/a/b/out.js" } },
|
||||
changes: [
|
||||
changeModuleFile1Shape,
|
||||
],
|
||||
@@ -275,7 +276,7 @@ describe("unittests:: tsc-watch:: emit for configured projects", () => {
|
||||
verifyTscWatchEmit({
|
||||
subScenario: "should return cascaded affected file list",
|
||||
getAdditionalFileOrFolder: () => [{
|
||||
path: "/a/b/file1Consumer1Consumer1.ts",
|
||||
path: "/home/src/projects/a/b/file1Consumer1Consumer1.ts",
|
||||
content: `import {y} from "./file1Consumer1";`,
|
||||
}],
|
||||
changes: [
|
||||
@@ -300,21 +301,21 @@ describe("unittests:: tsc-watch:: emit for configured projects", () => {
|
||||
subScenario: "should work fine for files with circular references",
|
||||
getAdditionalFileOrFolder: () => [
|
||||
{
|
||||
path: "/a/b/file1.ts",
|
||||
path: "/home/src/projects/a/b/file1.ts",
|
||||
content: `/// <reference path="./file2.ts" />
|
||||
export var t1 = 10;`,
|
||||
},
|
||||
{
|
||||
path: "/a/b/file2.ts",
|
||||
path: "/home/src/projects/a/b/file2.ts",
|
||||
content: `/// <reference path="./file1.ts" />
|
||||
export var t2 = 10;`,
|
||||
},
|
||||
],
|
||||
firstReloadFileList: [libFile.path, "/a/b/file1.ts", "/a/b/file2.ts", configFilePath],
|
||||
firstReloadFileList: ["/home/src/projects/a/b/file1.ts", "/home/src/projects/a/b/file2.ts", configFilePath],
|
||||
changes: [
|
||||
{
|
||||
caption: "change file1",
|
||||
edit: sys => sys.appendFile("/a/b/file1.ts", "export var t3 = 10;"),
|
||||
edit: sys => sys.appendFile("/home/src/projects/a/b/file1.ts", "export var t3 = 10;"),
|
||||
timeouts: sys => sys.runQueuedTimeoutCallbacks(),
|
||||
},
|
||||
],
|
||||
@@ -323,11 +324,11 @@ export var t2 = 10;`,
|
||||
verifyTscWatchEmit({
|
||||
subScenario: "should detect removed code file",
|
||||
getAdditionalFileOrFolder: () => [{
|
||||
path: "/a/b/referenceFile1.ts",
|
||||
path: "/home/src/projects/a/b/referenceFile1.ts",
|
||||
content: `/// <reference path="./moduleFile1.ts" />
|
||||
export var x = Foo();`,
|
||||
}],
|
||||
firstReloadFileList: [libFile.path, "/a/b/referenceFile1.ts", moduleFile1Path, configFilePath],
|
||||
firstReloadFileList: ["/home/src/projects/a/b/referenceFile1.ts", moduleFile1Path, configFilePath],
|
||||
changes: [
|
||||
{
|
||||
caption: "delete moduleFile1",
|
||||
@@ -340,15 +341,15 @@ export var x = Foo();`,
|
||||
verifyTscWatchEmit({
|
||||
subScenario: "should detect non existing code file",
|
||||
getAdditionalFileOrFolder: () => [{
|
||||
path: "/a/b/referenceFile1.ts",
|
||||
path: "/home/src/projects/a/b/referenceFile1.ts",
|
||||
content: `/// <reference path="./moduleFile2.ts" />
|
||||
export var x = Foo();`,
|
||||
}],
|
||||
firstReloadFileList: [libFile.path, "/a/b/referenceFile1.ts", configFilePath],
|
||||
firstReloadFileList: ["/home/src/projects/a/b/referenceFile1.ts", configFilePath],
|
||||
changes: [
|
||||
{
|
||||
caption: "edit refereceFile1",
|
||||
edit: sys => sys.appendFile("/a/b/referenceFile1.ts", "export var yy = Foo();"),
|
||||
edit: sys => sys.appendFile("/home/src/projects/a/b/referenceFile1.ts", "export var yy = Foo();"),
|
||||
timeouts: sys => sys.runQueuedTimeoutCallbacks(),
|
||||
},
|
||||
{
|
||||
@@ -360,27 +361,24 @@ export var x = Foo();`,
|
||||
});
|
||||
});
|
||||
|
||||
describe("unittests:: tsc-watch:: emit file content", () => {
|
||||
describe("unittests:: tscWatch:: emit:: file content", () => {
|
||||
function verifyNewLine(subScenario: string, newLine: string) {
|
||||
verifyTscWatch({
|
||||
scenario,
|
||||
subScenario: `emit file content/${subScenario}`,
|
||||
commandLineArgs: ["--w", "/a/app.ts"],
|
||||
commandLineArgs: ["--w", "/home/src/projects/a/app.ts"],
|
||||
sys: () =>
|
||||
createWatchedSystem(
|
||||
[
|
||||
{
|
||||
path: "/a/app.ts",
|
||||
content: ["var x = 1;", "var y = 2;"].join(newLine),
|
||||
},
|
||||
libFile,
|
||||
],
|
||||
{ newLine },
|
||||
TestServerHost.createWatchedSystem(
|
||||
[{
|
||||
path: "/home/src/projects/a/app.ts",
|
||||
content: ["var x = 1;", "var y = 2;"].join(newLine),
|
||||
}],
|
||||
{ newLine, currentDirectory: "/home/src/projects/a" },
|
||||
),
|
||||
edits: [
|
||||
{
|
||||
caption: "Append a line",
|
||||
edit: sys => sys.appendFile("/a/app.ts", newLine + "var z = 3;"),
|
||||
edit: sys => sys.appendFile("/home/src/projects/a/app.ts", newLine + "var z = 3;"),
|
||||
timeouts: sys => sys.runQueuedTimeoutCallbacks(),
|
||||
},
|
||||
],
|
||||
@@ -392,38 +390,41 @@ describe("unittests:: tsc-watch:: emit file content", () => {
|
||||
verifyTscWatch({
|
||||
scenario,
|
||||
subScenario: "emit file content/should emit specified file",
|
||||
commandLineArgs: ["-w", "-p", "/a/b/tsconfig.json"],
|
||||
commandLineArgs: ["-w", "-p", "/home/src/projects/a/b/tsconfig.json"],
|
||||
sys: () => {
|
||||
const file1 = {
|
||||
path: "/a/b/f1.ts",
|
||||
path: "/home/src/projects/a/b/f1.ts",
|
||||
content: `export function Foo() { return 10; }`,
|
||||
};
|
||||
|
||||
const file2 = {
|
||||
path: "/a/b/f2.ts",
|
||||
path: "/home/src/projects/a/b/f2.ts",
|
||||
content: `import {Foo} from "./f1"; export let y = Foo();`,
|
||||
};
|
||||
|
||||
const file3 = {
|
||||
path: "/a/b/f3.ts",
|
||||
path: "/home/src/projects/a/b/f3.ts",
|
||||
content: `import {y} from "./f2"; let x = y;`,
|
||||
};
|
||||
|
||||
const configFile = {
|
||||
path: "/a/b/tsconfig.json",
|
||||
path: "/home/src/projects/a/b/tsconfig.json",
|
||||
content: "{}",
|
||||
};
|
||||
return createWatchedSystem([file1, file2, file3, configFile, libFile]);
|
||||
return TestServerHost.createWatchedSystem(
|
||||
[file1, file2, file3, configFile],
|
||||
{ currentDirectory: ts.getDirectoryPath(configFile.path) },
|
||||
);
|
||||
},
|
||||
edits: [
|
||||
{
|
||||
caption: "Append content to f1",
|
||||
edit: sys => sys.appendFile("/a/b/f1.ts", "export function foo2() { return 2; }"),
|
||||
edit: sys => sys.appendFile("/home/src/projects/a/b/f1.ts", "export function foo2() { return 2; }"),
|
||||
timeouts: sys => sys.runQueuedTimeoutCallbacks(),
|
||||
},
|
||||
{
|
||||
caption: "Again Append content to f1",
|
||||
edit: sys => sys.appendFile("/a/b/f1.ts", "export function fooN() { return 2; }"),
|
||||
edit: sys => sys.appendFile("/home/src/projects/a/b/f1.ts", "export function fooN() { return 2; }"),
|
||||
timeouts: sys => sys.runQueuedTimeoutCallbacks(),
|
||||
},
|
||||
],
|
||||
@@ -447,7 +448,10 @@ describe("unittests:: tsc-watch:: emit file content", () => {
|
||||
path: `${currentDirectory}/file3.ts`,
|
||||
content: `import { E2 } from "./file2"; const v: E2 = E2.V;`,
|
||||
};
|
||||
return createWatchedSystem([file1, file2, file3, libFile]);
|
||||
return TestServerHost.createWatchedSystem(
|
||||
[file1, file2, file3],
|
||||
{ currentDirectory },
|
||||
);
|
||||
},
|
||||
edits: [
|
||||
{
|
||||
@@ -463,7 +467,7 @@ describe("unittests:: tsc-watch:: emit file content", () => {
|
||||
subScenario: "emit file content/file is deleted and created as part of change",
|
||||
commandLineArgs: ["-w"],
|
||||
sys: () => {
|
||||
const projectLocation = "/home/username/project";
|
||||
const projectLocation = "/home/username/projects/project";
|
||||
const file: File = {
|
||||
path: `${projectLocation}/app/file.ts`,
|
||||
content: "var a = 10;",
|
||||
@@ -476,27 +480,32 @@ describe("unittests:: tsc-watch:: emit file content", () => {
|
||||
],
|
||||
}),
|
||||
};
|
||||
const files = [file, configFile, libFile];
|
||||
return createWatchedSystem(files, { currentDirectory: projectLocation, useCaseSensitiveFileNames: true });
|
||||
return TestServerHost.createWatchedSystem(
|
||||
[file, configFile],
|
||||
{
|
||||
currentDirectory: projectLocation,
|
||||
useCaseSensitiveFileNames: true,
|
||||
},
|
||||
);
|
||||
},
|
||||
edits: [
|
||||
{
|
||||
caption: "file is deleted and then created to modify content",
|
||||
edit: sys => sys.appendFile("/home/username/project/app/file.ts", "\nvar b = 10;", { invokeFileDeleteCreateAsPartInsteadOfChange: true }),
|
||||
edit: sys => sys.appendFile("/home/username/projects/project/app/file.ts", "\nvar b = 10;", { invokeFileDeleteCreateAsPartInsteadOfChange: true }),
|
||||
timeouts: sys => sys.runQueuedTimeoutCallbacks(),
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
describe("unittests:: tsc-watch:: emit with when module emit is specified as node", () => {
|
||||
describe("unittests:: tscWatch:: emit:: with when module emit is specified as node", () => {
|
||||
verifyTscWatch({
|
||||
scenario,
|
||||
subScenario: "when module emit is specified as node/when instead of filechanged recursive directory watcher is invoked",
|
||||
commandLineArgs: ["--w", "--p", "/a/rootFolder/project/tsconfig.json"],
|
||||
commandLineArgs: ["--w"],
|
||||
sys: () => {
|
||||
const configFile: File = {
|
||||
path: "/a/rootFolder/project/tsconfig.json",
|
||||
path: "/home/src/projects/a/rootFolder/project/tsconfig.json",
|
||||
content: jsonToReadableText({
|
||||
compilerOptions: {
|
||||
module: "none",
|
||||
@@ -509,21 +518,24 @@ describe("unittests:: tsc-watch:: emit with when module emit is specified as nod
|
||||
}),
|
||||
};
|
||||
const file1: File = {
|
||||
path: "/a/rootFolder/project/Scripts/TypeScript.ts",
|
||||
path: "/home/src/projects/a/rootFolder/project/Scripts/TypeScript.ts",
|
||||
content: "var z = 10;",
|
||||
};
|
||||
const file2: File = {
|
||||
path: "/a/rootFolder/project/Scripts/Javascript.js",
|
||||
path: "/home/src/projects/a/rootFolder/project/Scripts/Javascript.js",
|
||||
content: "var zz = 10;",
|
||||
};
|
||||
return createWatchedSystem([configFile, file1, file2, libFile]);
|
||||
return TestServerHost.createWatchedSystem(
|
||||
[configFile, file1, file2],
|
||||
{ currentDirectory: ts.getDirectoryPath(configFile.path) },
|
||||
);
|
||||
},
|
||||
edits: [
|
||||
{
|
||||
caption: "Modify typescript file",
|
||||
edit: sys =>
|
||||
sys.modifyFile(
|
||||
"/a/rootFolder/project/Scripts/TypeScript.ts",
|
||||
"/home/src/projects/a/rootFolder/project/Scripts/TypeScript.ts",
|
||||
"var zz30 = 100;",
|
||||
{ invokeDirectoryWatcherInsteadOfFileChanged: true },
|
||||
),
|
||||
|
||||
@@ -1,41 +1,34 @@
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import { FsContents } from "../helpers/contents.js";
|
||||
import {
|
||||
TscWatchCompileChange,
|
||||
verifyTscWatch,
|
||||
} from "../helpers/tscWatch.js";
|
||||
import {
|
||||
createWatchedSystem,
|
||||
File,
|
||||
libFile,
|
||||
FileOrFolderOrSymLinkMap,
|
||||
TestServerHost,
|
||||
} from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsc-watch:: Emit times and Error updates in builder after program changes", () => {
|
||||
describe("unittests:: tscWatch:: emitAndErrorUpdates:: Emit times and Error updates in builder after program changes", () => {
|
||||
const config: File = {
|
||||
path: `/user/username/projects/myproject/tsconfig.json`,
|
||||
content: `{}`,
|
||||
};
|
||||
interface VerifyEmitAndErrorUpdates {
|
||||
subScenario: string;
|
||||
files: () => FsContents | readonly File[];
|
||||
currentDirectory?: string;
|
||||
files: () => FileOrFolderOrSymLinkMap | readonly File[];
|
||||
changes: TscWatchCompileChange[];
|
||||
}
|
||||
function verifyEmitAndErrorUpdates({
|
||||
subScenario,
|
||||
files,
|
||||
currentDirectory,
|
||||
changes,
|
||||
}: VerifyEmitAndErrorUpdates) {
|
||||
verifyTscWatch({
|
||||
scenario: "emitAndErrorUpdates",
|
||||
subScenario: `default/${subScenario}`,
|
||||
commandLineArgs: ["--w"],
|
||||
sys: () =>
|
||||
createWatchedSystem(
|
||||
files(),
|
||||
{ currentDirectory: currentDirectory || "/user/username/projects/myproject" },
|
||||
),
|
||||
sys,
|
||||
edits: changes,
|
||||
baselineIncremental: true,
|
||||
});
|
||||
@@ -44,11 +37,7 @@ describe("unittests:: tsc-watch:: Emit times and Error updates in builder after
|
||||
scenario: "emitAndErrorUpdates",
|
||||
subScenario: `defaultAndD/${subScenario}`,
|
||||
commandLineArgs: ["--w", "--d"],
|
||||
sys: () =>
|
||||
createWatchedSystem(
|
||||
files(),
|
||||
{ currentDirectory: currentDirectory || "/user/username/projects/myproject" },
|
||||
),
|
||||
sys,
|
||||
edits: changes,
|
||||
baselineIncremental: true,
|
||||
});
|
||||
@@ -57,11 +46,7 @@ describe("unittests:: tsc-watch:: Emit times and Error updates in builder after
|
||||
scenario: "emitAndErrorUpdates",
|
||||
subScenario: `isolatedModules/${subScenario}`,
|
||||
commandLineArgs: ["--w", "--isolatedModules"],
|
||||
sys: () =>
|
||||
createWatchedSystem(
|
||||
files(),
|
||||
{ currentDirectory: currentDirectory || "/user/username/projects/myproject" },
|
||||
),
|
||||
sys,
|
||||
edits: changes,
|
||||
baselineIncremental: true,
|
||||
});
|
||||
@@ -70,11 +55,7 @@ describe("unittests:: tsc-watch:: Emit times and Error updates in builder after
|
||||
scenario: "emitAndErrorUpdates",
|
||||
subScenario: `isolatedModulesAndD/${subScenario}`,
|
||||
commandLineArgs: ["--w", "--isolatedModules", "--d"],
|
||||
sys: () =>
|
||||
createWatchedSystem(
|
||||
files(),
|
||||
{ currentDirectory: currentDirectory || "/user/username/projects/myproject" },
|
||||
),
|
||||
sys,
|
||||
edits: changes,
|
||||
baselineIncremental: true,
|
||||
});
|
||||
@@ -83,11 +64,7 @@ describe("unittests:: tsc-watch:: Emit times and Error updates in builder after
|
||||
scenario: "emitAndErrorUpdates",
|
||||
subScenario: `assumeChangesOnlyAffectDirectDependencies/${subScenario}`,
|
||||
commandLineArgs: ["--w", "--assumeChangesOnlyAffectDirectDependencies"],
|
||||
sys: () =>
|
||||
createWatchedSystem(
|
||||
files(),
|
||||
{ currentDirectory: currentDirectory || "/user/username/projects/myproject" },
|
||||
),
|
||||
sys,
|
||||
edits: changes,
|
||||
baselineIncremental: true,
|
||||
});
|
||||
@@ -96,14 +73,17 @@ describe("unittests:: tsc-watch:: Emit times and Error updates in builder after
|
||||
scenario: "emitAndErrorUpdates",
|
||||
subScenario: `assumeChangesOnlyAffectDirectDependenciesAndD/${subScenario}`,
|
||||
commandLineArgs: ["--w", "--assumeChangesOnlyAffectDirectDependencies", "--d"],
|
||||
sys: () =>
|
||||
createWatchedSystem(
|
||||
files(),
|
||||
{ currentDirectory: currentDirectory || "/user/username/projects/myproject" },
|
||||
),
|
||||
sys,
|
||||
edits: changes,
|
||||
baselineIncremental: true,
|
||||
});
|
||||
|
||||
function sys() {
|
||||
return TestServerHost.createWatchedSystem(
|
||||
files(),
|
||||
{ currentDirectory: "/user/username/projects/myproject" },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
describe("deep import changes", () => {
|
||||
@@ -118,7 +98,7 @@ console.log(b.c.d);`,
|
||||
function verifyDeepImportChange(subScenario: string, bFile: File, cFile: File) {
|
||||
verifyEmitAndErrorUpdates({
|
||||
subScenario: `deepImportChanges/${subScenario}`,
|
||||
files: () => [aFile, bFile, cFile, config, libFile],
|
||||
files: () => [aFile, bFile, cFile, config],
|
||||
changes: [
|
||||
{
|
||||
caption: "Rename property d to d2 of class C to initialize signatures",
|
||||
@@ -226,7 +206,7 @@ getPoint().c.x;`,
|
||||
};
|
||||
verifyEmitAndErrorUpdates({
|
||||
subScenario: "file not exporting a deep multilevel import that changes",
|
||||
files: () => [aFile, bFile, cFile, dFile, eFile, config, libFile],
|
||||
files: () => [aFile, bFile, cFile, dFile, eFile, config],
|
||||
changes: [
|
||||
{
|
||||
caption: "Rename property x2 to x of interface Coords to initialize signatures",
|
||||
@@ -297,7 +277,7 @@ export class Data {
|
||||
function verifyTransitiveExports(subScenario: string, files: readonly File[]) {
|
||||
verifyEmitAndErrorUpdates({
|
||||
subScenario: `transitive exports/${subScenario}`,
|
||||
files: () => [lib1ToolsInterface, lib1ToolsPublic, app, lib2Public, lib1Public, ...files, config, libFile],
|
||||
files: () => [lib1ToolsInterface, lib1ToolsPublic, app, lib2Public, lib1Public, ...files, config],
|
||||
changes: [
|
||||
{
|
||||
caption: "Rename property title to title2 of interface ITest to initialize signatures",
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
import {
|
||||
getConfigDirExtendsSys,
|
||||
forConfigDirExtendsSysScenario,
|
||||
getSymlinkedExtendsSys,
|
||||
modifyFirstExtendedConfigOfConfigDirExtendsSys,
|
||||
} from "../helpers/extends.js";
|
||||
import { verifyTscWatch } from "../helpers/tscWatch.js";
|
||||
import { createWatchedSystem } from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsc-watch:: extends::", () => {
|
||||
describe("unittests:: tscWatch:: extends::", () => {
|
||||
verifyTscWatch({
|
||||
scenario: "extends",
|
||||
subScenario: "resolves the symlink path",
|
||||
@@ -14,15 +12,15 @@ describe("unittests:: tsc-watch:: extends::", () => {
|
||||
commandLineArgs: ["-w", "-p", "src", "--extendedDiagnostics"],
|
||||
});
|
||||
|
||||
verifyTscWatch({
|
||||
scenario: "extends",
|
||||
subScenario: "configDir template",
|
||||
sys: () => createWatchedSystem(getConfigDirExtendsSys(), { currentDirectory: "/home/src/projects/myproject" }),
|
||||
commandLineArgs: ["-w", "--extendedDiagnostics", "--explainFiles"],
|
||||
edits: [{
|
||||
caption: "edit extended config file",
|
||||
edit: modifyFirstExtendedConfigOfConfigDirExtendsSys,
|
||||
timeouts: sys => sys.runQueuedTimeoutCallbacks(),
|
||||
}],
|
||||
});
|
||||
forConfigDirExtendsSysScenario(
|
||||
/*forTsserver*/ false,
|
||||
(subScenario, sys, edits) =>
|
||||
verifyTscWatch({
|
||||
scenario: "extends",
|
||||
subScenario,
|
||||
sys,
|
||||
commandLineArgs: ["-w", "--extendedDiagnostics", "--explainFiles"],
|
||||
edits: edits(),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
import { dedent } from "../../_namespaces/Utils.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import { getFsContentsForMultipleErrorsForceConsistentCasingInFileNames } from "../helpers/forceConsistentCasingInFileNames.js";
|
||||
import { getSysForMultipleErrorsForceConsistentCasingInFileNames } from "../helpers/forceConsistentCasingInFileNames.js";
|
||||
import {
|
||||
TscWatchCompileChange,
|
||||
verifyTscWatch,
|
||||
} from "../helpers/tscWatch.js";
|
||||
import {
|
||||
createWatchedSystem,
|
||||
File,
|
||||
libFile,
|
||||
SymLink,
|
||||
TestServerHost,
|
||||
} from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsc-watch:: forceConsistentCasingInFileNames::", () => {
|
||||
describe("unittests:: tscWatch:: forceConsistentCasingInFileNames::", () => {
|
||||
const loggerFile: File = {
|
||||
path: `/user/username/projects/myproject/logger.ts`,
|
||||
content: `export class logger { }`,
|
||||
@@ -33,7 +32,11 @@ describe("unittests:: tsc-watch:: forceConsistentCasingInFileNames::", () => {
|
||||
scenario: "forceConsistentCasingInFileNames",
|
||||
subScenario,
|
||||
commandLineArgs: ["--w", "--p", tsconfig.path],
|
||||
sys: () => createWatchedSystem([loggerFile, anotherFile, tsconfig, libFile]),
|
||||
sys: () =>
|
||||
TestServerHost.createWatchedSystem(
|
||||
[loggerFile, anotherFile, tsconfig],
|
||||
{ currentDirectory: "/user/username/projects/myproject" },
|
||||
),
|
||||
edits: changes,
|
||||
});
|
||||
}
|
||||
@@ -81,7 +84,10 @@ describe("unittests:: tsc-watch:: forceConsistentCasingInFileNames::", () => {
|
||||
path: `/user/username/projects/myproject/tsconfig.json`,
|
||||
content: jsonToReadableText({ compilerOptions: { forceConsistentCasingInFileNames: true } }),
|
||||
};
|
||||
return createWatchedSystem([moduleA, moduleB, moduleC, libFile, tsconfig], { currentDirectory: "/user/username/projects/myproject" });
|
||||
return TestServerHost.createWatchedSystem(
|
||||
[moduleA, moduleB, moduleC, tsconfig],
|
||||
{ currentDirectory: "/user/username/projects/myproject" },
|
||||
);
|
||||
},
|
||||
edits: [
|
||||
{
|
||||
@@ -102,8 +108,7 @@ describe("unittests:: tsc-watch:: forceConsistentCasingInFileNames::", () => {
|
||||
subScenario: "jsxImportSource option changed",
|
||||
commandLineArgs: ["--w", "--p", ".", "--explainFiles"],
|
||||
sys: () =>
|
||||
createWatchedSystem([
|
||||
libFile,
|
||||
TestServerHost.createWatchedSystem([
|
||||
{
|
||||
path: `/user/username/projects/myproject/node_modules/react/Jsx-runtime/index.d.ts`,
|
||||
content: `export namespace JSX {
|
||||
@@ -141,36 +146,43 @@ export const Fragment: unique symbol;
|
||||
verifyTscWatch({
|
||||
scenario: "forceConsistentCasingInFileNames",
|
||||
subScenario,
|
||||
commandLineArgs: ["--w", "--p", `${windowsStyleRoot}/${projectRootRelative}`, "--explainFiles"],
|
||||
commandLineArgs: ["--w", "--p", `${windowsStyleRoot}workspaces/solution/${projectRootRelative}`, "--explainFiles"],
|
||||
sys: () => {
|
||||
const moduleA: File = {
|
||||
path: `${windowsStyleRoot}/${projectRootRelative}/a.ts`,
|
||||
path: `${windowsStyleRoot}workspaces/solution/${projectRootRelative}/a.ts`,
|
||||
content: `
|
||||
export const a = 1;
|
||||
export const b = 2;
|
||||
`,
|
||||
};
|
||||
const moduleB: File = {
|
||||
path: `${windowsStyleRoot}/${projectRootRelative}/b.ts`,
|
||||
path: `${windowsStyleRoot}workspaces/solution/${projectRootRelative}/b.ts`,
|
||||
content: `
|
||||
import { a } from "${windowsStyleRoot.toLocaleUpperCase()}/${projectRootRelative}/a"
|
||||
import { b } from "${windowsStyleRoot.toLocaleLowerCase()}/${projectRootRelative}/a"
|
||||
import { a } from "${windowsStyleRoot.toLocaleUpperCase()}workspaces/solution/${projectRootRelative}/a"
|
||||
import { b } from "${windowsStyleRoot.toLocaleLowerCase()}workspaces/solution/${projectRootRelative}/a"
|
||||
|
||||
a;b;
|
||||
`,
|
||||
};
|
||||
const tsconfig: File = {
|
||||
path: `${windowsStyleRoot}/${projectRootRelative}/tsconfig.json`,
|
||||
path: `${windowsStyleRoot}workspaces/solution/${projectRootRelative}/tsconfig.json`,
|
||||
content: jsonToReadableText({ compilerOptions: { forceConsistentCasingInFileNames: true } }),
|
||||
};
|
||||
return createWatchedSystem([moduleA, moduleB, libFile, tsconfig], { windowsStyleRoot, useCaseSensitiveFileNames: false });
|
||||
return TestServerHost.createWatchedSystem(
|
||||
[moduleA, moduleB, tsconfig],
|
||||
{
|
||||
windowsStyleRoot,
|
||||
useCaseSensitiveFileNames: false,
|
||||
currentDirectory: `${windowsStyleRoot}workspaces/solution`,
|
||||
},
|
||||
);
|
||||
},
|
||||
edits: [
|
||||
{
|
||||
caption: "Prepend a line to moduleA",
|
||||
edit: sys =>
|
||||
sys.prependFile(
|
||||
`${windowsStyleRoot}/${projectRootRelative}/a.ts`,
|
||||
`${windowsStyleRoot}workspaces/solution/${projectRootRelative}/a.ts`,
|
||||
`// some comment
|
||||
`,
|
||||
),
|
||||
@@ -213,7 +225,10 @@ a;b;
|
||||
path: `/user/username/projects/myproject/tsconfig.json`,
|
||||
content: jsonToReadableText({ compilerOptions: { forceConsistentCasingInFileNames: true } }),
|
||||
};
|
||||
return createWatchedSystem([moduleA, symlinkA, moduleB, libFile, tsconfig], { currentDirectory: "/user/username/projects/myproject" });
|
||||
return TestServerHost.createWatchedSystem(
|
||||
[moduleA, symlinkA, moduleB, tsconfig],
|
||||
{ currentDirectory: "/user/username/projects/myproject" },
|
||||
);
|
||||
},
|
||||
edits: [
|
||||
{
|
||||
@@ -267,7 +282,10 @@ a;b;
|
||||
// Use outFile because otherwise the real and linked files will have the same output path
|
||||
content: jsonToReadableText({ compilerOptions: { forceConsistentCasingInFileNames: true, outFile: "out.js", module: "system" } }),
|
||||
};
|
||||
return createWatchedSystem([moduleA, symlinkA, moduleB, libFile, tsconfig], { currentDirectory: "/user/username/projects/myproject" });
|
||||
return TestServerHost.createWatchedSystem(
|
||||
[moduleA, symlinkA, moduleB, tsconfig],
|
||||
{ currentDirectory: "/user/username/projects/myproject" },
|
||||
);
|
||||
},
|
||||
edits: [
|
||||
{
|
||||
@@ -295,7 +313,7 @@ a;b;
|
||||
subScenario: "with nodeNext resolution",
|
||||
commandLineArgs: ["--w", "--explainFiles"],
|
||||
sys: () =>
|
||||
createWatchedSystem({
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/Users/name/projects/web/src/bin.ts": `import { foo } from "yargs";`,
|
||||
"/Users/name/projects/web/node_modules/@types/yargs/index.d.ts": "export function foo(): void;",
|
||||
"/Users/name/projects/web/node_modules/@types/yargs/index.d.mts": "export function foo(): void;",
|
||||
@@ -318,7 +336,6 @@ a;b;
|
||||
traceResolution: true,
|
||||
},
|
||||
}),
|
||||
[libFile.path]: libFile.content,
|
||||
}, { currentDirectory: "/Users/name/projects/web" }),
|
||||
});
|
||||
|
||||
@@ -327,7 +344,7 @@ a;b;
|
||||
subScenario: "self name package reference",
|
||||
commandLineArgs: ["-w", "--explainFiles"],
|
||||
sys: () =>
|
||||
createWatchedSystem({
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/Users/name/projects/web/package.json": jsonToReadableText({
|
||||
name: "@this/package",
|
||||
type: "module",
|
||||
@@ -350,7 +367,6 @@ a;b;
|
||||
traceResolution: true,
|
||||
},
|
||||
}),
|
||||
"/a/lib/lib.esnext.full.d.ts": libFile.content,
|
||||
}, { currentDirectory: "/Users/name/projects/web" }),
|
||||
});
|
||||
|
||||
@@ -359,7 +375,7 @@ a;b;
|
||||
subScenario: "package json is looked up for file",
|
||||
commandLineArgs: ["-w", "--explainFiles"],
|
||||
sys: () =>
|
||||
createWatchedSystem({
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/Users/name/projects/lib-boilerplate/package.json": jsonToReadableText({
|
||||
name: "lib-boilerplate",
|
||||
version: "0.0.2",
|
||||
@@ -380,7 +396,6 @@ a;b;
|
||||
traceResolution: true,
|
||||
},
|
||||
}),
|
||||
"/a/lib/lib.es2021.full.d.ts": libFile.content,
|
||||
}, { currentDirectory: "/Users/name/projects/lib-boilerplate" }),
|
||||
});
|
||||
|
||||
@@ -388,11 +403,7 @@ a;b;
|
||||
scenario: "forceConsistentCasingInFileNames",
|
||||
subScenario: "when file is included from multiple places with different casing",
|
||||
commandLineArgs: ["-w", "--explainFiles"],
|
||||
sys: () =>
|
||||
createWatchedSystem(
|
||||
getFsContentsForMultipleErrorsForceConsistentCasingInFileNames(),
|
||||
{ currentDirectory: "/home/src/projects/project" },
|
||||
),
|
||||
sys: getSysForMultipleErrorsForceConsistentCasingInFileNames,
|
||||
edits: [
|
||||
{
|
||||
caption: "change to reuse imports",
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
import * as Harness from "../../_namespaces/Harness.js";
|
||||
import { Baseline } from "../../_namespaces/Harness.js";
|
||||
import * as ts from "../../_namespaces/ts.js";
|
||||
import { jsonToReadableText } from "../helpers.js";
|
||||
import { CommandLineProgram } from "../helpers/baseline.js";
|
||||
import { libContent } from "../helpers/contents.js";
|
||||
import {
|
||||
applyEdit,
|
||||
CommandLineProgram,
|
||||
createBaseline,
|
||||
} from "../helpers/baseline.js";
|
||||
import {
|
||||
verifyTscWatch,
|
||||
watchBaseline,
|
||||
} from "../helpers/tscWatch.js";
|
||||
import {
|
||||
createWatchedSystem,
|
||||
File,
|
||||
libFile,
|
||||
TestServerHost,
|
||||
} from "../helpers/virtualFileSystemWithWatch.js";
|
||||
|
||||
describe("unittests:: tsc-watch:: emit file --incremental", () => {
|
||||
describe("unittests:: tscWatch:: incremental:: emit file --incremental", () => {
|
||||
const project = "/users/username/projects/project";
|
||||
|
||||
const configFile: File = {
|
||||
@@ -45,7 +45,10 @@ describe("unittests:: tsc-watch:: emit file --incremental", () => {
|
||||
{ subScenario, files, optionsToExtend, modifyFs }: VerifyIncrementalWatchEmitInput,
|
||||
incremental: boolean,
|
||||
) {
|
||||
const { sys, baseline, cb, getPrograms } = createBaseline(createWatchedSystem(files(), { currentDirectory: project }));
|
||||
const { sys, baseline, cb, getPrograms } = createBaseline(TestServerHost.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(" ")}`);
|
||||
@@ -57,7 +60,7 @@ describe("unittests:: tsc-watch:: emit file --incremental", () => {
|
||||
build();
|
||||
}
|
||||
|
||||
Harness.Baseline.runBaseline(`${ts.isBuild(argsToPass) ? "tsbuild/watchMode" : "tscWatch"}/incremental/${subScenario.split(" ").join("-")}-${incremental ? "incremental" : "watch"}.js`, baseline.join("\r\n"));
|
||||
Baseline.runBaseline(`${ts.isBuild(argsToPass) ? "tsbuild/watchMode" : "tscWatch"}/incremental/${subScenario.split(" ").join("-")}-${incremental ? "incremental" : "watch"}.js`, baseline.join("\r\n"));
|
||||
|
||||
function build() {
|
||||
const closer = ts.executeCommandLine(
|
||||
@@ -88,7 +91,7 @@ describe("unittests:: tsc-watch:: emit file --incremental", () => {
|
||||
function verify(subScenario: string, optionsToExtend?: readonly string[]) {
|
||||
const modifiedFile2Content = file2.content.replace("y", "z").replace("20", "10");
|
||||
verifyIncrementalWatchEmit({
|
||||
files: () => [libFile, file1, file2, configFile],
|
||||
files: () => [file1, file2, configFile],
|
||||
optionsToExtend,
|
||||
subScenario: `own file emit without errors/${subScenario}`,
|
||||
modifyFs: host => host.writeFile(file2.path, modifiedFile2Content),
|
||||
@@ -99,7 +102,7 @@ describe("unittests:: tsc-watch:: emit file --incremental", () => {
|
||||
});
|
||||
|
||||
verifyIncrementalWatchEmit({
|
||||
files: () => [libFile, file1, configFile, {
|
||||
files: () => [file1, configFile, {
|
||||
path: file2.path,
|
||||
content: `const y: string = 20;`,
|
||||
}],
|
||||
@@ -108,7 +111,7 @@ describe("unittests:: tsc-watch:: emit file --incremental", () => {
|
||||
});
|
||||
|
||||
verifyIncrementalWatchEmit({
|
||||
files: () => [libFile, file1, file2, {
|
||||
files: () => [file1, file2, {
|
||||
path: configFile.path,
|
||||
content: jsonToReadableText({ compilerOptions: { incremental: true, outFile: "out.js" } }),
|
||||
}],
|
||||
@@ -131,7 +134,7 @@ describe("unittests:: tsc-watch:: emit file --incremental", () => {
|
||||
};
|
||||
|
||||
verifyIncrementalWatchEmit({
|
||||
files: () => [libFile, file1, file2, config],
|
||||
files: () => [file1, file2, config],
|
||||
subScenario: "module compilation/own file emit without errors",
|
||||
modifyFs: host => host.writeFile(file2.path, file2.content.replace("y", "z").replace("20", "10")),
|
||||
});
|
||||
@@ -143,13 +146,16 @@ describe("unittests:: tsc-watch:: emit file --incremental", () => {
|
||||
};
|
||||
|
||||
verifyIncrementalWatchEmit({
|
||||
files: () => [libFile, file1, fileModified, config],
|
||||
files: () => [file1, fileModified, config],
|
||||
subScenario: "module compilation/own file emit with errors",
|
||||
modifyFs: host => host.writeFile(file1.path, file1.content.replace("x = 10", "z = 10")),
|
||||
});
|
||||
|
||||
it("verify that state is read correctly", () => {
|
||||
const system = createWatchedSystem([libFile, file1, fileModified, config], { currentDirectory: project });
|
||||
const system = TestServerHost.createWatchedSystem(
|
||||
[file1, fileModified, config],
|
||||
{ currentDirectory: project },
|
||||
);
|
||||
const reportDiagnostic = ts.createDiagnosticReporter(system);
|
||||
const parsedConfig = ts.parseConfigFileWithSystem("tsconfig.json", {}, /*extendedConfigCache*/ undefined, /*watchOptionsToExtend*/ undefined, system, reportDiagnostic)!;
|
||||
ts.performIncrementalCompilation({
|
||||
@@ -173,7 +179,7 @@ describe("unittests:: tsc-watch:: emit file --incremental", () => {
|
||||
assert.equal(builderProgram.state.changedFilesSet!.size, 0, "changes");
|
||||
|
||||
assert.equal(builderProgram.state.fileInfos.size, 3, "FileInfo size");
|
||||
assert.deepEqual(builderProgram.state.fileInfos.get(libFile.path as ts.Path), {
|
||||
assert.deepEqual(builderProgram.state.fileInfos.get(ts.toFileNameLowerCase(libFile.path) as ts.Path), {
|
||||
version: system.createHash(libFile.content),
|
||||
signature: system.createHash(libFile.content),
|
||||
affectsGlobalScope: true,
|
||||
@@ -201,7 +207,7 @@ describe("unittests:: tsc-watch:: emit file --incremental", () => {
|
||||
assert.equal(ts.arrayFrom(builderProgram.state.referencedMap!.keys()).length, 0);
|
||||
|
||||
assert.equal(builderProgram.state.semanticDiagnosticsPerFile.size, 3);
|
||||
assert.deepEqual(builderProgram.state.semanticDiagnosticsPerFile.get(libFile.path as ts.Path), ts.emptyArray);
|
||||
assert.deepEqual(builderProgram.state.semanticDiagnosticsPerFile.get(ts.toFileNameLowerCase(libFile.path) as ts.Path), ts.emptyArray);
|
||||
assert.deepEqual(builderProgram.state.semanticDiagnosticsPerFile.get(file1.path as ts.Path), ts.emptyArray);
|
||||
assert.deepEqual(builderProgram.state.semanticDiagnosticsPerFile.get(file2.path as ts.Path), [{
|
||||
file: builderProgram.state.program!.getSourceFileByPath(file2.path as ts.Path)!,
|
||||
@@ -220,7 +226,7 @@ describe("unittests:: tsc-watch:: emit file --incremental", () => {
|
||||
});
|
||||
|
||||
verifyIncrementalWatchEmit({
|
||||
files: () => [libFile, file1, file2, {
|
||||
files: () => [file1, file2, {
|
||||
path: configFile.path,
|
||||
content: jsonToReadableText({ compilerOptions: { incremental: true, module: "amd", outFile: "out.js" } }),
|
||||
}],
|
||||
@@ -273,7 +279,7 @@ export { B } from "./b";
|
||||
export { C } from "./c";
|
||||
`,
|
||||
};
|
||||
return [libFile, aTs, bTs, cTs, indexTs, config];
|
||||
return [aTs, bTs, cTs, indexTs, config];
|
||||
},
|
||||
subScenario: "incremental with circular references",
|
||||
modifyFs: host =>
|
||||
@@ -291,7 +297,6 @@ export interface A {
|
||||
verifyIncrementalWatchEmit({
|
||||
subScenario: "when file with ambient global declaration file is deleted",
|
||||
files: () => [
|
||||
{ path: libFile.path, content: libContent },
|
||||
{ path: `${project}/globals.d.ts`, content: `declare namespace Config { const value: string;} ` },
|
||||
{ path: `${project}/index.ts`, content: `console.log(Config.value);` },
|
||||
{ path: configFile.path, content: jsonToReadableText({ compilerOptions: { incremental: true } }) },
|
||||
@@ -317,7 +322,6 @@ export const Fragment: unique symbol;
|
||||
verifyIncrementalWatchEmit({
|
||||
subScenario: "jsxImportSource option changed",
|
||||
files: () => [
|
||||
{ path: libFile.path, content: libContent },
|
||||
{ path: `${project}/node_modules/react/jsx-runtime/index.d.ts`, content: jsxLibraryContent },
|
||||
{ path: `${project}/node_modules/react/package.json`, content: jsonToReadableText({ name: "react", version: "0.0.1" }) },
|
||||
{ path: `${project}/node_modules/preact/jsx-runtime/index.d.ts`, content: jsxLibraryContent.replace("propA", "propB") },
|
||||
@@ -332,7 +336,6 @@ export const Fragment: unique symbol;
|
||||
verifyIncrementalWatchEmit({
|
||||
subScenario: "jsxImportSource backing types added",
|
||||
files: () => [
|
||||
{ path: libFile.path, content: libContent },
|
||||
{ path: `${project}/index.tsx`, content: `export const App = () => <div propA={true}></div>;` },
|
||||
{ path: configFile.path, content: jsonToReadableText({ compilerOptions: jsxImportSourceOptions }) },
|
||||
],
|
||||
@@ -348,7 +351,6 @@ export const Fragment: unique symbol;
|
||||
verifyIncrementalWatchEmit({
|
||||
subScenario: "jsxImportSource backing types removed",
|
||||
files: () => [
|
||||
{ path: libFile.path, content: libContent },
|
||||
{ path: `${project}/node_modules/react/jsx-runtime/index.d.ts`, content: jsxLibraryContent },
|
||||
{ path: `${project}/node_modules/react/package.json`, content: jsonToReadableText({ name: "react", version: "0.0.1" }) },
|
||||
{ path: `${project}/index.tsx`, content: `export const App = () => <div propA={true}></div>;` },
|
||||
@@ -363,7 +365,6 @@ export const Fragment: unique symbol;
|
||||
verifyIncrementalWatchEmit({
|
||||
subScenario: "importHelpers backing types removed",
|
||||
files: () => [
|
||||
{ path: libFile.path, content: libContent },
|
||||
{ path: `${project}/node_modules/tslib/index.d.ts`, content: "export function __assign(...args: any[]): any;" },
|
||||
{ path: `${project}/node_modules/tslib/package.json`, content: jsonToReadableText({ name: "tslib", version: "0.0.1" }) },
|
||||
{ path: `${project}/index.tsx`, content: `export const x = {...{}};` },
|
||||
@@ -380,7 +381,6 @@ export const Fragment: unique symbol;
|
||||
verifyIncrementalWatchEmit({
|
||||
subScenario: "editing module augmentation",
|
||||
files: () => [
|
||||
{ path: libFile.path, content: libContent },
|
||||
{ path: `${project}/node_modules/classnames/index.d.ts`, content: `export interface Result {} export default function classNames(): Result;` },
|
||||
{ path: `${project}/src/types/classnames.d.ts`, content: `export {}; declare module "classnames" { interface Result { foo } }` },
|
||||
{ path: `${project}/src/index.ts`, content: `import classNames from "classnames"; classNames().foo;` },
|
||||
@@ -397,12 +397,11 @@ export const Fragment: unique symbol;
|
||||
scenario: "incremental",
|
||||
subScenario: "tsbuildinfo has error",
|
||||
sys: () =>
|
||||
createWatchedSystem({
|
||||
"/src/project/main.ts": "export const x = 10;",
|
||||
"/src/project/tsconfig.json": "{}",
|
||||
"/src/project/tsconfig.tsbuildinfo": "Some random string",
|
||||
[libFile.path]: libFile.content,
|
||||
}),
|
||||
commandLineArgs: ["--p", "src/project", "-i", "-w"],
|
||||
TestServerHost.createWatchedSystem({
|
||||
"/home/src/projects/project/main.ts": "export const x = 10;",
|
||||
"/home/src/projects/project/tsconfig.json": "{}",
|
||||
"/home/src/projects/project/tsconfig.tsbuildinfo": "Some random string",
|
||||
}, { currentDirectory: "/home/src/projects/project" }),
|
||||
commandLineArgs: ["-i", "-w"],
|
||||
});
|
||||
});
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user