@@ -10,7 +10,10 @@ var ejs = require('gulp-ejs');
1010var path = require ( 'path' ) ;
1111var through2 = require ( 'through2' ) ;
1212var file2moduleName = require ( './file2modulename' ) ;
13- var exec = require ( 'child_process' ) . exec ;
13+ var spawn = require ( 'child_process' ) . spawn ;
14+ var fs = require ( 'fs' ) ;
15+ var path = require ( 'path' ) ;
16+ var readline = require ( 'readline' ) ;
1417var Q = require ( 'q' ) ;
1518
1619var js2es5Options = {
@@ -31,14 +34,6 @@ var js2dartOptions = {
3134
3235var gulpTraceur = require ( './tools/transpiler/gulp-traceur' ) ;
3336
34- function execWithLog ( command , options , done ) {
35- exec ( command , options , function ( err , stdout , stderr ) {
36- stdout && console . log ( stdout ) ;
37- stderr && console . log ( stderr ) ;
38- done ( err ) ;
39- } ) ;
40- }
41-
4237// ---------
4338// traceur runtime
4439
@@ -55,29 +50,18 @@ var sourceTypeConfigs = {
5550 compilerOptions : js2dartOptions ,
5651 transpileSrc : [ 'modules/**/*.js' ] ,
5752 htmlSrc : [ 'modules/*/src/**/*.html' ] ,
58- copySrc : [ 'modules/**/*.dart' , 'modules/**/*.yaml' ] ,
53+ copySrc : [ 'modules/**/*.dart' ] ,
5954 outputDir : 'build/dart' ,
6055 outputExt : 'dart' ,
61- mimeType : 'application/dart' ,
62- postProcess : function ( file , done ) {
63- if ( file . path . match ( / p u b s p e c \. y a m l / ) ) {
64- console . log ( 'pub get ' + file . path ) ;
65- execWithLog ( 'pub get' , {
66- cwd : path . dirname ( file . path )
67- } , done ) ;
68- } else {
69- done ( ) ;
70- }
71- }
56+ mimeType : 'application/dart'
7257 } ,
7358 js : {
7459 compilerOptions : js2es5Options ,
7560 transpileSrc : [ 'modules/**/*.js' , 'modules/**/*.es6' ] ,
7661 htmlSrc : [ 'modules/*/src/**/*.html' ] ,
7762 copySrc : [ 'modules/**/*.es5' ] ,
7863 outputDir : 'build/js' ,
79- outputExt : 'js' ,
80- postProcess : null
64+ outputExt : 'js'
8165 }
8266} ;
8367
@@ -91,24 +75,35 @@ gulp.task('modules/build.dart/src', function() {
9175 return createModuleTask ( sourceTypeConfigs . dart ) ;
9276} ) ;
9377
94- gulp . task ( 'modules/build.dart/analyzer' , function ( ) {
95- var baseDir = sourceTypeConfigs . dart . outputDir ;
96- var files = [ ] . slice . call ( glob . sync ( '*/lib/*.dart' , {
97- cwd : baseDir
98- } ) ) ;
99- files = files . filter ( function ( fileName ) {
100- return fileName . match ( / ( \w + ) \/ l i b \/ \1/ ) ;
101- } ) ;
102- return Q . all ( files . map ( function ( fileName ) {
103- var deferred = Q . defer ( ) ;
104- execWithLog ( 'dartanalyzer ' + baseDir + '/' + fileName , { } , deferred . makeNodeResolver ( ) ) ;
105- return deferred . promise ;
106- } ) ) ;
78+ gulp . task ( 'modules/build.dart/pubspec' , function ( done ) {
79+ var outputDir = sourceTypeConfigs . dart . outputDir ;
80+ return gulp . src ( 'modules/*/pubspec.yaml' )
81+ . pipe ( through2 . obj ( function ( file , enc , done ) {
82+ var targetFile = path . join ( outputDir , file . relative ) ;
83+ if ( fs . existsSync ( targetFile ) ) {
84+ file . previousContents = fs . readFileSync ( targetFile ) ;
85+ } else {
86+ file . previousContents = '' ;
87+ }
88+ this . push ( file ) ;
89+ done ( ) ;
90+ } ) )
91+ . pipe ( gulp . dest ( outputDir ) )
92+ . pipe ( through2 . obj ( function ( file , enc , done ) {
93+ if ( file . previousContents . toString ( ) !== file . contents . toString ( ) ) {
94+ console . log ( file . path + ' changed, calling pub get' ) ;
95+ var stream = spawn ( 'pub' , [ 'get' ] , {
96+ stdio : [ process . stdin , process . stdout , process . stderr ] ,
97+ cwd : path . dirname ( file . path )
98+ } ) ;
99+ stream . on ( 'close' , done ) ;
100+ } else {
101+ done ( ) ;
102+ }
103+ } ) ) ;
107104} ) ;
108105
109- gulp . task ( 'modules/build.dart' , function ( done ) {
110- runSequence ( 'modules/build.dart/src' , 'modules/build.dart/analyzer' , done ) ;
111- } ) ;
106+ gulp . task ( 'modules/build.dart' , [ 'modules/build.dart/src' , 'modules/build.dart/pubspec' ] ) ;
112107
113108gulp . task ( 'modules/build.js' , function ( ) {
114109 return createModuleTask ( sourceTypeConfigs . js ) ;
@@ -136,15 +131,77 @@ function createModuleTask(sourceTypeConfig) {
136131 } ) )
137132 . pipe ( gulp . dest ( sourceTypeConfig . outputDir ) ) ;
138133
139- var s = mergeStreams ( transpile , copy , html ) ;
140- if ( ! sourceTypeConfig . postProcess ) {
141- return s ;
142- }
143- return s . pipe ( through2 . obj ( function ( file , enc , done ) {
144- sourceTypeConfig . postProcess ( file , done ) ;
145- } ) ) ;
134+ return mergeStreams ( transpile , copy , html ) ;
146135}
147136
137+ // ------------------
138+ // ANALYZE
139+
140+ gulp . task ( 'analyze/dartanalyzer' , function ( done ) {
141+ var pubSpecs = [ ] . slice . call ( glob . sync ( 'build/dart/*/pubspec.yaml' , {
142+ cwd : __dirname
143+ } ) ) ;
144+ var tempFile = '_analyzer.dart' ;
145+ // analyze in parallel!
146+ return Q . all ( pubSpecs . map ( function ( pubSpecFile ) {
147+ var dir = path . dirname ( pubSpecFile ) ;
148+ var srcFiles = [ ] . slice . call ( glob . sync ( 'lib/**/*.dart' , {
149+ cwd : dir
150+ } ) ) ;
151+ var testFiles = [ ] . slice . call ( glob . sync ( 'test/**/*_spec.dart' , {
152+ cwd : dir
153+ } ) ) ;
154+ var analyzeFile = [ 'library _analyzer;' ] ;
155+ srcFiles . concat ( testFiles ) . forEach ( function ( fileName , index ) {
156+ if ( fileName !== tempFile ) {
157+ analyzeFile . push ( 'import "./' + fileName + '" as mod' + index + ';' ) ;
158+ }
159+ } ) ;
160+ fs . writeFileSync ( path . join ( dir , tempFile ) , analyzeFile . join ( '\n' ) ) ;
161+ var defer = Q . defer ( ) ;
162+ analyze ( dir , defer . makeNodeResolver ( ) ) ;
163+ return defer . promise ;
164+ } ) ) ;
165+
166+ function analyze ( dirName , done ) {
167+ var stream = spawn ( 'dartanalyzer' , [ '--fatal-warnings' , tempFile ] , {
168+ // inherit stdin and stderr, but filter stdout
169+ stdio : [ process . stdin , 'pipe' , process . stderr ] ,
170+ cwd : dirName
171+ } ) ;
172+ // Filter out unused imports from our generated file.
173+ // We don't reexports from the generated file
174+ // as this could lead to name clashes when two files
175+ // export the same thing.
176+ var rl = require ( 'readline' ) . createInterface ( {
177+ input : stream . stdout ,
178+ output : process . stdout ,
179+ terminal : false
180+ } ) ;
181+ var hintCount = 0 ;
182+ rl . on ( 'line' , function ( line ) {
183+ if ( line . match ( / U n u s e d i m p o r t .* _ a n a l y z e r \. d a r t / ) ) {
184+ return ;
185+ }
186+ if ( line . match ( / \[ h i n t \] / ) ) {
187+ hintCount ++ ;
188+ }
189+ console . log ( dirName + ':' + line ) ;
190+ } ) ;
191+ stream . on ( 'close' , function ( code ) {
192+ var error ;
193+ if ( code !== 0 ) {
194+ error = new Error ( 'Dartanalyzer failed with exit code ' + code ) ;
195+ }
196+ if ( hintCount > 0 ) {
197+ error = new Error ( 'Dartanalyzer showed hints' ) ;
198+ }
199+ done ( error ) ;
200+ } ) ;
201+ }
202+ } ) ;
203+
204+
148205// ------------------
149206// WEB SERVER
150207gulp . task ( 'serve' , connect . server ( {
@@ -167,4 +224,15 @@ gulp.task('serve', connect.server({
167224
168225gulp . task ( 'clean' , [ 'modules/clean' ] ) ;
169226
170- gulp . task ( 'build' , [ 'jsRuntime/build' , 'modules/build.dart' , 'modules/build.js' ] ) ;
227+ gulp . task ( 'build' , function ( done ) {
228+ runSequence (
229+ // parallel
230+ [ 'jsRuntime/build' , 'modules/build.dart' , 'modules/build.js' ] ,
231+ // sequential
232+ 'analyze/dartanalyzer'
233+ ) ;
234+ } ) ;
235+
236+ gulp . task ( 'analyze' , function ( done ) {
237+ runSequence ( 'analyze/dartanalyzer' ) ;
238+ } ) ;
0 commit comments