X Tutup
Skip to content

Commit a4b5cb8

Browse files
vicbjeffbcross
authored andcommitted
build(node): split test and src compilation units
1 parent c785a1e commit a4b5cb8

File tree

4 files changed

+186
-46
lines changed

4 files changed

+186
-46
lines changed

modules/angular2/manual_typings/globals-es6.d.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66

77
/// <reference path="../typings/zone/zone.d.ts"/>
88
/// <reference path="../typings/hammerjs/hammerjs.d.ts"/>
9-
/// <reference path="../typings/jasmine/jasmine.d.ts"/>
10-
/// <reference path="../typings/angular-protractor/angular-protractor.d.ts"/>
119

1210
// TODO: ideally the node.d.ts reference should be scoped only for files that need and not to all
1311
// the code including client code

modules/angular2/src/common/directives/ng_switch.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import {ListWrapper, Map} from 'angular2/src/facade/collection';
44

55
const _WHEN_DEFAULT = CONST_EXPR(new Object());
66

7-
class SwitchView {
7+
/** @internal */
8+
export class SwitchView {
89
constructor(private _viewContainerRef: ViewContainerRef, private _templateRef: TemplateRef) {}
910

1011
create(): void { this._viewContainerRef.createEmbeddedView(this._templateRef); }

tools/broccoli/broccoli-typescript.ts

Lines changed: 76 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,26 @@ const FS_OPTS = {
1313
encoding: 'utf-8'
1414
};
1515

16+
// Sub-directory where the @internal typing files (.d.ts) are stored
17+
export const INTERNAL_TYPINGS_PATH: string = 'internal_typings';
18+
19+
// Monkey patch the TS compiler to be able to re-emit files with @internal symbols
20+
let tsEmitInternal: boolean = false;
21+
22+
const originalEmitFiles: Function = (<any>ts).emitFiles;
23+
24+
(<any>ts).emitFiles = function(resolver: any, host: any, targetSourceFile: any): any {
25+
if (tsEmitInternal) {
26+
const orignalgetCompilerOptions = host.getCompilerOptions;
27+
host.getCompilerOptions = () => {
28+
let options = clone(orignalgetCompilerOptions.call(host));
29+
options.stripInternal = false;
30+
options.outDir = `${options.outDir}/${INTERNAL_TYPINGS_PATH}`;
31+
return options;
32+
}
33+
}
34+
return originalEmitFiles(resolver, host, targetSourceFile);
35+
};
1636

1737
/**
1838
* Broccoli plugin that implements incremental Typescript compiler.
@@ -32,6 +52,9 @@ class DiffingTSCompiler implements DiffingBroccoliPlugin {
3252
private tsService: ts.LanguageService;
3353
private firstRun: boolean = true;
3454
private previousRunFailed: boolean = false;
55+
// Whether to generate the @internal typing files (they are only generated when `stripInternal` is
56+
// true)
57+
private genInternalTypings: boolean = false;
3558

3659
static includeExtensions = ['.ts'];
3760
static excludeExtensions = ['.d.ts'];
@@ -44,11 +67,21 @@ class DiffingTSCompiler implements DiffingBroccoliPlugin {
4467
this.rootFilePaths = [];
4568
}
4669

70+
if (options.internalTypings) {
71+
this.genInternalTypings = true;
72+
delete options.internalTypings;
73+
}
74+
4775
// the conversion is a bit awkward, see https://github.com/Microsoft/TypeScript/issues/5276
4876
// in 1.8 use convertCompilerOptionsFromJson
4977
this.tsOpts =
5078
ts.parseJsonConfigFileContent({compilerOptions: options, files: []}, null, null).options;
5179

80+
if ((<any>this.tsOpts).stripInternal === false) {
81+
// @internal are included in the generated .d.ts, do not generate them separately
82+
this.genInternalTypings = false;
83+
}
84+
5285
// TODO: the above turns rootDir set to './' into an empty string - looks like a tsc bug
5386
// check back when we upgrade to 1.7.x
5487
if (this.tsOpts.rootDir === '') {
@@ -91,6 +124,7 @@ class DiffingTSCompiler implements DiffingBroccoliPlugin {
91124
this.firstRun = false;
92125
this.doFullBuild();
93126
} else {
127+
tsEmitInternal = false;
94128
pathsToEmit.forEach((tsFilePath) => {
95129
let output = this.tsService.getEmitOutput(tsFilePath);
96130

@@ -117,11 +151,26 @@ class DiffingTSCompiler implements DiffingBroccoliPlugin {
117151
throw error;
118152
} else if (this.previousRunFailed) {
119153
this.doFullBuild();
154+
} else if (this.genInternalTypings) {
155+
// serialize the .d.ts files containing @internal symbols
156+
tsEmitInternal = true;
157+
pathsToEmit.forEach((tsFilePath) => {
158+
let output = this.tsService.getEmitOutput(tsFilePath);
159+
if (!output.emitSkipped) {
160+
output.outputFiles.forEach(o => {
161+
if (endsWith(o.name, '.d.ts')) {
162+
let destDirPath = path.dirname(o.name);
163+
fse.mkdirsSync(destDirPath);
164+
fs.writeFileSync(o.name, this.fixSourceMapSources(o.text), FS_OPTS);
165+
}
166+
});
167+
}
168+
});
169+
tsEmitInternal = false;
120170
}
121171
}
122172
}
123173

124-
125174
private collectErrors(tsFilePath): String {
126175
let allDiagnostics = this.tsService.getCompilerOptionsDiagnostics()
127176
.concat(this.tsService.getSyntacticDiagnostics(tsFilePath))
@@ -143,14 +192,27 @@ class DiffingTSCompiler implements DiffingBroccoliPlugin {
143192
}
144193
}
145194

146-
147195
private doFullBuild() {
148196
let program = this.tsService.getProgram();
197+
198+
tsEmitInternal = false;
149199
let emitResult = program.emit(undefined, (absoluteFilePath, fileContent) => {
150200
fse.mkdirsSync(path.dirname(absoluteFilePath));
151201
fs.writeFileSync(absoluteFilePath, this.fixSourceMapSources(fileContent), FS_OPTS);
152202
});
153203

204+
if (this.genInternalTypings) {
205+
// serialize the .d.ts files containing @internal symbols
206+
tsEmitInternal = true;
207+
program.emit(undefined, (absoluteFilePath, fileContent) => {
208+
if (endsWith(absoluteFilePath, '.d.ts')) {
209+
fse.mkdirsSync(path.dirname(absoluteFilePath));
210+
fs.writeFileSync(absoluteFilePath, fileContent, FS_OPTS);
211+
}
212+
});
213+
tsEmitInternal = false;
214+
}
215+
154216
if (emitResult.emitSkipped) {
155217
let allDiagnostics = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics);
156218
let errorMessages = [];
@@ -293,5 +355,16 @@ class CustomLanguageServiceHost implements ts.LanguageServiceHost {
293355
}
294356
}
295357

296-
297358
export default wrapDiffingPlugin(DiffingTSCompiler);
359+
360+
function clone<T>(object: T): T {
361+
const result: any = {};
362+
for (const id in object) {
363+
result[id] = (<any>object)[id];
364+
}
365+
return <T>result;
366+
}
367+
368+
function endsWith(str: string, substring: string): boolean {
369+
return str.indexOf(substring, str.length - substring.length) !== -1;
370+
}

tools/broccoli/trees/node_tree.ts

Lines changed: 108 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
'use strict';
22

33
import destCopy from '../broccoli-dest-copy';
4-
import compileWithTypescript from '../broccoli-typescript';
4+
import compileWithTypescript, { INTERNAL_TYPINGS_PATH }
5+
from '../broccoli-typescript';
56
var Funnel = require('broccoli-funnel');
67
import mergeTrees from '../broccoli-merge-trees';
78
var path = require('path');
@@ -11,13 +12,47 @@ var stew = require('broccoli-stew');
1112

1213
var projectRootDir = path.normalize(path.join(__dirname, '..', '..', '..', '..'));
1314

14-
1515
module.exports = function makeNodeTree(projects, destinationPath) {
1616
// list of npm packages that this build will create
1717
var outputPackages = ['angular2', 'benchpress'];
1818

19-
var modulesTree = new Funnel('modules', {
20-
include: ['angular2/**', 'benchpress/**', '**/e2e_test/**'],
19+
let srcTree = new Funnel('modules', {
20+
include: ['angular2/**'],
21+
exclude: [
22+
'**/e2e_test/**',
23+
'angular2/test/**',
24+
'angular2/examples/**',
25+
26+
'angular2/src/testing/**',
27+
'angular2/testing.ts',
28+
'angular2/testing_internal.ts',
29+
'angular2/src/upgrade/**',
30+
'angular2/upgrade.ts',
31+
'angular2/platform/testing/**',
32+
]
33+
});
34+
35+
// Compile the sources and generate the @internal .d.ts
36+
let compiledSrcTreeWithInternals =
37+
compileTree(srcTree, true, ['angular2/manual_typings/globals.d.ts']);
38+
39+
var testTree = new Funnel('modules', {
40+
include: [
41+
'angular2/manual_typings/**',
42+
'angular2/typings/**',
43+
44+
'angular2/test/**',
45+
'benchpress/**',
46+
'**/e2e_test/**',
47+
'angular2/examples/**/*_spec.ts',
48+
49+
'angular2/src/testing/**',
50+
'angular2/testing.ts',
51+
'angular2/testing_internal.ts',
52+
'angular2/src/upgrade/**',
53+
'angular2/upgrade.ts',
54+
'angular2/platform/testing/**',
55+
],
2156
exclude: [
2257
// the following code and tests are not compatible with CJS/node environment
2358
'angular2/test/animate/**',
@@ -41,58 +76,48 @@ module.exports = function makeNodeTree(projects, destinationPath) {
4176
'angular2/test/upgrade/**/*.ts',
4277

4378
'angular1_router/**',
44-
'angular2/examples/**/!(*_spec.ts)',
4579
]
4680
});
4781

48-
var typescriptTree = compileWithTypescript(modulesTree, {
49-
emitDecoratorMetadata: true,
50-
experimentalDecorators: true,
51-
declaration: true,
52-
stripInternal: true,
53-
module: 'commonjs',
54-
moduleResolution: 'classic',
55-
noEmitOnError: true,
56-
rootDir: '.',
57-
rootFilePaths:
58-
['angular2/manual_typings/globals.d.ts', 'angular2/typings/es6-shim/es6-shim.d.ts'],
59-
inlineSourceMap: true,
60-
inlineSources: true,
61-
target: 'es5'
62-
});
82+
// Compile the tests against the src @internal .d.ts
83+
let srcPrivateDeclarations =
84+
new Funnel(compiledSrcTreeWithInternals, {srcDir: INTERNAL_TYPINGS_PATH});
85+
86+
testTree = mergeTrees([testTree, srcPrivateDeclarations]);
87+
88+
let compiledTestTree = compileTree(testTree, false, [
89+
'angular2/typings/jasmine/jasmine.d.ts',
90+
'angular2/typings/angular-protractor/angular-protractor.d.ts',
91+
'angular2/manual_typings/globals.d.ts'
92+
]);
93+
94+
// Merge the compiled sources and tests
95+
let compiledSrcTree =
96+
new Funnel(compiledSrcTreeWithInternals, {exclude: [`${INTERNAL_TYPINGS_PATH}/**`]});
97+
98+
let compiledTree = mergeTrees([compiledSrcTree, compiledTestTree]);
6399

64100
// Now we add the LICENSE file into all the folders that will become npm packages
65101
outputPackages.forEach(function(destDir) {
66102
var license = new Funnel('.', {files: ['LICENSE'], destDir: destDir});
67-
typescriptTree = mergeTrees([typescriptTree, license]);
103+
// merge the test tree
104+
compiledTree = mergeTrees([compiledTree, license]);
68105
});
69106

70107
// Get all docs and related assets and prepare them for js build
71-
var docs = new Funnel(modulesTree, {include: ['**/*.md', '**/*.png'], exclude: ['**/*.dart.md']});
72-
docs = stew.rename(docs, 'README.js.md', 'README.md');
108+
var srcDocs = extractDocs(srcTree);
109+
var testDocs = extractDocs(testTree);
73110

74-
// Generate shared package.json info
75111
var BASE_PACKAGE_JSON = require(path.join(projectRootDir, 'package.json'));
76-
var COMMON_PACKAGE_JSON = {
77-
version: BASE_PACKAGE_JSON.version,
78-
homepage: BASE_PACKAGE_JSON.homepage,
79-
bugs: BASE_PACKAGE_JSON.bugs,
80-
license: BASE_PACKAGE_JSON.license,
81-
repository: BASE_PACKAGE_JSON.repository,
82-
contributors: BASE_PACKAGE_JSON.contributors,
83-
dependencies: BASE_PACKAGE_JSON.dependencies,
84-
devDependencies: BASE_PACKAGE_JSON.devDependencies,
85-
defaultDevDependencies: {}
86-
};
87-
88-
var packageJsons = new Funnel(modulesTree, {include: ['**/package.json']});
89-
packageJsons =
90-
renderLodashTemplate(packageJsons, {context: {'packageJson': COMMON_PACKAGE_JSON}});
112+
var srcPkgJsons = extractPkgJsons(srcTree, BASE_PACKAGE_JSON);
113+
var testPkgJsons = extractPkgJsons(testTree, BASE_PACKAGE_JSON);
91114

92115
var typingsTree = new Funnel(
93116
'modules',
94117
{include: ['angular2/typings/**/*.d.ts', 'angular2/manual_typings/*.d.ts'], destDir: '/'});
95-
var nodeTree = mergeTrees([typescriptTree, docs, packageJsons, typingsTree]);
118+
119+
var nodeTree =
120+
mergeTrees([compiledTree, srcDocs, testDocs, srcPkgJsons, testPkgJsons, typingsTree]);
96121

97122
// Transform all tests to make them runnable in node
98123
nodeTree = replace(nodeTree, {
@@ -132,3 +157,46 @@ module.exports = function makeNodeTree(projects, destinationPath) {
132157

133158
return destCopy(nodeTree, destinationPath);
134159
};
160+
161+
function compileTree(tree, genInternalTypings, rootFilePaths: string[] = []) {
162+
return compileWithTypescript(tree, {
163+
// build pipeline options
164+
"rootFilePaths": rootFilePaths,
165+
"internalTypings": genInternalTypings,
166+
// tsc options
167+
"emitDecoratorMetadata": true,
168+
"experimentalDecorators": true,
169+
"declaration": true,
170+
"stripInternal": true,
171+
"module": "commonjs",
172+
"moduleResolution": "classic",
173+
"noEmitOnError": true,
174+
"rootDir": ".",
175+
"inlineSourceMap": true,
176+
"inlineSources": true,
177+
"target": "es5"
178+
});
179+
}
180+
181+
function extractDocs(tree) {
182+
var docs = new Funnel(tree, {include: ['**/*.md', '**/*.png'], exclude: ['**/*.dart.md']});
183+
return stew.rename(docs, 'README.js.md', 'README.md');
184+
}
185+
186+
function extractPkgJsons(tree, BASE_PACKAGE_JSON) {
187+
// Generate shared package.json info
188+
var COMMON_PACKAGE_JSON = {
189+
version: BASE_PACKAGE_JSON.version,
190+
homepage: BASE_PACKAGE_JSON.homepage,
191+
bugs: BASE_PACKAGE_JSON.bugs,
192+
license: BASE_PACKAGE_JSON.license,
193+
repository: BASE_PACKAGE_JSON.repository,
194+
contributors: BASE_PACKAGE_JSON.contributors,
195+
dependencies: BASE_PACKAGE_JSON.dependencies,
196+
devDependencies: BASE_PACKAGE_JSON.devDependencies,
197+
defaultDevDependencies: {}
198+
};
199+
200+
var packageJsons = new Funnel(tree, {include: ['**/package.json']});
201+
return renderLodashTemplate(packageJsons, {context: {'packageJson': COMMON_PACKAGE_JSON}});
202+
}

0 commit comments

Comments
 (0)
X Tutup