@@ -4,7 +4,6 @@ var fs = require("fs");
4
4
var os = require ( "os" ) ;
5
5
var path = require ( "path" ) ;
6
6
var child_process = require ( "child_process" ) ;
7
- var Linter = require ( "tslint" ) ;
8
7
var fold = require ( "travis-fold" ) ;
9
8
var runTestsInParallel = require ( "./scripts/mocha-parallel" ) . runTestsInParallel ;
10
9
@@ -33,6 +32,28 @@ if (process.env.path !== undefined) {
33
32
process . env . PATH = nodeModulesPathPrefix + process . env . PATH ;
34
33
}
35
34
35
+ function toNs ( diff ) {
36
+ return diff [ 0 ] * 1e9 + diff [ 1 ] ;
37
+ }
38
+
39
+ function mark ( ) {
40
+ if ( ! fold . isTravis ( ) ) return ;
41
+ var stamp = process . hrtime ( ) ;
42
+ var id = Math . floor ( Math . random ( ) * 0xFFFFFFFF ) . toString ( 16 ) ;
43
+ console . log ( "travis_time:start:" + id + "\r" ) ;
44
+ return {
45
+ stamp : stamp ,
46
+ id : id
47
+ } ;
48
+ }
49
+
50
+ function measure ( marker ) {
51
+ if ( ! fold . isTravis ( ) ) return ;
52
+ var diff = process . hrtime ( marker . stamp ) ;
53
+ var total = [ marker . stamp [ 0 ] + diff [ 0 ] , marker . stamp [ 1 ] + diff [ 1 ] ] ;
54
+ console . log ( "travis_time:end:" + marker . id + ":start=" + toNs ( marker . stamp ) + ",finish=" + toNs ( total ) + ",duration=" + toNs ( diff ) + "\r" ) ;
55
+ }
56
+
36
57
var compilerSources = [
37
58
"core.ts" ,
38
59
"performance.ts" ,
@@ -286,6 +307,7 @@ var builtLocalCompiler = path.join(builtLocalDirectory, compilerFilename);
286
307
*/
287
308
function compileFile ( outFile , sources , prereqs , prefixes , useBuiltCompiler , opts , callback ) {
288
309
file ( outFile , prereqs , function ( ) {
310
+ var startCompileTime = mark ( ) ;
289
311
opts = opts || { } ;
290
312
var compilerPath = useBuiltCompiler ? builtLocalCompiler : LKGCompiler ;
291
313
var options = "--noImplicitAny --noImplicitThis --noEmitOnError --types "
@@ -362,11 +384,13 @@ function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, opts
362
384
callback ( ) ;
363
385
}
364
386
387
+ measure ( startCompileTime ) ;
365
388
complete ( ) ;
366
389
} ) ;
367
390
ex . addListener ( "error" , function ( ) {
368
391
fs . unlinkSync ( outFile ) ;
369
392
fail ( "Compilation of " + outFile + " unsuccessful" ) ;
393
+ measure ( startCompileTime ) ;
370
394
} ) ;
371
395
ex . run ( ) ;
372
396
} , { async : true } ) ;
@@ -769,6 +793,7 @@ function runConsoleTests(defaultReporter, runInParallel) {
769
793
// timeout normally isn't necessary but Travis-CI has been timing out on compiler baselines occasionally
770
794
// default timeout is 2sec which really should be enough, but maybe we just need a small amount longer
771
795
if ( ! runInParallel ) {
796
+ var startTime = mark ( ) ;
772
797
tests = tests ? ' -g "' + tests + '"' : '' ;
773
798
var cmd = "mocha" + ( debug ? " --debug-brk" : "" ) + " -R " + reporter + tests + colors + bail + ' -t ' + testTimeout + ' ' + run ;
774
799
console . log ( cmd ) ;
@@ -777,20 +802,23 @@ function runConsoleTests(defaultReporter, runInParallel) {
777
802
process . env . NODE_ENV = "development" ;
778
803
exec ( cmd , function ( ) {
779
804
process . env . NODE_ENV = savedNodeEnv ;
805
+ measure ( startTime ) ;
780
806
runLinter ( ) ;
781
807
finish ( ) ;
782
808
} , function ( e , status ) {
783
809
process . env . NODE_ENV = savedNodeEnv ;
810
+ measure ( startTime ) ;
784
811
finish ( status ) ;
785
812
} ) ;
786
813
787
814
}
788
815
else {
789
816
var savedNodeEnv = process . env . NODE_ENV ;
790
817
process . env . NODE_ENV = "development" ;
818
+ var startTime = mark ( ) ;
791
819
runTestsInParallel ( taskConfigsFolder , run , { testTimeout : testTimeout , noColors : colors === " --no-colors " } , function ( err ) {
792
820
process . env . NODE_ENV = savedNodeEnv ;
793
-
821
+ measure ( startTime ) ;
794
822
// last worker clean everything and runs linter in case if there were no errors
795
823
deleteTemporaryProjectOutput ( ) ;
796
824
jake . rmRf ( taskConfigsFolder ) ;
@@ -909,16 +937,16 @@ task("tests-debug", ["setDebugMode", "tests"]);
909
937
// Makes the test results the new baseline
910
938
desc ( "Makes the most recent test results the new baseline, overwriting the old baseline" ) ;
911
939
task ( "baseline-accept" , function ( hardOrSoft ) {
912
- if ( ! hardOrSoft || hardOrSoft === "hard" ) {
913
- jake . rmRf ( refBaseline ) ;
914
- fs . renameSync ( localBaseline , refBaseline ) ;
915
- }
916
- else if ( hardOrSoft === "soft" ) {
917
- var files = jake . readdirR ( localBaseline ) ;
918
- for ( var i in files ) {
940
+ var files = jake . readdirR ( localBaseline ) ;
941
+ var deleteEnding = '.delete' ;
942
+ for ( var i in files ) {
943
+ if ( files [ i ] . substr ( files [ i ] . length - deleteEnding . length ) === deleteEnding ) {
944
+ var filename = path . basename ( files [ i ] ) ;
945
+ filename = filename . substr ( 0 , filename . length - deleteEnding . length ) ;
946
+ fs . unlink ( path . join ( refBaseline , filename ) ) ;
947
+ } else {
919
948
jake . cpR ( files [ i ] , refBaseline ) ;
920
949
}
921
- jake . rmRf ( path . join ( refBaseline , "local" ) ) ;
922
950
}
923
951
} ) ;
924
952
@@ -1025,36 +1053,6 @@ task("build-rules-end", [] , function() {
1025
1053
if ( fold . isTravis ( ) ) console . log ( fold . end ( "build-rules" ) ) ;
1026
1054
} ) ;
1027
1055
1028
- function getLinterOptions ( ) {
1029
- return {
1030
- configuration : require ( "./tslint.json" ) ,
1031
- formatter : "prose" ,
1032
- formattersDirectory : undefined ,
1033
- rulesDirectory : "built/local/tslint"
1034
- } ;
1035
- }
1036
-
1037
- function lintFileContents ( options , path , contents ) {
1038
- var ll = new Linter ( path , contents , options ) ;
1039
- console . log ( "Linting '" + path + "'." ) ;
1040
- return ll . lint ( ) ;
1041
- }
1042
-
1043
- function lintFile ( options , path ) {
1044
- var contents = fs . readFileSync ( path , "utf8" ) ;
1045
- return lintFileContents ( options , path , contents ) ;
1046
- }
1047
-
1048
- function lintFileAsync ( options , path , cb ) {
1049
- fs . readFile ( path , "utf8" , function ( err , contents ) {
1050
- if ( err ) {
1051
- return cb ( err ) ;
1052
- }
1053
- var result = lintFileContents ( options , path , contents ) ;
1054
- cb ( undefined , result ) ;
1055
- } ) ;
1056
- }
1057
-
1058
1056
var lintTargets = compilerSources
1059
1057
. concat ( harnessSources )
1060
1058
// Other harness sources
@@ -1065,73 +1063,78 @@ var lintTargets = compilerSources
1065
1063
. concat ( [ "Gulpfile.ts" ] )
1066
1064
. concat ( [ nodeServerInFile , perftscPath , "tests/perfsys.ts" , webhostPath ] ) ;
1067
1065
1066
+ function sendNextFile ( files , child , callback , failures ) {
1067
+ var file = files . pop ( ) ;
1068
+ if ( file ) {
1069
+ console . log ( "Linting '" + file + "'." ) ;
1070
+ child . send ( { kind : "file" , name : file } ) ;
1071
+ }
1072
+ else {
1073
+ child . send ( { kind : "close" } ) ;
1074
+ callback ( failures ) ;
1075
+ }
1076
+ }
1077
+
1078
+ function spawnLintWorker ( files , callback ) {
1079
+ var child = child_process . fork ( "./scripts/parallel-lint" ) ;
1080
+ var failures = 0 ;
1081
+ child . on ( "message" , function ( data ) {
1082
+ switch ( data . kind ) {
1083
+ case "result" :
1084
+ if ( data . failures > 0 ) {
1085
+ failures += data . failures ;
1086
+ console . log ( data . output ) ;
1087
+ }
1088
+ sendNextFile ( files , child , callback , failures ) ;
1089
+ break ;
1090
+ case "error" :
1091
+ console . error ( data . error ) ;
1092
+ failures ++ ;
1093
+ sendNextFile ( files , child , callback , failures ) ;
1094
+ break ;
1095
+ }
1096
+ } ) ;
1097
+ sendNextFile ( files , child , callback , failures ) ;
1098
+ }
1068
1099
1069
1100
desc ( "Runs tslint on the compiler sources. Optional arguments are: f[iles]=regex" ) ;
1070
1101
task ( "lint" , [ "build-rules" ] , function ( ) {
1071
1102
if ( fold . isTravis ( ) ) console . log ( fold . start ( "lint" ) ) ;
1072
- var lintOptions = getLinterOptions ( ) ;
1103
+ var startTime = mark ( ) ;
1073
1104
var failed = 0 ;
1074
1105
var fileMatcher = RegExp ( process . env . f || process . env . file || process . env . files || "" ) ;
1075
1106
var done = { } ;
1076
1107
for ( var i in lintTargets ) {
1077
1108
var target = lintTargets [ i ] ;
1078
1109
if ( ! done [ target ] && fileMatcher . test ( target ) ) {
1079
- var result = lintFile ( lintOptions , target ) ;
1080
- if ( result . failureCount > 0 ) {
1081
- console . log ( result . output ) ;
1082
- failed += result . failureCount ;
1083
- }
1084
- done [ target ] = true ;
1110
+ done [ target ] = fs . statSync ( target ) . size ;
1085
1111
}
1086
1112
}
1087
- if ( fold . isTravis ( ) ) console . log ( fold . end ( "lint" ) ) ;
1088
- if ( failed > 0 ) {
1089
- fail ( 'Linter errors.' , failed ) ;
1090
- }
1091
- } ) ;
1092
1113
1093
- /**
1094
- * This is required because file watches on Windows get fires _twice_
1095
- * when a file changes on some node/windows version configuations
1096
- * (node v4 and win 10, for example). By not running a lint for a file
1097
- * which already has a pending lint, we avoid duplicating our work.
1098
- * (And avoid printing duplicate results!)
1099
- */
1100
- var lintSemaphores = { } ;
1101
-
1102
- function lintWatchFile ( filename ) {
1103
- fs . watch ( filename , { persistent : true } , function ( event ) {
1104
- if ( event !== "change" ) {
1105
- return ;
1106
- }
1114
+ var workerCount = ( process . env . workerCount && + process . env . workerCount ) || os . cpus ( ) . length ;
1107
1115
1108
- if ( ! lintSemaphores [ filename ] ) {
1109
- lintSemaphores [ filename ] = true ;
1110
- lintFileAsync ( getLinterOptions ( ) , filename , function ( err , result ) {
1111
- delete lintSemaphores [ filename ] ;
1112
- if ( err ) {
1113
- console . log ( err ) ;
1114
- return ;
1115
- }
1116
- if ( result . failureCount > 0 ) {
1117
- console . log ( "***Lint failure***" ) ;
1118
- for ( var i = 0 ; i < result . failures . length ; i ++ ) {
1119
- var failure = result . failures [ i ] ;
1120
- var start = failure . startPosition . lineAndCharacter ;
1121
- var end = failure . endPosition . lineAndCharacter ;
1122
- console . log ( "warning " + filename + " (" + ( start . line + 1 ) + "," + ( start . character + 1 ) + "," + ( end . line + 1 ) + "," + ( end . character + 1 ) + "): " + failure . failure ) ;
1123
- }
1124
- console . log ( "*** Total " + result . failureCount + " failures." ) ;
1125
- }
1126
- } ) ;
1127
- }
1116
+ var names = Object . keys ( done ) . sort ( function ( namea , nameb ) {
1117
+ return done [ namea ] - done [ nameb ] ;
1128
1118
} ) ;
1129
- }
1130
1119
1131
- desc ( "Watches files for changes to rerun a lint pass" ) ;
1132
- task ( "lint-server" , [ "build-rules" ] , function ( ) {
1133
- console . log ( "Watching ./src for changes to linted files" ) ;
1134
- for ( var i = 0 ; i < lintTargets . length ; i ++ ) {
1135
- lintWatchFile ( lintTargets [ i ] ) ;
1120
+ for ( var i = 0 ; i < workerCount ; i ++ ) {
1121
+ spawnLintWorker ( names , finished ) ;
1136
1122
}
1137
- } ) ;
1123
+
1124
+ var completed = 0 ;
1125
+ var failures = 0 ;
1126
+ function finished ( fails ) {
1127
+ completed ++ ;
1128
+ failures += fails ;
1129
+ if ( completed === workerCount ) {
1130
+ measure ( startTime ) ;
1131
+ if ( fold . isTravis ( ) ) console . log ( fold . end ( "lint" ) ) ;
1132
+ if ( failures > 0 ) {
1133
+ fail ( 'Linter errors.' , failed ) ;
1134
+ }
1135
+ else {
1136
+ complete ( ) ;
1137
+ }
1138
+ }
1139
+ }
1140
+ } , { async : true } ) ;
0 commit comments