Using Vera++

  1. Vera++ can look in alternative directories for input like rules and profiles, but it doesn't look in multiple directories. So if we customize it by using a ~/.vera++ directory, it ignores /usr/lib/vera++. We must there fore copy the latter to the former:

    cp -rp /usr/lib/vera++ ~/.vera++

    if
  2. Vera++ 1.2.1 and vera++ 1.3 apparently expect different layouts of their configuration directories. So we add a symlink, to make them both work:

    ln -sT ../rules ~/.vera++/scripts/rules

  3. A rule might be a Tcl script. This is ~/.vera++/rules/J001:

    #!/usr/bin/tclsh
    # Binary operators should have whitespace on both sides.
    
    # FixMe: '*' and '&' not checked because vera++ doesn't know whether they are
    # pointer or arithmetic operators, and I've insufficient tcl skills to expand
    # the state machine
    
    set binops {
            andand
            andassign
            assign
            divide
            divideassign
            equal
            greater
            greaterequal
            less
            lessequal
            minus
            minusassign
            notequal
            or
            orassign
            oror
            percent
            percentassign
            plus
            plusassign
            question_mark
            shiftleft
            shiftleftassign
            shiftright
            shiftrightassign
            starassign
            xor
            xorassign
    }
    
    
    proc isBinop {s} {
            global binops
            return [expr [lsearch $binops $s] != -1]
    }
    
    # Current token
    set tokenName "other"
    set tokenValue ""
    set line "0"
    set column "0"
    
    # Previous token
    set tmin1Name "other"
    set tmin1Val ""
    set tmin1Line "0"
    set tmin1Col "0"
    
    # Two tokens ago
    set tmin2Name "other"
    # Don't remember anything else about tmin2
    
    foreach f [getSourceFileNames] {
            foreach t [getTokens $f 1 0 -1 -1 {}] {
                    set tmin1Line $line
                    set tmin1Col $column
                    set line [lindex $t 1]
                    set column [lindex $t 2]
                    
                    set tmin2Name $tmin1Name
                    set tmin1Name $tokenName
                    set tmin1Val $tokenValue
                    
                    set tokenValue [lindex $t 0]
                    set tokenName [lindex $t 3]
                    if [isBinop $tmin1Name] {
                            if {$tmin2Name != "space" || $tokenName != "space"} {
                                    report $f $line "binary operator \'${tmin1Val}\' not surrounded by whitespace"
                            }
                    }
            }
    }

  4. This is ~/.vera++/profiles/cppc:

    # L002 No tabs
    # L003 No leading and no trailing empty lines
    # L004 Line cannot be too long
    # L005 There should not be too many consecutive empty lines
    # L006 Source file should not be too long
    # T001 One-line comments should not have forced continuation
    # T004 Some keywords should be immediately followed by a colon
    # T005 Keywords break and continue should be immediately followed by a
    # T006 Keywords return and throw should be immediately followed by a
    # T008 Blank after keywords (if, for, while, ...)
    # T018 Using namespace is not allowed in header files
    # T011 Curly brackets from the same pair should be either in the same
    # J001 Blanks around binary operators
    set rules {
            L002
            L003
            L004
            L005
            L006
            T001
            T004
            T005
            T006
            T008
            T011
            T018
            J001
    }

  5. Now we can check sources:

    vera++ -e -p cppc --parameters ~/.vera++/profiles/cppc.params main.cc