mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-06-25 22:01:51 -05:00
@@ -131,6 +131,81 @@ namespace ts {
|
||||
return Extension.Js;
|
||||
}
|
||||
|
||||
function rootDirOfOptions(configFile: ParsedCommandLine) {
|
||||
return configFile.options.rootDir || getDirectoryPath(Debug.assertDefined(configFile.options.configFilePath));
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function getOutputDeclarationFileName(inputFileName: string, configFile: ParsedCommandLine, ignoreCase: boolean) {
|
||||
Debug.assert(!fileExtensionIs(inputFileName, Extension.Dts) && hasTSFileExtension(inputFileName));
|
||||
const relativePath = getRelativePathFromDirectory(rootDirOfOptions(configFile), inputFileName, ignoreCase);
|
||||
const outputPath = resolvePath(configFile.options.declarationDir || configFile.options.outDir || getDirectoryPath(Debug.assertDefined(configFile.options.configFilePath)), relativePath);
|
||||
return changeExtension(outputPath, Extension.Dts);
|
||||
}
|
||||
|
||||
function getOutputJSFileName(inputFileName: string, configFile: ParsedCommandLine, ignoreCase: boolean) {
|
||||
const relativePath = getRelativePathFromDirectory(rootDirOfOptions(configFile), inputFileName, ignoreCase);
|
||||
const outputPath = resolvePath(configFile.options.outDir || getDirectoryPath(Debug.assertDefined(configFile.options.configFilePath)), relativePath);
|
||||
const isJsonFile = fileExtensionIs(inputFileName, Extension.Json);
|
||||
const outputFileName = changeExtension(outputPath, isJsonFile ?
|
||||
Extension.Json :
|
||||
fileExtensionIs(inputFileName, Extension.Tsx) && configFile.options.jsx === JsxEmit.Preserve ?
|
||||
Extension.Jsx :
|
||||
Extension.Js);
|
||||
return !isJsonFile || comparePaths(inputFileName, outputFileName, Debug.assertDefined(configFile.options.configFilePath), ignoreCase) !== Comparison.EqualTo ?
|
||||
outputFileName :
|
||||
undefined;
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
export function getAllProjectOutputs(configFile: ParsedCommandLine, ignoreCase: boolean): ReadonlyArray<string> {
|
||||
let outputs: string[] | undefined;
|
||||
const addOutput = (path: string | undefined) => path && (outputs || (outputs = [])).push(path);
|
||||
if (configFile.options.outFile || configFile.options.out) {
|
||||
const { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, buildInfoPath } = getOutputPathsForBundle(configFile.options, /*forceDtsPaths*/ false);
|
||||
addOutput(jsFilePath);
|
||||
addOutput(sourceMapFilePath);
|
||||
addOutput(declarationFilePath);
|
||||
addOutput(declarationMapPath);
|
||||
addOutput(buildInfoPath);
|
||||
}
|
||||
else {
|
||||
for (const inputFileName of configFile.fileNames) {
|
||||
if (fileExtensionIs(inputFileName, Extension.Dts)) continue;
|
||||
const js = getOutputJSFileName(inputFileName, configFile, ignoreCase);
|
||||
addOutput(js);
|
||||
if (fileExtensionIs(inputFileName, Extension.Json)) continue;
|
||||
if (configFile.options.sourceMap) {
|
||||
addOutput(`${js}.map`);
|
||||
}
|
||||
if (getEmitDeclarations(configFile.options) && hasTSFileExtension(inputFileName)) {
|
||||
const dts = getOutputDeclarationFileName(inputFileName, configFile, ignoreCase);
|
||||
addOutput(dts);
|
||||
if (configFile.options.declarationMap) {
|
||||
addOutput(`${dts}.map`);
|
||||
}
|
||||
}
|
||||
}
|
||||
addOutput(getOutputPathForBuildInfo(configFile.options));
|
||||
}
|
||||
return outputs || emptyArray;
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
export function getFirstProjectOutput(configFile: ParsedCommandLine, ignoreCase: boolean): string {
|
||||
if (configFile.options.outFile || configFile.options.out) {
|
||||
const { jsFilePath } = getOutputPathsForBundle(configFile.options, /*forceDtsPaths*/ false);
|
||||
return Debug.assertDefined(jsFilePath, `project ${configFile.options.configFilePath} expected to have at least one output`);
|
||||
}
|
||||
|
||||
for (const inputFileName of configFile.fileNames) {
|
||||
if (fileExtensionIs(inputFileName, Extension.Dts)) continue;
|
||||
const jsFilePath = getOutputJSFileName(inputFileName, configFile, ignoreCase);
|
||||
if (jsFilePath) return jsFilePath;
|
||||
}
|
||||
return Debug.fail(`project ${configFile.options.configFilePath} expected to have at least one output`);
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
// targetSourceFile is when users only want one file in entire project to be emitted. This is used in compileOnSave feature
|
||||
export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile | undefined, emitOnlyDtsFiles?: boolean, transformers?: TransformerFactory<Bundle | SourceFile>[], declarationTransformers?: TransformerFactory<Bundle | SourceFile>[], onlyBuildInfo?: boolean): EmitResult {
|
||||
|
||||
@@ -833,7 +833,7 @@ namespace ts {
|
||||
else if (getEmitModuleKind(parsedRef.commandLine.options) === ModuleKind.None) {
|
||||
for (const fileName of parsedRef.commandLine.fileNames) {
|
||||
if (!fileExtensionIs(fileName, Extension.Dts) && hasTSFileExtension(fileName)) {
|
||||
processSourceFile(getOutputDeclarationFileName(fileName, parsedRef.commandLine), /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, /*packageId*/ undefined);
|
||||
processSourceFile(getOutputDeclarationFileName(fileName, parsedRef.commandLine, !host.useCaseSensitiveFileNames()), /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, /*packageId*/ undefined);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2378,7 +2378,7 @@ namespace ts {
|
||||
const out = referencedProject.commandLine.options.outFile || referencedProject.commandLine.options.out;
|
||||
return out ?
|
||||
changeExtension(out, Extension.Dts) :
|
||||
getOutputDeclarationFileName(fileName, referencedProject.commandLine);
|
||||
getOutputDeclarationFileName(fileName, referencedProject.commandLine, !host.useCaseSensitiveFileNames());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -276,60 +276,6 @@ namespace ts {
|
||||
return getOrCreateValueFromConfigFileMap<Map<T>>(configFileMap, resolved, createMap);
|
||||
}
|
||||
|
||||
export function getOutputDeclarationFileName(inputFileName: string, configFile: ParsedCommandLine) {
|
||||
const relativePath = getRelativePathFromDirectory(rootDirOfOptions(configFile.options, configFile.options.configFilePath!), inputFileName, /*ignoreCase*/ true);
|
||||
const outputPath = resolvePath(configFile.options.declarationDir || configFile.options.outDir || getDirectoryPath(configFile.options.configFilePath!), relativePath);
|
||||
return changeExtension(outputPath, Extension.Dts);
|
||||
}
|
||||
|
||||
function getOutputJSFileName(inputFileName: string, configFile: ParsedCommandLine) {
|
||||
const relativePath = getRelativePathFromDirectory(rootDirOfOptions(configFile.options, configFile.options.configFilePath!), inputFileName, /*ignoreCase*/ true);
|
||||
const outputPath = resolvePath(configFile.options.outDir || getDirectoryPath(configFile.options.configFilePath!), relativePath);
|
||||
const newExtension = fileExtensionIs(inputFileName, Extension.Json) ? Extension.Json :
|
||||
fileExtensionIs(inputFileName, Extension.Tsx) && configFile.options.jsx === JsxEmit.Preserve ? Extension.Jsx : Extension.Js;
|
||||
return changeExtension(outputPath, newExtension);
|
||||
}
|
||||
|
||||
function getOutputFileNames(inputFileName: string, configFile: ParsedCommandLine): ReadonlyArray<string> {
|
||||
// outFile is handled elsewhere; .d.ts files don't generate outputs
|
||||
if (configFile.options.outFile || configFile.options.out || fileExtensionIs(inputFileName, Extension.Dts)) {
|
||||
return emptyArray;
|
||||
}
|
||||
|
||||
const outputs: string[] = [];
|
||||
const js = getOutputJSFileName(inputFileName, configFile);
|
||||
outputs.push(js);
|
||||
if (configFile.options.sourceMap) {
|
||||
outputs.push(`${js}.map`);
|
||||
}
|
||||
if (getEmitDeclarations(configFile.options) && !fileExtensionIs(inputFileName, Extension.Json)) {
|
||||
const dts = getOutputDeclarationFileName(inputFileName, configFile);
|
||||
outputs.push(dts);
|
||||
if (configFile.options.declarationMap) {
|
||||
outputs.push(`${dts}.map`);
|
||||
}
|
||||
}
|
||||
return outputs;
|
||||
}
|
||||
|
||||
function getOutFileOutputs(project: ParsedCommandLine, ignoreBuildInfo?: boolean): ReadonlyArray<string> {
|
||||
Debug.assert(!!project.options.outFile || !!project.options.out, "outFile must be set");
|
||||
const { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, buildInfoPath } = getOutputPathsForBundle(project.options, /*forceDtsPaths*/ false);
|
||||
|
||||
let outputs: string[] | undefined = [];
|
||||
const addOutput = (path: string | undefined) => path && (outputs || (outputs = [])).push(path);
|
||||
addOutput(jsFilePath);
|
||||
addOutput(sourceMapFilePath);
|
||||
addOutput(declarationFilePath);
|
||||
addOutput(declarationMapPath);
|
||||
if (!ignoreBuildInfo) addOutput(buildInfoPath);
|
||||
return outputs || emptyArray;
|
||||
}
|
||||
|
||||
function rootDirOfOptions(opts: CompilerOptions, configFileName: string) {
|
||||
return opts.rootDir || getDirectoryPath(configFileName);
|
||||
}
|
||||
|
||||
function newer(date1: Date, date2: Date): Date {
|
||||
return date2 > date1 ? date2 : date1;
|
||||
}
|
||||
@@ -715,7 +661,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
// Collect the expected outputs of this project
|
||||
const outputs = getAllProjectOutputs(project);
|
||||
const outputs = getAllProjectOutputs(project, !host.useCaseSensitiveFileNames());
|
||||
|
||||
if (outputs.length === 0) {
|
||||
return {
|
||||
@@ -1202,7 +1148,7 @@ namespace ts {
|
||||
const status: Status.UpToDate = {
|
||||
type: UpToDateStatusType.UpToDate,
|
||||
newestDeclarationFileContentChangedTime: anyDtsChanged ? maximumDate : newestDeclarationFileContentChangedTime,
|
||||
oldestOutputFileName: outputFiles.length ? outputFiles[0].name : getFirstProjectOutput(configFile)
|
||||
oldestOutputFileName: outputFiles.length ? outputFiles[0].name : getFirstProjectOutput(configFile, !host.useCaseSensitiveFileNames())
|
||||
};
|
||||
diagnostics.removeKey(proj);
|
||||
projectStatus.setValue(proj, status);
|
||||
@@ -1295,13 +1241,13 @@ namespace ts {
|
||||
const status: Status.UpToDate = {
|
||||
type: UpToDateStatusType.UpToDate,
|
||||
newestDeclarationFileContentChangedTime: priorNewestUpdateTime,
|
||||
oldestOutputFileName: getFirstProjectOutput(proj)
|
||||
oldestOutputFileName: getFirstProjectOutput(proj, !host.useCaseSensitiveFileNames())
|
||||
};
|
||||
projectStatus.setValue(proj.options.configFilePath as ResolvedConfigFilePath, status);
|
||||
}
|
||||
|
||||
function updateOutputTimestampsWorker(proj: ParsedCommandLine, priorNewestUpdateTime: Date, verboseMessage: DiagnosticMessage, skipOutputs?: FileMap<true>) {
|
||||
const outputs = getAllProjectOutputs(proj);
|
||||
const outputs = getAllProjectOutputs(proj, !host.useCaseSensitiveFileNames());
|
||||
if (!skipOutputs || outputs.length !== skipOutputs.getSize()) {
|
||||
if (options.verbose) {
|
||||
reportStatus(verboseMessage, proj.options.configFilePath!);
|
||||
@@ -1337,7 +1283,7 @@ namespace ts {
|
||||
reportParseConfigFileDiagnostic(proj);
|
||||
continue;
|
||||
}
|
||||
const outputs = getAllProjectOutputs(parsed);
|
||||
const outputs = getAllProjectOutputs(parsed, !host.useCaseSensitiveFileNames());
|
||||
for (const output of outputs) {
|
||||
if (host.fileExists(output)) {
|
||||
filesToDelete.push(output);
|
||||
@@ -1499,35 +1445,6 @@ namespace ts {
|
||||
return combinePaths(project, "tsconfig.json") as ResolvedConfigFileName;
|
||||
}
|
||||
|
||||
export function getAllProjectOutputs(project: ParsedCommandLine): ReadonlyArray<string> {
|
||||
if (project.options.outFile || project.options.out) {
|
||||
return getOutFileOutputs(project);
|
||||
}
|
||||
else {
|
||||
const outputs: string[] = [];
|
||||
for (const inputFile of project.fileNames) {
|
||||
outputs.push(...getOutputFileNames(inputFile, project));
|
||||
}
|
||||
const buildInfoPath = getOutputPathForBuildInfo(project.options);
|
||||
if (buildInfoPath) outputs.push(buildInfoPath);
|
||||
return outputs;
|
||||
}
|
||||
}
|
||||
|
||||
function getFirstProjectOutput(project: ParsedCommandLine): string {
|
||||
if (project.options.outFile || project.options.out) {
|
||||
return first(getOutFileOutputs(project));
|
||||
}
|
||||
|
||||
for (const inputFile of project.fileNames) {
|
||||
const outputs = getOutputFileNames(inputFile, project);
|
||||
if (outputs.length) {
|
||||
return first(outputs);
|
||||
}
|
||||
}
|
||||
return Debug.fail(`project ${project.options.configFilePath} expected to have at least one output`);
|
||||
}
|
||||
|
||||
export function formatUpToDateStatus<T>(configFileName: string, status: UpToDateStatus, relName: (fileName: string) => string, formatMessage: (message: DiagnosticMessage, ...args: string[]) => T) {
|
||||
switch (status.type) {
|
||||
case UpToDateStatusType.OutOfDateWithSelf:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
namespace ts {
|
||||
describe("unittests:: tsbuild:: with resolveJsonModule option", () => {
|
||||
let projFs: vfs.FileSystem;
|
||||
const allExpectedOutputs = ["/src/tests/dist/src/index.js", "/src/tests/dist/src/index.d.ts", "/src/tests/dist/src/hello.json"];
|
||||
const allExpectedOutputs = ["/src/dist/src/index.js", "/src/dist/src/index.d.ts", "/src/dist/src/hello.json"];
|
||||
before(() => {
|
||||
projFs = loadProjectFromDisk("tests/projects/resolveJsonModuleAndComposite");
|
||||
});
|
||||
@@ -29,33 +29,53 @@ namespace ts {
|
||||
}
|
||||
|
||||
it("with resolveJsonModule and include only", () => {
|
||||
verifyProjectWithResolveJsonModule("/src/tests/tsconfig_withInclude.json", [
|
||||
verifyProjectWithResolveJsonModule("/src/tsconfig_withInclude.json", [
|
||||
Diagnostics.File_0_is_not_in_project_file_list_Projects_must_list_all_files_or_use_an_include_pattern,
|
||||
"/src/tests/src/hello.json"
|
||||
"/src/src/hello.json"
|
||||
]);
|
||||
});
|
||||
|
||||
it("with resolveJsonModule and include of *.json along with other include", () => {
|
||||
verifyProjectWithResolveJsonModule("/src/tests/tsconfig_withIncludeOfJson.json");
|
||||
verifyProjectWithResolveJsonModule("/src/tsconfig_withIncludeOfJson.json");
|
||||
});
|
||||
|
||||
it("with resolveJsonModule and include of *.json along with other include and file name matches ts file", () => {
|
||||
const fs = projFs.shadow();
|
||||
fs.rimrafSync("/src/tests/src/hello.json");
|
||||
fs.writeFileSync("/src/tests/src/index.json", JSON.stringify({ hello: "world" }));
|
||||
fs.writeFileSync("/src/tests/src/index.ts", `import hello from "./index.json"
|
||||
fs.rimrafSync("/src/src/hello.json");
|
||||
fs.writeFileSync("/src/src/index.json", JSON.stringify({ hello: "world" }));
|
||||
fs.writeFileSync("/src/src/index.ts", `import hello from "./index.json"
|
||||
|
||||
export default hello.hello`);
|
||||
const allExpectedOutputs = ["/src/tests/dist/src/index.js", "/src/tests/dist/src/index.d.ts", "/src/tests/dist/src/index.json"];
|
||||
verifyProjectWithResolveJsonModuleWithFs(fs, "/src/tests/tsconfig_withIncludeOfJson.json", allExpectedOutputs);
|
||||
const allExpectedOutputs = ["/src/dist/src/index.js", "/src/dist/src/index.d.ts", "/src/dist/src/index.json"];
|
||||
verifyProjectWithResolveJsonModuleWithFs(fs, "/src/tsconfig_withIncludeOfJson.json", allExpectedOutputs);
|
||||
});
|
||||
|
||||
it("with resolveJsonModule and files containing json file", () => {
|
||||
verifyProjectWithResolveJsonModule("/src/tests/tsconfig_withFiles.json");
|
||||
verifyProjectWithResolveJsonModule("/src/tsconfig_withFiles.json");
|
||||
});
|
||||
|
||||
it("with resolveJsonModule and include and files", () => {
|
||||
verifyProjectWithResolveJsonModule("/src/tests/tsconfig_withIncludeAndFiles.json");
|
||||
verifyProjectWithResolveJsonModule("/src/tsconfig_withIncludeAndFiles.json");
|
||||
});
|
||||
|
||||
it("with resolveJsonModule and sourceMap", () => {
|
||||
const fs = projFs.shadow();
|
||||
const configFile = "src/tsconfig_withFiles.json";
|
||||
replaceText(fs, configFile, `"composite": true,`, `"composite": true, "sourceMap": true,`);
|
||||
const host = new fakes.SolutionBuilderHost(fs);
|
||||
const builder = createSolutionBuilder(host, [configFile], { verbose: false });
|
||||
builder.buildAllProjects();
|
||||
host.assertDiagnosticMessages();
|
||||
for (const output of [...allExpectedOutputs, "/src/dist/src/index.js.map"]) {
|
||||
assert(fs.existsSync(output), `Expect file ${output} to exist`);
|
||||
}
|
||||
|
||||
const newBuilder = createSolutionBuilder(host, [configFile], { verbose: true });
|
||||
newBuilder.buildAllProjects();
|
||||
host.assertDiagnosticMessages(
|
||||
getExpectedDiagnosticForProjectsInBuild(configFile),
|
||||
[Diagnostics.Project_0_is_up_to_date_because_newest_input_1_is_older_than_oldest_output_2, configFile, "src/src/index.ts", "src/dist/src/index.js"]
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user