mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-10 06:41:59 -06:00
Component commits: c44de23315 Fix compileOnSaveEmit when using source of project reference redirect with --out Fixes #35226 522efb4798 Fix typo
This commit is contained in:
parent
c4d6cec389
commit
41d1ce62cd
@ -23,7 +23,7 @@ namespace ts {
|
||||
forceDtsEmit = false,
|
||||
onlyBuildInfo?: boolean,
|
||||
includeBuildInfo?: boolean) {
|
||||
const sourceFiles = isArray(sourceFilesOrTargetSourceFile) ? sourceFilesOrTargetSourceFile : getSourceFilesToEmit(host, sourceFilesOrTargetSourceFile);
|
||||
const sourceFiles = isArray(sourceFilesOrTargetSourceFile) ? sourceFilesOrTargetSourceFile : getSourceFilesToEmit(host, sourceFilesOrTargetSourceFile, forceDtsEmit);
|
||||
const options = host.getCompilerOptions();
|
||||
if (options.outFile || options.out) {
|
||||
const prepends = host.getPrependNodes();
|
||||
@ -274,7 +274,7 @@ namespace ts {
|
||||
forEachEmittedFile(
|
||||
host,
|
||||
emitSourceFileOrBundle,
|
||||
getSourceFilesToEmit(host, targetSourceFile),
|
||||
getSourceFilesToEmit(host, targetSourceFile, forceDtsEmit),
|
||||
forceDtsEmit,
|
||||
onlyBuildInfo,
|
||||
!targetSourceFile
|
||||
@ -754,6 +754,7 @@ namespace ts {
|
||||
getLibFileFromReference: notImplemented,
|
||||
isSourceFileFromExternalLibrary: returnFalse,
|
||||
getResolvedProjectReferenceToRedirect: returnUndefined,
|
||||
isSourceOfProjectReferenceRedirect: returnFalse,
|
||||
writeFile: (name, text, writeByteOrderMark) => {
|
||||
switch (name) {
|
||||
case jsFilePath:
|
||||
|
||||
@ -1010,15 +1010,9 @@ namespace ts {
|
||||
return ts.toPath(fileName, currentDirectory, getCanonicalFileName);
|
||||
}
|
||||
|
||||
function isValidSourceFileForEmit(file: SourceFile) {
|
||||
// source file is allowed to be emitted and its not source of project reference redirect
|
||||
return sourceFileMayBeEmitted(file, options, isSourceFileFromExternalLibrary, getResolvedProjectReferenceToRedirect) &&
|
||||
!isSourceOfProjectReferenceRedirect(file.fileName);
|
||||
}
|
||||
|
||||
function getCommonSourceDirectory() {
|
||||
if (commonSourceDirectory === undefined) {
|
||||
const emittedFiles = filter(files, file => isValidSourceFileForEmit(file));
|
||||
const emittedFiles = filter(files, file => sourceFileMayBeEmitted(file, program));
|
||||
if (options.rootDir && checkSourceFilesBelongToPath(emittedFiles, options.rootDir)) {
|
||||
// If a rootDir is specified use it as the commonSourceDirectory
|
||||
commonSourceDirectory = getNormalizedAbsolutePath(options.rootDir, currentDirectory);
|
||||
@ -1477,6 +1471,7 @@ namespace ts {
|
||||
getLibFileFromReference: program.getLibFileFromReference,
|
||||
isSourceFileFromExternalLibrary,
|
||||
getResolvedProjectReferenceToRedirect,
|
||||
isSourceOfProjectReferenceRedirect,
|
||||
getProbableSymlinks,
|
||||
writeFile: writeFileCallback || (
|
||||
(fileName, data, writeByteOrderMark, onError, sourceFiles) => host.writeFile(fileName, data, writeByteOrderMark, onError, sourceFiles)),
|
||||
@ -2945,7 +2940,7 @@ namespace ts {
|
||||
const rootPaths = arrayToSet(rootNames, toPath);
|
||||
for (const file of files) {
|
||||
// Ignore file that is not emitted
|
||||
if (isValidSourceFileForEmit(file) && !rootPaths.has(file.path)) {
|
||||
if (sourceFileMayBeEmitted(file, program) && !rootPaths.has(file.path)) {
|
||||
addProgramDiagnosticAtRefPath(
|
||||
file,
|
||||
rootPaths,
|
||||
|
||||
@ -5714,13 +5714,19 @@ namespace ts {
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export interface EmitHost extends ScriptReferenceHost, ModuleSpecifierResolutionHost {
|
||||
export interface SourceFileMayBeEmittedHost {
|
||||
getCompilerOptions(): CompilerOptions;
|
||||
isSourceFileFromExternalLibrary(file: SourceFile): boolean;
|
||||
getResolvedProjectReferenceToRedirect(fileName: string): ResolvedProjectReference | undefined;
|
||||
isSourceOfProjectReferenceRedirect(fileName: string): boolean;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export interface EmitHost extends ScriptReferenceHost, ModuleSpecifierResolutionHost, SourceFileMayBeEmittedHost {
|
||||
getSourceFiles(): readonly SourceFile[];
|
||||
useCaseSensitiveFileNames(): boolean;
|
||||
getCurrentDirectory(): string;
|
||||
|
||||
isSourceFileFromExternalLibrary(file: SourceFile): boolean;
|
||||
getResolvedProjectReferenceToRedirect(fileName: string): ResolvedProjectReference | undefined;
|
||||
getLibFileFromReference(ref: FileReference): SourceFile | undefined;
|
||||
|
||||
getCommonSourceDirectory(): string;
|
||||
|
||||
@ -3659,34 +3659,36 @@ namespace ts {
|
||||
* @param host An EmitHost.
|
||||
* @param targetSourceFile An optional target source file to emit.
|
||||
*/
|
||||
export function getSourceFilesToEmit(host: EmitHost, targetSourceFile?: SourceFile): readonly SourceFile[] {
|
||||
export function getSourceFilesToEmit(host: EmitHost, targetSourceFile?: SourceFile, forceDtsEmit?: boolean): readonly SourceFile[] {
|
||||
const options = host.getCompilerOptions();
|
||||
const isSourceFileFromExternalLibrary = (file: SourceFile) => host.isSourceFileFromExternalLibrary(file);
|
||||
const getResolvedProjectReferenceToRedirect = (fileName: string) => host.getResolvedProjectReferenceToRedirect(fileName);
|
||||
if (options.outFile || options.out) {
|
||||
const moduleKind = getEmitModuleKind(options);
|
||||
const moduleEmitEnabled = options.emitDeclarationOnly || moduleKind === ModuleKind.AMD || moduleKind === ModuleKind.System;
|
||||
// Can emit only sources that are not declaration file and are either non module code or module with --module or --target es6 specified
|
||||
return filter(host.getSourceFiles(), sourceFile =>
|
||||
(moduleEmitEnabled || !isExternalModule(sourceFile)) && sourceFileMayBeEmitted(sourceFile, options, isSourceFileFromExternalLibrary, getResolvedProjectReferenceToRedirect));
|
||||
return filter(
|
||||
host.getSourceFiles(),
|
||||
sourceFile =>
|
||||
(moduleEmitEnabled || !isExternalModule(sourceFile)) &&
|
||||
sourceFileMayBeEmitted(sourceFile, host, forceDtsEmit)
|
||||
);
|
||||
}
|
||||
else {
|
||||
const sourceFiles = targetSourceFile === undefined ? host.getSourceFiles() : [targetSourceFile];
|
||||
return filter(sourceFiles, sourceFile => sourceFileMayBeEmitted(sourceFile, options, isSourceFileFromExternalLibrary, getResolvedProjectReferenceToRedirect));
|
||||
return filter(
|
||||
sourceFiles,
|
||||
sourceFile => sourceFileMayBeEmitted(sourceFile, host, forceDtsEmit)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/** Don't call this for `--outFile`, just for `--outDir` or plain emit. `--outFile` needs additional checks. */
|
||||
export function sourceFileMayBeEmitted(
|
||||
sourceFile: SourceFile,
|
||||
options: CompilerOptions,
|
||||
isSourceFileFromExternalLibrary: (file: SourceFile) => boolean,
|
||||
getResolvedProjectReferenceToRedirect: (fileName: string) => ResolvedProjectReference | undefined
|
||||
) {
|
||||
export function sourceFileMayBeEmitted(sourceFile: SourceFile, host: SourceFileMayBeEmittedHost, forceDtsEmit?: boolean) {
|
||||
const options = host.getCompilerOptions();
|
||||
return !(options.noEmitForJsFiles && isSourceFileJS(sourceFile)) &&
|
||||
!sourceFile.isDeclarationFile &&
|
||||
!isSourceFileFromExternalLibrary(sourceFile) &&
|
||||
!(isJsonSourceFile(sourceFile) && getResolvedProjectReferenceToRedirect(sourceFile.fileName));
|
||||
!host.isSourceFileFromExternalLibrary(sourceFile) &&
|
||||
!(isJsonSourceFile(sourceFile) && host.getResolvedProjectReferenceToRedirect(sourceFile.fileName)) &&
|
||||
(forceDtsEmit || !host.isSourceOfProjectReferenceRedirect(sourceFile.fileName));
|
||||
}
|
||||
|
||||
export function getSourceFilePathInNewDir(fileName: string, host: EmitHost, newDirPath: string): string {
|
||||
|
||||
@ -406,4 +406,83 @@ ${appendDts}`
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("unittests:: tsserver:: with project references and compile on save with external projects", () => {
|
||||
it("compile on save emits same output as project build", () => {
|
||||
const tsbaseJson: File = {
|
||||
path: `${projectRoot}/tsbase.json`,
|
||||
content: JSON.stringify({
|
||||
compileOnSave: true,
|
||||
compilerOptions: {
|
||||
module: "none",
|
||||
composite: true
|
||||
}
|
||||
})
|
||||
};
|
||||
const buttonClass = `${projectRoot}/buttonClass`;
|
||||
const buttonConfig: File = {
|
||||
path: `${buttonClass}/tsconfig.json`,
|
||||
content: JSON.stringify({
|
||||
extends: "../tsbase.json",
|
||||
compilerOptions: {
|
||||
outFile: "Source.js"
|
||||
},
|
||||
files: ["Source.ts"]
|
||||
})
|
||||
};
|
||||
const buttonSource: File = {
|
||||
path: `${buttonClass}/Source.ts`,
|
||||
content: `module Hmi {
|
||||
export class Button {
|
||||
public static myStaticFunction() {
|
||||
}
|
||||
}
|
||||
}`
|
||||
};
|
||||
|
||||
const siblingClass = `${projectRoot}/SiblingClass`;
|
||||
const siblingConfig: File = {
|
||||
path: `${siblingClass}/tsconfig.json`,
|
||||
content: JSON.stringify({
|
||||
extends: "../tsbase.json",
|
||||
references: [{
|
||||
path: "../buttonClass/"
|
||||
}],
|
||||
compilerOptions: {
|
||||
outFile: "Source.js"
|
||||
},
|
||||
files: ["Source.ts"]
|
||||
})
|
||||
};
|
||||
const siblingSource: File = {
|
||||
path: `${siblingClass}/Source.ts`,
|
||||
content: `module Hmi {
|
||||
export class Sibling {
|
||||
public mySiblingFunction() {
|
||||
}
|
||||
}
|
||||
}`
|
||||
};
|
||||
const host = createServerHost([libFile, tsbaseJson, buttonConfig, buttonSource, siblingConfig, siblingSource], { useCaseSensitiveFileNames: true });
|
||||
|
||||
// ts build should succeed
|
||||
const solutionBuilder = tscWatch.createSolutionBuilder(host, [siblingConfig.path], {});
|
||||
solutionBuilder.build();
|
||||
assert.equal(host.getOutput().length, 0, JSON.stringify(host.getOutput(), /*replacer*/ undefined, " "));
|
||||
const sourceJs = changeExtension(siblingSource.path, ".js");
|
||||
const expectedSiblingJs = host.readFile(sourceJs);
|
||||
|
||||
const session = createSession(host);
|
||||
openFilesForSession([siblingSource], session);
|
||||
|
||||
session.executeCommandSeq<protocol.CompileOnSaveEmitFileRequest>({
|
||||
command: protocol.CommandTypes.CompileOnSaveEmitFile,
|
||||
arguments: {
|
||||
file: siblingSource.path,
|
||||
projectFileName: siblingConfig.path
|
||||
}
|
||||
});
|
||||
assert.equal(host.readFile(sourceJs), expectedSiblingJs);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user