John,

Wrote extendable nit hunting framework ;-)  (attached)
Fill free to add/change rules.

This script doesn't change a source file but complains
about found formatting errors.

It should save a bit of time during code review.

-Dmitry


On 2012-03-03 23:55, John Rose wrote:
> Lest Kelly have all the fun, I'll jump in.
> 
> On Mar 3, 2012, at 3:36 AM, David Holmes wrote:
> 
>> So the question is: what does the script think a TAB represents?
> 
> The same thing that /usr/bin/expand does, as noted earlier.  Or read the
> perl code.
> 
> When was the last time anybody on the hotspot team used '\t' (the source
> file octet, not the keyboard key) to mean anything else than
> /usr/bin/expand?  This stuff about 2 and 4 width indents is irrelevant,
> except to people who accidentally use anti-social IDE settings, and they
> get socialized quickly.
> 
> On Mar 3, 2012, at 8:39 AM, Jonathan Gibbons wrote:
> 
>> Kelly,
>>
>> Is there a reason you don't use "expand"?
>>
>> For a while now I've been using the following simple script to fix the
>> whitespace in my files before I commit a change set.
> 
> The perl script does what your script does, probably to 95%
> compatibility.  (File list generation logic and last-line behavior may
> perhaps vary on corner cases.)  Your script uses perl plus other shell
> commands, while the standard script uses perl only; your script uses
> expand instead of an obscure couple of perl lines which do the same
> thing.  It seems a matter of taste not greatly worth discussing.  There
> are 10 different ways to code this operation; 9 of those ways will not
> get used, but (IMO) it's not very interesting to ask why not.
> 
> — John


-- 
Dmitry Samersoff
Java Hotspot development team, SPB04
* There will come soft rains ...
#!/usr/bin/python
#
# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#

import sys
import glob 
import getopt

import datetime

# Check source file for formatting nits
# Fill free to add your own rules

class NitHunter(object): 
    """Base class, contains controller"""

    def __init__(self,p_exlist = []):
        """It's possible to blacklist some rules""" 
        self.exlist = p_exlist
        self.nits   = 0


    def execute(self,fileName):
        """Controller. Enumerate all hunt_* methods, check whether
           it is blacklisted, execute it and print warning if necessary
        """   
        f = file(fileName,"r")
        lineCount = 0
        self.nits = 0
        for line in f :
            lineCount+=1
            for name in dir(self) :
                if name.startswith("hunt_") and not name in self.exlist :
                   item = getattr(self, name)
                   (shouldWarn,message) = item(line)
                   if shouldWarn == True : 
                      print "%s:%-4d [%s] %s" % (fileName, lineCount, name, message) 
                      self.nits+=1
        f.close()    

        if self.nits == 0 :
           print "+ %s is OK" % fileName
        else:   
           print "! %s contains %d nits" % (fileName,self.nits)


#
# Rulesets
#

class NitHunterGeneric(NitHunter): 
    """Common rules"""

    def hunt_tab(self,line):
        """Check for presence of tab cahracter"""
        return (line.find('\t') != -1, "Line contains tab character")

    def hunt_trailing_space(self,line): 
        """Check for trailing whitespace""" 
        return (len(line) > 1 and line[-2]==' ',"Line contains trailing space")

    def hunt_if(self,line):
        """Control should be as (nnnn = mmm) {"""
        message = "Line contains: "
        shouldWarn = False

        if line.find("( ") != -1 :
           message += "space after (; "
           shouldWarn = True

        if line.find(" )") != -1 :
           message += "space before ); "
           shouldWarn = True

        n = line.find("{")
        if n > 0 and line[n-1] != ' ':
           message += "no space before {;"
           shouldWarn = True

        return (shouldWarn, message)

    def hunt_copyright(self,line):
        """Copyright year should mach current year"""
        now = datetime.datetime.now()
        year = now.year
        shouldWarn =  line.find("Copyright") != -1 and line.find("%s" % year) == -1 
        return (shouldWarn, "Copyright doesn't contain current year (%s)" % year)

    """ Tools """
    def check_indent(self,line,boundary): 
        shouldWarn = False 
        i = 0
        while(line[i] == ' ' and i < len(line)-1 ) :
            i+=1

        if i % boundary != 0 :
           if line[i] != '*' and line[i] != '"':
              # Assume it's a block comments or string. Don't complain about indent 
              shouldWarn = True
        return (shouldWarn ,"Line contains wrong indent %d" % i)




class NitHunterHotspot(NitHunterGeneric) :
    """Hotspot private ruleset"""

    def hunt_indent(self,line):
        """Check that first non-space character is on 2 boundary"""
        return self.check_indent(line,2) 


class NitHunterJDK(NitHunterGeneric) :
    """JDK private ruleset"""

    def hunt_indent(self,line):
        """Check that first non-space character is on 4 boundary"""
        return self.check_indent(line,4) 


def usage():
    print "Usage: nithunter.py [--exclude=rules1,rules2...] [--hunter=hotspot|jdk] filepattern"
    sys.exit(2)

# ----------- MAIN -------------------        
if __name__ == '__main__':

    try: 
      opts, args = getopt.getopt(sys.argv[1:], "he:u:", ["help", "exclude=", "hunter="])
    except getopt.GetoptError, err:
      print str(err) 
      usage()


    exclude = [] 
    nhName = "hotspot"
    for o, a in opts:
        if o in ("-h", "--help"):
           usage()
        elif o in ("-e", "--exclude"):
           exclude = a.split(',')
        elif o in ("-u", "--hunter"):
           nhName = a
        else:
            assert False, "unhandled option"

    if nhName == "hotspot" :
       nh = NitHunterHotspot(exclude)
    elif name == "jdk" :
       nh = NitHunterJDK(exclude)
    else:   
      print "Invalid hunter name " + nhName 
      usage()

    for pat in args :
       for fileName in glob.iglob(pat) :
          nh.execute(fileName)

Reply via email to