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