diff --git a/gulpfile.js b/gulpfile.js index 02911f7ec6..34939bf8d7 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -10,7 +10,10 @@ var ejs = require('gulp-ejs'); var path = require('path'); var through2 = require('through2'); var file2moduleName = require('./file2modulename'); -var exec = require('child_process').exec; +var spawn = require('child_process').spawn; +var fs = require('fs'); +var path = require('path'); +var readline = require('readline'); var Q = require('q'); var js2es5Options = { @@ -31,14 +34,6 @@ var js2dartOptions = { var gulpTraceur = require('./tools/transpiler/gulp-traceur'); -function execWithLog(command, options, done) { - exec(command, options, function (err, stdout, stderr) { - stdout && console.log(stdout); - stderr && console.log(stderr); - done(err); - }); -} - // --------- // traceur runtime @@ -55,20 +50,10 @@ var sourceTypeConfigs = { compilerOptions: js2dartOptions, transpileSrc: ['modules/**/*.js'], htmlSrc: ['modules/*/src/**/*.html'], - copySrc: ['modules/**/*.dart', 'modules/**/*.yaml'], + copySrc: ['modules/**/*.dart'], outputDir: 'build/dart', outputExt: 'dart', - mimeType: 'application/dart', - postProcess: function(file, done) { - if (file.path.match(/pubspec\.yaml/)) { - console.log('pub get ' + file.path); - execWithLog('pub get', { - cwd: path.dirname(file.path) - }, done); - } else { - done(); - } - } + mimeType: 'application/dart' }, js: { compilerOptions: js2es5Options, @@ -76,8 +61,7 @@ var sourceTypeConfigs = { htmlSrc: ['modules/*/src/**/*.html'], copySrc: ['modules/**/*.es5'], outputDir: 'build/js', - outputExt: 'js', - postProcess: null + outputExt: 'js' } }; @@ -91,24 +75,35 @@ gulp.task('modules/build.dart/src', function() { return createModuleTask(sourceTypeConfigs.dart); }); -gulp.task('modules/build.dart/analyzer', function() { - var baseDir = sourceTypeConfigs.dart.outputDir; - var files = [].slice.call(glob.sync('*/lib/*.dart', { - cwd: baseDir - })); - files = files.filter(function(fileName) { - return fileName.match(/(\w+)\/lib\/\1/); - }); - return Q.all(files.map(function(fileName) { - var deferred = Q.defer(); - execWithLog('dartanalyzer '+baseDir+'/'+fileName, {}, deferred.makeNodeResolver()); - return deferred.promise; - })); +gulp.task('modules/build.dart/pubspec', function(done) { + var outputDir = sourceTypeConfigs.dart.outputDir; + return gulp.src('modules/*/pubspec.yaml') + .pipe(through2.obj(function(file, enc, done) { + var targetFile = path.join(outputDir, file.relative); + if (fs.existsSync(targetFile)) { + file.previousContents = fs.readFileSync(targetFile); + } else { + file.previousContents = ''; + } + this.push(file); + done(); + })) + .pipe(gulp.dest(outputDir)) + .pipe(through2.obj(function(file, enc, done) { + if (file.previousContents.toString() !== file.contents.toString()) { + console.log(file.path + ' changed, calling pub get'); + var stream = spawn('pub', ['get'], { + stdio: [process.stdin, process.stdout, process.stderr], + cwd: path.dirname(file.path) + }); + stream.on('close', done); + } else { + done(); + } + })); }); -gulp.task('modules/build.dart', function(done) { - runSequence('modules/build.dart/src', 'modules/build.dart/analyzer', done); -}); +gulp.task('modules/build.dart', ['modules/build.dart/src', 'modules/build.dart/pubspec']); gulp.task('modules/build.js', function() { return createModuleTask(sourceTypeConfigs.js); @@ -136,15 +131,77 @@ function createModuleTask(sourceTypeConfig) { })) .pipe(gulp.dest(sourceTypeConfig.outputDir)); - var s = mergeStreams(transpile, copy, html); - if (!sourceTypeConfig.postProcess) { - return s; - } - return s.pipe(through2.obj(function(file, enc, done) { - sourceTypeConfig.postProcess(file, done); - })); + return mergeStreams(transpile, copy, html); } +// ------------------ +// ANALYZE + +gulp.task('analyze/dartanalyzer', function(done) { + var pubSpecs = [].slice.call(glob.sync('build/dart/*/pubspec.yaml', { + cwd: __dirname + })); + var tempFile = '_analyzer.dart'; + // analyze in parallel! + return Q.all(pubSpecs.map(function(pubSpecFile) { + var dir = path.dirname(pubSpecFile); + var srcFiles = [].slice.call(glob.sync('lib/**/*.dart', { + cwd: dir + })); + var testFiles = [].slice.call(glob.sync('test/**/*_spec.dart', { + cwd: dir + })); + var analyzeFile = ['library _analyzer;']; + srcFiles.concat(testFiles).forEach(function(fileName, index) { + if (fileName !== tempFile) { + analyzeFile.push('import "./'+fileName+'" as mod'+index+';'); + } + }); + fs.writeFileSync(path.join(dir, tempFile), analyzeFile.join('\n')); + var defer = Q.defer(); + analyze(dir, defer.makeNodeResolver()); + return defer.promise; + })); + + function analyze(dirName, done) { + var stream = spawn('dartanalyzer', ['--fatal-warnings', tempFile], { + // inherit stdin and stderr, but filter stdout + stdio: [process.stdin, 'pipe', process.stderr], + cwd: dirName + }); + // Filter out unused imports from our generated file. + // We don't reexports from the generated file + // as this could lead to name clashes when two files + // export the same thing. + var rl = require('readline').createInterface({ + input: stream.stdout, + output: process.stdout, + terminal: false + }); + var hintCount = 0; + rl.on('line', function(line) { + if (line.match(/Unused import .*_analyzer\.dart/)) { + return; + } + if (line.match(/\[hint\]/)) { + hintCount++; + } + console.log(dirName + ':' + line); + }); + stream.on('close', function(code) { + var error; + if (code !== 0) { + error = new Error('Dartanalyzer failed with exit code ' + code); + } + if (hintCount > 0) { + error = new Error('Dartanalyzer showed hints'); + } + done(error); + }); + } +}); + + // ------------------ // WEB SERVER gulp.task('serve', connect.server({ @@ -167,4 +224,15 @@ gulp.task('serve', connect.server({ gulp.task('clean', ['modules/clean']); -gulp.task('build', ['jsRuntime/build', 'modules/build.dart', 'modules/build.js']); +gulp.task('build', function(done) { + runSequence( + // parallel + ['jsRuntime/build', 'modules/build.dart', 'modules/build.js'], + // sequential + 'analyze/dartanalyzer' + ); +}); + +gulp.task('analyze', function(done) { + runSequence('analyze/dartanalyzer'); +}); diff --git a/modules/change_detection/pubspec.yaml b/modules/change_detection/pubspec.yaml index 9f912e20ce..eda854fbf6 100644 --- a/modules/change_detection/pubspec.yaml +++ b/modules/change_detection/pubspec.yaml @@ -2,8 +2,9 @@ name: change_detection environment: sdk: '>=1.4.0' dependencies: + facade: + path: ../facade dev_dependencies: test_lib: path: ../test_lib - facade: - path: ../facade + guinness: ">=0.1.5 <0.2.0" diff --git a/modules/change_detection/src/parser/scanner.js b/modules/change_detection/src/parser/scanner.js index b27a3ce09a..3ca4f60b96 100644 --- a/modules/change_detection/src/parser/scanner.js +++ b/modules/change_detection/src/parser/scanner.js @@ -368,7 +368,7 @@ export class Scanner { } error(message:string) { - var position:int = this.index + this.offset; + var position:int = this.index; throw `Lexer Error: ${message} at column ${position} in expression [${input}]`; } } diff --git a/modules/change_detection/src/record.js b/modules/change_detection/src/record.js index 9774486b43..5813604aca 100644 --- a/modules/change_detection/src/record.js +++ b/modules/change_detection/src/record.js @@ -25,12 +25,14 @@ export class ProtoRecord { this.prev = null; this.changeNotifier = null; this._clone = null; - } + this.changeContext = null; + this.dispatcherContext = null; + } instantiate(watchGroup/*:wg.WatchGroup*/):Record { var record = this._clone = new Record(watchGroup, this); record.prev = this.prev._clone; - record._checkPrev = this._prev._clone; + record._checkPrev = this.prev._clone; return _clone; } diff --git a/modules/change_detection/test/change_detection_spec.js b/modules/change_detection/test/change_detection_spec.js index 9f43086f3b..07da7050dd 100644 --- a/modules/change_detection/test/change_detection_spec.js +++ b/modules/change_detection/test/change_detection_spec.js @@ -1,13 +1,11 @@ -import {describe, it, expect} from 'test_lib/test_lib'; -import {ProtoWatchGroup, WatchGroup, WatchGroupDispatcher} from 'change_detection/change_detection'; -import {DOM} from 'facade/dom'; +import {describe, it, xit, expect} from 'test_lib/test_lib'; +import {ProtoWatchGroup, WatchGroup, WatchGroupDispatcher, ChangeDetection} from 'change_detection/change_detection'; export function main() { describe('change_detection', function() { describe('ChangeDetection', function() { - it('should do simple watching', function() { - return; // remove me once xit or CD works. + xit('should do simple watching', function() { var person = new Person('misko', 38); var pwg = new ProtoWatchGroup(); pwg.watch('name', 'nameToken'); @@ -32,11 +30,16 @@ export function main() { class Person { constructor(name:string, age:number) { - this.name = null; - this.a + this.name = name; + this.age = age; } } -class Dispatcher extends WatchGroupDispatcher { +class LoggingDispatcher extends WatchGroupDispatcher { + constructor() { + this.log = null; + } + clear() { + } } diff --git a/modules/change_detection/test/parser/lexer_spec.js b/modules/change_detection/test/parser/lexer_spec.js index 96434f06d6..1375cc3055 100644 --- a/modules/change_detection/test/parser/lexer_spec.js +++ b/modules/change_detection/test/parser/lexer_spec.js @@ -1,6 +1,5 @@ import {describe, it, expect} from 'test_lib/test_lib'; import {Scanner, Token} from 'change_detection/parser/scanner'; -import {DOM} from 'facade/dom'; import {List, ListWrapper} from "facade/collection"; import {StringWrapper} from "facade/lang"; diff --git a/modules/core/pubspec.yaml b/modules/core/pubspec.yaml index 79e6e01bb4..b60bd85b71 100644 --- a/modules/core/pubspec.yaml +++ b/modules/core/pubspec.yaml @@ -11,3 +11,4 @@ dependencies: dev_dependencies: test_lib: path: ../test_lib + guinness: ">=0.1.5 <0.2.0" diff --git a/modules/core/src/annotations/directive.js b/modules/core/src/annotations/directive.js index c8493dfcb7..c87d861014 100644 --- a/modules/core/src/annotations/directive.js +++ b/modules/core/src/annotations/directive.js @@ -1,19 +1,19 @@ -import {Type} from 'facade/lang'; -import {ElementServicesFunction} from './facade'; +// import {Type} from 'facade/lang'; +// import {ElementServicesFunction} from './facade'; import {ABSTRACT} from 'facade/lang'; -@ABSTRACT +@ABSTRACT() export class Directive { constructor({ selector, lightDomServices, implementsTypes - }:{ + }/*:{ selector:String, lightDomServices:ElementServicesFunction, implementsTypes:Array - }) + }*/) { this.lightDomServices = lightDomServices; this.selector = selector; diff --git a/modules/core/src/annotations/facade.dart b/modules/core/src/annotations/facade.dart index fcb9ee3718..833a7d4476 100644 --- a/modules/core/src/annotations/facade.dart +++ b/modules/core/src/annotations/facade.dart @@ -1,3 +1,5 @@ +library core.annotations.facade; + import 'package:di/di.dart' show Module; import '../compiler/element_module.dart' show ElementModule; diff --git a/modules/core/src/annotations/template_config.js b/modules/core/src/annotations/template_config.js index 321f8292bd..48ac1a427a 100644 --- a/modules/core/src/annotations/template_config.js +++ b/modules/core/src/annotations/template_config.js @@ -1,4 +1,4 @@ -import {Type, List} from 'facade/lang'; +// import {Type, List} from 'facade/lang'; export class TemplateConfig { constructor({ @@ -6,11 +6,11 @@ export class TemplateConfig { directives, formatters, source - }: { + }/*: { url: String, directives: List, formatters: List, source: List - }) + }*/) {} } \ No newline at end of file diff --git a/modules/core/src/compiler/compiler.js b/modules/core/src/compiler/compiler.js index a9048795f3..d1ecf77711 100644 --- a/modules/core/src/compiler/compiler.js +++ b/modules/core/src/compiler/compiler.js @@ -1,6 +1,6 @@ import {Future, Type} from 'facade/lang'; import {Element} from 'facade/dom'; -import {ProtoView} from './view'; +//import {ProtoView} from './view'; import {TemplateLoader} from './template_loader'; import {FIELD} from 'facade/lang'; @@ -19,7 +19,7 @@ export class Compiler { * - don't know about injector in deserialization * - compile does not need the injector, only the ViewFactory does */ - compile(component:Type, element:Element/* = null*/):Future { + compile(component:Type, element:Element/* = null*/):Future/**/ { return null; } diff --git a/modules/core/src/compiler/template_loader.js b/modules/core/src/compiler/template_loader.js index cc03cf8551..346a9343c4 100644 --- a/modules/core/src/compiler/template_loader.js +++ b/modules/core/src/compiler/template_loader.js @@ -1,11 +1,11 @@ import {Future} from 'facade/lang'; -import {Document} from 'facade/dom'; +//import {Document} from 'facade/dom'; export class TemplateLoader { constructor() {} - load(url:String):Future { + load(url:String):Future/**/ { return null; } } \ No newline at end of file diff --git a/modules/core/src/life_cycle/life_cycle.js b/modules/core/src/life_cycle/life_cycle.js index 62513eec52..e0128438b6 100644 --- a/modules/core/src/life_cycle/life_cycle.js +++ b/modules/core/src/life_cycle/life_cycle.js @@ -4,7 +4,10 @@ export class LifeCycle { @FIELD('final _changeDetection:ChangeDetection') @FIELD('final _onChangeDispatcher:OnChangeDispatcher') - constructor() {} + constructor() { + this._changeDetection = null; + this._onChangeDispatcher = null; + } digest() { _changeDetection.detectChanges(); diff --git a/modules/core/test/compiler/compiler_spec.js b/modules/core/test/compiler/compiler_spec.js index b087e86467..f6ce46a564 100644 --- a/modules/core/test/compiler/compiler_spec.js +++ b/modules/core/test/compiler/compiler_spec.js @@ -1,5 +1,5 @@ -import {describe, it, expect} from 'test_lib/test_lib'; -import {Compiler} from 'core/compiler/compiler'; +import {describe, it} from 'test_lib/test_lib'; +//import {Compiler} from 'core/compiler/compiler'; export function main() { describe('compiler', function() { diff --git a/modules/di/pubspec.yaml b/modules/di/pubspec.yaml index 47f23d1078..c7d6d81848 100644 --- a/modules/di/pubspec.yaml +++ b/modules/di/pubspec.yaml @@ -7,3 +7,4 @@ dependencies: dev_dependencies: test_lib: path: ../test_lib + guinness: ">=0.1.5 <0.2.0" diff --git a/modules/examples/pubspec.yaml b/modules/examples/pubspec.yaml index 4fef0f5046..2e033ff7ad 100644 --- a/modules/examples/pubspec.yaml +++ b/modules/examples/pubspec.yaml @@ -2,6 +2,9 @@ name: examples environment: sdk: '>=1.4.0' dependencies: + facade: + path: ../facade dev_dependencies: test_lib: path: ../test_lib + guinness: ">=0.1.5 <0.2.0" diff --git a/modules/facade/pubspec.yaml b/modules/facade/pubspec.yaml index 7814562608..000fd0515b 100644 --- a/modules/facade/pubspec.yaml +++ b/modules/facade/pubspec.yaml @@ -5,3 +5,4 @@ dependencies: dev_dependencies: test_lib: path: ../test_lib + guinness: ">=0.1.5 <0.2.0" diff --git a/modules/facade/src/dom.dart b/modules/facade/src/dom.dart index bafe427424..7efc313b59 100644 --- a/modules/facade/src/dom.dart +++ b/modules/facade/src/dom.dart @@ -6,7 +6,7 @@ export 'dart:html' show DocumentFragment, Node, Element, TemplateElement, Text; class DOM { static query(selector) { - return document.query(selector); + return document.querySelector(selector); } static on(element, event, callback) { element.addEventListener(event, callback); diff --git a/modules/facade/src/lang.dart b/modules/facade/src/lang.dart index 6c00582265..ca5004b9c2 100644 --- a/modules/facade/src/lang.dart +++ b/modules/facade/src/lang.dart @@ -4,12 +4,20 @@ export 'dart:async' show Future; export 'dart:core' show Type, int; class FIELD { - const constructor(this.definition); + final String definition; + const FIELD(this.definition); } -class CONST {} -class ABSTRACT {} -class IMPLEMENTS {} +class CONST { + const CONST(); +} +class ABSTRACT { + const ABSTRACT(); +} +class IMPLEMENTS { + final interfaceClass; + const IMPLEMENTS(this.interfaceClass); +} class StringWrapper { diff --git a/modules/test_lib/src/test_lib.dart b/modules/test_lib/src/test_lib.dart index 78c44a36f0..f2dcb370d3 100644 --- a/modules/test_lib/src/test_lib.dart +++ b/modules/test_lib/src/test_lib.dart @@ -1,3 +1,4 @@ +library test_lib.test_lib; export 'package:guinness/guinness.dart' show describe, ddescribe, xdescribe, it, xit, iit, diff --git a/pubspec.yaml b/pubspec.yaml index ce83bf4e7d..95efea1af6 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,6 +2,8 @@ name: angular environment: sdk: '>=1.4.0' dependencies: + examples: + path: build/dart/examples test_lib: path: build/dart/test_lib facade: diff --git a/tools/transpiler/src/dart_writer.js b/tools/transpiler/src/dart_writer.js index 34bd765b1c..213808b97b 100644 --- a/tools/transpiler/src/dart_writer.js +++ b/tools/transpiler/src/dart_writer.js @@ -255,13 +255,16 @@ export class DartTreeWriter extends JavaScriptParseTreeWriter { // ANNOTATIONS // TODO(vojta): this is just fixing a bug in Traceur, send a PR. visitAnnotation(tree) { - if (tree.name.identifierToken) { - var nameValue = tree.name.identifierToken.value; - if (nameValue === nameValue.toUpperCase()) { - // control annotations for transpiler - return; - } - } + // TODO(tbosch): Disabled the removal of control annotations (annotations in uppercase), + // as they should be handeled by a transformer and right now lead + // to errors (unused import) in dartanalyzer. + // if (tree.name.identifierToken) { + // var nameValue = tree.name.identifierToken.value; + // if (nameValue === nameValue.toUpperCase()) { + // // control annotations for transpiler + // return; + // } + // } this.write_(AT); this.visitAny(tree.name);