Ticket #37: noWarn.patch
File noWarn.patch, 11.8 KB (added by hopscc, 16 years ago) |
---|
-
Source/Tokenizer.cobra
300 300 var _tokenDefs as List<of TokenDef>? 301 301 var _tokenDefsByFirstChar as Dictionary<of char, List<of TokenDef>>? 302 302 var _tokenDefsByWhich as Dictionary<of String, TokenDef>? 303 var _noWarnLines as ISet<of String> 303 304 var _curTokenDef as TokenDef? 304 305 var _lastTokenDef as TokenDef? 305 306 var _avgCount = 0 … … 314 315 var _charNum as int 315 316 316 317 def init 318 _noWarnLines = Set<of String>() 317 319 _didReset = false 318 320 _reset() 319 321 … … 368 370 369 371 get tokenDefsByWhich from var 370 372 373 get noWarnLines from var 371 374 372 375 ## Other 373 376 … … 436 439 Returns all remaining tokens as a list. 437 440 """ 438 441 tokens = List<of IToken>() 442 #st = DateTime.now 439 443 while true 440 444 t = .nextToken 441 445 if t 442 446 tokens.add(t) 443 447 else 444 448 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)" 445 462 return tokens 446 463 447 464 def restart … … 591 608 return nil 592 609 try 593 610 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) 604 612 for tokenDef in tokenDefs 605 613 count += 1 606 if tokenDef.ignoreCount 607 tokenDef.ignoreCount -= 1 614 if _skipMatchAttempt(tokenDef, _sourceLineIndex) 608 615 continue 609 if not tokenDef.isActive610 continue611 if _sourceLineIndex>0 and tokenDef.requiresBOL612 continue613 if not .isActiveCall(tokenDef)614 continue615 616 #print '<> Trying to match [tokenDef]' 616 617 sourceLine = _sourceLine to ! 617 618 #print '_sourceLineIndex=[_sourceLineIndex]' … … 634 635 635 636 # enable methods to customize handling of tokens 636 637 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) 646 639 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 660 644 661 645 # finished with current line? 662 646 if _sourceLine.length==0 … … 689 673 _avgCount += count 690 674 _avgCountNum += 1 691 675 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 692 725 def pushTokenDefs(defs as List<of TokenDef>) 693 726 ensure 694 727 _tokenDefs is defs … … 762 795 # TODO: like parser, this should probably not be recorded unless it "makes it out". see comment in CobraParser.throwError 763 796 throw .recordError(msg) 764 797 798 def addNoWarn(token as IToken) 799 entry='[token.fileName]:[token.lineNum]' 800 _noWarnLines.add(entry) 801 765 802 def checkTokens(tokens as List<of IToken>, expected as String) 766 803 is shared 767 804 """ -
Source/Compiler.cobra
74 74 var _warnings as List<of SourceException> 75 75 var _messages as List<of SourceException> # all errors and warnings 76 76 var _messagesPerSourceLine as IDictionary<of String, List<of SourceException>> # key is 'filename:lineNum' 77 var _warningSuppressBySourceLine as ISet<of String> # key is 'filename:lineNum' 77 78 78 79 var _intermediateFileNames as List<of String> 79 80 var _baseExeFileName as String = '' … … 104 105 _codeMemberStack = Stack<of AbstractMethod>() 105 106 _messages = List<of SourceException>() 106 107 _messagesPerSourceLine = Dictionary<of String, List<of SourceException>>() 108 _warningSuppressBySourceLine = Set<of String>() 107 109 _errors = List<of SourceException>() 108 110 _warnings = List<of SourceException>() 109 111 _intermediateFileNames = List<of String>() … … 181 183 get warnings from var 182 184 183 185 get messages from var 186 187 set warningSuppressLines as ISet<of String> 188 _warningSuppressBySourceLine = value 184 189 185 190 pro htmlWriter from var 186 191 """ … … 1153 1158 1154 1159 def warning(cw as CobraWarning) 1155 1160 require not cw.isError 1161 if _suppressWarning(cw), return 1156 1162 _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 1158 1170 def augmentWarning(node as ISyntaxNode, lookFor as String, search as String, augment as String) as bool 1159 1171 require 1160 1172 lookFor.length -
Source/CobraParser.cobra
219 219 msg = 'Token error: ' + msg 220 220 .throwError(te.token, msg) 221 221 222 #TODO: fold all occcurrences of this lookup to a helper 223 compiler = .typeProvider to? Compiler 224 if compiler, compiler.warningSuppressLines = tokenizer.noWarnLines 225 222 226 if tokenizer.errors.count 223 227 for error in tokenizer.errors 224 228 .recordError(error.token, error.message) 225 229 226 230 _nextTokenIndex = 0 227 231 228 232 … … 548 552 if typeName.text not in ['decimal', 'float', 'float32', 'float64'] 549 553 .throwError('Compiler directive "number": unrecognized type "[typeName.text]". Must be one of "decimal", "float", "float32" or "float64".') 550 554 .expect('EOL') 551 comp = .typeProvider to Compiler?555 comp = .typeProvider to? Compiler 552 556 if comp, comp.numberTypeName = typeName.text 553 557 else 554 558 .throwError('Unknown compiler directive.') -
Source/CobraTokenizer.cobra
389 389 def onWHITESPACE_COMMENT_2(tok as IToken) as IToken? 390 390 #print '<> onWHITESPACE_COMMENT_2' 391 391 return nil 392 392 393 393 ## 394 394 ## Comment out block 395 395 ## … … 506 506 507 507 def onSINGLE_LINE_COMMENT(tok as IToken) as IToken? 508 508 # eat these 509 .chkForLeadingCommentToken(tok) 509 510 return nil 510 511 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 511 518 def onSPACE(tok as IToken) as IToken? 512 519 # eat these 513 520 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. 3 class 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
1 1 Post 0.8 2 2 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 3 7 * Add support for commenting full blocks of lines using /# and #/. Block comments can be nested. 4 8 '/#' block comment start and '#/' block comment end as initial chars on line 5 9