chore(lint): format tools dir
This commit is contained in:
parent
5936624d11
commit
9096481744
10
DEVELOPER.md
10
DEVELOPER.md
|
@ -238,17 +238,17 @@ repository, allowing many tools and editors to share our settings.
|
|||
|
||||
To check the formatting of your code, run
|
||||
|
||||
gulp check-format
|
||||
gulp lint
|
||||
|
||||
Note that the continuous build on Travis runs `gulp enforce-format`. Unlike the `check-format` task,
|
||||
this will actually fail the build if files aren't formatted according to the style guide.
|
||||
Note that the continuous build on CircleCI will fail the build if files aren't formatted according
|
||||
to the style guide.
|
||||
|
||||
Your life will be easier if you include the formatter in your standard workflow. Otherwise, you'll
|
||||
likely forget to check the formatting, and waste time waiting for a build on Travis that fails due
|
||||
to some whitespace difference.
|
||||
|
||||
* Use `$(npm bin)/clang-format -i [file name]` to format a file (or multiple).
|
||||
* Use `gulp enforce-format` to check if your code is `clang-format` clean. This also gives
|
||||
* Use `gulp format` to format everything.
|
||||
* Use `gulp lint` to check if your code is `clang-format` clean. This also gives
|
||||
you a command line to format your code.
|
||||
* `clang-format` also includes a git hook, run `git clang-format` to format all files you
|
||||
touched.
|
||||
|
|
|
@ -11,10 +11,7 @@ export type ProjectMap = {
|
|||
};
|
||||
|
||||
export type Options = {
|
||||
projects: ProjectMap;
|
||||
noTypeChecks: boolean;
|
||||
generateEs6: boolean;
|
||||
useBundles: boolean;
|
||||
projects: ProjectMap; noTypeChecks: boolean; generateEs6: boolean; useBundles: boolean;
|
||||
};
|
||||
|
||||
export interface AngularBuilderOptions {
|
||||
|
@ -133,14 +130,16 @@ export class AngularBuilder {
|
|||
writeBuildLog(result, name);
|
||||
return result;
|
||||
},
|
||||
(error): any => {
|
||||
// the build tree is the same during rebuilds, only leaf properties of the nodes change
|
||||
// so let's traverse it and get updated values for input/cache/output paths
|
||||
if (this.firstResult) {
|
||||
writeBuildLog(this.firstResult, name);
|
||||
}
|
||||
throw error;
|
||||
});
|
||||
(error):
|
||||
any => {
|
||||
// the build tree is the same during rebuilds, only leaf properties of the nodes
|
||||
// change
|
||||
// so let's traverse it and get updated values for input/cache/output paths
|
||||
if (this.firstResult) {
|
||||
writeBuildLog(this.firstResult, name);
|
||||
}
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -159,16 +158,17 @@ function writeBuildLog(result: BuildResult, name: string) {
|
|||
function broccoliNodeToBuildNode(broccoliNode: BroccoliNode): BuildNode {
|
||||
let tree = broccoliNode.tree.newStyleTree || broccoliNode.tree;
|
||||
|
||||
return new BuildNode(tree.description || (<any>tree.constructor).name,
|
||||
tree.inputPath ? [tree.inputPath] : tree.inputPaths, tree.cachePath,
|
||||
tree.outputPath, broccoliNode.selfTime / (1000 * 1000 * 1000),
|
||||
broccoliNode.totalTime / (1000 * 1000 * 1000),
|
||||
broccoliNode.subtrees.map(broccoliNodeToBuildNode));
|
||||
return new BuildNode(
|
||||
tree.description || (<any>tree.constructor).name,
|
||||
tree.inputPath ? [tree.inputPath] : tree.inputPaths, tree.cachePath, tree.outputPath,
|
||||
broccoliNode.selfTime / (1000 * 1000 * 1000), broccoliNode.totalTime / (1000 * 1000 * 1000),
|
||||
broccoliNode.subtrees.map(broccoliNodeToBuildNode));
|
||||
}
|
||||
|
||||
|
||||
class BuildNode {
|
||||
constructor(public pluginName: string, public inputPaths: string[], public cachePath: string,
|
||||
public outputPath: string, public selfTime: number, public totalTime: number,
|
||||
public inputNodes: BuildNode[]) {}
|
||||
constructor(
|
||||
public pluginName: string, public inputPaths: string[], public cachePath: string,
|
||||
public outputPath: string, public selfTime: number, public totalTime: number,
|
||||
public inputNodes: BuildNode[]) {}
|
||||
}
|
||||
|
|
|
@ -9,16 +9,16 @@ import {wrapDiffingPlugin, DiffingBroccoliPlugin, DiffResult} from './diffing-br
|
|||
* This guarantees that platform-independent modules remain platoform-independent.
|
||||
*/
|
||||
class CheckImports implements DiffingBroccoliPlugin {
|
||||
static IMPORT_DECL_REGEXP = new RegExp(`^import[^;]+;`, "mg");
|
||||
static IMPORT_PATH_REGEXP = new RegExp(`['"]([^'"]+)+['"]`, "m");
|
||||
static IMPORT_DECL_REGEXP = new RegExp(`^import[^;]+;`, 'mg');
|
||||
static IMPORT_PATH_REGEXP = new RegExp(`['"]([^'"]+)+['"]`, 'm');
|
||||
|
||||
static ALLOWED_IMPORTS: {[s: string]: string[]} = {
|
||||
"angular2/src/core": ["angular2/src/facade"],
|
||||
"angular2/src/facade": ["rxjs"],
|
||||
"angular2/src/common": ["angular2/core", "angular2/src/facade"],
|
||||
"angular2/src/http": ["angular2/core", "angular2/src/facade", "rxjs"],
|
||||
"angular2/src/upgrade":
|
||||
["angular2/core", "angular2/src/facade", "angular2/platform/browser", "angular2/compiler"]
|
||||
'angular2/src/core': ['angular2/src/facade'],
|
||||
'angular2/src/facade': ['rxjs'],
|
||||
'angular2/src/common': ['angular2/core', 'angular2/src/facade'],
|
||||
'angular2/src/http': ['angular2/core', 'angular2/src/facade', 'rxjs'],
|
||||
'angular2/src/upgrade':
|
||||
['angular2/core', 'angular2/src/facade', 'angular2/platform/browser', 'angular2/compiler']
|
||||
//"angular2/src/render": [
|
||||
// "angular2/animate",
|
||||
// "angular2/core",
|
||||
|
@ -55,8 +55,8 @@ class CheckImports implements DiffingBroccoliPlugin {
|
|||
|
||||
private checkFilePath(filePath: string) {
|
||||
const sourceFilePath = path.join(this.inputPath, filePath);
|
||||
if (endsWith(sourceFilePath, ".ts") && fs.existsSync(sourceFilePath)) {
|
||||
const content = fs.readFileSync(sourceFilePath, "UTF-8");
|
||||
if (endsWith(sourceFilePath, '.ts') && fs.existsSync(sourceFilePath)) {
|
||||
const content = fs.readFileSync(sourceFilePath, 'UTF-8');
|
||||
const imports = content.match(CheckImports.IMPORT_DECL_REGEXP);
|
||||
if (imports) {
|
||||
return imports.filter(i => !this.isAllowedImport(filePath, i))
|
||||
|
@ -73,14 +73,14 @@ class CheckImports implements DiffingBroccoliPlugin {
|
|||
if (!res || res.length < 2) return true; // non-es6 import
|
||||
const importPath = res[1];
|
||||
|
||||
if (startsWith(importPath, "./") || startsWith(importPath, "../")) return true;
|
||||
if (startsWith(importPath, './') || startsWith(importPath, '../')) return true;
|
||||
|
||||
const c = CheckImports.ALLOWED_IMPORTS;
|
||||
for (var prop in c) {
|
||||
if (c.hasOwnProperty(prop) && startsWith(sourceFile, prop)) {
|
||||
const allowedPaths = c[prop];
|
||||
return startsWith(importPath, prop) ||
|
||||
allowedPaths.filter(p => startsWith(importPath, p)).length > 0;
|
||||
allowedPaths.filter(p => startsWith(importPath, p)).length > 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -88,7 +88,7 @@ class CheckImports implements DiffingBroccoliPlugin {
|
|||
}
|
||||
|
||||
private formatError(filePath: string, importPath: string): string {
|
||||
const i = importPath.replace(new RegExp(`\n`, 'g'), "\\n");
|
||||
const i = importPath.replace(new RegExp(`\n`, 'g'), '\\n');
|
||||
return `${filePath}: ${i}`;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ class DartFormatter implements DiffingBroccoliPlugin {
|
|||
private firstBuild: boolean = true;
|
||||
|
||||
constructor(public inputPath: string, public cachePath: string, options: AngularBuilderOptions) {
|
||||
if (!options.dartSDK) throw new Error("Missing Dart SDK");
|
||||
if (!options.dartSDK) throw new Error('Missing Dart SDK');
|
||||
this.DARTFMT = options.dartSDK.DARTFMT;
|
||||
this.verbose = options.logs.dartfmt;
|
||||
}
|
||||
|
@ -34,22 +34,21 @@ class DartFormatter implements DiffingBroccoliPlugin {
|
|||
let argsLength = 2;
|
||||
let argPackages: string[][] = [];
|
||||
let firstBuild = this.firstBuild;
|
||||
treeDiff.addedPaths.concat(treeDiff.changedPaths)
|
||||
.forEach((changedFile) => {
|
||||
let sourcePath = path.join(this.inputPath, changedFile);
|
||||
let destPath = path.join(this.cachePath, changedFile);
|
||||
if (!firstBuild && /\.dart$/.test(changedFile)) {
|
||||
if ((argsLength + destPath.length + 2) >= 0x2000) {
|
||||
// Win32 command line arguments length
|
||||
argPackages.push(args);
|
||||
args = ['-w'];
|
||||
argsLength = 2;
|
||||
}
|
||||
args.push(destPath);
|
||||
argsLength += destPath.length + 2;
|
||||
}
|
||||
fse.copySync(sourcePath, destPath);
|
||||
});
|
||||
treeDiff.addedPaths.concat(treeDiff.changedPaths).forEach((changedFile) => {
|
||||
let sourcePath = path.join(this.inputPath, changedFile);
|
||||
let destPath = path.join(this.cachePath, changedFile);
|
||||
if (!firstBuild && /\.dart$/.test(changedFile)) {
|
||||
if ((argsLength + destPath.length + 2) >= 0x2000) {
|
||||
// Win32 command line arguments length
|
||||
argPackages.push(args);
|
||||
args = ['-w'];
|
||||
argsLength = 2;
|
||||
}
|
||||
args.push(destPath);
|
||||
argsLength += destPath.length + 2;
|
||||
}
|
||||
fse.copySync(sourcePath, destPath);
|
||||
});
|
||||
treeDiff.removedPaths.forEach((removedFile) => {
|
||||
let destPath = path.join(this.cachePath, removedFile);
|
||||
fse.removeSync(destPath);
|
||||
|
@ -60,8 +59,7 @@ class DartFormatter implements DiffingBroccoliPlugin {
|
|||
}
|
||||
|
||||
let execute = (args: string[]) => {
|
||||
if (args.length < 2)
|
||||
return Promise.resolve();
|
||||
if (args.length < 2) return Promise.resolve();
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
exec(this.DARTFMT + ' ' + args.join(' '), (err: Error, stdout: string, stderr: string) => {
|
||||
if (this.verbose) {
|
||||
|
|
|
@ -12,14 +12,13 @@ class DestCopy implements DiffingBroccoliPlugin {
|
|||
|
||||
|
||||
rebuild(treeDiff: DiffResult) {
|
||||
treeDiff.addedPaths.concat(treeDiff.changedPaths)
|
||||
.forEach((changedFilePath) => {
|
||||
var destFilePath = path.join(this.outputRoot, changedFilePath);
|
||||
treeDiff.addedPaths.concat(treeDiff.changedPaths).forEach((changedFilePath) => {
|
||||
var destFilePath = path.join(this.outputRoot, changedFilePath);
|
||||
|
||||
var destDirPath = path.dirname(destFilePath);
|
||||
fse.mkdirsSync(destDirPath);
|
||||
fse.copySync(path.join(this.inputPath, changedFilePath), destFilePath);
|
||||
});
|
||||
var destDirPath = path.dirname(destFilePath);
|
||||
fse.mkdirsSync(destDirPath);
|
||||
fse.copySync(path.join(this.inputPath, changedFilePath), destFilePath);
|
||||
});
|
||||
|
||||
treeDiff.removedPaths.forEach((removedFilePath) => {
|
||||
var destFilePath = path.join(this.outputRoot, removedFilePath);
|
||||
|
|
|
@ -8,10 +8,10 @@ describe('Flatten', () => {
|
|||
afterEach(() => mockfs.restore());
|
||||
|
||||
let flatten = (inputPaths: string) => new DiffingFlatten(inputPaths, 'output', null);
|
||||
let read = (path: string) => fs.readFileSync(path, {encoding: "utf-8"});
|
||||
let read = (path: string) => fs.readFileSync(path, {encoding: 'utf-8'});
|
||||
let rm = (path: string) => fs.unlinkSync(path);
|
||||
let write =
|
||||
(path: string, content: string) => { fs.writeFileSync(path, content, {encoding: "utf-8"}); }
|
||||
(path: string, content: string) => { fs.writeFileSync(path, content, {encoding: 'utf-8'}); }
|
||||
|
||||
|
||||
it('should flatten files and be incremental', () => {
|
||||
|
@ -67,7 +67,8 @@ describe('Flatten', () => {
|
|||
let differ = new TreeDiffer('testLabel', 'input');
|
||||
let flattenedTree = flatten('input');
|
||||
expect(() => flattenedTree.rebuild(differ.diffTree()))
|
||||
.toThrowError("Duplicate file 'file-1.txt' found in path 'dir1" + path.sep + "subdir-1" +
|
||||
path.sep + "file-1.txt'");
|
||||
.toThrowError(
|
||||
'Duplicate file \'file-1.txt\' found in path \'dir1' + path.sep + 'subdir-1' +
|
||||
path.sep + 'file-1.txt\'');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -14,8 +14,9 @@ var isWindows = process.platform === 'win32';
|
|||
* the associated changes.
|
||||
*/
|
||||
export class DiffingFlatten implements DiffingBroccoliPlugin {
|
||||
constructor(private inputPath: string, private cachePath: string,
|
||||
private options: AngularBuilderOptions) {}
|
||||
constructor(
|
||||
private inputPath: string, private cachePath: string,
|
||||
private options: AngularBuilderOptions) {}
|
||||
|
||||
|
||||
rebuild(treeDiff: DiffResult) {
|
||||
|
@ -39,8 +40,9 @@ export class DiffingFlatten implements DiffingBroccoliPlugin {
|
|||
if (!fs.existsSync(destFilePath)) {
|
||||
symlinkOrCopy(sourceFilePath, destFilePath);
|
||||
} else {
|
||||
throw new Error(`Duplicate file '${path.basename(changedFilePath)}' ` +
|
||||
`found in path '${changedFilePath}'`);
|
||||
throw new Error(
|
||||
`Duplicate file '${path.basename(changedFilePath)}' ` +
|
||||
`found in path '${changedFilePath}'`);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -13,23 +13,26 @@ import {wrapDiffingPlugin, DiffingBroccoliPlugin, DiffResult} from './diffing-br
|
|||
class GeneratorForTest implements DiffingBroccoliPlugin {
|
||||
private seenFiles: {[key: string]: boolean} = {};
|
||||
|
||||
constructor(private inputPath: string, private outputPath: string,
|
||||
private options: { files: string[], dartPath: string }) {}
|
||||
constructor(private inputPath: string, private outputPath: string, private options: {
|
||||
files: string[],
|
||||
dartPath: string
|
||||
}) {}
|
||||
|
||||
rebuild(treeDiff: DiffResult) {
|
||||
var matchedFiles: string[] = [];
|
||||
this.options.files.forEach(
|
||||
(file) => { matchedFiles = matchedFiles.concat(glob.sync(file, {cwd: this.inputPath})); });
|
||||
return Promise.all(matchedFiles.map((matchedFile) => {
|
||||
var inputFilePath = path.join(this.inputPath, matchedFile);
|
||||
var outputFilePath = path.join(this.outputPath, matchedFile);
|
||||
return Promise
|
||||
.all(matchedFiles.map((matchedFile) => {
|
||||
var inputFilePath = path.join(this.inputPath, matchedFile);
|
||||
var outputFilePath = path.join(this.outputPath, matchedFile);
|
||||
|
||||
var outputDirPath = path.dirname(outputFilePath);
|
||||
if (!fs.existsSync(outputDirPath)) {
|
||||
fse.mkdirpSync(outputDirPath);
|
||||
}
|
||||
return this.invokeGenerator(matchedFile, inputFilePath, outputFilePath)
|
||||
}))
|
||||
var outputDirPath = path.dirname(outputFilePath);
|
||||
if (!fs.existsSync(outputDirPath)) {
|
||||
fse.mkdirpSync(outputDirPath);
|
||||
}
|
||||
return this.invokeGenerator(matchedFile, inputFilePath, outputFilePath)
|
||||
}))
|
||||
.then(() => {
|
||||
var result = new DiffResult();
|
||||
matchedFiles.forEach((file) => {
|
||||
|
@ -44,8 +47,8 @@ class GeneratorForTest implements DiffingBroccoliPlugin {
|
|||
});
|
||||
}
|
||||
|
||||
private invokeGenerator(file: string, inputFilePath: string,
|
||||
outputFilePath: string): Promise<any> {
|
||||
private invokeGenerator(file: string, inputFilePath: string, outputFilePath: string):
|
||||
Promise<any> {
|
||||
return new Promise((resolve, reject) => {
|
||||
var args: string[];
|
||||
var vmPath: string;
|
||||
|
@ -62,15 +65,14 @@ class GeneratorForTest implements DiffingBroccoliPlugin {
|
|||
}
|
||||
|
||||
var stdoutStream = fs.createWriteStream(outputFilePath);
|
||||
var proc = childProcess.spawn(
|
||||
vmPath, args,
|
||||
{ stdio: ['ignore', 'pipe', 'inherit'],
|
||||
env: (<any>Object)['assign']({}, process.env, env)
|
||||
});
|
||||
var proc = childProcess.spawn(vmPath, args, {
|
||||
stdio: ['ignore', 'pipe', 'inherit'],
|
||||
env: (<any>Object)['assign']({}, process.env, env)
|
||||
});
|
||||
proc.on('error', function(code: any) {
|
||||
console.error(code);
|
||||
reject(new Error('Failed while generating code. Please run manually: ' + vmPath + ' ' +
|
||||
args.join(' ')));
|
||||
reject(new Error(
|
||||
'Failed while generating code. Please run manually: ' + vmPath + ' ' + args.join(' ')));
|
||||
});
|
||||
proc.on('close', function() {
|
||||
stdoutStream.close();
|
||||
|
|
|
@ -23,8 +23,9 @@ const kDefaultOptions: LodashRendererOptions = {
|
|||
* the associated changes.
|
||||
*/
|
||||
export class LodashRenderer implements DiffingBroccoliPlugin {
|
||||
constructor(private inputPath: string, private cachePath: string,
|
||||
private options: LodashRendererOptions = kDefaultOptions) {}
|
||||
constructor(
|
||||
private inputPath: string, private cachePath: string,
|
||||
private options: LodashRendererOptions = kDefaultOptions) {}
|
||||
|
||||
rebuild(treeDiff: DiffResult) {
|
||||
let {encoding = 'utf-8', context = {}} = this.options;
|
||||
|
|
|
@ -15,7 +15,7 @@ describe('MergeTrees', () => {
|
|||
}
|
||||
|
||||
let diffTrees = (differs: TreeDiffer[]): DiffResult[] => differs.map(tree => tree.diffTree());
|
||||
function read(path: string) { return fs.readFileSync(path, "utf-8"); }
|
||||
function read(path: string) { return fs.readFileSync(path, 'utf-8'); }
|
||||
|
||||
it('should copy the file from the right-most inputTree with overwrite=true', () => {
|
||||
let testDir: any = {
|
||||
|
|
|
@ -24,8 +24,8 @@ export class MergeTrees implements DiffingBroccoliPlugin {
|
|||
public options: MergeTreesOptions;
|
||||
private firstBuild: boolean = true;
|
||||
|
||||
constructor(public inputPaths: string[], public cachePath: string,
|
||||
options: MergeTreesOptions = {}) {
|
||||
constructor(
|
||||
public inputPaths: string[], public cachePath: string, options: MergeTreesOptions = {}) {
|
||||
this.options = options || {};
|
||||
}
|
||||
|
||||
|
|
|
@ -18,37 +18,36 @@ class DiffingReplace implements DiffingBroccoliPlugin {
|
|||
var patterns = this.options.patterns;
|
||||
var files = this.options.files;
|
||||
|
||||
treeDiff.addedPaths.concat(treeDiff.changedPaths)
|
||||
.forEach((changedFilePath) => {
|
||||
var sourceFilePath = path.join(this.inputPath, changedFilePath);
|
||||
var destFilePath = path.join(this.cachePath, changedFilePath);
|
||||
var destDirPath = path.dirname(destFilePath);
|
||||
treeDiff.addedPaths.concat(treeDiff.changedPaths).forEach((changedFilePath) => {
|
||||
var sourceFilePath = path.join(this.inputPath, changedFilePath);
|
||||
var destFilePath = path.join(this.cachePath, changedFilePath);
|
||||
var destDirPath = path.dirname(destFilePath);
|
||||
|
||||
if (!fs.existsSync(destDirPath)) {
|
||||
fse.mkdirpSync(destDirPath);
|
||||
}
|
||||
if (!fs.existsSync(destDirPath)) {
|
||||
fse.mkdirpSync(destDirPath);
|
||||
}
|
||||
|
||||
var fileMatches = files.some((filePath: string) => minimatch(changedFilePath, filePath));
|
||||
if (fileMatches) {
|
||||
var content = fs.readFileSync(sourceFilePath, FILE_ENCODING);
|
||||
patterns.forEach((pattern: any) => {
|
||||
var replacement = pattern.replacement;
|
||||
if (typeof replacement === 'function') {
|
||||
replacement = function(content: string) {
|
||||
return pattern.replacement(content, changedFilePath);
|
||||
};
|
||||
}
|
||||
content = content.replace(pattern.match, replacement);
|
||||
});
|
||||
fs.writeFileSync(destFilePath, content, FILE_ENCODING);
|
||||
} else if (!fs.existsSync(destFilePath)) {
|
||||
try {
|
||||
fs.symlinkSync(sourceFilePath, destFilePath);
|
||||
} catch (e) {
|
||||
fs.writeFileSync(destFilePath, fs.readFileSync(sourceFilePath));
|
||||
}
|
||||
var fileMatches = files.some((filePath: string) => minimatch(changedFilePath, filePath));
|
||||
if (fileMatches) {
|
||||
var content = fs.readFileSync(sourceFilePath, FILE_ENCODING);
|
||||
patterns.forEach((pattern: any) => {
|
||||
var replacement = pattern.replacement;
|
||||
if (typeof replacement === 'function') {
|
||||
replacement = function(content: string) {
|
||||
return pattern.replacement(content, changedFilePath);
|
||||
};
|
||||
}
|
||||
content = content.replace(pattern.match, replacement);
|
||||
});
|
||||
fs.writeFileSync(destFilePath, content, FILE_ENCODING);
|
||||
} else if (!fs.existsSync(destFilePath)) {
|
||||
try {
|
||||
fs.symlinkSync(sourceFilePath, destFilePath);
|
||||
} catch (e) {
|
||||
fs.writeFileSync(destFilePath, fs.readFileSync(sourceFilePath));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
treeDiff.removedPaths.forEach((removedFilePath) => {
|
||||
var destFilePath = path.join(this.cachePath, removedFilePath);
|
||||
|
|
|
@ -8,8 +8,9 @@ class TSToDartTranspiler implements DiffingBroccoliPlugin {
|
|||
|
||||
private transpiler: any /*ts2dart.Transpiler*/;
|
||||
|
||||
constructor(public inputPath: string, public cachePath: string,
|
||||
public options: any /*ts2dart.TranspilerOptions*/) {
|
||||
constructor(
|
||||
public inputPath: string, public cachePath: string,
|
||||
public options: any /*ts2dart.TranspilerOptions*/) {
|
||||
options.basePath = inputPath;
|
||||
options.tsconfig = path.join(inputPath, options.tsconfig);
|
||||
// Workaround for https://github.com/dart-lang/dart_style/issues/493
|
||||
|
@ -24,17 +25,16 @@ class TSToDartTranspiler implements DiffingBroccoliPlugin {
|
|||
path.resolve(this.inputPath, 'angular2/typings/es6-collections/es6-collections.d.ts')
|
||||
];
|
||||
let getDartFilePath = (path: string) => path.replace(/((\.js)|(\.ts))$/i, '.dart');
|
||||
treeDiff.addedPaths.concat(treeDiff.changedPaths)
|
||||
.forEach((changedPath) => {
|
||||
let inputFilePath = path.resolve(this.inputPath, changedPath);
|
||||
treeDiff.addedPaths.concat(treeDiff.changedPaths).forEach((changedPath) => {
|
||||
let inputFilePath = path.resolve(this.inputPath, changedPath);
|
||||
|
||||
// Ignore files which don't need to be transpiled to Dart
|
||||
let dartInputFilePath = getDartFilePath(inputFilePath);
|
||||
if (fs.existsSync(dartInputFilePath)) return;
|
||||
// Ignore files which don't need to be transpiled to Dart
|
||||
let dartInputFilePath = getDartFilePath(inputFilePath);
|
||||
if (fs.existsSync(dartInputFilePath)) return;
|
||||
|
||||
// Prepare to rebuild
|
||||
toEmit.push(path.resolve(this.inputPath, changedPath));
|
||||
});
|
||||
// Prepare to rebuild
|
||||
toEmit.push(path.resolve(this.inputPath, changedPath));
|
||||
});
|
||||
|
||||
treeDiff.removedPaths.forEach((removedPath) => {
|
||||
let absolutePath = path.resolve(this.inputPath, removedPath);
|
||||
|
|
|
@ -85,8 +85,8 @@ class DiffingTSCompiler implements DiffingBroccoliPlugin {
|
|||
this.tsOpts.baseUrl = inputPath;
|
||||
this.tsOpts.outDir = this.cachePath;
|
||||
|
||||
this.tsServiceHost = new CustomLanguageServiceHost(this.tsOpts, this.rootFilePaths,
|
||||
this.fileRegistry, this.inputPath);
|
||||
this.tsServiceHost = new CustomLanguageServiceHost(
|
||||
this.tsOpts, this.rootFilePaths, this.fileRegistry, this.inputPath);
|
||||
this.tsService = ts.createLanguageService(this.tsServiceHost, ts.createDocumentRegistry());
|
||||
this.metadataCollector = new MetadataCollector();
|
||||
}
|
||||
|
@ -97,17 +97,16 @@ class DiffingTSCompiler implements DiffingBroccoliPlugin {
|
|||
let pathsWithErrors: string[] = [];
|
||||
let errorMessages: string[] = [];
|
||||
|
||||
treeDiff.addedPaths.concat(treeDiff.changedPaths)
|
||||
.forEach((tsFilePath) => {
|
||||
if (!this.fileRegistry[tsFilePath]) {
|
||||
this.fileRegistry[tsFilePath] = {version: 0};
|
||||
this.rootFilePaths.push(tsFilePath);
|
||||
} else {
|
||||
this.fileRegistry[tsFilePath].version++;
|
||||
}
|
||||
treeDiff.addedPaths.concat(treeDiff.changedPaths).forEach((tsFilePath) => {
|
||||
if (!this.fileRegistry[tsFilePath]) {
|
||||
this.fileRegistry[tsFilePath] = {version: 0};
|
||||
this.rootFilePaths.push(tsFilePath);
|
||||
} else {
|
||||
this.fileRegistry[tsFilePath].version++;
|
||||
}
|
||||
|
||||
pathsToEmit.push(path.join(this.inputPath, tsFilePath));
|
||||
});
|
||||
pathsToEmit.push(path.join(this.inputPath, tsFilePath));
|
||||
});
|
||||
|
||||
treeDiff.removedPaths.forEach((tsFilePath) => {
|
||||
console.log('removing outputs for', tsFilePath);
|
||||
|
@ -181,7 +180,7 @@ class DiffingTSCompiler implements DiffingBroccoliPlugin {
|
|||
let errors: string[] = [];
|
||||
|
||||
allDiagnostics.forEach(diagnostic => {
|
||||
let message = ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n");
|
||||
let message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
|
||||
if (diagnostic.file) {
|
||||
let {line, character} = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
|
||||
errors.push(` ${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`);
|
||||
|
@ -257,8 +256,8 @@ class DiffingTSCompiler implements DiffingBroccoliPlugin {
|
|||
* Emit a .metadata.json file to correspond to the .d.ts file if the module contains classes that
|
||||
* use decorators or exported constants.
|
||||
*/
|
||||
private emitMetadata(dtsFileName: string, sourceFile: ts.SourceFile,
|
||||
typeChecker: ts.TypeChecker) {
|
||||
private emitMetadata(
|
||||
dtsFileName: string, sourceFile: ts.SourceFile, typeChecker: ts.TypeChecker) {
|
||||
if (sourceFile) {
|
||||
const metadata = this.metadataCollector.getMetadata(sourceFile, typeChecker);
|
||||
if (metadata && metadata.metadata) {
|
||||
|
@ -281,16 +280,16 @@ class DiffingTSCompiler implements DiffingBroccoliPlugin {
|
|||
*/
|
||||
private fixSourceMapSources(content: string): string {
|
||||
try {
|
||||
const marker = "//# sourceMappingURL=data:application/json;base64,";
|
||||
const marker = '//# sourceMappingURL=data:application/json;base64,';
|
||||
const index = content.indexOf(marker);
|
||||
if (index == -1) return content;
|
||||
|
||||
const base = content.substring(0, index + marker.length);
|
||||
const sourceMapBit =
|
||||
new Buffer(content.substring(index + marker.length), 'base64').toString("utf8");
|
||||
new Buffer(content.substring(index + marker.length), 'base64').toString('utf8');
|
||||
const sourceMaps = JSON.parse(sourceMapBit);
|
||||
const source = sourceMaps.sources[0];
|
||||
sourceMaps.sources = [source.substring(source.lastIndexOf("../") + 3)];
|
||||
sourceMaps.sources = [source.substring(source.lastIndexOf('../') + 3)];
|
||||
return `${base}${new Buffer(JSON.stringify(sourceMaps)).toString('base64')}`;
|
||||
} catch (e) {
|
||||
return content;
|
||||
|
@ -319,8 +318,9 @@ class CustomLanguageServiceHost implements ts.LanguageServiceHost {
|
|||
private defaultLibFilePath: string;
|
||||
|
||||
|
||||
constructor(private compilerOptions: ts.CompilerOptions, private fileNames: string[],
|
||||
private fileRegistry: FileRegistry, private treeInputPath: string) {
|
||||
constructor(
|
||||
private compilerOptions: ts.CompilerOptions, private fileNames: string[],
|
||||
private fileRegistry: FileRegistry, private treeInputPath: string) {
|
||||
this.currentDirectory = process.cwd();
|
||||
this.defaultLibFilePath = ts.getDefaultLibFilePath(compilerOptions).replace(/\\/g, '/');
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
declare module "broccoli-writer" {
|
||||
declare module 'broccoli-writer' {
|
||||
class Writer {
|
||||
write(readTree: (tree: BroccoliTree) => Promise<string>, destDir: string): Promise<any>;
|
||||
}
|
||||
|
|
|
@ -63,13 +63,13 @@ interface BroccoliTree {
|
|||
*/
|
||||
description?: string;
|
||||
|
||||
rebuild(): (Promise<any>| void);
|
||||
rebuild(): (Promise<any>|void);
|
||||
cleanup(): void;
|
||||
}
|
||||
|
||||
|
||||
interface OldBroccoliTree {
|
||||
read?(readTree: (tree: BroccoliTree) => Promise<string>): (Promise<string>| string);
|
||||
read?(readTree: (tree: BroccoliTree) => Promise<string>): (Promise<string>|string);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -23,13 +23,13 @@ export function wrapDiffingPlugin(pluginClass: PluginClass): DiffingPluginWrappe
|
|||
|
||||
|
||||
export interface DiffingBroccoliPlugin {
|
||||
rebuild(diff: (DiffResult | DiffResult[])): (Promise<DiffResult | void>| DiffResult | void);
|
||||
cleanup ? () : void;
|
||||
rebuild(diff: (DiffResult|DiffResult[])): (Promise<DiffResult|void>|DiffResult|void);
|
||||
cleanup?(): void;
|
||||
}
|
||||
|
||||
|
||||
export type DiffingPluginWrapperFactory =
|
||||
(inputTrees: (BroccoliTree | BroccoliTree[]), options?: any) => BroccoliTree;
|
||||
(inputTrees: (BroccoliTree | BroccoliTree[]), options?: any) => BroccoliTree;
|
||||
|
||||
|
||||
class DiffingPluginWrapper implements BroccoliTree {
|
||||
|
@ -59,7 +59,7 @@ class DiffingPluginWrapper implements BroccoliTree {
|
|||
this.description = this.pluginClass.name;
|
||||
}
|
||||
|
||||
private getDiffResult(): (DiffResult | DiffResult[]) {
|
||||
private getDiffResult(): (DiffResult|DiffResult[]) {
|
||||
let returnOrCalculateDiffResult = (tree: BroccoliTree, index: number) => {
|
||||
// returnOrCalculateDiffResult will do one of two things:
|
||||
//
|
||||
|
@ -80,16 +80,16 @@ class DiffingPluginWrapper implements BroccoliTree {
|
|||
} else if (this.inputTree) {
|
||||
return returnOrCalculateDiffResult(this.inputTree, -1);
|
||||
} else {
|
||||
throw new Error("Missing TreeDiffer");
|
||||
throw new Error('Missing TreeDiffer');
|
||||
}
|
||||
}
|
||||
|
||||
private maybeStoreDiffResult(value: (DiffResult | void)) {
|
||||
private maybeStoreDiffResult(value: (DiffResult|void)) {
|
||||
if (!(value instanceof DiffResult)) value = null;
|
||||
this.diffResult = <DiffResult>(value);
|
||||
}
|
||||
|
||||
rebuild(): (Promise<any>| void) {
|
||||
rebuild(): (Promise<any>|void) {
|
||||
try {
|
||||
let firstRun = !this.initialized;
|
||||
this.init();
|
||||
|
@ -99,7 +99,7 @@ class DiffingPluginWrapper implements BroccoliTree {
|
|||
let result = this.wrappedPlugin.rebuild(diffResult);
|
||||
|
||||
if (result) {
|
||||
let resultPromise = <Promise<DiffResult | void>>(result);
|
||||
let resultPromise = <Promise<DiffResult|void>>(result);
|
||||
if (resultPromise.then) {
|
||||
// rebuild() -> Promise<>
|
||||
return resultPromise.then((result: (DiffResult | void)) => {
|
||||
|
@ -139,15 +139,15 @@ class DiffingPluginWrapper implements BroccoliTree {
|
|||
let description = this.description;
|
||||
this.initialized = true;
|
||||
if (this.inputPaths) {
|
||||
this.treeDiffers =
|
||||
this.inputPaths.map((inputPath) => new TreeDiffer(
|
||||
description, inputPath, includeExtensions, excludeExtensions));
|
||||
this.treeDiffers = this.inputPaths.map(
|
||||
(inputPath) =>
|
||||
new TreeDiffer(description, inputPath, includeExtensions, excludeExtensions));
|
||||
} else if (this.inputPath) {
|
||||
this.treeDiffer =
|
||||
new TreeDiffer(description, this.inputPath, includeExtensions, excludeExtensions);
|
||||
}
|
||||
this.wrappedPlugin = new this.pluginClass(this.inputPaths || this.inputPath, this.cachePath,
|
||||
this.wrappedPluginArguments[1]);
|
||||
this.wrappedPlugin = new this.pluginClass(
|
||||
this.inputPaths || this.inputPath, this.cachePath, this.wrappedPluginArguments[1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,9 +3,9 @@ var path = require('path');
|
|||
|
||||
module.exports = read;
|
||||
function read(file: string) {
|
||||
var content = fs.readFileSync(path.join('tools/broccoli/html-replace', file + '.html'),
|
||||
{encoding: 'utf-8'});
|
||||
var content = fs.readFileSync(
|
||||
path.join('tools/broccoli/html-replace', file + '.html'), {encoding: 'utf-8'});
|
||||
// TODO(broccoli): we don't really need this, it's here to make the output match the
|
||||
// tools/build/html
|
||||
return content.substring(0, content.lastIndexOf("\n"));
|
||||
return content.substring(0, content.lastIndexOf('\n'));
|
||||
}
|
||||
|
|
|
@ -7,5 +7,5 @@ function readJs(file: string) {
|
|||
fs.readFileSync(path.join('tools/broccoli/js-replace', file + '.js'), {encoding: 'utf-8'});
|
||||
// TODO(broccoli): we don't really need this, it's here to make the output match the
|
||||
// tools/build/html
|
||||
return content.substring(0, content.lastIndexOf("\n"));
|
||||
return content.substring(0, content.lastIndexOf('\n'));
|
||||
}
|
||||
|
|
|
@ -24,24 +24,23 @@ export class MultiCopy extends Writer {
|
|||
constructor(private inputTree: BroccoliTree, private options: MultiCopyOptions) { super(); }
|
||||
|
||||
write(readTree: (tree: BroccoliTree) => Promise<string>, destDir: string): Promise<any> {
|
||||
return readTree(this.inputTree)
|
||||
.then((inputPath: string) => {
|
||||
var fileName = path.basename(this.options.srcPath);
|
||||
var data = fs.readFileSync(path.join(inputPath, this.options.srcPath), 'utf-8');
|
||||
return readTree(this.inputTree).then((inputPath: string) => {
|
||||
var fileName = path.basename(this.options.srcPath);
|
||||
var data = fs.readFileSync(path.join(inputPath, this.options.srcPath), 'utf-8');
|
||||
|
||||
this.options.targetPatterns.forEach(pattern => {
|
||||
var paths: string[] = glob.sync(pattern);
|
||||
paths = paths.filter(p => fs.statSync(p).isDirectory());
|
||||
if (this.options.exclude) {
|
||||
paths = paths.filter(p => !this.options.exclude.some((excl) => minimatch(p, excl)));
|
||||
}
|
||||
paths.forEach(p => {
|
||||
var folder = path.join(destDir, p);
|
||||
fsx.mkdirsSync(folder);
|
||||
var outputPath = path.join(folder, fileName);
|
||||
fs.writeFileSync(outputPath, data);
|
||||
});
|
||||
});
|
||||
this.options.targetPatterns.forEach(pattern => {
|
||||
var paths: string[] = glob.sync(pattern);
|
||||
paths = paths.filter(p => fs.statSync(p).isDirectory());
|
||||
if (this.options.exclude) {
|
||||
paths = paths.filter(p => !this.options.exclude.some((excl) => minimatch(p, excl)));
|
||||
}
|
||||
paths.forEach(p => {
|
||||
var folder = path.join(destDir, p);
|
||||
fsx.mkdirsSync(folder);
|
||||
var outputPath = path.join(folder, fileName);
|
||||
fs.writeFileSync(outputPath, data);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,8 +28,9 @@ describe('TreeDiffer', () => {
|
|||
|
||||
let diffResult = differ.diffTree();
|
||||
|
||||
expect(diffResult.addedPaths)
|
||||
.toEqual(['file-1.txt', 'file-2.txt', 'subdir-1' + path.sep + 'file-1.1.txt']);
|
||||
expect(diffResult.addedPaths).toEqual([
|
||||
'file-1.txt', 'file-2.txt', 'subdir-1' + path.sep + 'file-1.1.txt'
|
||||
]);
|
||||
|
||||
expect(diffResult.changedPaths).toEqual([]);
|
||||
expect(diffResult.removedPaths).toEqual([]);
|
||||
|
@ -81,8 +82,9 @@ describe('TreeDiffer', () => {
|
|||
|
||||
let diffResult = differ.diffTree();
|
||||
|
||||
expect(diffResult.addedPaths)
|
||||
.toEqual(['file-1.txt', 'file-2.txt', 'subdir-1' + path.sep + 'file-1.1.txt']);
|
||||
expect(diffResult.addedPaths).toEqual([
|
||||
'file-1.txt', 'file-2.txt', 'subdir-1' + path.sep + 'file-1.1.txt'
|
||||
]);
|
||||
|
||||
// change two files
|
||||
testDir['dir1']['file-1.txt'] = mockfs.file({content: 'new content', mtime: new Date(1000)});
|
||||
|
@ -92,8 +94,9 @@ describe('TreeDiffer', () => {
|
|||
|
||||
diffResult = differ.diffTree();
|
||||
|
||||
expect(diffResult.changedPaths)
|
||||
.toEqual(['file-1.txt', 'subdir-1' + path.sep + 'file-1.1.txt']);
|
||||
expect(diffResult.changedPaths).toEqual([
|
||||
'file-1.txt', 'subdir-1' + path.sep + 'file-1.1.txt'
|
||||
]);
|
||||
|
||||
expect(diffResult.removedPaths).toEqual([]);
|
||||
|
||||
|
@ -128,8 +131,9 @@ describe('TreeDiffer', () => {
|
|||
|
||||
let diffResult = differ.diffTree();
|
||||
|
||||
expect(diffResult.addedPaths)
|
||||
.toEqual(['file-1.txt', 'file-2.txt', 'subdir-1' + path.sep + 'file-1.1.txt']);
|
||||
expect(diffResult.addedPaths).toEqual([
|
||||
'file-1.txt', 'file-2.txt', 'subdir-1' + path.sep + 'file-1.1.txt'
|
||||
]);
|
||||
|
||||
// change two files
|
||||
testDir['orig_path']['file-1.txt'] =
|
||||
|
@ -141,8 +145,9 @@ describe('TreeDiffer', () => {
|
|||
diffResult = differ.diffTree();
|
||||
|
||||
expect(diffResult.addedPaths).toEqual([]);
|
||||
expect(diffResult.changedPaths)
|
||||
.toEqual(['file-1.txt', 'subdir-1' + path.sep + 'file-1.1.txt']);
|
||||
expect(diffResult.changedPaths).toEqual([
|
||||
'file-1.txt', 'subdir-1' + path.sep + 'file-1.1.txt'
|
||||
]);
|
||||
expect(diffResult.removedPaths).toEqual([]);
|
||||
|
||||
// change one file
|
||||
|
@ -181,14 +186,14 @@ describe('TreeDiffer', () => {
|
|||
});
|
||||
|
||||
|
||||
it("should throw an error if an extension isn't prefixed with doc", () => {
|
||||
it('should throw an error if an extension isn\'t prefixed with doc', () => {
|
||||
// includeExtensions
|
||||
expect(() => new TreeDiffer('testLabel', 'dir1', ['js']))
|
||||
.toThrowError("Extension must begin with '.'. Was: 'js'");
|
||||
.toThrowError('Extension must begin with \'.\'. Was: \'js\'');
|
||||
|
||||
// excludeExtentions
|
||||
expect(() => new TreeDiffer('testLabel', 'dir1', [], ['js']))
|
||||
.toThrowError("Extension must begin with '.'. Was: 'js'");
|
||||
.toThrowError('Extension must begin with \'.\'. Was: \'js\'');
|
||||
});
|
||||
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ function tryStatSync(path: string) {
|
|||
try {
|
||||
return fs.statSync(path);
|
||||
} catch (e) {
|
||||
if (e.code === "ENOENT") return null;
|
||||
if (e.code === 'ENOENT') return null;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
@ -19,17 +19,18 @@ export class TreeDiffer {
|
|||
private include: RegExp = null;
|
||||
private exclude: RegExp = null;
|
||||
|
||||
constructor(private label: string, private rootPath: string, includeExtensions?: string[],
|
||||
excludeExtensions?: string[]) {
|
||||
constructor(
|
||||
private label: string, private rootPath: string, includeExtensions?: string[],
|
||||
excludeExtensions?: string[]) {
|
||||
this.rootDirName = path.basename(rootPath);
|
||||
|
||||
let buildRegexp = (arr: string[]) => new RegExp(`(${arr.reduce(combine, "")})$`, "i");
|
||||
let buildRegexp = (arr: string[]) => new RegExp(`(${arr.reduce(combine, "")})$`, 'i');
|
||||
|
||||
this.include = (includeExtensions || []).length ? buildRegexp(includeExtensions) : null;
|
||||
this.exclude = (excludeExtensions || []).length ? buildRegexp(excludeExtensions) : null;
|
||||
|
||||
function combine(prev: string, curr: string) {
|
||||
if (curr.charAt(0) !== ".") {
|
||||
if (curr.charAt(0) !== '.') {
|
||||
throw new Error(`Extension must begin with '.'. Was: '${curr}'`);
|
||||
}
|
||||
let kSpecialRegexpChars = /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g;
|
||||
|
@ -144,17 +145,17 @@ class DirtyCheckingDiffResult extends DiffResult {
|
|||
|
||||
toString() {
|
||||
return `${pad(this.label, 30)}, ${pad(this.endTime - this.startTime, 5)}ms, ` +
|
||||
`${pad(this.addedPaths.length + this.changedPaths.length + this.removedPaths.length, 5)} changes ` +
|
||||
`(files: ${pad(this.filesChecked, 5)}, dirs: ${pad(this.directoriesChecked, 4)})`;
|
||||
`${pad(this.addedPaths.length + this.changedPaths.length + this.removedPaths.length, 5)} changes ` +
|
||||
`(files: ${pad(this.filesChecked, 5)}, dirs: ${pad(this.directoriesChecked, 4)})`;
|
||||
}
|
||||
|
||||
log(verbose: boolean) {
|
||||
let prefixedPaths = this.addedPaths.map(p => `+ ${p}`)
|
||||
.concat(this.changedPaths.map(p => `* ${p}`))
|
||||
.concat(this.removedPaths.map(p => `- ${p}`));
|
||||
console.log(`Tree diff: ${this}` + ((verbose && prefixedPaths.length) ?
|
||||
` [\n ${prefixedPaths.join('\n ')}\n]` :
|
||||
''));
|
||||
console.log(
|
||||
`Tree diff: ${this}` +
|
||||
((verbose && prefixedPaths.length) ? ` [\n ${prefixedPaths.join('\n ')}\n]` : ''));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ const kServedPaths = [
|
|||
'playground/src/web_workers/images',
|
||||
'playground/src/web_workers/message_broker',
|
||||
'playground/src/web_workers/router',
|
||||
'playground/src/web_workers/input'
|
||||
'playground/src/web_workers/input',
|
||||
];
|
||||
|
||||
|
||||
|
@ -87,9 +87,9 @@ module.exports = function makeBrowserTree(options: any, destinationPath: string)
|
|||
}
|
||||
|
||||
if (modules.benchmarks) {
|
||||
var benchmarksTree =
|
||||
new Funnel('modules/benchmarks',
|
||||
{include: ['**/**'], exclude: ['e2e_test/**'], destDir: '/benchmarks/'});
|
||||
var benchmarksTree = new Funnel(
|
||||
'modules/benchmarks',
|
||||
{include: ['**/**'], exclude: ['e2e_test/**'], destDir: '/benchmarks/'});
|
||||
}
|
||||
|
||||
if (modules.benchmarks_external) {
|
||||
|
@ -99,21 +99,21 @@ module.exports = function makeBrowserTree(options: any, destinationPath: string)
|
|||
}
|
||||
|
||||
if (modules.payload_tests) {
|
||||
var payloadTestsTree =
|
||||
new Funnel('modules/payload_tests',
|
||||
{include: ['**/ts/**'], exclude: ['e2e_test/**'], destDir: '/payload_tests/'});
|
||||
var payloadTestsTree = new Funnel(
|
||||
'modules/payload_tests',
|
||||
{include: ['**/ts/**'], exclude: ['e2e_test/**'], destDir: '/payload_tests/'});
|
||||
}
|
||||
|
||||
if (modules.playground) {
|
||||
var playgroundTree =
|
||||
new Funnel('modules/playground',
|
||||
{include: ['**/**'], exclude: ['e2e_test/**'], destDir: '/playground/'});
|
||||
var playgroundTree = new Funnel(
|
||||
'modules/playground',
|
||||
{include: ['**/**'], exclude: ['e2e_test/**'], destDir: '/playground/'});
|
||||
}
|
||||
|
||||
if (modules.benchpress) {
|
||||
var benchpressTree =
|
||||
new Funnel('modules/benchpress',
|
||||
{include: ['**/**'], exclude: ['e2e_test/**'], destDir: '/benchpress/'});
|
||||
var benchpressTree = new Funnel(
|
||||
'modules/benchpress',
|
||||
{include: ['**/**'], exclude: ['e2e_test/**'], destDir: '/benchpress/'});
|
||||
}
|
||||
|
||||
let externalTypings =
|
||||
|
@ -160,7 +160,7 @@ module.exports = function makeBrowserTree(options: any, destinationPath: string)
|
|||
modulesTree = checkImports(modulesTree);
|
||||
|
||||
modulesTree = replace(modulesTree, {
|
||||
files: ["playground*/**/*.js"],
|
||||
files: ['playground*/**/*.js'],
|
||||
patterns: [{match: /\$SCRIPTS\$/, replacement: jsReplace('SCRIPTS')}]
|
||||
});
|
||||
|
||||
|
@ -170,7 +170,7 @@ module.exports = function makeBrowserTree(options: any, destinationPath: string)
|
|||
'node_modules/zone.js/dist/zone.js.d.ts',
|
||||
'angular2/manual_typings/globals.d.ts',
|
||||
'angular2/typings/es6-collections/es6-collections.d.ts',
|
||||
'angular2/typings/es6-promise/es6-promise.d.ts'
|
||||
'angular2/typings/es6-promise/es6-promise.d.ts',
|
||||
];
|
||||
|
||||
// Use TypeScript to transpile the *.ts files to ES5
|
||||
|
@ -195,7 +195,7 @@ module.exports = function makeBrowserTree(options: any, destinationPath: string)
|
|||
'node_modules/zone.js/dist/long-stack-trace-zone.js',
|
||||
'node_modules/systemjs/dist/system.src.js',
|
||||
'node_modules/base64-js/lib/b64.js',
|
||||
'node_modules/reflect-metadata/Reflect.js'
|
||||
'node_modules/reflect-metadata/Reflect.js',
|
||||
]
|
||||
}));
|
||||
|
||||
|
@ -233,10 +233,8 @@ module.exports = function makeBrowserTree(options: any, destinationPath: string)
|
|||
htmlTree = replace(htmlTree, {
|
||||
files: ['playground*/**/*.html'],
|
||||
patterns: [
|
||||
{match: /\$SCRIPTS\$/, replacement: htmlReplace('SCRIPTS')},
|
||||
scriptPathPatternReplacement,
|
||||
scriptFilePatternReplacement,
|
||||
useBundlesPatternReplacement
|
||||
{match: /\$SCRIPTS\$/, replacement: htmlReplace('SCRIPTS')}, scriptPathPatternReplacement,
|
||||
scriptFilePatternReplacement, useBundlesPatternReplacement
|
||||
]
|
||||
});
|
||||
}
|
||||
|
@ -246,9 +244,7 @@ module.exports = function makeBrowserTree(options: any, destinationPath: string)
|
|||
files: ['benchmarks/**'],
|
||||
patterns: [
|
||||
{match: /\$SCRIPTS\$/, replacement: htmlReplace('SCRIPTS_benchmarks')},
|
||||
scriptPathPatternReplacement,
|
||||
scriptFilePatternReplacement,
|
||||
useBundlesPatternReplacement
|
||||
scriptPathPatternReplacement, scriptFilePatternReplacement, useBundlesPatternReplacement
|
||||
]
|
||||
});
|
||||
}
|
||||
|
@ -258,9 +254,7 @@ module.exports = function makeBrowserTree(options: any, destinationPath: string)
|
|||
files: ['benchmarks_external/**'],
|
||||
patterns: [
|
||||
{match: /\$SCRIPTS\$/, replacement: htmlReplace('SCRIPTS_benchmarks_external')},
|
||||
scriptPathPatternReplacement,
|
||||
scriptFilePatternReplacement,
|
||||
useBundlesPatternReplacement
|
||||
scriptPathPatternReplacement, scriptFilePatternReplacement, useBundlesPatternReplacement
|
||||
]
|
||||
});
|
||||
}
|
||||
|
@ -270,7 +264,7 @@ module.exports = function makeBrowserTree(options: any, destinationPath: string)
|
|||
// for web-worker e2e tests.
|
||||
htmlTree = replace(htmlTree, {
|
||||
files: ['playground*/**/web_workers/**/*.html'],
|
||||
patterns: [{match: "/bundle/angular2.dev.js", replacement: "/bundle/web_worker/ui.dev.js"}]
|
||||
patterns: [{match: '/bundle/angular2.dev.js', replacement: '/bundle/web_worker/ui.dev.js'}]
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -284,7 +278,7 @@ module.exports = function makeBrowserTree(options: any, destinationPath: string)
|
|||
'bower_components/polymer/polymer.html',
|
||||
'bower_components/polymer/polymer-micro.html',
|
||||
'bower_components/polymer/polymer-mini.html',
|
||||
'tools/build/snippets/url_params_to_form.js'
|
||||
'tools/build/snippets/url_params_to_form.js',
|
||||
]
|
||||
});
|
||||
var polymer = stew.mv(flatten(polymerFiles), 'benchmarks_external/src/tree/polymer');
|
||||
|
|
|
@ -26,7 +26,7 @@ var global_excludes = [
|
|||
'playground/src/http/**/*',
|
||||
'playground/src/jsonp/**/*',
|
||||
'playground/test/http/**/*',
|
||||
'playground/test/jsonp/**/*'
|
||||
'playground/test/jsonp/**/*',
|
||||
];
|
||||
|
||||
|
||||
|
@ -50,7 +50,7 @@ function replaceScriptTagInHtml(placeholder: string, relativePath: string): stri
|
|||
}
|
||||
var scriptName = relativePath.replace(/\\/g, '/').replace(/.*\/([^/]+)\.html$/, '$1.dart');
|
||||
scriptTags += '<script src="' + scriptName + '" type="application/dart"></script>\n' +
|
||||
'<script src="packages/browser/dart.js" type="text/javascript"></script>';
|
||||
'<script src="packages/browser/dart.js" type="text/javascript"></script>';
|
||||
return scriptTags;
|
||||
}
|
||||
|
||||
|
@ -69,7 +69,7 @@ function getSourceTree(options: AngularBuilderOptions) {
|
|||
'zone-ts2dart.d.ts',
|
||||
'**/*.js',
|
||||
'**/*.ts',
|
||||
'**/*.dart'
|
||||
'**/*.dart',
|
||||
],
|
||||
[
|
||||
'rollup-test/**/*',
|
||||
|
@ -115,7 +115,8 @@ function fixDartFolderLayout(sourceTree: BroccoliTree) {
|
|||
{pattern: /^playground\/test\//, insertion: ''},
|
||||
{pattern: /^playground\//, insertion: 'web/'},
|
||||
{pattern: /^[^\/]*\/test\//, insertion: ''},
|
||||
{pattern: /^./, insertion: 'lib'}, // catch all.
|
||||
// catch all.
|
||||
{pattern: /^./, insertion: 'lib'},
|
||||
];
|
||||
|
||||
for (var i = 0; i < replacements.length; i++) {
|
||||
|
@ -181,18 +182,20 @@ function getDocsTree() {
|
|||
'*/angular1_router',
|
||||
'*/angular2/src/http',
|
||||
'*/payload_tests',
|
||||
'*/upgrade'
|
||||
'*/upgrade',
|
||||
] // Not in dart.
|
||||
});
|
||||
licenses = stew.rename(licenses, stripModulePrefix);
|
||||
|
||||
// Documentation.
|
||||
// Rename *.dart.md -> *.dart.
|
||||
var mdTree = stew.rename(modulesFunnel(['**/*.dart.md']),
|
||||
(relativePath: string) => relativePath.replace(/\.dart\.md$/, '.md'));
|
||||
var mdTree = stew.rename(
|
||||
modulesFunnel(['**/*.dart.md']),
|
||||
(relativePath: string) => relativePath.replace(/\.dart\.md$/, '.md'));
|
||||
// Copy all assets, ignore .js. and .dart. (handled above).
|
||||
var docs = modulesFunnel(['**/*.md', '**/*.png', '**/*.html', '**/*.css', '**/*.scss'],
|
||||
['**/*.js.md', '**/*.dart.md', 'angular1_router/**/*']);
|
||||
var docs = modulesFunnel(
|
||||
['**/*.md', '**/*.png', '**/*.html', '**/*.css', '**/*.scss'],
|
||||
['**/*.js.md', '**/*.dart.md', 'angular1_router/**/*']);
|
||||
|
||||
var assets = modulesFunnel(['playground/**/*.json']);
|
||||
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
import destCopy from '../broccoli-dest-copy';
|
||||
import compileWithTypescript, { INTERNAL_TYPINGS_PATH }
|
||||
from '../broccoli-typescript';
|
||||
import compileWithTypescript, {INTERNAL_TYPINGS_PATH} from '../broccoli-typescript';
|
||||
var Funnel = require('broccoli-funnel');
|
||||
import mergeTrees from '../broccoli-merge-trees';
|
||||
var path = require('path');
|
||||
|
@ -32,7 +31,7 @@ module.exports = function makeNodeTree(projects: string[], destinationPath: stri
|
|||
'angular2/upgrade.ts',
|
||||
'angular2/platform/testing/**',
|
||||
'angular2/manual_typings/**',
|
||||
'angular2/typings/**'
|
||||
'angular2/typings/**',
|
||||
]
|
||||
});
|
||||
|
||||
|
@ -41,7 +40,7 @@ module.exports = function makeNodeTree(projects: string[], destinationPath: stri
|
|||
'angular2/typings/node/node.d.ts',
|
||||
'angular2/manual_typings/globals.d.ts',
|
||||
'angular2/typings/es6-collections/es6-collections.d.ts',
|
||||
'angular2/typings/es6-promise/es6-promise.d.ts'
|
||||
'angular2/typings/es6-promise/es6-promise.d.ts',
|
||||
];
|
||||
|
||||
let externalTypingsTree = new Funnel('modules', {files: externalTypings});
|
||||
|
@ -95,7 +94,7 @@ module.exports = function makeNodeTree(projects: string[], destinationPath: stri
|
|||
|
||||
'angular2/test/upgrade/**/*.ts',
|
||||
'angular1_router/**',
|
||||
'payload_tests/**'
|
||||
'payload_tests/**',
|
||||
]
|
||||
});
|
||||
|
||||
|
@ -130,17 +129,14 @@ module.exports = function makeNodeTree(projects: string[], destinationPath: stri
|
|||
// Compile generated test files against the src @internal .d.ts and the test files
|
||||
compiledTree = mergeTrees(
|
||||
[
|
||||
compiledTree,
|
||||
generatedJsTestFiles,
|
||||
compiledTree, generatedJsTestFiles,
|
||||
compileTree(
|
||||
new Funnel(
|
||||
mergeTrees([
|
||||
packageTypings,
|
||||
new Funnel('modules',
|
||||
{include: ['angular2/manual_typings/**', 'angular2/typings/**']}),
|
||||
generatedTsTestFiles,
|
||||
srcPrivateDeclarations,
|
||||
compiledTestTree
|
||||
new Funnel(
|
||||
'modules', {include: ['angular2/manual_typings/**', 'angular2/typings/**']}),
|
||||
generatedTsTestFiles, srcPrivateDeclarations, compiledTestTree
|
||||
]),
|
||||
{include: ['angular2/**', 'rxjs/**', 'zone.js/**']}),
|
||||
false, [])
|
||||
|
@ -153,9 +149,9 @@ module.exports = function makeNodeTree(projects: string[], destinationPath: stri
|
|||
files: ['**/*.d.ts'],
|
||||
patterns: [
|
||||
// all readonly keywords
|
||||
{match: /^(\s*(static\s+|private\s+)*)readonly\s+/mg, replacement: "$1"},
|
||||
{match: /^(\s*(static\s+|private\s+)*)readonly\s+/mg, replacement: '$1'},
|
||||
// abstract properties (but not methods or classes)
|
||||
{match: /^(\s+)abstract\s+([^\(\n]*$)/mg, replacement: "$1$2"},
|
||||
{match: /^(\s+)abstract\s+([^\(\n]*$)/mg, replacement: '$1$2'},
|
||||
]
|
||||
});
|
||||
|
||||
|
@ -176,17 +172,16 @@ module.exports = function makeNodeTree(projects: string[], destinationPath: stri
|
|||
|
||||
// Copy es6 typings so quickstart doesn't require typings install
|
||||
let typingsTree = mergeTrees([
|
||||
new Funnel('modules',
|
||||
{
|
||||
include: [
|
||||
'angular2/typings/es6-collections/es6-collections.d.ts',
|
||||
'angular2/typings/es6-promise/es6-promise.d.ts',
|
||||
]
|
||||
}),
|
||||
writeFile('angular2/typings/browser.d.ts',
|
||||
'// Typings needed for compilation with --target=es5\n' +
|
||||
'///<reference path="./es6-collections/es6-collections.d.ts"/>\n' +
|
||||
'///<reference path="./es6-promise/es6-promise.d.ts"/>\n')
|
||||
new Funnel('modules', {
|
||||
include: [
|
||||
'angular2/typings/es6-collections/es6-collections.d.ts',
|
||||
'angular2/typings/es6-promise/es6-promise.d.ts',
|
||||
]
|
||||
}),
|
||||
writeFile(
|
||||
'angular2/typings/browser.d.ts', '// Typings needed for compilation with --target=es5\n' +
|
||||
'///<reference path="./es6-collections/es6-collections.d.ts"/>\n' +
|
||||
'///<reference path="./es6-promise/es6-promise.d.ts"/>\n')
|
||||
]);
|
||||
|
||||
var nodeTree =
|
||||
|
@ -201,9 +196,9 @@ module.exports = function makeNodeTree(projects: string[], destinationPath: stri
|
|||
replacement:
|
||||
() =>
|
||||
`var parse5Adapter = require('angular2/src/platform/server/parse5_adapter');\r\n` +
|
||||
`parse5Adapter.Parse5DomAdapter.makeCurrent();`
|
||||
`parse5Adapter.Parse5DomAdapter.makeCurrent();`
|
||||
},
|
||||
{match: /$/, replacement: (_: any, relativePath: string) => "\r\n main(); \r\n"}
|
||||
{match: /$/, replacement: (_: any, relativePath: string) => '\r\n main(); \r\n'}
|
||||
]
|
||||
});
|
||||
|
||||
|
@ -215,24 +210,24 @@ module.exports = function makeNodeTree(projects: string[], destinationPath: stri
|
|||
return destCopy(nodeTree, destinationPath);
|
||||
};
|
||||
|
||||
function compileTree(tree: BroccoliTree, genInternalTypings: boolean,
|
||||
rootFilePaths: string[] = []) {
|
||||
function compileTree(
|
||||
tree: BroccoliTree, genInternalTypings: boolean, rootFilePaths: string[] = []) {
|
||||
return compileWithTypescript(tree, {
|
||||
// build pipeline options
|
||||
"rootFilePaths": rootFilePaths,
|
||||
"internalTypings": genInternalTypings,
|
||||
'rootFilePaths': rootFilePaths,
|
||||
'internalTypings': genInternalTypings,
|
||||
// tsc options
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"declaration": true,
|
||||
"stripInternal": true,
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "classic",
|
||||
"noEmitOnError": true,
|
||||
"rootDir": ".",
|
||||
"inlineSourceMap": true,
|
||||
"inlineSources": true,
|
||||
"target": "es5"
|
||||
'emitDecoratorMetadata': true,
|
||||
'experimentalDecorators': true,
|
||||
'declaration': true,
|
||||
'stripInternal': true,
|
||||
'module': 'commonjs',
|
||||
'moduleResolution': 'classic',
|
||||
'noEmitOnError': true,
|
||||
'rootDir': '.',
|
||||
'inlineSourceMap': true,
|
||||
'inlineSources': true,
|
||||
'target': 'es5'
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ if (globsIndex < 0) {
|
|||
}
|
||||
|
||||
var specFiles = args.map(function(globstr: string) { return glob.sync(globstr, {cwd: toolsDir}); })
|
||||
.reduce((specFiles:string[], paths: string[]) => specFiles.concat(paths), []);
|
||||
.reduce((specFiles: string[], paths: string[]) => specFiles.concat(paths), []);
|
||||
|
||||
jasmine.DEFAULT_TIMEOUT_INTERVAL = 100;
|
||||
|
||||
|
|
|
@ -32,25 +32,26 @@ if (globsIndex < 0) {
|
|||
}
|
||||
|
||||
var specFiles: any =
|
||||
args.map(function(globstr: string): string[] {
|
||||
return glob.sync(globstr, {
|
||||
cwd: distAll,
|
||||
ignore: [
|
||||
// the following code and tests are not compatible with CJS/node environment
|
||||
'@angular/platform-browser/**',
|
||||
'@angular/core/test/zone/**',
|
||||
'@angular/core/test/fake_async_spec.*',
|
||||
'@angular/common/test/forms/**',
|
||||
'@angular/router/test/route_config/route_config_spec.*',
|
||||
'@angular/router/test/integration/bootstrap_spec.*',
|
||||
'@angular/integration_test/symbol_inspector/**',
|
||||
'@angular/upgrade/**',
|
||||
'@angular/examples/**',
|
||||
'angular1_router/**',
|
||||
'payload_tests/**'
|
||||
]
|
||||
});
|
||||
})
|
||||
args.map(function(globstr: string):
|
||||
string[] {
|
||||
return glob.sync(globstr, {
|
||||
cwd: distAll,
|
||||
ignore: [
|
||||
// the following code and tests are not compatible with CJS/node environment
|
||||
'@angular/platform-browser/**',
|
||||
'@angular/core/test/zone/**',
|
||||
'@angular/core/test/fake_async_spec.*',
|
||||
'@angular/common/test/forms/**',
|
||||
'@angular/router/test/route_config/route_config_spec.*',
|
||||
'@angular/router/test/integration/bootstrap_spec.*',
|
||||
'@angular/integration_test/symbol_inspector/**',
|
||||
'@angular/upgrade/**',
|
||||
'@angular/examples/**',
|
||||
'angular1_router/**',
|
||||
'payload_tests/**',
|
||||
]
|
||||
});
|
||||
})
|
||||
// The security spec however works (and must work!) on the server side.
|
||||
.concat(glob.sync('@angular/platform-browser/test/security/**/*_spec.js', {cwd: distAll}))
|
||||
.reduce((specFiles: string[], paths: string[]) => specFiles.concat(paths), <string[]>[]);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
var testingPlatformServer = require('../../all/@angular/platform-server/testing/server.js');
|
||||
var testing = require('../../all/@angular/core/testing');
|
||||
|
||||
testing.setBaseTestProviders(testingPlatformServer.TEST_SERVER_PLATFORM_PROVIDERS,
|
||||
testingPlatformServer.TEST_SERVER_APPLICATION_PROVIDERS);
|
||||
testing.setBaseTestProviders(
|
||||
testingPlatformServer.TEST_SERVER_PLATFORM_PROVIDERS,
|
||||
testingPlatformServer.TEST_SERVER_APPLICATION_PROVIDERS);
|
||||
|
|
|
@ -581,7 +581,7 @@ const CORE = [
|
|||
'state(stateNameExpr:string, styles:AnimationStyleMetadata):AnimationStateDeclarationMetadata',
|
||||
'style(tokens:string|{[key:string]:string|number}|Array<string|{[key:string]:string|number}>):AnimationStyleMetadata',
|
||||
'transition(stateChangeExpr:string, animationData:AnimationMetadata|AnimationMetadata[]):AnimationStateTransitionMetadata',
|
||||
'trigger(name:string, animation:AnimationMetadata|AnimationMetadata[]):AnimationEntryMetadata'
|
||||
'trigger(name:string, animation:AnimationMetadata|AnimationMetadata[]):AnimationEntryMetadata',
|
||||
];
|
||||
|
||||
const COMMON = [
|
||||
|
@ -1320,11 +1320,11 @@ const PLATFORM_BROWSER = [
|
|||
];
|
||||
|
||||
describe('public API', () => {
|
||||
check("@angular/core", CORE);
|
||||
check("@angular/common", COMMON);
|
||||
check("@angular/compiler", COMPILER);
|
||||
check("@angular/upgrade", UPGRADE);
|
||||
check("@angular/platform-browser", PLATFORM_BROWSER);
|
||||
check('@angular/core', CORE);
|
||||
check('@angular/common', COMMON);
|
||||
check('@angular/compiler', COMPILER);
|
||||
check('@angular/upgrade', UPGRADE);
|
||||
check('@angular/platform-browser', PLATFORM_BROWSER);
|
||||
});
|
||||
|
||||
function check(file: string, expected: string[]) {
|
||||
|
@ -1342,12 +1342,12 @@ function checkPublicApi(file: string, expected: string[]) {
|
|||
console.log('=================================================================');
|
||||
console.log('=================================================================');
|
||||
console.log('=================================================================');
|
||||
console.log("Missing:");
|
||||
console.log('Missing:');
|
||||
missing.forEach((m) => console.log(m));
|
||||
}
|
||||
|
||||
if (extra.length > 0) {
|
||||
console.log("Extra:");
|
||||
console.log('Extra:');
|
||||
extra.forEach((m) => console.log(m));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
import {spawn} from 'child_process';
|
||||
import {TscWatch, TSC, reportError} from './tsc_watch';
|
||||
import {writeFileSync, mkdirSync, existsSync} from 'fs';
|
||||
|
||||
import {TscWatch, TSC, reportError} from './tsc_watch';
|
||||
|
||||
export * from './tsc_watch';
|
||||
import 'reflect-metadata';
|
||||
|
||||
const OFFLINE_COMPILE = [
|
||||
'output/output_emitter_codegen_untyped',
|
||||
'output/output_emitter_codegen_typed',
|
||||
'offline_compiler_codegen_untyped',
|
||||
'offline_compiler_codegen_typed'
|
||||
'output/output_emitter_codegen_untyped', 'output/output_emitter_codegen_typed',
|
||||
'offline_compiler_codegen_untyped', 'offline_compiler_codegen_typed'
|
||||
];
|
||||
|
||||
function processOutputEmitterCodeGen(): Promise<number> {
|
||||
|
@ -20,8 +20,9 @@ function processOutputEmitterCodeGen(): Promise<number> {
|
|||
var codegen = require('../../all/@angular/compiler/test/' + file + '.js');
|
||||
if (codegen.emit) {
|
||||
console.log(` ${file} has changed, regenerating...`);
|
||||
promises.push(Promise.resolve(codegen.emit())
|
||||
.then((code) => { writeFileSync(outDir + file + '.ts', code); }));
|
||||
promises.push(Promise.resolve(codegen.emit()).then((code) => {
|
||||
writeFileSync(outDir + file + '.ts', code);
|
||||
}));
|
||||
}
|
||||
});
|
||||
if (promises.length) {
|
||||
|
@ -33,8 +34,9 @@ function processOutputEmitterCodeGen(): Promise<number> {
|
|||
var tsc = spawn(TSC, args, {stdio: 'pipe'});
|
||||
tsc.stdout.on('data', (data: any) => process.stdout.write(data));
|
||||
tsc.stderr.on('data', (data: any) => process.stderr.write(data));
|
||||
tsc.on('close',
|
||||
(code: any) => code ? reject('Tsc exited with: ' + code) : resolve(code));
|
||||
tsc.on(
|
||||
'close',
|
||||
(code: any) => code ? reject('Tsc exited with: ' + code) : resolve(code));
|
||||
})
|
||||
.catch(reportError);
|
||||
} else {
|
||||
|
@ -68,10 +70,7 @@ if (platform == 'node') {
|
|||
onChangeCmds: [
|
||||
processOutputEmitterCodeGen,
|
||||
[
|
||||
'node',
|
||||
'dist/tools/cjs-jasmine',
|
||||
'--',
|
||||
'{@angular,benchpress}/**/*_spec.js',
|
||||
'node', 'dist/tools/cjs-jasmine', '--', '{@angular,benchpress}/**/*_spec.js',
|
||||
'@angular/compiler_cli/test/**/*_spec.js'
|
||||
]
|
||||
]
|
||||
|
@ -92,9 +91,10 @@ if (platform == 'node') {
|
|||
start: 'File change detected. Starting incremental compilation...',
|
||||
error: 'error',
|
||||
complete: 'Compilation complete. Watching for file changes.',
|
||||
onChangeCmds: [
|
||||
['node', 'dist/tools/cjs-jasmine/index-tools', '--', '{public_api_guard,tsc-wrapped}/**/*{_,.}spec.js']
|
||||
]
|
||||
onChangeCmds: [[
|
||||
'node', 'dist/tools/cjs-jasmine/index-tools', '--',
|
||||
'{public_api_guard,tsc-wrapped}/**/*{_,.}spec.js'
|
||||
]]
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -12,22 +12,20 @@ export type Command = (stdIn: any, stdErr: any) => Promise<number>;
|
|||
|
||||
export class TscWatch {
|
||||
private tsconfig: string;
|
||||
private start: string | RegExp;
|
||||
private error: string | RegExp;
|
||||
private complete: string | RegExp;
|
||||
private onStartCmds: Array<string[] | Command>;
|
||||
private onChangeCmds: Array<string[] | Command>;
|
||||
private start: string|RegExp;
|
||||
private error: string|RegExp;
|
||||
private complete: string|RegExp;
|
||||
private onStartCmds: Array<string[]|Command>;
|
||||
private onChangeCmds: Array<string[]|Command>;
|
||||
private state: State;
|
||||
private triggered: Promise<number> = null;
|
||||
private runOnce: boolean = false;
|
||||
|
||||
constructor({tsconfig, start, error, complete, onStartCmds = null, onChangeCmds = null}: {
|
||||
tsconfig: string,
|
||||
error: string | RegExp,
|
||||
error: string|RegExp,
|
||||
start: string,
|
||||
complete: string,
|
||||
onStartCmds?: Array<string[] | Command>,
|
||||
onChangeCmds?: Array<string[] | Command>
|
||||
complete: string, onStartCmds?: Array<string[]|Command>, onChangeCmds?: Array<string[]|Command>
|
||||
}) {
|
||||
console.log('Watching:', tsconfig, 'in', process.cwd());
|
||||
this.tsconfig = tsconfig;
|
||||
|
@ -50,9 +48,9 @@ export class TscWatch {
|
|||
this.onStartCmds.forEach((cmd) => this.runCmd(cmd, null, () => null, () => null));
|
||||
}
|
||||
|
||||
private runCmd(argsOrCmd: string[] | Command, env?: {[k: string]: string},
|
||||
stdOut = pipeStdOut, stdErr = pipeStdErr): Promise<number>
|
||||
{
|
||||
private runCmd(
|
||||
argsOrCmd: string[]|Command, env?: {[k: string]: string}, stdOut = pipeStdOut,
|
||||
stdErr = pipeStdErr): Promise<number> {
|
||||
if (typeof argsOrCmd == 'function') {
|
||||
return (argsOrCmd as Command)(stdErr, stdOut);
|
||||
} else if (argsOrCmd instanceof Array) {
|
||||
|
@ -105,8 +103,9 @@ export class TscWatch {
|
|||
this.state = State.idle;
|
||||
} else {
|
||||
if (this.triggered) {
|
||||
this.triggered.then(() => this.triggerCmds(),
|
||||
(e) => {console.log("Error while running commands....", e)});
|
||||
this.triggered.then(
|
||||
() => this.triggerCmds(),
|
||||
(e) => {console.log('Error while running commands....', e)});
|
||||
} else {
|
||||
this.triggerCmds();
|
||||
}
|
||||
|
|
|
@ -1,17 +1,9 @@
|
|||
import * as ts from 'typescript';
|
||||
|
||||
import {Evaluator, ImportMetadata, ImportSpecifierMetadata} from './evaluator';
|
||||
import {ClassMetadata, ConstructorMetadata, ModuleMetadata, MemberMetadata, MetadataMap, MetadataSymbolicExpression, MetadataSymbolicReferenceExpression, MetadataValue, MethodMetadata} from './schema';
|
||||
import {Symbols} from './symbols';
|
||||
import {
|
||||
ClassMetadata,
|
||||
ConstructorMetadata,
|
||||
ModuleMetadata,
|
||||
MemberMetadata,
|
||||
MetadataMap,
|
||||
MetadataSymbolicExpression,
|
||||
MetadataSymbolicReferenceExpression,
|
||||
MetadataValue,
|
||||
MethodMetadata
|
||||
} from './schema';
|
||||
|
||||
|
||||
/**
|
||||
* Collect decorator metadata from a TypeScript module.
|
||||
|
@ -40,14 +32,13 @@ export class MetadataCollector {
|
|||
switch (bindings.kind) {
|
||||
case ts.SyntaxKind.NamedImports:
|
||||
const namedImports: ImportSpecifierMetadata[] = [];
|
||||
(<ts.NamedImports>bindings)
|
||||
.elements.forEach(i => {
|
||||
const namedImport = {name: i.name.text};
|
||||
if (i.propertyName) {
|
||||
(<any>namedImport)['propertyName'] = i.propertyName.text;
|
||||
}
|
||||
namedImports.push(namedImport);
|
||||
});
|
||||
(<ts.NamedImports>bindings).elements.forEach(i => {
|
||||
const namedImport = {name: i.name.text};
|
||||
if (i.propertyName) {
|
||||
(<any>namedImport)['propertyName'] = i.propertyName.text;
|
||||
}
|
||||
namedImports.push(namedImport);
|
||||
});
|
||||
(<any>newImport)['namedImports'] = namedImports;
|
||||
break;
|
||||
case ts.SyntaxKind.NamespaceImport:
|
||||
|
@ -86,7 +77,7 @@ export class MetadataCollector {
|
|||
}
|
||||
|
||||
function classMetadataOf(classDeclaration: ts.ClassDeclaration): ClassMetadata {
|
||||
let result: ClassMetadata = {__symbolic: "class"};
|
||||
let result: ClassMetadata = {__symbolic: 'class'};
|
||||
|
||||
function getDecorators(decorators: ts.Decorator[]): MetadataSymbolicExpression[] {
|
||||
if (decorators && decorators.length)
|
||||
|
@ -114,7 +105,7 @@ export class MetadataCollector {
|
|||
isConstructor = true;
|
||||
// fallthrough
|
||||
case ts.SyntaxKind.MethodDeclaration:
|
||||
const method = <ts.MethodDeclaration | ts.ConstructorDeclaration>member;
|
||||
const method = <ts.MethodDeclaration|ts.ConstructorDeclaration>member;
|
||||
const methodDecorators = getDecorators(method.decorators);
|
||||
const parameters = method.parameters;
|
||||
const parameterDecoratorData: MetadataSymbolicExpression[][] = [];
|
||||
|
@ -131,8 +122,8 @@ export class MetadataCollector {
|
|||
hasParameterData = true;
|
||||
}
|
||||
}
|
||||
const data: MethodMetadata = {__symbolic: isConstructor ? "constructor" : "method"};
|
||||
const name = isConstructor ? "__ctor__" : evaluator.nameOf(member.name);
|
||||
const data: MethodMetadata = {__symbolic: isConstructor ? 'constructor' : 'method'};
|
||||
const name = isConstructor ? '__ctor__' : evaluator.nameOf(member.name);
|
||||
if (methodDecorators) {
|
||||
data.decorators = methodDecorators;
|
||||
}
|
||||
|
@ -150,8 +141,9 @@ export class MetadataCollector {
|
|||
const property = <ts.PropertyDeclaration>member;
|
||||
const propertyDecorators = getDecorators(property.decorators);
|
||||
if (propertyDecorators) {
|
||||
recordMember(evaluator.nameOf(property.name),
|
||||
{__symbolic: 'property', decorators: propertyDecorators});
|
||||
recordMember(
|
||||
evaluator.nameOf(property.name),
|
||||
{__symbolic: 'property', decorators: propertyDecorators});
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -194,6 +186,6 @@ export class MetadataCollector {
|
|||
}
|
||||
}
|
||||
|
||||
return metadata && {__symbolic: "module", metadata};
|
||||
return metadata && {__symbolic: 'module', metadata};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
import * as ts from 'typescript';
|
||||
import {writeFileSync} from 'fs';
|
||||
import {convertDecorators} from 'tsickle';
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {MetadataCollector} from './collector';
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of CompilerHost that forwards all methods to another instance.
|
||||
* Useful for partial implementations to override only methods they care about.
|
||||
|
@ -58,9 +60,7 @@ const IGNORED_FILES = /\.ngfactory\.js$|\.css\.js$|\.css\.shim\.js$/;
|
|||
|
||||
export class MetadataWriterHost extends DelegatingHost {
|
||||
private metadataCollector = new MetadataCollector();
|
||||
constructor(delegate: ts.CompilerHost, private program: ts.Program) {
|
||||
super(delegate);
|
||||
}
|
||||
constructor(delegate: ts.CompilerHost, private program: ts.Program) { super(delegate); }
|
||||
|
||||
private writeMetadata(emitFilePath: string, sourceFile: ts.SourceFile) {
|
||||
// TODO: replace with DTS filePath when https://github.com/Microsoft/TypeScript/pull/8412 is
|
||||
|
@ -68,7 +68,7 @@ export class MetadataWriterHost extends DelegatingHost {
|
|||
if (/*DTS*/ /\.js$/.test(emitFilePath)) {
|
||||
const path = emitFilePath.replace(/*DTS*/ /\.js$/, '.metadata.json');
|
||||
const metadata =
|
||||
this.metadataCollector.getMetadata(sourceFile, this.program.getTypeChecker());
|
||||
this.metadataCollector.getMetadata(sourceFile, this.program.getTypeChecker());
|
||||
if (metadata && metadata.metadata) {
|
||||
const metadataText = JSON.stringify(metadata);
|
||||
writeFileSync(path, metadataText, {encoding: 'utf-8'});
|
||||
|
@ -76,29 +76,31 @@ export class MetadataWriterHost extends DelegatingHost {
|
|||
}
|
||||
}
|
||||
|
||||
writeFile: ts.WriteFileCallback = (fileName: string, data: string, writeByteOrderMark: boolean,
|
||||
onError?: (message: string) => void,
|
||||
sourceFiles?: ts.SourceFile[]) => {
|
||||
if (/\.d\.ts$/.test(fileName)) {
|
||||
// Let the original file be written first; this takes care of creating parent directories
|
||||
this.delegate.writeFile(fileName, data, writeByteOrderMark, onError, sourceFiles);
|
||||
writeFile: ts.WriteFileCallback =
|
||||
(fileName: string, data: string, writeByteOrderMark: boolean,
|
||||
onError?: (message: string) => void, sourceFiles?: ts.SourceFile[]) => {
|
||||
if (/\.d\.ts$/.test(fileName)) {
|
||||
// Let the original file be written first; this takes care of creating parent directories
|
||||
this.delegate.writeFile(fileName, data, writeByteOrderMark, onError, sourceFiles);
|
||||
|
||||
// TODO: remove this early return after https://github.com/Microsoft/TypeScript/pull/8412 is
|
||||
// released
|
||||
return;
|
||||
}
|
||||
// TODO: remove this early return after https://github.com/Microsoft/TypeScript/pull/8412
|
||||
// is
|
||||
// released
|
||||
return;
|
||||
}
|
||||
|
||||
if (IGNORED_FILES.test(fileName)) {
|
||||
return;
|
||||
}
|
||||
if (IGNORED_FILES.test(fileName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!sourceFiles) {
|
||||
throw new Error('Metadata emit requires the sourceFiles are passed to WriteFileCallback. ' +
|
||||
'Update to TypeScript ^1.9.0-dev');
|
||||
}
|
||||
if (sourceFiles.length > 1) {
|
||||
throw new Error('Bundled emit with --out is not supported');
|
||||
}
|
||||
this.writeMetadata(fileName, sourceFiles[0]);
|
||||
};
|
||||
if (!sourceFiles) {
|
||||
throw new Error(
|
||||
'Metadata emit requires the sourceFiles are passed to WriteFileCallback. ' +
|
||||
'Update to TypeScript ^1.9.0-dev');
|
||||
}
|
||||
if (sourceFiles.length > 1) {
|
||||
throw new Error('Bundled emit with --out is not supported');
|
||||
}
|
||||
this.writeMetadata(fileName, sourceFiles[0]);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
import * as ts from 'typescript';
|
||||
|
||||
import {MetadataValue, MetadataSymbolicCallExpression, MetadataSymbolicReferenceExpression} from './schema';
|
||||
import {Symbols} from './symbols';
|
||||
|
||||
import {
|
||||
MetadataValue,
|
||||
MetadataSymbolicCallExpression,
|
||||
MetadataSymbolicReferenceExpression
|
||||
} from './schema';
|
||||
|
||||
// TOOD: Remove when tools directory is upgraded to support es6 target
|
||||
interface Map<K, V> {
|
||||
|
@ -75,8 +72,9 @@ export interface ImportMetadata {
|
|||
* possible.
|
||||
*/
|
||||
export class Evaluator {
|
||||
constructor(private typeChecker: ts.TypeChecker, private symbols: Symbols,
|
||||
private imports: ImportMetadata[]) {}
|
||||
constructor(
|
||||
private typeChecker: ts.TypeChecker, private symbols: Symbols,
|
||||
private imports: ImportMetadata[]) {}
|
||||
|
||||
symbolReference(symbol: ts.Symbol): MetadataSymbolicReferenceExpression {
|
||||
if (symbol) {
|
||||
|
@ -97,7 +95,7 @@ export class Evaluator {
|
|||
}
|
||||
}
|
||||
}
|
||||
return {__symbolic: "reference", name, module};
|
||||
return {__symbolic: 'reference', name, module};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -169,7 +167,7 @@ export class Evaluator {
|
|||
case ts.SyntaxKind.CallExpression:
|
||||
const callExpression = <ts.CallExpression>node;
|
||||
// We can fold a <array>.concat(<v>).
|
||||
if (isMethodCallOf(callExpression, "concat") && callExpression.arguments.length === 1) {
|
||||
if (isMethodCallOf(callExpression, 'concat') && callExpression.arguments.length === 1) {
|
||||
const arrayNode = (<ts.PropertyAccessExpression>callExpression.expression).expression;
|
||||
if (this.isFoldableWorker(arrayNode, folding) &&
|
||||
this.isFoldableWorker(callExpression.arguments[0], folding)) {
|
||||
|
@ -182,7 +180,7 @@ export class Evaluator {
|
|||
}
|
||||
|
||||
// We can fold a call to CONST_EXPR
|
||||
if (isCallOf(callExpression, "CONST_EXPR") && callExpression.arguments.length === 1)
|
||||
if (isCallOf(callExpression, 'CONST_EXPR') && callExpression.arguments.length === 1)
|
||||
return this.isFoldableWorker(callExpression.arguments[0], folding);
|
||||
return false;
|
||||
case ts.SyntaxKind.NoSubstitutionTemplateLiteral:
|
||||
|
@ -206,7 +204,7 @@ export class Evaluator {
|
|||
case ts.SyntaxKind.AmpersandAmpersandToken:
|
||||
case ts.SyntaxKind.BarBarToken:
|
||||
return this.isFoldableWorker(binaryExpression.left, folding) &&
|
||||
this.isFoldableWorker(binaryExpression.right, folding);
|
||||
this.isFoldableWorker(binaryExpression.right, folding);
|
||||
}
|
||||
case ts.SyntaxKind.PropertyAccessExpression:
|
||||
const propertyAccessExpression = <ts.PropertyAccessExpression>node;
|
||||
|
@ -214,7 +212,7 @@ export class Evaluator {
|
|||
case ts.SyntaxKind.ElementAccessExpression:
|
||||
const elementAccessExpression = <ts.ElementAccessExpression>node;
|
||||
return this.isFoldableWorker(elementAccessExpression.expression, folding) &&
|
||||
this.isFoldableWorker(elementAccessExpression.argumentExpression, folding);
|
||||
this.isFoldableWorker(elementAccessExpression.argumentExpression, folding);
|
||||
case ts.SyntaxKind.Identifier:
|
||||
let symbol = this.typeChecker.getSymbolAtLocation(node);
|
||||
if (symbol.flags & ts.SymbolFlags.Alias) {
|
||||
|
@ -277,14 +275,14 @@ export class Evaluator {
|
|||
const callExpression = <ts.CallExpression>node;
|
||||
const args = callExpression.arguments.map(arg => this.evaluateNode(arg));
|
||||
if (this.isFoldable(callExpression)) {
|
||||
if (isMethodCallOf(callExpression, "concat")) {
|
||||
if (isMethodCallOf(callExpression, 'concat')) {
|
||||
const arrayValue = <MetadataValue[]>this.evaluateNode(
|
||||
(<ts.PropertyAccessExpression>callExpression.expression).expression);
|
||||
return arrayValue.concat(args[0]);
|
||||
}
|
||||
}
|
||||
// Always fold a CONST_EXPR even if the argument is not foldable.
|
||||
if (isCallOf(callExpression, "CONST_EXPR") && callExpression.arguments.length === 1) {
|
||||
if (isCallOf(callExpression, 'CONST_EXPR') && callExpression.arguments.length === 1) {
|
||||
return args[0];
|
||||
}
|
||||
if (isCallOf(callExpression, 'forwardRef') && callExpression.arguments.length === 1) {
|
||||
|
@ -297,7 +295,7 @@ export class Evaluator {
|
|||
const expression = this.evaluateNode(callExpression.expression);
|
||||
if (isDefined(expression) && args.every(isDefined)) {
|
||||
const result:
|
||||
MetadataSymbolicCallExpression = {__symbolic: "call", expression: expression};
|
||||
MetadataSymbolicCallExpression = {__symbolic: 'call', expression: expression};
|
||||
if (args && args.length) {
|
||||
result.arguments = args;
|
||||
}
|
||||
|
@ -309,7 +307,7 @@ export class Evaluator {
|
|||
const newArgs = newExpression.arguments.map(arg => this.evaluateNode(arg));
|
||||
const newTarget = this.evaluateNode(newExpression.expression);
|
||||
if (isDefined(newTarget) && newArgs.every(isDefined)) {
|
||||
const result: MetadataSymbolicCallExpression = {__symbolic: "new", expression: newTarget};
|
||||
const result: MetadataSymbolicCallExpression = {__symbolic: 'new', expression: newTarget};
|
||||
if (newArgs.length) {
|
||||
result.arguments = newArgs;
|
||||
}
|
||||
|
@ -325,7 +323,7 @@ export class Evaluator {
|
|||
return this.nodeSymbolReference(propertyAccessExpression);
|
||||
}
|
||||
if (isDefined(expression)) {
|
||||
return {__symbolic: "select", expression, member};
|
||||
return {__symbolic: 'select', expression, member};
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -335,9 +333,9 @@ export class Evaluator {
|
|||
const index = this.evaluateNode(elementAccessExpression.argumentExpression);
|
||||
if (this.isFoldable(elementAccessExpression.expression) &&
|
||||
this.isFoldable(elementAccessExpression.argumentExpression))
|
||||
return (<any>expression)[<string | number>index];
|
||||
return (<any>expression)[<string|number>index];
|
||||
if (isDefined(expression) && isDefined(index)) {
|
||||
return {__symbolic: "index", expression, index};
|
||||
return {__symbolic: 'index', expression, index};
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -404,7 +402,7 @@ export class Evaluator {
|
|||
default:
|
||||
return undefined;
|
||||
}
|
||||
return {__symbolic: "pre", operator: operatorText, operand: operand };
|
||||
return {__symbolic: 'pre', operator: operatorText, operand: operand};
|
||||
case ts.SyntaxKind.BinaryExpression:
|
||||
const binaryExpression = <ts.BinaryExpression>node;
|
||||
const left = this.evaluateNode(binaryExpression.left);
|
||||
|
@ -456,7 +454,7 @@ export class Evaluator {
|
|||
return <any>left % <any>right;
|
||||
}
|
||||
return {
|
||||
__symbolic: "binop",
|
||||
__symbolic: 'binop',
|
||||
operator: binaryExpression.operatorToken.getText(),
|
||||
left: left,
|
||||
right: right
|
||||
|
|
|
@ -5,10 +5,10 @@ import {tsc, check} from './tsc';
|
|||
import NgOptions from './options';
|
||||
import {MetadataWriterHost, TsickleHost} from './compiler_host';
|
||||
|
||||
export type CodegenExtension = (ngOptions: NgOptions, program: ts.Program, host: ts.CompilerHost) => Promise<any>;
|
||||
export type CodegenExtension = (ngOptions: NgOptions, program: ts.Program, host: ts.CompilerHost) =>
|
||||
Promise<any>;
|
||||
|
||||
export function main(project: string, basePath?: string,
|
||||
codegen?: CodegenExtension): Promise<any> {
|
||||
export function main(project: string, basePath?: string, codegen?: CodegenExtension): Promise<any> {
|
||||
try {
|
||||
let projectDir = project;
|
||||
if (fs.lstatSync(project).isFile()) {
|
||||
|
@ -58,7 +58,7 @@ if (require.main === module) {
|
|||
.then(exitCode => process.exit(exitCode))
|
||||
.catch(e => {
|
||||
console.error(e.stack);
|
||||
console.error("Compilation failed");
|
||||
console.error('Compilation failed');
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,32 +1,32 @@
|
|||
export interface ModuleMetadata {
|
||||
__symbolic: "module";
|
||||
__symbolic: 'module';
|
||||
metadata: {[name: string]: (ClassMetadata | MetadataValue)};
|
||||
}
|
||||
export function isModuleMetadata(value: any): value is ModuleMetadata {
|
||||
return value && value.__symbolic === "module";
|
||||
return value && value.__symbolic === 'module';
|
||||
}
|
||||
|
||||
export interface ClassMetadata {
|
||||
__symbolic: "class";
|
||||
__symbolic: 'class';
|
||||
decorators?: MetadataSymbolicExpression[];
|
||||
members?: MetadataMap;
|
||||
}
|
||||
export function isClassMetadata(value: any): value is ClassMetadata {
|
||||
return value && value.__symbolic === "class";
|
||||
return value && value.__symbolic === 'class';
|
||||
}
|
||||
|
||||
export interface MetadataMap { [name: string]: MemberMetadata[]; }
|
||||
|
||||
export interface MemberMetadata {
|
||||
__symbolic: "constructor" | "method" | "property";
|
||||
__symbolic: 'constructor'|'method'|'property';
|
||||
decorators?: MetadataSymbolicExpression[];
|
||||
}
|
||||
export function isMemberMetadata(value: any): value is MemberMetadata {
|
||||
if (value) {
|
||||
switch (value.__symbolic) {
|
||||
case "constructor":
|
||||
case "method":
|
||||
case "property":
|
||||
case 'constructor':
|
||||
case 'method':
|
||||
case 'property':
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -34,19 +34,19 @@ export function isMemberMetadata(value: any): value is MemberMetadata {
|
|||
}
|
||||
|
||||
export interface MethodMetadata extends MemberMetadata {
|
||||
__symbolic: "constructor" | "method";
|
||||
__symbolic: 'constructor'|'method';
|
||||
parameterDecorators?: MetadataSymbolicExpression[][];
|
||||
}
|
||||
export function isMethodMetadata(value: any): value is MemberMetadata {
|
||||
return value && (value.__symbolic === "constructor" || value.__symbolic === "method");
|
||||
return value && (value.__symbolic === 'constructor' || value.__symbolic === 'method');
|
||||
}
|
||||
|
||||
export interface ConstructorMetadata extends MethodMetadata {
|
||||
__symbolic: "constructor";
|
||||
__symbolic: 'constructor';
|
||||
parameters?: MetadataSymbolicExpression[];
|
||||
}
|
||||
export function isConstructorMetadata(value: any): value is ConstructorMetadata {
|
||||
return value && value.__symbolic === "constructor";
|
||||
return value && value.__symbolic === 'constructor';
|
||||
}
|
||||
|
||||
export type MetadataValue =
|
||||
|
@ -57,18 +57,18 @@ export interface MetadataObject { [name: string]: MetadataValue; }
|
|||
export interface MetadataArray { [name: number]: MetadataValue; }
|
||||
|
||||
export interface MetadataSymbolicExpression {
|
||||
__symbolic: "binary" | "call" | "index" | "new" | "pre" | "reference" | "select"
|
||||
__symbolic: 'binary'|'call'|'index'|'new'|'pre'|'reference'|'select'
|
||||
}
|
||||
export function isMetadataSymbolicExpression(value: any): value is MetadataSymbolicExpression {
|
||||
if (value) {
|
||||
switch (value.__symbolic) {
|
||||
case "binary":
|
||||
case "call":
|
||||
case "index":
|
||||
case "new":
|
||||
case "pre":
|
||||
case "reference":
|
||||
case "select":
|
||||
case 'binary':
|
||||
case 'call':
|
||||
case 'index':
|
||||
case 'new':
|
||||
case 'pre':
|
||||
case 'reference':
|
||||
case 'select':
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -76,63 +76,63 @@ export function isMetadataSymbolicExpression(value: any): value is MetadataSymbo
|
|||
}
|
||||
|
||||
export interface MetadataSymbolicBinaryExpression extends MetadataSymbolicExpression {
|
||||
__symbolic: "binary";
|
||||
operator: "&&" | "||" | "|" | "^" | "&" | "==" | "!=" | "===" | "!==" | "<" | ">" | "<=" | ">=" |
|
||||
"instanceof" | "in" | "as" | "<<" | ">>" | ">>>" | "+" | "-" | "*" | "/" | "%" | "**";
|
||||
__symbolic: 'binary';
|
||||
operator: '&&'|'||'|'|'|'^'|'&'|'=='|'!='|'==='|'!=='|'<'|'>'|'<='|'>='|'instanceof'|'in'|'as'|
|
||||
'<<'|'>>'|'>>>'|'+'|'-'|'*'|'/'|'%'|'**';
|
||||
left: MetadataValue;
|
||||
right: MetadataValue;
|
||||
}
|
||||
export function isMetadataSymbolicBinaryExpression(
|
||||
value: any): value is MetadataSymbolicBinaryExpression {
|
||||
return value && value.__symbolic === "binary";
|
||||
export function isMetadataSymbolicBinaryExpression(value: any):
|
||||
value is MetadataSymbolicBinaryExpression {
|
||||
return value && value.__symbolic === 'binary';
|
||||
}
|
||||
|
||||
export interface MetadataSymbolicIndexExpression extends MetadataSymbolicExpression {
|
||||
__symbolic: "index";
|
||||
__symbolic: 'index';
|
||||
expression: MetadataValue;
|
||||
index: MetadataValue;
|
||||
}
|
||||
export function isMetadataSymbolicIndexExpression(
|
||||
value: any): value is MetadataSymbolicIndexExpression {
|
||||
return value && value.__symbolic === "index";
|
||||
export function isMetadataSymbolicIndexExpression(value: any):
|
||||
value is MetadataSymbolicIndexExpression {
|
||||
return value && value.__symbolic === 'index';
|
||||
}
|
||||
|
||||
export interface MetadataSymbolicCallExpression extends MetadataSymbolicExpression {
|
||||
__symbolic: "call" | "new";
|
||||
__symbolic: 'call'|'new';
|
||||
expression: MetadataValue;
|
||||
arguments?: MetadataValue[];
|
||||
}
|
||||
export function isMetadataSymbolicCallExpression(
|
||||
value: any): value is MetadataSymbolicCallExpression {
|
||||
return value && (value.__symbolic === "call" || value.__symbolic === "new");
|
||||
export function isMetadataSymbolicCallExpression(value: any):
|
||||
value is MetadataSymbolicCallExpression {
|
||||
return value && (value.__symbolic === 'call' || value.__symbolic === 'new');
|
||||
}
|
||||
|
||||
export interface MetadataSymbolicPrefixExpression extends MetadataSymbolicExpression {
|
||||
__symbolic: "pre";
|
||||
operator: "+" | "-" | "~" | "!";
|
||||
__symbolic: 'pre';
|
||||
operator: '+'|'-'|'~'|'!';
|
||||
operand: MetadataValue;
|
||||
}
|
||||
export function isMetadataSymbolicPrefixExpression(
|
||||
value: any): value is MetadataSymbolicPrefixExpression {
|
||||
return value && value.__symbolic === "pre";
|
||||
export function isMetadataSymbolicPrefixExpression(value: any):
|
||||
value is MetadataSymbolicPrefixExpression {
|
||||
return value && value.__symbolic === 'pre';
|
||||
}
|
||||
|
||||
export interface MetadataSymbolicReferenceExpression extends MetadataSymbolicExpression {
|
||||
__symbolic: "reference";
|
||||
__symbolic: 'reference';
|
||||
name: string;
|
||||
module: string;
|
||||
}
|
||||
export function isMetadataSymbolicReferenceExpression(
|
||||
value: any): value is MetadataSymbolicReferenceExpression {
|
||||
return value && value.__symbolic === "reference";
|
||||
export function isMetadataSymbolicReferenceExpression(value: any):
|
||||
value is MetadataSymbolicReferenceExpression {
|
||||
return value && value.__symbolic === 'reference';
|
||||
}
|
||||
|
||||
export interface MetadataSymbolicSelectExpression extends MetadataSymbolicExpression {
|
||||
__symbolic: "select";
|
||||
__symbolic: 'select';
|
||||
expression: MetadataValue;
|
||||
name: string;
|
||||
}
|
||||
export function isMetadataSymbolicSelectExpression(
|
||||
value: any): value is MetadataSymbolicSelectExpression {
|
||||
return value && value.__symbolic === "select";
|
||||
export function isMetadataSymbolicSelectExpression(value: any):
|
||||
value is MetadataSymbolicSelectExpression {
|
||||
return value && value.__symbolic === 'select';
|
||||
}
|
||||
|
|
|
@ -26,7 +26,9 @@ export class Symbols {
|
|||
|
||||
public has(symbol: ts.Symbol): boolean { return this.map.has(symbol.getDeclarations()[0]); }
|
||||
|
||||
public set(symbol: ts.Symbol, value: any): void { this.map.set(symbol.getDeclarations()[0], value); }
|
||||
public set(symbol: ts.Symbol, value: any): void {
|
||||
this.map.set(symbol.getDeclarations()[0], value);
|
||||
}
|
||||
|
||||
public get(symbol: ts.Symbol): any { return this.map.get(symbol.getDeclarations()[0]); }
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import * as ts from 'typescript';
|
||||
import * as path from 'path';
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import AngularCompilerOptions from './options';
|
||||
import {TsickleHost} from './compiler_host';
|
||||
|
||||
|
@ -9,9 +10,8 @@ import {TsickleHost} from './compiler_host';
|
|||
* you should implement a similar interface.
|
||||
*/
|
||||
export interface CompilerInterface {
|
||||
readConfiguration(
|
||||
project: string,
|
||||
basePath: string): {parsed: ts.ParsedCommandLine, ngOptions: AngularCompilerOptions};
|
||||
readConfiguration(project: string, basePath: string):
|
||||
{parsed: ts.ParsedCommandLine, ngOptions: AngularCompilerOptions};
|
||||
typeCheck(compilerHost: ts.CompilerHost, program: ts.Program): void;
|
||||
emit(compilerHost: ts.CompilerHost, program: ts.Program): number;
|
||||
}
|
||||
|
@ -23,16 +23,17 @@ function debug(msg: string, ...o: any[]) {
|
|||
}
|
||||
|
||||
export function formatDiagnostics(diags: ts.Diagnostic[]): string {
|
||||
return diags.map((d) => {
|
||||
let res = ts.DiagnosticCategory[d.category];
|
||||
if (d.file) {
|
||||
res += ' at ' + d.file.fileName + ':';
|
||||
const {line, character} = d.file.getLineAndCharacterOfPosition(d.start);
|
||||
res += (line + 1) + ':' + (character + 1) + ':';
|
||||
}
|
||||
res += ' ' + ts.flattenDiagnosticMessageText(d.messageText, '\n');
|
||||
return res;
|
||||
})
|
||||
return diags
|
||||
.map((d) => {
|
||||
let res = ts.DiagnosticCategory[d.category];
|
||||
if (d.file) {
|
||||
res += ' at ' + d.file.fileName + ':';
|
||||
const {line, character} = d.file.getLineAndCharacterOfPosition(d.start);
|
||||
res += (line + 1) + ':' + (character + 1) + ':';
|
||||
}
|
||||
res += ' ' + ts.flattenDiagnosticMessageText(d.messageText, '\n');
|
||||
return res;
|
||||
})
|
||||
.join('\n');
|
||||
}
|
||||
|
||||
|
@ -55,7 +56,7 @@ export class Tsc implements CompilerInterface {
|
|||
// Allow a directory containing tsconfig.json as the project value
|
||||
try {
|
||||
this.readDirectory(project);
|
||||
project = path.join(project, "tsconfig.json");
|
||||
project = path.join(project, 'tsconfig.json');
|
||||
} catch (e) {
|
||||
// Was not a directory, continue on assuming it's a file
|
||||
}
|
||||
|
@ -82,11 +83,11 @@ export class Tsc implements CompilerInterface {
|
|||
// Create a new program since codegen files were created after making the old program
|
||||
const program =
|
||||
ts.createProgram(this.parsed.fileNames, this.parsed.options, compilerHost, oldProgram);
|
||||
debug("Checking global diagnostics...");
|
||||
debug('Checking global diagnostics...');
|
||||
check(program.getGlobalDiagnostics());
|
||||
|
||||
let diagnostics: ts.Diagnostic[] = [];
|
||||
debug("Type checking...");
|
||||
debug('Type checking...');
|
||||
|
||||
for (let sf of program.getSourceFiles()) {
|
||||
diagnostics.push(...ts.getPreEmitDiagnostics(program, sf));
|
||||
|
@ -97,7 +98,7 @@ export class Tsc implements CompilerInterface {
|
|||
emit(compilerHost: TsickleHost, oldProgram: ts.Program): number {
|
||||
// Create a new program since the host may be different from the old program.
|
||||
const program = ts.createProgram(this.parsed.fileNames, this.parsed.options, compilerHost);
|
||||
debug("Emitting outputs...");
|
||||
debug('Emitting outputs...');
|
||||
const emitResult = program.emit();
|
||||
let diagnostics: ts.Diagnostic[] = [];
|
||||
diagnostics.push(...emitResult.diagnostics);
|
||||
|
|
|
@ -29,22 +29,21 @@ describe('Collector', () => {
|
|||
expect(metadata).toBeUndefined();
|
||||
});
|
||||
|
||||
it("should be able to collect import statements", () => {
|
||||
it('should be able to collect import statements', () => {
|
||||
const sourceFile = program.getSourceFile('app/app.component.ts');
|
||||
expect(collector.collectImports(sourceFile))
|
||||
.toEqual([
|
||||
{
|
||||
from: 'angular2/core',
|
||||
namedImports: [{name: 'MyComponent', propertyName: 'Component'}, {name: 'OnInit'}]
|
||||
},
|
||||
{from: 'angular2/common', namespace: 'common'},
|
||||
{from: './hero', namedImports: [{name: 'Hero'}]},
|
||||
{from: './hero-detail.component', namedImports: [{name: 'HeroDetailComponent'}]},
|
||||
{from: './hero.service', defaultName: 'HeroService'}
|
||||
]);
|
||||
expect(collector.collectImports(sourceFile)).toEqual([
|
||||
{
|
||||
from: 'angular2/core',
|
||||
namedImports: [{name: 'MyComponent', propertyName: 'Component'}, {name: 'OnInit'}]
|
||||
},
|
||||
{from: 'angular2/common', namespace: 'common'},
|
||||
{from: './hero', namedImports: [{name: 'Hero'}]},
|
||||
{from: './hero-detail.component', namedImports: [{name: 'HeroDetailComponent'}]},
|
||||
{from: './hero.service', defaultName: 'HeroService'}
|
||||
]);
|
||||
});
|
||||
|
||||
it("should be able to collect a simple component's metadata", () => {
|
||||
it('should be able to collect a simple component\'s metadata', () => {
|
||||
const sourceFile = program.getSourceFile('app/hero-detail.component.ts');
|
||||
const metadata = collector.getMetadata(sourceFile, typeChecker);
|
||||
expect(metadata).toEqual({
|
||||
|
@ -52,14 +51,12 @@ describe('Collector', () => {
|
|||
metadata: {
|
||||
HeroDetailComponent: {
|
||||
__symbolic: 'class',
|
||||
decorators: [
|
||||
{
|
||||
__symbolic: 'call',
|
||||
expression: {__symbolic: 'reference', name: 'Component', module: 'angular2/core'},
|
||||
arguments: [
|
||||
{
|
||||
selector: 'my-hero-detail',
|
||||
template: `
|
||||
decorators: [{
|
||||
__symbolic: 'call',
|
||||
expression: {__symbolic: 'reference', name: 'Component', module: 'angular2/core'},
|
||||
arguments: [{
|
||||
selector: 'my-hero-detail',
|
||||
template: `
|
||||
<div *ngIf="hero">
|
||||
<h2>{{hero.name}} details!</h2>
|
||||
<div><label>id: </label>{{hero.id}}</div>
|
||||
|
@ -69,30 +66,24 @@ describe('Collector', () => {
|
|||
</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
}]
|
||||
}],
|
||||
members: {
|
||||
hero: [
|
||||
{
|
||||
__symbolic: 'property',
|
||||
decorators: [
|
||||
{
|
||||
__symbolic: 'call',
|
||||
expression:
|
||||
{__symbolic: 'reference', name: 'Input', module: 'angular2/core'}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
hero: [{
|
||||
__symbolic: 'property',
|
||||
decorators: [{
|
||||
__symbolic: 'call',
|
||||
expression:
|
||||
{__symbolic: 'reference', name: 'Input', module: 'angular2/core'}
|
||||
}]
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it("should be able to get a more complicated component's metadata", () => {
|
||||
it('should be able to get a more complicated component\'s metadata', () => {
|
||||
const sourceFile = program.getSourceFile('/app/app.component.ts');
|
||||
const metadata = collector.getMetadata(sourceFile, typeChecker);
|
||||
expect(metadata).toEqual({
|
||||
|
@ -100,14 +91,12 @@ describe('Collector', () => {
|
|||
metadata: {
|
||||
AppComponent: {
|
||||
__symbolic: 'class',
|
||||
decorators: [
|
||||
{
|
||||
__symbolic: 'call',
|
||||
expression: {__symbolic: 'reference', name: 'Component', module: 'angular2/core'},
|
||||
arguments: [
|
||||
{
|
||||
selector: 'my-app',
|
||||
template: `
|
||||
decorators: [{
|
||||
__symbolic: 'call',
|
||||
expression: {__symbolic: 'reference', name: 'Component', module: 'angular2/core'},
|
||||
arguments: [{
|
||||
selector: 'my-app',
|
||||
template: `
|
||||
<h2>My Heroes</h2>
|
||||
<ul class="heroes">
|
||||
<li *ngFor="#hero of heroes"
|
||||
|
@ -118,35 +107,26 @@ describe('Collector', () => {
|
|||
</ul>
|
||||
<my-hero-detail [hero]="selectedHero"></my-hero-detail>
|
||||
`,
|
||||
directives: [
|
||||
{
|
||||
__symbolic: 'reference',
|
||||
name: 'HeroDetailComponent',
|
||||
module: './hero-detail.component'
|
||||
},
|
||||
{__symbolic: 'reference', name: 'NgFor', module: 'angular2/common'}
|
||||
],
|
||||
providers: [{__symbolic: 'reference', name: undefined, module: './hero.service'}],
|
||||
pipes: [
|
||||
{__symbolic: 'reference', name: 'LowerCasePipe', module: 'angular2/common'},
|
||||
{
|
||||
__symbolic: 'reference',
|
||||
name: 'UpperCasePipe',
|
||||
module: 'angular2/common'
|
||||
}
|
||||
]
|
||||
}
|
||||
directives: [
|
||||
{
|
||||
__symbolic: 'reference',
|
||||
name: 'HeroDetailComponent',
|
||||
module: './hero-detail.component'
|
||||
},
|
||||
{__symbolic: 'reference', name: 'NgFor', module: 'angular2/common'}
|
||||
],
|
||||
providers: [{__symbolic: 'reference', name: undefined, module: './hero.service'}],
|
||||
pipes: [
|
||||
{__symbolic: 'reference', name: 'LowerCasePipe', module: 'angular2/common'},
|
||||
{__symbolic: 'reference', name: 'UpperCasePipe', module: 'angular2/common'}
|
||||
]
|
||||
}
|
||||
],
|
||||
}]
|
||||
}],
|
||||
members: {
|
||||
__ctor__: [
|
||||
{
|
||||
__symbolic: 'constructor',
|
||||
parameters:
|
||||
[{__symbolic: 'reference', name: undefined, module: './hero.service'}]
|
||||
}
|
||||
],
|
||||
__ctor__: [{
|
||||
__symbolic: 'constructor',
|
||||
parameters: [{__symbolic: 'reference', name: undefined, module: './hero.service'}]
|
||||
}],
|
||||
onSelect: [{__symbolic: 'method'}],
|
||||
ngOnInit: [{__symbolic: 'method'}],
|
||||
getHeroes: [{__symbolic: 'method'}]
|
||||
|
@ -163,16 +143,11 @@ describe('Collector', () => {
|
|||
__symbolic: 'module',
|
||||
metadata: {
|
||||
HEROES: [
|
||||
{"id": 11, "name": "Mr. Nice"},
|
||||
{"id": 12, "name": "Narco"},
|
||||
{"id": 13, "name": "Bombasto"},
|
||||
{"id": 14, "name": "Celeritas"},
|
||||
{"id": 15, "name": "Magneta"},
|
||||
{"id": 16, "name": "RubberMan"},
|
||||
{"id": 17, "name": "Dynama"},
|
||||
{"id": 18, "name": "Dr IQ"},
|
||||
{"id": 19, "name": "Magma"},
|
||||
{"id": 20, "name": "Tornado"}
|
||||
{'id': 11, 'name': 'Mr. Nice'}, {'id': 12, 'name': 'Narco'},
|
||||
{'id': 13, 'name': 'Bombasto'}, {'id': 14, 'name': 'Celeritas'},
|
||||
{'id': 15, 'name': 'Magneta'}, {'id': 16, 'name': 'RubberMan'},
|
||||
{'id': 17, 'name': 'Dynama'}, {'id': 18, 'name': 'Dr IQ'}, {'id': 19, 'name': 'Magma'},
|
||||
{'id': 20, 'name': 'Tornado'}
|
||||
]
|
||||
}
|
||||
});
|
||||
|
@ -202,18 +177,14 @@ describe('Collector', () => {
|
|||
|
||||
it('should record annotations on set and get declarations', () => {
|
||||
const propertyData = {
|
||||
name: [
|
||||
{
|
||||
__symbolic: 'property',
|
||||
decorators: [
|
||||
{
|
||||
__symbolic: 'call',
|
||||
expression: {__symbolic: 'reference', module: 'angular2/core', name: 'Input'},
|
||||
arguments: ['firstName']
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
name: [{
|
||||
__symbolic: 'property',
|
||||
decorators: [{
|
||||
__symbolic: 'call',
|
||||
expression: {__symbolic: 'reference', module: 'angular2/core', name: 'Input'},
|
||||
arguments: ['firstName']
|
||||
}]
|
||||
}]
|
||||
};
|
||||
const caseGetProp = <ClassMetadata>casesMetadata.metadata['GetProp'];
|
||||
expect(caseGetProp.members).toEqual(propertyData);
|
||||
|
@ -238,7 +209,9 @@ const FILES: Directory = {
|
|||
|
||||
@MyComponent({
|
||||
selector: 'my-app',
|
||||
template:` + "`" + `
|
||||
template:` +
|
||||
'`' +
|
||||
`
|
||||
<h2>My Heroes</h2>
|
||||
<ul class="heroes">
|
||||
<li *ngFor="#hero of heroes"
|
||||
|
@ -249,7 +222,8 @@ const FILES: Directory = {
|
|||
</ul>
|
||||
<my-hero-detail [hero]="selectedHero"></my-hero-detail>
|
||||
` +
|
||||
"`" + `,
|
||||
'`' +
|
||||
`,
|
||||
directives: [HeroDetailComponent, common.NgFor],
|
||||
providers: [HeroService],
|
||||
pipes: [common.LowerCasePipe, common.UpperCasePipe]
|
||||
|
@ -282,7 +256,9 @@ const FILES: Directory = {
|
|||
|
||||
@Component({
|
||||
selector: 'my-hero-detail',
|
||||
template: ` + "`" + `
|
||||
template: ` +
|
||||
'`' +
|
||||
`
|
||||
<div *ngIf="hero">
|
||||
<h2>{{hero.name}} details!</h2>
|
||||
<div><label>id: </label>{{hero.id}}</div>
|
||||
|
@ -291,7 +267,9 @@ const FILES: Directory = {
|
|||
<input [(ngModel)]="hero.name" placeholder="name"/>
|
||||
</div>
|
||||
</div>
|
||||
` + "`" + `,
|
||||
` +
|
||||
'`' +
|
||||
`,
|
||||
})
|
||||
export class HeroDetailComponent {
|
||||
@Input() public hero: Hero;
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import * as ts from 'typescript';
|
||||
import * as fs from 'fs';
|
||||
import {Directory, Host, expectNoDiagnostics, findVar} from './typescript.mocks';
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {Evaluator} from '../src/evaluator';
|
||||
import {Symbols} from '../src/symbols';
|
||||
|
||||
import {Directory, Host, expectNoDiagnostics, findVar} from './typescript.mocks';
|
||||
|
||||
describe('Evaluator', () => {
|
||||
let host: ts.LanguageServiceHost;
|
||||
let service: ts.LanguageService;
|
||||
|
@ -76,13 +78,13 @@ describe('Evaluator', () => {
|
|||
expect(evaluator.evaluateNode(findVar(expressions, 'bBAnd').initializer)).toEqual(0x11 & 0x03);
|
||||
expect(evaluator.evaluateNode(findVar(expressions, 'bXor').initializer)).toEqual(0x11 ^ 0x21);
|
||||
expect(evaluator.evaluateNode(findVar(expressions, 'bEqual').initializer))
|
||||
.toEqual(1 == <any>"1");
|
||||
.toEqual(1 == <any>'1');
|
||||
expect(evaluator.evaluateNode(findVar(expressions, 'bNotEqual').initializer))
|
||||
.toEqual(1 != <any>"1");
|
||||
.toEqual(1 != <any>'1');
|
||||
expect(evaluator.evaluateNode(findVar(expressions, 'bIdentical').initializer))
|
||||
.toEqual(1 === <any>"1");
|
||||
.toEqual(1 === <any>'1');
|
||||
expect(evaluator.evaluateNode(findVar(expressions, 'bNotIdentical').initializer))
|
||||
.toEqual(1 !== <any>"1");
|
||||
.toEqual(1 !== <any>'1');
|
||||
expect(evaluator.evaluateNode(findVar(expressions, 'bLessThan').initializer)).toEqual(1 < 2);
|
||||
expect(evaluator.evaluateNode(findVar(expressions, 'bGreaterThan').initializer)).toEqual(1 > 2);
|
||||
expect(evaluator.evaluateNode(findVar(expressions, 'bLessThanEqual').initializer))
|
||||
|
@ -100,9 +102,9 @@ describe('Evaluator', () => {
|
|||
it('should report recursive references as symbolic', () => {
|
||||
var expressions = program.getSourceFile('expressions.ts');
|
||||
expect(evaluator.evaluateNode(findVar(expressions, 'recursiveA').initializer))
|
||||
.toEqual({__symbolic: "reference", name: "recursiveB", module: undefined});
|
||||
.toEqual({__symbolic: 'reference', name: 'recursiveB', module: undefined});
|
||||
expect(evaluator.evaluateNode(findVar(expressions, 'recursiveB').initializer))
|
||||
.toEqual({__symbolic: "reference", name: "recursiveA", module: undefined});
|
||||
.toEqual({__symbolic: 'reference', name: 'recursiveA', module: undefined});
|
||||
});
|
||||
|
||||
it('should correctly handle special cases for CONST_EXPR', () => {
|
||||
|
@ -121,18 +123,16 @@ describe('Evaluator', () => {
|
|||
evaluator =
|
||||
new Evaluator(typeChecker, symbols, [{from: './classes', namedImports: [{name: 'Value'}]}]);
|
||||
var newExpression = program.getSourceFile('newExpression.ts');
|
||||
expect(evaluator.evaluateNode(findVar(newExpression, 'someValue').initializer))
|
||||
.toEqual({
|
||||
__symbolic: "new",
|
||||
expression: {__symbolic: "reference", name: "Value", module: "./classes"},
|
||||
arguments: ["name", 12]
|
||||
});
|
||||
expect(evaluator.evaluateNode(findVar(newExpression, 'complex').initializer))
|
||||
.toEqual({
|
||||
__symbolic: "new",
|
||||
expression: {__symbolic: "reference", name: "Value", module: "./classes"},
|
||||
arguments: ["name", 12]
|
||||
});
|
||||
expect(evaluator.evaluateNode(findVar(newExpression, 'someValue').initializer)).toEqual({
|
||||
__symbolic: 'new',
|
||||
expression: {__symbolic: 'reference', name: 'Value', module: './classes'},
|
||||
arguments: ['name', 12]
|
||||
});
|
||||
expect(evaluator.evaluateNode(findVar(newExpression, 'complex').initializer)).toEqual({
|
||||
__symbolic: 'new',
|
||||
expression: {__symbolic: 'reference', name: 'Value', module: './classes'},
|
||||
arguments: ['name', 12]
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -3,7 +3,8 @@ import {Tsc} from '../src/tsc';
|
|||
|
||||
describe('options parsing', () => {
|
||||
|
||||
const tsc = new Tsc(() => `
|
||||
const tsc = new Tsc(
|
||||
() => `
|
||||
{
|
||||
"angularCompilerOptions": {
|
||||
"googleClosureOutput": true
|
||||
|
@ -12,13 +13,14 @@ describe('options parsing', () => {
|
|||
"module": "commonjs",
|
||||
"outDir": "built"
|
||||
}
|
||||
}`, () => ['tsconfig.json']);
|
||||
}`,
|
||||
() => ['tsconfig.json']);
|
||||
|
||||
it('should combine all options into ngOptions', () => {
|
||||
const {parsed, ngOptions} = tsc.readConfiguration('projectDir', 'basePath');
|
||||
|
||||
expect(ngOptions).toEqual({
|
||||
genDir:'basePath',
|
||||
genDir: 'basePath',
|
||||
googleClosureOutput: true,
|
||||
module: ts.ModuleKind.CommonJS,
|
||||
outDir: 'basePath/built',
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as ts from 'typescript';
|
||||
|
||||
export interface Directory { [name: string]: (Directory | string); }
|
||||
export interface Directory { [name: string]: (Directory|string); }
|
||||
|
||||
export class Host implements ts.LanguageServiceHost {
|
||||
constructor(private directory: Directory, private scripts: string[]) {}
|
||||
|
@ -17,7 +17,7 @@ export class Host implements ts.LanguageServiceHost {
|
|||
|
||||
getScriptFileNames(): string[] { return this.scripts; }
|
||||
|
||||
getScriptVersion(fileName: string): string { return "1"; }
|
||||
getScriptVersion(fileName: string): string { return '1'; }
|
||||
|
||||
getScriptSnapshot(fileName: string): ts.IScriptSnapshot {
|
||||
let content = this.getFileContent(fileName);
|
||||
|
@ -33,7 +33,7 @@ export class Host implements ts.LanguageServiceHost {
|
|||
if (names[names.length - 1] === 'lib.d.ts') {
|
||||
return fs.readFileSync(ts.getDefaultLibFilePath(this.getCompilationSettings()), 'utf8');
|
||||
}
|
||||
let current: Directory | string = this.directory;
|
||||
let current: Directory|string = this.directory;
|
||||
if (names.length && names[0] === '') names.shift();
|
||||
for (const name of names) {
|
||||
if (!current || typeof current === 'string') return undefined;
|
||||
|
@ -44,8 +44,9 @@ export class Host implements ts.LanguageServiceHost {
|
|||
}
|
||||
|
||||
export class MockNode implements ts.Node {
|
||||
constructor(public kind: ts.SyntaxKind = ts.SyntaxKind.Identifier, public flags: ts.NodeFlags = 0,
|
||||
public pos: number = 0, public end: number = 0) {}
|
||||
constructor(
|
||||
public kind: ts.SyntaxKind = ts.SyntaxKind.Identifier, public flags: ts.NodeFlags = 0,
|
||||
public pos: number = 0, public end: number = 0) {}
|
||||
getSourceFile(): ts.SourceFile { return null; }
|
||||
getChildCount(sourceFile?: ts.SourceFile): number { return 0 }
|
||||
getChildAt(index: number, sourceFile?: ts.SourceFile): ts.Node { return null; }
|
||||
|
@ -71,8 +72,9 @@ export class MockIdentifier extends MockNode implements ts.Identifier {
|
|||
public _unaryExpressionBrand: any;
|
||||
public _expressionBrand: any;
|
||||
|
||||
constructor(public name: string, kind: ts.SyntaxKind = ts.SyntaxKind.Identifier,
|
||||
flags: ts.NodeFlags = 0, pos: number = 0, end: number = 0) {
|
||||
constructor(
|
||||
public name: string, kind: ts.SyntaxKind = ts.SyntaxKind.Identifier, flags: ts.NodeFlags = 0,
|
||||
pos: number = 0, end: number = 0) {
|
||||
super(kind, flags, pos, end);
|
||||
this.text = name;
|
||||
}
|
||||
|
@ -81,31 +83,33 @@ export class MockIdentifier extends MockNode implements ts.Identifier {
|
|||
export class MockVariableDeclaration extends MockNode implements ts.VariableDeclaration {
|
||||
public _declarationBrand: any;
|
||||
|
||||
constructor(public name: ts.Identifier, kind: ts.SyntaxKind = ts.SyntaxKind.VariableDeclaration,
|
||||
flags: ts.NodeFlags = 0, pos: number = 0, end: number = 0) {
|
||||
constructor(
|
||||
public name: ts.Identifier, kind: ts.SyntaxKind = ts.SyntaxKind.VariableDeclaration,
|
||||
flags: ts.NodeFlags = 0, pos: number = 0, end: number = 0) {
|
||||
super(kind, flags, pos, end);
|
||||
}
|
||||
|
||||
static of(name: string): MockVariableDeclaration {
|
||||
static of (name: string): MockVariableDeclaration {
|
||||
return new MockVariableDeclaration(new MockIdentifier(name));
|
||||
}
|
||||
}
|
||||
|
||||
export class MockSymbol implements ts.Symbol {
|
||||
constructor(public name: string, private node: ts.Declaration = MockVariableDeclaration.of(name),
|
||||
public flags: ts.SymbolFlags = 0) {}
|
||||
constructor(
|
||||
public name: string, private node: ts.Declaration = MockVariableDeclaration.of(name),
|
||||
public flags: ts.SymbolFlags = 0) {}
|
||||
|
||||
getFlags(): ts.SymbolFlags { return this.flags; }
|
||||
getName(): string { return this.name; }
|
||||
getDeclarations(): ts.Declaration[] { return [this.node]; }
|
||||
getDocumentationComment(): ts.SymbolDisplayPart[] { return []; }
|
||||
|
||||
static of(name: string): MockSymbol { return new MockSymbol(name); }
|
||||
static of (name: string): MockSymbol { return new MockSymbol(name); }
|
||||
}
|
||||
|
||||
export function expectNoDiagnostics(diagnostics: ts.Diagnostic[]) {
|
||||
for (const diagnostic of diagnostics) {
|
||||
let message = ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n");
|
||||
let message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
|
||||
let {line, character} = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
|
||||
console.log(`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`);
|
||||
}
|
||||
|
@ -131,13 +135,13 @@ export function allChildren<T>(node: ts.Node, cb: (node: ts.Node) => T): T {
|
|||
}
|
||||
|
||||
export function findClass(sourceFile: ts.SourceFile, name: string): ts.ClassDeclaration {
|
||||
return ts.forEachChild(sourceFile,
|
||||
node => isClass(node) && isNamed(node.name, name) ? node : undefined);
|
||||
return ts.forEachChild(
|
||||
sourceFile, node => isClass(node) && isNamed(node.name, name) ? node : undefined);
|
||||
}
|
||||
|
||||
export function findVar(sourceFile: ts.SourceFile, name: string): ts.VariableDeclaration {
|
||||
return allChildren(sourceFile,
|
||||
node => isVar(node) && isNamed(node.name, name) ? node : undefined);
|
||||
return allChildren(
|
||||
sourceFile, node => isVar(node) && isNamed(node.name, name) ? node : undefined);
|
||||
}
|
||||
|
||||
export function isClass(node: ts.Node): node is ts.ClassDeclaration {
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import {RuleWalker} from 'tslint/lib/language/walker';
|
||||
import {RuleFailure} from 'tslint/lib/lint';
|
||||
import {AbstractRule} from 'tslint/lib/rules';
|
||||
import {RuleWalker} from 'tslint/lib/language/walker';
|
||||
import * as ts from 'typescript';
|
||||
|
||||
export class Rule extends AbstractRule {
|
||||
public static FAILURE_STRING = "duplicate module import";
|
||||
public static FAILURE_STRING = 'duplicate module import';
|
||||
|
||||
public apply(sourceFile: ts.SourceFile): RuleFailure[] {
|
||||
const typedefWalker = new ModuleImportWalker(sourceFile, this.getOptions());
|
||||
|
@ -27,12 +27,12 @@ class ModuleImportWalker extends RuleWalker {
|
|||
|
||||
private checkTypeAnnotation(location: number, typeAnnotation: ts.TypeNode, name?: ts.Node) {
|
||||
if (typeAnnotation == null) {
|
||||
let ns = "<name missing>";
|
||||
let ns = '<name missing>';
|
||||
if (name != null && name.kind === ts.SyntaxKind.Identifier) {
|
||||
ns = (<ts.Identifier>name).text;
|
||||
}
|
||||
if (ns.charAt(0) === '_') return;
|
||||
let failure = this.createFailure(location, 1, "expected parameter " + ns + " to have a type");
|
||||
let failure = this.createFailure(location, 1, 'expected parameter ' + ns + ' to have a type');
|
||||
this.addFailure(failure);
|
||||
}
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ class ModuleImportWalker extends RuleWalker {
|
|||
var text = moduleSpecifier.getText();
|
||||
if (this.importModulesSeen.indexOf(text) >= 0) {
|
||||
let failure =
|
||||
this.createFailure(moduleSpecifier.getEnd(), 1, "Duplicate imports from module " + text);
|
||||
this.createFailure(moduleSpecifier.getEnd(), 1, 'Duplicate imports from module ' + text);
|
||||
this.addFailure(failure);
|
||||
}
|
||||
this.importModulesSeen.push(text);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import {RuleWalker} from 'tslint/lib/language/walker';
|
||||
import {RuleFailure} from 'tslint/lib/lint';
|
||||
import {AbstractRule} from 'tslint/lib/rules';
|
||||
import {RuleWalker} from 'tslint/lib/language/walker';
|
||||
import * as ts from 'typescript';
|
||||
|
||||
export class Rule extends AbstractRule {
|
||||
|
@ -24,7 +24,7 @@ class TypedefWalker extends RuleWalker {
|
|||
private hasInternalAnnotation(range: ts.CommentRange): boolean {
|
||||
let text = this.getSourceFile().text;
|
||||
let comment = text.substring(range.pos, range.end);
|
||||
return comment.indexOf("@internal") >= 0;
|
||||
return comment.indexOf('@internal') >= 0;
|
||||
}
|
||||
|
||||
private assertInternalAnnotationPresent(node: ts.Declaration) {
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import {RuleWalker} from 'tslint/lib/language/walker';
|
||||
import {RuleFailure} from 'tslint/lib/lint';
|
||||
import {AbstractRule} from 'tslint/lib/rules';
|
||||
import {RuleWalker} from 'tslint/lib/language/walker';
|
||||
import * as ts from 'typescript';
|
||||
|
||||
export class Rule extends AbstractRule {
|
||||
public static FAILURE_STRING = "missing type declaration";
|
||||
public static FAILURE_STRING = 'missing type declaration';
|
||||
|
||||
public apply(sourceFile: ts.SourceFile): RuleFailure[] {
|
||||
const typedefWalker = new TypedefWalker(sourceFile, this.getOptions());
|
||||
|
@ -28,12 +28,12 @@ class TypedefWalker extends RuleWalker {
|
|||
|
||||
private checkTypeAnnotation(location: number, typeAnnotation: ts.TypeNode, name?: ts.Node) {
|
||||
if (typeAnnotation == null) {
|
||||
let ns = "<name missing>";
|
||||
let ns = '<name missing>';
|
||||
if (name != null && name.kind === ts.SyntaxKind.Identifier) {
|
||||
ns = (<ts.Identifier>name).text;
|
||||
}
|
||||
if (ns.charAt(0) === '_') return;
|
||||
let failure = this.createFailure(location, 1, "expected parameter " + ns + " to have a type");
|
||||
let failure = this.createFailure(location, 1, 'expected parameter ' + ns + ' to have a type');
|
||||
this.addFailure(failure);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import {RuleWalker} from 'tslint/lib/language/walker';
|
||||
import {RuleFailure} from 'tslint/lib/lint';
|
||||
import {AbstractRule} from 'tslint/lib/rules';
|
||||
import {RuleWalker} from 'tslint/lib/language/walker';
|
||||
import * as ts from 'typescript';
|
||||
|
||||
export class Rule extends AbstractRule {
|
||||
public static FAILURE_STRING = "missing type declaration";
|
||||
public static FAILURE_STRING = 'missing type declaration';
|
||||
|
||||
public apply(sourceFile: ts.SourceFile): RuleFailure[] {
|
||||
const typedefWalker = new TypedefWalker(sourceFile, this.getOptions());
|
||||
|
@ -50,12 +50,12 @@ class TypedefWalker extends RuleWalker {
|
|||
|
||||
private checkTypeAnnotation(typeAnnotation: ts.TypeNode, name: ts.Node, start: number) {
|
||||
if (typeAnnotation == null) {
|
||||
let ns = "<name missing>";
|
||||
let ns = '<name missing>';
|
||||
if (name != null && name.kind === ts.SyntaxKind.Identifier) {
|
||||
ns = (<ts.Identifier>name).text;
|
||||
}
|
||||
if (ns.charAt(0) === '_') return;
|
||||
let failure = this.createFailure(start, 1, "expected " + ns + " to have a return type");
|
||||
let failure = this.createFailure(start, 1, 'expected ' + ns + ' to have a return type');
|
||||
this.addFailure(failure);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue