chore(lint): format tools dir

This commit is contained in:
Alex Eagle 2016-05-26 10:45:37 -07:00
parent 5936624d11
commit 9096481744
46 changed files with 633 additions and 654 deletions

View File

@ -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.

View File

@ -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[]) {}
}

View File

@ -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}`;
}
}

View File

@ -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) {

View File

@ -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);

View File

@ -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\'');
});
});

View File

@ -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}'`);
}
});

View File

@ -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();

View File

@ -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;

View File

@ -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 = {

View File

@ -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 || {};
}

View File

@ -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);

View File

@ -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);

View File

@ -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, '/');
}

View File

@ -1,4 +1,4 @@
declare module "broccoli-writer" {
declare module 'broccoli-writer' {
class Writer {
write(readTree: (tree: BroccoliTree) => Promise<string>, destDir: string): Promise<any>;
}

View File

@ -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);
}

View File

@ -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]);
}
}

View File

@ -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'));
}

View File

@ -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'));
}

View File

@ -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);
});
});
});
}
}

View File

@ -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\'');
});

View File

@ -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]` : ''));
}
}

View File

@ -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');

View File

@ -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']);

View File

@ -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'
});
}

View File

@ -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;

View File

@ -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[]>[]);

View File

@ -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);

View File

@ -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));
}

View File

@ -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'
]]
});
}

View File

@ -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();
}

View File

@ -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};
}
}

View File

@ -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]);
};
}

View File

@ -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

View File

@ -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);
});
}

View File

@ -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';
}

View File

@ -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]); }

View File

@ -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);

View File

@ -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;

View File

@ -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]
});
});
});

View File

@ -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',

View File

@ -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 {

View File

@ -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);

View File

@ -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) {

View File

@ -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);
}
}

View File

@ -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);
}
}