Wiki

Ticket #37: noWarn.patch

File noWarn.patch, 11.8 KB (added by hopscc, 16 years ago)
  • Source/Tokenizer.cobra

     
    300300    var _tokenDefs as List<of TokenDef>? 
    301301    var _tokenDefsByFirstChar as Dictionary<of char, List<of TokenDef>>? 
    302302    var _tokenDefsByWhich as Dictionary<of String, TokenDef>? 
     303    var _noWarnLines as ISet<of String> 
    303304    var _curTokenDef as TokenDef? 
    304305    var _lastTokenDef as TokenDef? 
    305306    var _avgCount = 0 
     
    314315    var _charNum as int 
    315316 
    316317    def init 
     318        _noWarnLines = Set<of String>() 
    317319        _didReset = false 
    318320        _reset() 
    319321 
     
    368370 
    369371    get tokenDefsByWhich from var 
    370372     
     373    get noWarnLines from var 
    371374 
    372375    ## Other 
    373376 
     
    436439        Returns all remaining tokens as a list. 
    437440        """ 
    438441        tokens = List<of IToken>() 
     442        #st = DateTime.now 
    439443        while true 
    440444            t = .nextToken 
    441445            if t 
    442446                tokens.add(t) 
    443447            else 
    444448                break 
     449        # determine timings for various Tokeniser lexing changes 
     450        #duration = DateTime.now.subtract(st) 
     451        #if  tokens.count > 100 and duration > TimeSpan(0) 
     452        #   avt = (duration.ticks to int) / (tokens.count to int) 
     453        #   ms = avt/10000 
     454        #   fnm = _fileName 
     455        #   if _fileName.startsWith("(") 
     456        #       fnm = '(None)' 
     457        #   lastsl =_fileName.lastIndexOf("\\") 
     458        #   if lastsl > 0 
     459        #       fnm = _fileName[lastsl+1:] to ! 
     460        #   print "[fnm.padRight(20)]\t[duration]\t[tokens.count]\t" stop 
     461        #   print " [ms:N3] ms/Token av ([ms/1000:N3]sec)" 
    445462        return tokens 
    446463 
    447464    def restart 
     
    591608                    return nil 
    592609            try 
    593610                assert _tokenDefs 
    594                 if _narrowTokenDefs and _tokenDefs.count >= _minNumTokenDefsToNarrow 
    595                     assert _tokenDefsByFirstChar 
    596                     assert _sourceLine.length 
    597                     if _tokenDefsByFirstChar.containsKey(_sourceLine[0]) 
    598                         # print 'Using short list for char: [_sourceLine[0]], [_sourceLine[0] to int]' 
    599                         tokenDefs = _tokenDefsByFirstChar[_sourceLine[0]] 
    600                     else 
    601                         tokenDefs = _tokenDefs to ! 
    602                 else 
    603                     tokenDefs = _tokenDefs to ! 
     611                tokenDefs = _getCandidateTokenDefs(_sourceLine) 
    604612                for tokenDef in tokenDefs 
    605613                    count += 1 
    606                     if tokenDef.ignoreCount 
    607                         tokenDef.ignoreCount -= 1 
     614                    if _skipMatchAttempt(tokenDef, _sourceLineIndex) 
    608615                        continue 
    609                     if not tokenDef.isActive 
    610                         continue 
    611                     if _sourceLineIndex>0 and tokenDef.requiresBOL 
    612                         continue 
    613                     if not .isActiveCall(tokenDef) 
    614                         continue 
    615616                    #print '<> Trying to match [tokenDef]' 
    616617                    sourceLine = _sourceLine to ! 
    617618                    #print '_sourceLineIndex=[_sourceLineIndex]' 
     
    634635 
    635636                    # enable methods to customize handling of tokens 
    636637                    reinvoke = false 
    637  
    638                     which = tok.which 
    639                     if _onTokenTypeCache.containsKey(which) 
    640                         meth = _onTokenTypeCache[which] 
    641                     else 
    642                         methName = 'On' + which 
    643                         meth = .getType.getMethod(methName) 
    644                         _onTokenTypeCache[which] = meth 
    645                          
     638                    meth = _getTokenMethod(tok.which) 
    646639                    if meth 
    647                         try 
    648                             tok = meth.invoke(this, @[tok]) to IToken? 
    649                         catch tie as TargetInvocationException 
    650                             throw tie.innerException 
    651                         if tok is nil 
    652                             # skip token, so go to the next one 
    653                             reinvoke = true 
    654                         else 
    655                             # TODO: could probably make this more efficient by axing the queue and just checking for nextToken in this method 
    656                             while tok 
    657                                 _tokenQueue.enqueue(tok) 
    658                                 tok = tok.nextToken 
    659                             reinvoke = true  # to pick up the queue 
     640                        tok = _tokenPostProcess(meth, tok ) 
     641                        # nil indicates skipped token - will re call this method 
     642                        if not tok  
     643                            reinvoke = true  # to pick up next token after skipped 
    660644 
    661645                    # finished with current line? 
    662646                    if _sourceLine.length==0 
     
    689673            _avgCount += count 
    690674            _avgCountNum += 1 
    691675 
     676    def _getCandidateTokenDefs(sourceLine as String?) as List<of TokenDef> 
     677        if _narrowTokenDefs and _tokenDefs.count >= _minNumTokenDefsToNarrow 
     678            assert _tokenDefsByFirstChar 
     679            assert _sourceLine.length 
     680            if _tokenDefsByFirstChar.containsKey(_sourceLine[0]) 
     681                # print 'Using short list for char: [_sourceLine[0]], [_sourceLine[0] to int]' 
     682                return _tokenDefsByFirstChar[_sourceLine[0]] 
     683        return _tokenDefs to ! 
     684 
     685    def _skipMatchAttempt(tokenDef as TokenDef, sourceLineIndex as int) as bool 
     686        if tokenDef.ignoreCount 
     687            tokenDef.ignoreCount -= 1 
     688            return true 
     689        if not tokenDef.isActive 
     690            return true 
     691        if sourceLineIndex>0 and tokenDef.requiresBOL 
     692            return true 
     693        if not .isActiveCall(tokenDef) 
     694            return true 
     695        return false     
     696 
     697    # get method for token (On<which>)  from cache if there else from reflection and cache it 
     698    def _getTokenMethod(which as String) as  MethodInfo?  
     699        if not _onTokenTypeCache.containsKey(which) # not already in methods cache 
     700            methName = 'On' + which                  
     701            meth = .getType.getMethod(methName)      
     702            _onTokenTypeCache[which] = meth          
     703        else 
     704            meth = _onTokenTypeCache[which] 
     705        return meth 
     706         
     707    # invoke any tokenMethod and return adjusted token or first token in any returned 
     708    # token chain (rest of chain queued) 
     709    # nil token returned indicates token is skipped. 
     710    def _tokenPostProcess(meth as MethodInfo,  tok as IToken?) as IToken? 
     711        try 
     712            tok = meth.invoke(this, @[tok]) to IToken? 
     713        catch tie as TargetInvocationException 
     714            throw tie.innerException 
     715        if not tok 
     716            return nil  # token is to be skipped 
     717        retTok = tok 
     718        tok = tok.nextToken 
     719        while tok 
     720        # TODO: could probably make this more efficient by axing the queue and just checking for nextToken in this method 
     721            _tokenQueue.enqueue(tok)  # store any token chain returned by method call 
     722            tok = tok.nextToken 
     723        return retTok    
     724 
    692725    def pushTokenDefs(defs as List<of TokenDef>) 
    693726        ensure 
    694727            _tokenDefs is defs 
     
    762795        # TODO: like parser, this should probably not be recorded unless it "makes it out". see comment in CobraParser.throwError 
    763796        throw .recordError(msg) 
    764797 
     798    def addNoWarn(token as IToken) 
     799        entry='[token.fileName]:[token.lineNum]' 
     800        _noWarnLines.add(entry) 
     801         
    765802    def checkTokens(tokens as List<of IToken>, expected as String) 
    766803        is shared 
    767804        """ 
  • Source/Compiler.cobra

     
    7474    var _warnings as List<of SourceException> 
    7575    var _messages as List<of SourceException>  # all errors and warnings 
    7676    var _messagesPerSourceLine as IDictionary<of String, List<of SourceException>>  # key is 'filename:lineNum' 
     77    var _warningSuppressBySourceLine as ISet<of String>     # key is 'filename:lineNum' 
    7778 
    7879    var _intermediateFileNames as List<of String> 
    7980    var _baseExeFileName as String = '' 
     
    104105        _codeMemberStack = Stack<of AbstractMethod>() 
    105106        _messages = List<of SourceException>() 
    106107        _messagesPerSourceLine = Dictionary<of String, List<of SourceException>>() 
     108        _warningSuppressBySourceLine = Set<of String>() 
    107109        _errors = List<of SourceException>() 
    108110        _warnings = List<of SourceException>() 
    109111        _intermediateFileNames = List<of String>() 
     
    181183    get warnings from var 
    182184 
    183185    get messages from var 
     186     
     187    set warningSuppressLines as ISet<of String> 
     188        _warningSuppressBySourceLine = value 
    184189 
    185190    pro htmlWriter from var 
    186191        """ 
     
    11531158 
    11541159    def warning(cw as CobraWarning) 
    11551160        require not cw.isError 
     1161        if _suppressWarning(cw), return 
    11561162        _addMessage(cw) 
    1157          
     1163     
     1164    def _suppressWarning(cw as CobraWarning) as bool 
     1165        # TODO: add suppress all warnings (cmdline sw) - maybe? 
     1166        # TODO: add suppress by error tag - maybe? 
     1167        entry = if(cw.hasSourceSite, '[cw.fileName]:[cw.lineNum]', '') 
     1168        return _warningSuppressBySourceLine.contains(entry) 
     1169             
    11581170    def augmentWarning(node as ISyntaxNode, lookFor as String, search as String, augment as String) as bool 
    11591171        require  
    11601172            lookFor.length 
  • Source/CobraParser.cobra

     
    219219                msg = 'Token error: ' + msg 
    220220            .throwError(te.token, msg) 
    221221 
     222        #TODO: fold all occcurrences of this lookup to a helper 
     223        compiler = .typeProvider to? Compiler 
     224        if compiler, compiler.warningSuppressLines = tokenizer.noWarnLines 
     225 
    222226        if tokenizer.errors.count 
    223227            for error in tokenizer.errors 
    224228                .recordError(error.token, error.message) 
    225              
     229 
    226230        _nextTokenIndex = 0 
    227231 
    228232 
     
    548552                if typeName.text not in ['decimal', 'float', 'float32', 'float64'] 
    549553                    .throwError('Compiler directive "number": unrecognized type "[typeName.text]". Must be one of "decimal", "float", "float32" or "float64".') 
    550554                .expect('EOL') 
    551                 comp = .typeProvider to Compiler? 
     555                comp = .typeProvider to? Compiler 
    552556                if comp, comp.numberTypeName = typeName.text 
    553557            else 
    554558                .throwError('Unknown compiler directive.') 
  • Source/CobraTokenizer.cobra

     
    389389    def onWHITESPACE_COMMENT_2(tok as IToken) as IToken? 
    390390        #print '<> onWHITESPACE_COMMENT_2' 
    391391        return nil 
    392  
     392     
    393393    ## 
    394394    ## Comment out block 
    395395    ## 
     
    506506 
    507507    def onSINGLE_LINE_COMMENT(tok as IToken) as IToken? 
    508508        # eat these 
     509        .chkForLeadingCommentToken(tok) 
    509510        return nil 
    510511 
     512    def chkForLeadingCommentToken(tok as IToken) 
     513        insens = tok.text.trimStart.toLower 
     514        # nowarn is only one to date 
     515        if insens.startsWith('#.nowarn.') or insens.startsWith('#.no-warn.') 
     516            .addNoWarn(tok) 
     517             
    511518    def onSPACE(tok as IToken) as IToken? 
    512519        # eat these 
    513520        return nil 
  • Tests/800-warnings/400-no-warn.cobra

     
     1# test use of various forms of .noWarn comment token to suppress warnings 
     2# probably should stick to either   #.nowarn.  #.noWarn. or #.no-warn. 
     3class E 
     4    var _count =0    
     5    var rCount =0 
     6     
     7    sig BumpEventHandler(sender as Object, args as EventArgs)  
     8    event bumpEvent as BumpEventHandler  
     9 
     10 
     11    # (protected) method to raise/fire the event for this class 
     12    def _onBumpEvent(args as EventArgs) 
     13        raise .bumpEvent, this, args    #.noWarn. warning:implied this 
     14         
     15    def bump 
     16        _count += 1  
     17        if _count % 10 == 0 
     18            ev = EventArgs() 
     19            _onBumpEvent(ev)     
     20            assert this.rCount  #.NoWarn. warning:unnecessary this literal   
     21             
     22             
     23    def doBump(source as Object, eArgs as EventArgs) 
     24        .rCount += 1 
     25 
     26#class Driver        
     27    def main is shared, shared #.No-WARN. warning:duplicate modifier 
     28        e = E() 
     29        listen e.bumpEvent, ref e.doBump 
     30        for i in 20 
     31            e.bump 
     32        assert e.rCount == 2 
     33 
     34        j=99        #.no-warn.  warning: never used 
     35        a = 99 
     36        if (a < 10) #.noWarn.  warning: Unnecessary parens 
     37            a=10 
     38        assert a is 99      #.NoWaRn.  warning:value Types   
     39        assert a is not 100 #.nOwArN.  warning:value Types   
     40 
     41        s='string' 
     42        t = s to String     #.no-Warn. warning:redundant typecast 
     43        t1 = s to String?   #.NOWARN.  warning:just use to ? 
  • Developer/IntermediateReleaseNotes.text

     
    11Post 0.8 
    22 
     3* Add support for warning suppression on arbitrary lines by placing a trailing 
     4    comment containing .nowarn. or .no-warn. immediately after the # 
     5    e.g.   this.call()  #.nowarn.  
     6 
    37* Add support for commenting full blocks of lines using /# and #/. Block comments can be nested. 
    48    '/#' block comment start and  '#/' block comment end as initial chars on line 
    59