@@ -34,7 +34,7 @@ import through2 = require("through2");
34
34
import merge2 = require( "merge2" ) ;
35
35
import intoStream = require( "into-stream" ) ;
36
36
import * as os from "os" ;
37
- import Linter = require( "tslint " ) ;
37
+ import fold = require( "travis-fold " ) ;
38
38
const gulp = helpMaker ( originalGulp ) ;
39
39
const mochaParallel = require ( "./scripts/mocha-parallel.js" ) ;
40
40
const { runTestsInParallel} = mochaParallel ;
@@ -59,7 +59,6 @@ const cmdLineOptions = minimist(process.argv.slice(2), {
59
59
browser : process . env . browser || process . env . b || "IE" ,
60
60
tests : process . env . test || process . env . tests || process . env . t ,
61
61
light : process . env . light || false ,
62
- port : process . env . port || process . env . p || "8888" ,
63
62
reporter : process . env . reporter || process . env . r ,
64
63
lint : process . env . lint || true ,
65
64
files : process . env . f || process . env . file || process . env . files || "" ,
@@ -450,7 +449,7 @@ gulp.task(tsserverLibraryFile, false, [servicesFile], (done) => {
450
449
} ) ;
451
450
452
451
gulp . task ( "lssl" , "Builds language service server library" , [ tsserverLibraryFile ] ) ;
453
- gulp . task ( "local" , "Builds the full compiler and services" , [ builtLocalCompiler , servicesFile , serverFile , builtGeneratedDiagnosticMessagesJSON ] ) ;
452
+ gulp . task ( "local" , "Builds the full compiler and services" , [ builtLocalCompiler , servicesFile , serverFile , builtGeneratedDiagnosticMessagesJSON , tsserverLibraryFile ] ) ;
454
453
gulp . task ( "tsc" , "Builds only the compiler" , [ builtLocalCompiler ] ) ;
455
454
456
455
@@ -504,7 +503,7 @@ gulp.task("VerifyLKG", false, [], () => {
504
503
return gulp . src ( expectedFiles ) . pipe ( gulp . dest ( LKGDirectory ) ) ;
505
504
} ) ;
506
505
507
- gulp . task ( "LKGInternal" , false , [ "lib" , "local" , "lssl" ] ) ;
506
+ gulp . task ( "LKGInternal" , false , [ "lib" , "local" ] ) ;
508
507
509
508
gulp . task ( "LKG" , "Makes a new LKG out of the built js files" , [ "clean" , "dontUseDebugMode" ] , ( ) => {
510
509
return runSequence ( "LKGInternal" , "VerifyLKG" ) ;
@@ -694,21 +693,50 @@ gulp.task(nodeServerOutFile, false, [servicesFile], () => {
694
693
. pipe ( gulp . dest ( path . dirname ( nodeServerOutFile ) ) ) ;
695
694
} ) ;
696
695
696
+ import convertMap = require( "convert-source-map" ) ;
697
+ import sorcery = require( "sorcery" ) ;
698
+ declare module "convert-source-map" {
699
+ export function fromSource ( source : string , largeSource ?: boolean ) : SourceMapConverter ;
700
+ }
701
+
697
702
gulp . task ( "browserify" , "Runs browserify on run.js to produce a file suitable for running tests in the browser" , [ servicesFile ] , ( done ) => {
698
703
const testProject = tsc . createProject ( "src/harness/tsconfig.json" , getCompilerSettings ( { outFile : "built/local/bundle.js" } , /*useBuiltCompiler*/ true ) ) ;
699
704
return testProject . src ( )
700
705
. pipe ( newer ( "built/local/bundle.js" ) )
701
706
. pipe ( sourcemaps . init ( ) )
702
707
. pipe ( tsc ( testProject ) )
703
708
. pipe ( through2 . obj ( ( file , enc , next ) => {
704
- browserify ( intoStream ( file . contents ) )
709
+ const originalMap = file . sourceMap ;
710
+ const prebundledContent = file . contents . toString ( ) ;
711
+ // Make paths absolute to help sorcery deal with all the terrible paths being thrown around
712
+ originalMap . sources = originalMap . sources . map ( s => path . resolve ( "src" , s ) ) ;
713
+ // intoStream (below) makes browserify think the input file is named this, so this is what it puts in the sourcemap
714
+ originalMap . file = "built/local/_stream_0.js" ;
715
+
716
+ browserify ( intoStream ( file . contents ) , { debug : true } )
705
717
. bundle ( ( err , res ) => {
706
718
// assumes file.contents is a Buffer
707
- file . contents = res ;
719
+ const maps = JSON . parse ( convertMap . fromSource ( res . toString ( ) , /*largeSource*/ true ) . toJSON ( ) ) ;
720
+ delete maps . sourceRoot ;
721
+ maps . sources = maps . sources . map ( s => path . resolve ( s === "_stream_0.js" ? "built/local/_stream_0.js" : s ) ) ;
722
+ // Strip browserify's inline comments away (could probably just let sorcery do this, but then we couldn't fix the paths)
723
+ file . contents = new Buffer ( convertMap . removeComments ( res . toString ( ) ) ) ;
724
+ const chain = sorcery . loadSync ( "built/local/bundle.js" , {
725
+ content : {
726
+ "built/local/_stream_0.js" : prebundledContent ,
727
+ "built/local/bundle.js" : file . contents . toString ( )
728
+ } ,
729
+ sourcemaps : {
730
+ "built/local/_stream_0.js" : originalMap ,
731
+ "built/local/bundle.js" : maps ,
732
+ }
733
+ } ) ;
734
+ const finalMap = chain . apply ( ) ;
735
+ file . sourceMap = finalMap ;
708
736
next ( undefined , file ) ;
709
737
} ) ;
710
738
} ) )
711
- . pipe ( sourcemaps . write ( "." , { includeContent : false , sourceRoot : "../../" } ) )
739
+ . pipe ( sourcemaps . write ( "." , { includeContent : false } ) )
712
740
. pipe ( gulp . dest ( "." ) ) ;
713
741
} ) ;
714
742
@@ -737,7 +765,7 @@ function writeTestConfigFile(tests: string, light: boolean, taskConfigsFolder?:
737
765
}
738
766
739
767
740
- gulp . task ( "runtests-browser" , "Runs the tests using the built run.js file like 'gulp runtests'. Syntax is gulp runtests-browser. Additional optional parameters --tests=[regex], --port=, -- browser=[chrome|IE]" , [ "browserify" , nodeServerOutFile ] , ( done ) => {
768
+ gulp . task ( "runtests-browser" , "Runs the tests using the built run.js file like 'gulp runtests'. Syntax is gulp runtests-browser. Additional optional parameters --tests=[regex], --browser=[chrome|IE]" , [ "browserify" , nodeServerOutFile ] , ( done ) => {
741
769
cleanTestDirs ( ( err ) => {
742
770
if ( err ) { console . error ( err ) ; done ( err ) ; process . exit ( 1 ) ; }
743
771
host = "node" ;
@@ -752,9 +780,6 @@ gulp.task("runtests-browser", "Runs the tests using the built run.js file like '
752
780
}
753
781
754
782
const args = [ nodeServerOutFile ] ;
755
- if ( cmdLineOptions [ "port" ] ) {
756
- args . push ( cmdLineOptions [ "port" ] ) ;
757
- }
758
783
if ( cmdLineOptions [ "browser" ] ) {
759
784
args . push ( cmdLineOptions [ "browser" ] ) ;
760
785
}
@@ -889,57 +914,20 @@ gulp.task("update-sublime", "Updates the sublime plugin's tsserver", ["local", s
889
914
return gulp . src ( [ serverFile , serverFile + ".map" ] ) . pipe ( gulp . dest ( "../TypeScript-Sublime-Plugin/tsserver/" ) ) ;
890
915
} ) ;
891
916
892
-
893
- const tslintRuleDir = "scripts/tslint" ;
894
- const tslintRules = [
895
- "nextLineRule" ,
896
- "preferConstRule" ,
897
- "booleanTriviaRule" ,
898
- "typeOperatorSpacingRule" ,
899
- "noInOperatorRule" ,
900
- "noIncrementDecrementRule" ,
901
- "objectLiteralSurroundingSpaceRule" ,
902
- ] ;
903
- const tslintRulesFiles = tslintRules . map ( function ( p ) {
904
- return path . join ( tslintRuleDir , p + ".ts" ) ;
905
- } ) ;
906
- const tslintRulesOutFiles = tslintRules . map ( function ( p , i ) {
907
- const pathname = path . join ( builtLocalDirectory , "tslint" , p + ".js" ) ;
908
- gulp . task ( pathname , false , [ ] , ( ) => {
909
- const settings : tsc . Settings = getCompilerSettings ( { module : "commonjs" } , /*useBuiltCompiler*/ false ) ;
910
- return gulp . src ( tslintRulesFiles [ i ] )
911
- . pipe ( newer ( pathname ) )
912
- . pipe ( sourcemaps . init ( ) )
913
- . pipe ( tsc ( settings ) )
914
- . pipe ( sourcemaps . write ( "." ) )
915
- . pipe ( gulp . dest ( path . join ( builtLocalDirectory , "tslint" ) ) ) ;
916
- } ) ;
917
- return pathname ;
917
+ gulp . task ( "build-rules" , "Compiles tslint rules to js" , ( ) => {
918
+ const settings : tsc . Settings = getCompilerSettings ( { module : "commonjs" } , /*useBuiltCompiler*/ false ) ;
919
+ const dest = path . join ( builtLocalDirectory , "tslint" ) ;
920
+ return gulp . src ( "scripts/tslint/**/*.ts" )
921
+ . pipe ( newer ( {
922
+ dest,
923
+ ext : ".js"
924
+ } ) )
925
+ . pipe ( sourcemaps . init ( ) )
926
+ . pipe ( tsc ( settings ) )
927
+ . pipe ( sourcemaps . write ( "." ) )
928
+ . pipe ( gulp . dest ( dest ) ) ;
918
929
} ) ;
919
930
920
- gulp . task ( "build-rules" , "Compiles tslint rules to js" , tslintRulesOutFiles ) ;
921
-
922
-
923
- function getLinterOptions ( ) {
924
- return {
925
- configuration : require ( "./tslint.json" ) ,
926
- formatter : "prose" ,
927
- formattersDirectory : undefined ,
928
- rulesDirectory : "built/local/tslint"
929
- } ;
930
- }
931
-
932
- function lintFileContents ( options , path , contents ) {
933
- const ll = new Linter ( path , contents , options ) ;
934
- console . log ( "Linting '" + path + "'." ) ;
935
- return ll . lint ( ) ;
936
- }
937
-
938
- function lintFile ( options , path ) {
939
- const contents = fs . readFileSync ( path , "utf8" ) ;
940
- return lintFileContents ( options , path , contents ) ;
941
- }
942
-
943
931
const lintTargets = [
944
932
"Gulpfile.ts" ,
945
933
"src/compiler/**/*.ts" ,
@@ -948,29 +936,75 @@ const lintTargets = [
948
936
"src/server/**/*.ts" ,
949
937
"scripts/tslint/**/*.ts" ,
950
938
"src/services/**/*.ts" ,
939
+ "tests/*.ts" , "tests/webhost/*.ts" // Note: does *not* descend recursively
951
940
] ;
952
941
942
+ function sendNextFile ( files : { path : string } [ ] , child : cp . ChildProcess , callback : ( failures : number ) => void , failures : number ) {
943
+ const file = files . pop ( ) ;
944
+ if ( file ) {
945
+ console . log ( `Linting '${ file . path } '.` ) ;
946
+ child . send ( { kind : "file" , name : file . path } ) ;
947
+ }
948
+ else {
949
+ child . send ( { kind : "close" } ) ;
950
+ callback ( failures ) ;
951
+ }
952
+ }
953
+
954
+ function spawnLintWorker ( files : { path : string } [ ] , callback : ( failures : number ) => void ) {
955
+ const child = cp . fork ( "./scripts/parallel-lint" ) ;
956
+ let failures = 0 ;
957
+ child . on ( "message" , function ( data ) {
958
+ switch ( data . kind ) {
959
+ case "result" :
960
+ if ( data . failures > 0 ) {
961
+ failures += data . failures ;
962
+ console . log ( data . output ) ;
963
+ }
964
+ sendNextFile ( files , child , callback , failures ) ;
965
+ break ;
966
+ case "error" :
967
+ console . error ( data . error ) ;
968
+ failures ++ ;
969
+ sendNextFile ( files , child , callback , failures ) ;
970
+ break ;
971
+ }
972
+ } ) ;
973
+ sendNextFile ( files , child , callback , failures ) ;
974
+ }
953
975
954
976
gulp . task ( "lint" , "Runs tslint on the compiler sources. Optional arguments are: --f[iles]=regex" , [ "build-rules" ] , ( ) => {
955
977
const fileMatcher = RegExp ( cmdLineOptions [ "files" ] ) ;
956
- const lintOptions = getLinterOptions ( ) ;
957
- let failed = 0 ;
958
- return gulp . src ( lintTargets )
959
- . pipe ( insert . transform ( ( contents , file ) => {
960
- if ( ! fileMatcher . test ( file . path ) ) return contents ;
961
- const result = lintFile ( lintOptions , file . path ) ;
962
- if ( result . failureCount > 0 ) {
963
- console . log ( result . output ) ;
964
- failed += result . failureCount ;
978
+ if ( fold . isTravis ( ) ) console . log ( fold . start ( "lint" ) ) ;
979
+
980
+ let files : { stat : fs . Stats , path : string } [ ] = [ ] ;
981
+ return gulp . src ( lintTargets , { read : false } )
982
+ . pipe ( through2 . obj ( ( chunk , enc , cb ) => {
983
+ files . push ( chunk ) ;
984
+ cb ( ) ;
985
+ } , ( cb ) => {
986
+ files = files . filter ( file => fileMatcher . test ( file . path ) ) . sort ( ( filea , fileb ) => filea . stat . size - fileb . stat . size ) ;
987
+ const workerCount = ( process . env . workerCount && + process . env . workerCount ) || os . cpus ( ) . length ;
988
+ for ( let i = 0 ; i < workerCount ; i ++ ) {
989
+ spawnLintWorker ( files , finished ) ;
965
990
}
966
- return contents ; // TODO (weswig): Automatically apply fixes? :3
967
- } ) )
968
- . on ( "end" , ( ) => {
969
- if ( failed > 0 ) {
970
- console . error ( "Linter errors." ) ;
971
- process . exit ( 1 ) ;
991
+
992
+ let completed = 0 ;
993
+ let failures = 0 ;
994
+ function finished ( fails ) {
995
+ completed ++ ;
996
+ failures += fails ;
997
+ if ( completed === workerCount ) {
998
+ if ( fold . isTravis ( ) ) console . log ( fold . end ( "lint" ) ) ;
999
+ if ( failures > 0 ) {
1000
+ throw new Error ( `Linter errors: ${ failures } ` ) ;
1001
+ }
1002
+ else {
1003
+ cb ( ) ;
1004
+ }
1005
+ }
972
1006
}
973
- } ) ;
1007
+ } ) ) ;
974
1008
} ) ;
975
1009
976
1010
0 commit comments