Merge pull request #32688 from uniqueiniquity/skipCOSForDTS

Avoid compile on save when there is no emit impact
This commit is contained in:
Ben Lichtman
2019-08-07 10:44:54 -07:00
committed by GitHub
2 changed files with 126 additions and 8 deletions

View File

@@ -42,6 +42,11 @@ namespace ts.server {
return false;
}
function dtsChangeCanAffectEmit(compilationSettings: CompilerOptions) {
return getEmitDeclarations(compilationSettings) || !!compilationSettings.emitDecoratorMetadata;
}
function formatDiag(fileName: NormalizedPath, project: Project, diag: Diagnostic): protocol.Diagnostic {
const scriptInfo = project.getScriptInfoForNormalizedPath(fileName)!; // TODO: GH#18217
return {
@@ -1606,15 +1611,22 @@ namespace ts.server {
path => this.projectService.getScriptInfoForPath(path)!,
projects,
(project, info) => {
let result: protocol.CompileOnSaveAffectedFileListSingleProject | undefined;
if (project.compileOnSaveEnabled && project.languageServiceEnabled && !project.isOrphan() && !project.getCompilationSettings().noEmit) {
result = {
projectFileName: project.getProjectName(),
fileNames: project.getCompileOnSaveAffectedFileList(info),
projectUsesOutFile: !!project.getCompilationSettings().outFile || !!project.getCompilationSettings().out
};
if (!project.compileOnSaveEnabled || !project.languageServiceEnabled || project.isOrphan()) {
return undefined;
}
return result;
const compilationSettings = project.getCompilationSettings();
if (!!compilationSettings.noEmit || fileExtensionIs(info.fileName, Extension.Dts) && !dtsChangeCanAffectEmit(compilationSettings)) {
// avoid triggering emit when a change is made in a .d.ts when declaration emit and decorator metadata emit are disabled
return undefined;
}
return {
projectFileName: project.getProjectName(),
fileNames: project.getCompileOnSaveAffectedFileList(info),
projectUsesOutFile: !!compilationSettings.outFile || !!compilationSettings.out
};
}
);
}

View File

@@ -503,6 +503,112 @@ namespace ts.projectSystem {
});
});
describe("for changes in declaration files", () => {
function testDTS(dtsFileContents: string, tsFileContents: string, opts: CompilerOptions, expectDTSEmit: boolean) {
const dtsFile = {
path: "/a/runtime/a.d.ts",
content: dtsFileContents
};
const f2 = {
path: "/a/b.ts",
content: tsFileContents
};
const config = {
path: "/a/tsconfig.json",
content: JSON.stringify({
compilerOptions: opts,
compileOnSave: true
})
};
const host = createServerHost([dtsFile, f2, config]);
const session = projectSystem.createSession(host);
session.executeCommand(<protocol.OpenRequest>{
seq: 1,
type: "request",
command: "open",
arguments: { file: dtsFile.path }
});
const projectService = session.getProjectService();
checkNumberOfProjects(projectService, { configuredProjects: 1 });
const project = projectService.configuredProjects.get(config.path)!;
checkProjectRootFiles(project, [dtsFile.path, f2.path]);
session.executeCommand(<protocol.OpenRequest>{
seq: 2,
type: "request",
command: "open",
arguments: { file: f2.path }
});
checkNumberOfProjects(session.getProjectService(), { configuredProjects: 1 });
const { response } = session.executeCommand(<protocol.CompileOnSaveAffectedFileListRequest>{
seq: 3,
type: "request",
command: "compileOnSaveAffectedFileList",
arguments: { file: dtsFile.path }
});
if (expectDTSEmit) {
assert.equal((response as protocol.CompileOnSaveAffectedFileListSingleProject[]).length, 1, "expected output from 1 project");
assert.equal((response as protocol.CompileOnSaveAffectedFileListSingleProject[])[0].fileNames.length, 2, "expected to affect 2 files");
}
else {
assert.equal((response as protocol.CompileOnSaveAffectedFileListSingleProject[]).length, 0, "expected no output");
}
const { response: response2 } = session.executeCommand(<protocol.CompileOnSaveAffectedFileListRequest>{
seq: 4,
type: "request",
command: "compileOnSaveAffectedFileList",
arguments: { file: f2.path }
});
assert.equal((response2 as protocol.CompileOnSaveAffectedFileListSingleProject[]).length, 1, "expected output from 1 project");
}
it("should return empty array if change is made in a global declaration file", () => {
testDTS(
/*dtsFileContents*/ "declare const x: string;",
/*tsFileContents*/ "var y = 1;",
/*opts*/ {},
/*expectDTSEmit*/ false
);
});
it("should return empty array if change is made in a module declaration file", () => {
testDTS(
/*dtsFileContents*/ "export const x: string;",
/*tsFileContents*/ "import { x } from './runtime/a;",
/*opts*/ {},
/*expectDTSEmit*/ false
);
});
it("should return results if change is made in a global declaration file with declaration emit", () => {
testDTS(
/*dtsFileContents*/ "declare const x: string;",
/*tsFileContents*/ "var y = 1;",
/*opts*/ { declaration: true },
/*expectDTSEmit*/ true
);
});
it("should return results if change is made in a global declaration file with composite enabled", () => {
testDTS(
/*dtsFileContents*/ "declare const x: string;",
/*tsFileContents*/ "var y = 1;",
/*opts*/ { composite: true },
/*expectDTSEmit*/ true
);
});
it("should return results if change is made in a global declaration file with decorator emit enabled", () => {
testDTS(
/*dtsFileContents*/ "declare const x: string;",
/*tsFileContents*/ "var y = 1;",
/*opts*/ { experimentalDecorators: true, emitDecoratorMetadata: true },
/*expectDTSEmit*/ true
);
});
});
describe("tsserverProjectSystem emit with outFile or out setting", () => {
function test(opts: CompilerOptions, expectedUsesOutFile: boolean) {
const f1 = {