Skip to content

Commit 95e9c2b

Browse files
authored
Merge pull request #579 from rbuckton/projectReferences
Add support for TS3.0 projectReferences
2 parents 36ff1f5 + 80ffc3d commit 95e9c2b

36 files changed

+1049
-880
lines changed

.gitmodules

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,7 @@
1111
[submodule "typescript/2.9"]
1212
path = typescript/2.9
1313
url = https://github.com/Microsoft/TypeScript
14+
[submodule "typescript/2.7"]
15+
path = typescript/2.7
16+
url = https://github.com/Microsoft/TypeScript.git
17+
branch = release-2.7

gulpfile.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const diff = require('gulp-diff');
1111
const tsVersions = {
1212
dev: './typescript/dev',
1313
release23: './typescript/2.3',
14+
release27: './typescript/2.7',
1415
release29: './typescript/2.9'
1516
};
1617

@@ -74,7 +75,7 @@ const typecheck = gulp.parallel(typecheckDev, typecheck2_3);
7475

7576
// We run every test on multiple typescript versions:
7677
const libs = [
77-
['2.7', undefined],
78+
['2.7', require(tsVersions.release27)],
7879
['2.3', require(tsVersions.release23)],
7980
['2.9', require(tsVersions.release29)],
8081
['dev', require(tsVersions.dev)]
@@ -97,8 +98,11 @@ async function runTest(name) {
9798
const newGulpTs = require('./release-2/main');
9899
const testTask = require(`./${path.posix.join(testDir, 'gulptask.js')}`);
99100

101+
const matchingLibs = testTask.match ? libs.filter(([, tsLib]) => testTask.match(tsLib)) : libs;
102+
if (matchingLibs.length === 0) return Promise.resolve();
103+
100104
fs.mkdirSync(outputDir);
101-
return Promise.all(libs.map(([tsVersion, tsLib]) => {
105+
return Promise.all(matchingLibs.map(([tsVersion, tsLib]) => {
102106
return new Promise((resolve, reject) => {
103107
const errors = [];
104108
let finishInfo;

lib/compiler.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,17 @@ export class ProjectCompiler implements ICompiler {
7272
this.project.options
7373
);
7474

75-
this.program = this.project.typescript.createProgram(rootFilenames, this.project.options, this.host, this.program);
75+
// Calling `createProgram` with an object is only supported in 3.0. Only call this overload
76+
// if we have project references (also only supported in 3.0)
77+
this.program = this.project.projectReferences
78+
? this.project.typescript.createProgram({
79+
rootNames: rootFilenames,
80+
options: this.project.options,
81+
projectReferences: this.project.projectReferences,
82+
host: this.host,
83+
oldProgram: this.program
84+
})
85+
: this.project.typescript.createProgram(rootFilenames, this.project.options, this.host, this.program);
7686

7787
const result = emptyCompilationResult(this.project.options.noEmit);
7888
result.optionsErrors = this.reportDiagnostics(this.program.getOptionsDiagnostics());

lib/main.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ module compile {
151151
let projectDirectory = process.cwd();
152152
let typescript: typeof ts;
153153
let compilerOptions: ts.CompilerOptions;
154+
let projectReferences: ReadonlyArray<ts.ProjectReference>;
154155
let fileName: string;
155156

156157
let rawConfig: any;
@@ -199,11 +200,12 @@ module compile {
199200
}
200201

201202
compilerOptions = parsed.options;
203+
projectReferences = parsed.projectReferences;
202204
}
203205
}
204206

205207
normalizeCompilerOptions(compilerOptions, typescript);
206-
const project = _project.setupProject(projectDirectory, tsConfigFileName, rawConfig, tsConfigContent, compilerOptions, typescript);
208+
const project = _project.setupProject(projectDirectory, tsConfigFileName, rawConfig, tsConfigContent, compilerOptions, projectReferences, typescript);
207209

208210
return project;
209211
}

lib/output.ts

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ export class Output {
2929
private pendingIO = 0;
3030

3131
writeJs(base: string, fileName: string, content: string, sourceMapContent: string, cwd: string, original: input.File) {
32+
this.pipeRejection(this.writeJsAsync(base, fileName, content, sourceMapContent, cwd, original), this.streamJs);
33+
}
34+
35+
private async writeJsAsync(base: string, fileName: string, content: string, sourceMapContent: string, cwd: string, original: input.File) {
3236
const file = new VinylFile({
3337
path: fileName,
3438
contents: Buffer.from(content),
@@ -38,7 +42,7 @@ export class Output {
3842

3943
this.pendingIO++;
4044

41-
this.applySourceMap(sourceMapContent, original, file).then(appliedSourceMap => {
45+
await this.applySourceMap(sourceMapContent, original, file).then(appliedSourceMap => {
4246
if (appliedSourceMap) file.sourceMap = JSON.parse(appliedSourceMap);
4347
this.streamFull.push(file);
4448
this.streamJs.push(file);
@@ -48,7 +52,11 @@ export class Output {
4852
});
4953
}
5054

51-
async writeDts(base: string, fileName: string, content: string, declarationMapContent: string, cwd: string, original: input.File) {
55+
writeDts(base: string, fileName: string, content: string, declarationMapContent: string, cwd: string, original: input.File) {
56+
this.pipeRejection(this.writeDtsAsync(base, fileName, content, declarationMapContent, cwd, original), this.streamDts);
57+
}
58+
59+
private async writeDtsAsync(base: string, fileName: string, content: string, declarationMapContent: string, cwd: string, original: input.File) {
5260
const file = new VinylFile({
5361
path: fileName,
5462
contents: Buffer.from(content),
@@ -58,7 +66,7 @@ export class Output {
5866

5967
this.pendingIO++;
6068

61-
this.applySourceMap(declarationMapContent, original, file).then(appliedSourceMap => {
69+
await this.applySourceMap(declarationMapContent, original, file).then(appliedSourceMap => {
6270
if (appliedSourceMap) file.sourceMap = JSON.parse(appliedSourceMap);
6371
this.streamFull.push(file);
6472
this.streamDts.push(file);
@@ -118,12 +126,20 @@ export class Output {
118126
}
119127
}
120128

129+
// Avoids UnhandledPromiseRejectionWarning in NodeJS
130+
private pipeRejection<T>(promise: Promise<T>, alternateStream: stream.Readable) {
131+
promise.catch(err => {
132+
this.streamFull.emit("error", err);
133+
alternateStream.emit("error", err);
134+
});
135+
}
136+
121137
finish(result: reporter.CompilationResult) {
122138
this.result = result;
123139

124140
this.mightFinish();
125141
}
126-
142+
127143
private mightFinish() {
128144
if (this.result === undefined || this.pendingIO !== 0) return;
129145

lib/project.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ interface PartialProject {
2222
rawConfig?: any;
2323
config?: TsConfig;
2424
options?: ts.CompilerOptions;
25+
projectReferences?: ReadonlyArray<ts.ProjectReference>;
2526
}
2627
export interface Project {
2728
(reporter?: Reporter): ICompileStream;
@@ -34,6 +35,7 @@ export interface Project {
3435
readonly rawConfig: any;
3536
readonly config: TsConfig;
3637
readonly options: ts.CompilerOptions;
38+
readonly projectReferences: ReadonlyArray<ts.ProjectReference> | undefined;
3739
}
3840

3941
export interface ProjectInfo {
@@ -42,12 +44,13 @@ export interface ProjectInfo {
4244
compiler: ICompiler;
4345
singleOutput: boolean;
4446
options: ts.CompilerOptions;
47+
projectReferences: ReadonlyArray<ts.ProjectReference>;
4548
typescript: typeof ts;
4649
directory: string;
4750
reporter: Reporter;
4851
}
4952

50-
export function setupProject(projectDirectory: string, configFileName: string, rawConfig: any, config: TsConfig, options: ts.CompilerOptions, typescript: typeof ts) {
53+
export function setupProject(projectDirectory: string, configFileName: string, rawConfig: any, config: TsConfig, options: ts.CompilerOptions, projectReferences: ReadonlyArray<ts.ProjectReference>, typescript: typeof ts) {
5154
const input = new FileCache(typescript, options);
5255
const compiler: ICompiler = options.isolatedModules ? new FileCompiler() : new ProjectCompiler();
5356
let running = false;
@@ -88,12 +91,14 @@ export function setupProject(projectDirectory: string, configFileName: string, r
8891
project.rawConfig = rawConfig;
8992
project.config = config;
9093
project.options = options;
94+
project.projectReferences = projectReferences;
9195

9296
const projectInfo: ProjectInfo = {
9397
input,
9498
singleOutput,
9599
compiler,
96100
options,
101+
projectReferences,
97102
typescript,
98103
directory: projectDirectory,
99104
// Set when `project` is called

0 commit comments

Comments
 (0)