1+ oldConsole = require ' console'
12fs = require ' fs'
23os = require ' os'
34path = require ' path'
@@ -30,6 +31,60 @@ header = """
3031majorVersion = parseInt CoffeeScript .VERSION .split (' .' )[0 ], 10
3132
3233
34+ class CakeConsole extends oldConsole.Console
35+ @LEVELS : [' debug' , ' info' , ' log' , ' warn' , ' error' , ' trace' ]
36+ @levelNumsMap : do =>
37+ ret = {}
38+ ret[k] = i for k, i in @LEVELS
39+ ret
40+ @ validLevels: => " [#{ (@LEVELS .map (l) -> " '#{ l} '" ).join ' , ' } ]"
41+
42+ constructor : ({@level = ' log' , ... opts} = {}) ->
43+ super opts
44+ unless @level in @constructor .LEVELS
45+ throw new TypeError " argument '#{ @level } ' was not a valid log level
46+ (should be: #{ @constructor .validLevels ()} )"
47+
48+ @ getLevelNum: (l ) => @levelNumsMap [l] ? throw new TypeError " invalid level #{ l} "
49+ curLevelNum : -> @constructor .getLevelNum @level
50+ doesThisLevelApply : (l ) -> @ curLevelNum () <= @constructor .getLevelNum l
51+
52+ # TODO: for some reason this is done lazily in buildParser, so let's do the same here.
53+ helpers .extend global , require ' util'
54+ for l in @LEVELS
55+ do (l ) => @ :: [l] = (... args ) ->
56+ if @ doesThisLevelApply l
57+ # NB: it's literally impossible to extend Console and propagate to the parent class because
58+ # of some horrific unexplained initialization code used for the singleton console
59+ # object, which employs a very complex prototype chain that makes it impossible to do
60+ # the simple thing: https://github.com/nodejs/node/blob/17fae65c72321659390c4cbcd9ddaf248accb953/lib/internal/console/global.js#L29-L33.
61+ # Undo the prototype chain nonsense and bind the method back to our subclass.
62+ (oldConsole[l].bind @ ) ... args
63+ else global .format ... args
64+
65+ @stdio : ({
66+ stdout = process .stdout ,
67+ stderr = process .stderr ,
68+ ... opts,
69+ } = {}) => new @ {
70+ stdout,
71+ stderr,
72+ ... opts
73+ }
74+
75+
76+ option ' -l' , ' --level [LEVEL]' , ' log level [debug < info < log(default) < warn < error]'
77+
78+ setupConsole = ({level} = {}) ->
79+ global .cakeConsole = CakeConsole .stdio {level}
80+ global .console = global .cakeConsole
81+ console .log " log level = #{ level} "
82+
83+ consoleTask = (name , description , action ) ->
84+ global .task name, description, ({level = ' log' , ... opts} = {}) ->
85+ setupConsole {level}
86+ action {... opts}
87+
3388# Log a message with a color.
3489log = (message , color , explanation ) ->
3590 console .log color + message + reset + ' ' + (explanation or ' ' )
@@ -60,6 +115,7 @@ buildParser = ->
60115buildExceptParser = (callback ) ->
61116 files = fs .readdirSync ' src'
62117 files = (' src/' + file for file in files when file .match (/ \. (lit)? coffee$ / ))
118+ console .info {files}
63119 run [' -c' , ' -o' , ' lib/coffeescript' ].concat (files), callback
64120
65121build = (callback ) ->
@@ -121,7 +177,7 @@ watchAndBuildAndTest = (harmony = no) ->
121177 buildAndTest no , harmony
122178
123179
124- task ' build' , ' build the CoffeeScript compiler from source' , build
180+ consoleTask ' build' , ' build the CoffeeScript compiler from source' , build
125181
126182task ' build:parser' , ' build the Jison parser only' , buildParser
127183
@@ -190,7 +246,7 @@ task 'build:browser:full', 'merge the built scripts into a single file for use i
190246 console .log " built ... running browser tests:"
191247 invoke ' test:browser'
192248
193- task ' build:watch' , ' watch and continually rebuild the CoffeeScript compiler, running tests on each build' , ->
249+ consoleTask ' build:watch' , ' watch and continually rebuild the CoffeeScript compiler, running tests on each build' , ->
194250 watchAndBuildAndTest ()
195251
196252task ' build:watch:harmony' , ' watch and continually rebuild the CoffeeScript compiler, running harmony tests on each build' , ->
@@ -400,16 +456,37 @@ task 'bench', 'quick benchmark of compilation time', ->
400456 console .log " total #{ fmt total } "
401457
402458
459+ class PatternSet
460+ constructor : (patternStrings = []) ->
461+ @matchers = (new RegExp p for p in patternStrings when p isnt ' ' )
462+
463+ isEmpty : -> @matchers .length is 0
464+
465+ iterMatchers : -> @matchers [Symbol .iterator ]()
466+
467+ matches : (arg ) -> if @ isEmpty () then yes else @ iterMatchers ().some (m) -> (m .exec arg)?
468+
469+ @ fromCommaDelimitedList: (commaListStr ) => new @ (commaListStr ? ' ' ).split / ,/
470+ @ empty: => new @ []
471+
472+
403473# Run the CoffeeScript test suite.
404- runTests = (CoffeeScript ) ->
474+ runTests = (CoffeeScript , { filePatterns , descPatterns } = {} ) ->
405475 CoffeeScript .register () unless global .testingBrowser
406476
477+ filePatterns ?= PatternSet .empty ()
478+ descPatterns ?= PatternSet .empty ()
479+ console .log {filePatterns, descPatterns}
480+
407481 # These are attached to `global` so that they’re accessible from within
408482 # `test/async.coffee`, which has an async-capable version of
409483 # `global.test`.
410484 global .currentFile = null
411485 global .passedTests = 0
412486 global .failures = []
487+ global .filteredOut =
488+ files : []
489+ tests : []
413490
414491 global [name] = func for name, func of require ' assert'
415492
@@ -429,9 +506,22 @@ runTests = (CoffeeScript) ->
429506 error : err
430507 description : description
431508 source : fn .toString () if fn .toString ?
509+ onFilteredOut = (description , fn ) ->
510+ console .info " test '#{ description} ' was filtered out by patterns"
511+ filteredOut .tests .push
512+ filename : global .currentFile
513+ description : description
514+ fn : fn
515+ onFilteredFile = (file ) ->
516+ console .info " file '#{ file} ' was filtered out by patterns"
517+ filteredOut .files .push
518+ filename : file
432519
433520 # Our test helper function for delimiting different test cases.
434521 global .test = (description , fn ) ->
522+ unless descPatterns .matches description
523+ onFilteredOut description, fn
524+ return
435525 try
436526 fn .test = {description, currentFile}
437527 result = fn .call (fn)
@@ -445,6 +535,7 @@ runTests = (CoffeeScript) ->
445535 passedTests++
446536 catch err
447537 onFail description, fn, err
538+ console .info " passed: #{ description} in #{ currentFile} "
448539
449540 helpers .extend global , require ' ./test/support/helpers'
450541
@@ -483,6 +574,9 @@ runTests = (CoffeeScript) ->
483574
484575 startTime = Date .now ()
485576 for file in files when helpers .isCoffee file
577+ unless filePatterns .matches file
578+ onFilteredFile file
579+ continue
486580 literate = helpers .isLiterate file
487581 currentFile = filename = path .join ' test' , file
488582 code = fs .readFileSync filename
@@ -495,9 +589,14 @@ runTests = (CoffeeScript) ->
495589 Promise .reject () if failures .length isnt 0
496590
497591
498- task ' test ' , ' run the CoffeeScript language test suite ' , ->
499- runTests (CoffeeScript). catch -> process . exit 1
592+ option ' -f ' , ' --file [REGEXP*] ' , ' test file patterns to match '
593+ option ' -d ' , ' --desc [REGEXP*] ' , ' test description patterns to match '
500594
595+ consoleTask ' test' , ' run the CoffeeScript language test suite' , ({file, desc} = {}) ->
596+ testOptions =
597+ filePatterns : new PatternSet file
598+ descPatterns : new PatternSet desc
599+ runTests (CoffeeScript, testOptions).catch -> process .exit 1
501600
502601task ' test:browser' , ' run the test suite against the modern browser compiler in a headless browser' , ->
503602 # Create very simple web server to serve the two files we need.
0 commit comments