|
|
#!/usr/bin/tclsh
|
|
|
# Declaration order inside classes
|
|
|
|
|
|
proc createMachine {visibility initState} {
|
|
|
set machine [dict create visibility $visibility state $initState waitingFor "typedef" previousState "" bracesCounter 0 isStatic 0]
|
|
|
return $machine
|
|
|
}
|
|
|
|
|
|
proc createVisibilityMachine {} {
|
|
|
set machine [dict create state "beforeLeftBrace" visibilityState "waitingForPublic" bracesCounter 0 visibility ""]
|
|
|
return $machine
|
|
|
}
|
|
|
|
|
|
set tokenFilter {
|
|
|
public
|
|
|
protected
|
|
|
private
|
|
|
colon
|
|
|
typedef
|
|
|
class
|
|
|
struct
|
|
|
enum
|
|
|
static
|
|
|
const
|
|
|
identifier
|
|
|
operator
|
|
|
assign
|
|
|
semicolon
|
|
|
leftbrace
|
|
|
rightbrace
|
|
|
leftparen
|
|
|
rightparen
|
|
|
}
|
|
|
|
|
|
set globalOrder "The global order is public members then public slots, protected members then protected slots and private members then private slots."
|
|
|
|
|
|
foreach fileName [getSourceFileNames] {
|
|
|
set machines [list]
|
|
|
set visibilityMachines [list]
|
|
|
|
|
|
set visibilityState "waitingForPublic"
|
|
|
|
|
|
set prev1 ""
|
|
|
set prev2 ""
|
|
|
set lastIdentifier ""
|
|
|
foreach token [getTokens $fileName 1 0 -1 -1 $tokenFilter] {
|
|
|
set type [lindex $token 3]
|
|
|
set line [lindex $token 1]
|
|
|
|
|
|
if {$type == "identifier"} {
|
|
|
set lastIdentifier [lindex $token 0]
|
|
|
}
|
|
|
|
|
|
if {$type == "class" || $type == "struct"} {
|
|
|
lappend visibilityMachines [createVisibilityMachine]
|
|
|
}
|
|
|
|
|
|
if {$type == "colon" && ($prev1 == "public" || $prev1 == "protected" || $prev1 == "private")} {
|
|
|
lappend machines [createMachine $prev1 "beforeVisibility"]
|
|
|
}
|
|
|
|
|
|
# Machines for the visibility order
|
|
|
set visibilityMachinesToKeep [list]
|
|
|
foreach m $visibilityMachines {
|
|
|
set keepMachine 1
|
|
|
dict with m {
|
|
|
if {$state == "beforeLeftBrace"} {
|
|
|
if {$type == "semicolon"} {
|
|
|
set keepMachine 0
|
|
|
} elseif {$type == "leftbrace"} {
|
|
|
set state "root"
|
|
|
}
|
|
|
} elseif {$state == "root"} {
|
|
|
if {$type == "public" || $type == "protected" || $type == "private"} {
|
|
|
set visibility $type
|
|
|
set state "waitingForColon"
|
|
|
} elseif {$type == "leftbrace"} {
|
|
|
incr bracesCounter
|
|
|
set state "consumeBraces"
|
|
|
} elseif {$type == "rightbrace"} {
|
|
|
set keepMachine 0
|
|
|
}
|
|
|
} elseif {$state == "waitingForColon"} {
|
|
|
if {$type == "colon"} {
|
|
|
if {$visibility == "public" && $prev1 != "identifier"} {
|
|
|
if {$visibilityState == "waitingForPublicSlots"
|
|
|
|| $visibilityState == "waitingForProtected"
|
|
|
|| $visibilityState == "waitingForProtectedSlots"
|
|
|
|| $visibilityState == "waitingForPrivate"
|
|
|
|| $visibilityState == "waitingForPrivateSlots"
|
|
|
|| $visibilityState == "done"} {
|
|
|
report $fileName $line "There should be at most one public visibility and it should be at the start of the class. $globalOrder"
|
|
|
} else {
|
|
|
set visibilityState "waitingForPublicSlots"
|
|
|
}
|
|
|
} elseif {$visibility == "public" && $prev1 == "identifier" && $lastIdentifier == "slots"} {
|
|
|
if {$visibilityState == "waitingForProtected"
|
|
|
|| $visibilityState == "waitingForProtectedSlots"
|
|
|
|| $visibilityState == "waitingForPrivate"
|
|
|
|| $visibilityState == "waitingForPrivateSlots"
|
|
|
|| $visibilityState == "done"} {
|
|
|
report $fileName $line "There should be at most one public slots visibility and it should be between public and protected. $globalOrder"
|
|
|
} else {
|
|
|
set visibilityState "waitingForProtected"
|
|
|
}
|
|
|
} elseif {$visibility == "protected" && $prev1 != "identifier"} {
|
|
|
if {$visibilityState == "waitingForProtectedSlots"
|
|
|
|| $visibilityState == "waitingForPrivate"
|
|
|
|| $visibilityState == "waitingForPrivateSlots"
|
|
|
|| $visibilityState == "done"} {
|
|
|
report $fileName $line "There should be at most one protected visibility and it should be between public slots and protected slots. $globalOrder"
|
|
|
} else {
|
|
|
set visibilityState "waitingForProtectedSlots"
|
|
|
}
|
|
|
} elseif {$visibility == "protected" && $prev1 == "identifier" && $lastIdentifier == "slots"} {
|
|
|
if {$visibilityState == "waitingForPrivate"
|
|
|
|| $visibilityState == "waitingForPrivateSlots"
|
|
|
|| $visibilityState == "done"} {
|
|
|
report $fileName $line "There should be at most one protected slots visibility and it should be between protected and private. $globalOrder"
|
|
|
} else {
|
|
|
set visibilityState "waitingForPrivate"
|
|
|
}
|
|
|
} elseif {$visibility == "private" && $prev1 != "identifier"} {
|
|
|
if {$visibilityState == "waitingForPrivateSlots"
|
|
|
|| $visibilityState == "done"} {
|
|
|
report $fileName $line "There should be at most one private visibility and it should be between protected slots and private slots. $globalOrder"
|
|
|
} else {
|
|
|
set visibilityState "waitingForPrivateSlots"
|
|
|
}
|
|
|
} elseif {$visibility == "private" && $prev1 == "identifier" && $lastIdentifier == "slots"} {
|
|
|
if {$visibilityState == "done"} {
|
|
|
report $fileName $line "There should be at most one private visibility and it should be the last of the class. $globalOrder"
|
|
|
} else {
|
|
|
set visibilityState "done"
|
|
|
}
|
|
|
}
|
|
|
|
|
|
set state "root"
|
|
|
}
|
|
|
} elseif {$state == "consumeBraces"} {
|
|
|
if {$type == "leftbrace"} {
|
|
|
incr bracesCounter
|
|
|
} elseif {$type == "rightbrace"} {
|
|
|
incr bracesCounter -1
|
|
|
if {$bracesCounter == 0} {
|
|
|
set state "root"
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if {$keepMachine} {
|
|
|
lappend visibilityMachinesToKeep $m
|
|
|
}
|
|
|
}
|
|
|
set visibilityMachines $visibilityMachinesToKeep
|
|
|
|
|
|
# Machines for the declaration order inside a visibility
|
|
|
set machinesToKeep [list]
|
|
|
foreach m $machines {
|
|
|
set keepMachine 1
|
|
|
dict with m {
|
|
|
if {$state == "beforeVisibility" && $type == $visibility} {
|
|
|
set state "root"
|
|
|
} elseif {$state == "root"} {
|
|
|
if {$type == "public" || $type == "protected" || $type == "private" || $type == "rightbrace"} {
|
|
|
# End of the state machine when we reach the next
|
|
|
# visibility block
|
|
|
set keepMachine 0
|
|
|
} else {
|
|
|
if {$type == "static"} {
|
|
|
set isStatic 1
|
|
|
}
|
|
|
|
|
|
if {$waitingFor == "typedef"} {
|
|
|
if {$type == "typedef"} {
|
|
|
set state "consumeUntilNextSemiColon"
|
|
|
} else {
|
|
|
set waitingFor "enum"
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if {$waitingFor == "enum"} {
|
|
|
if {$type == "typedef"} {
|
|
|
set state "consumeUntilNextSemiColon"
|
|
|
report $fileName $line "The typedefs should be before the enums"
|
|
|
} elseif {$type == "enum"} {
|
|
|
set state "consumeUntilNextSemiColon"
|
|
|
} else {
|
|
|
set waitingFor "class/struct"
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if {$waitingFor == "class/struct"} {
|
|
|
if {$type == "typedef" || $type == "enum"} {
|
|
|
set state "consumeUntilNextSemiColon"
|
|
|
report $fileName $line "The typedefs and enums should be before the classes/structs"
|
|
|
} elseif {$type == "class" || $type == "struct"} {
|
|
|
set state "consumeUntilNextSemiColon"
|
|
|
} else {
|
|
|
set waitingFor "staticFunc"
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if {$waitingFor == "staticFunc"} {
|
|
|
if {$type == "typedef" || $type == "enum" || $type == "class" || $type == "struct"} {
|
|
|
set state "consumeUntilNextSemiColon"
|
|
|
report $fileName $line "The typedefs, enums, classes and structs should be before the static functions"
|
|
|
} elseif {$prev1 == "identifier"} {
|
|
|
if {$type == "leftparen"} {
|
|
|
if {$isStatic} {
|
|
|
set state "consumeFunction"
|
|
|
} else {
|
|
|
set waitingFor "method"
|
|
|
}
|
|
|
} elseif {$type == "assign" || $type == "semicolon"} {
|
|
|
set waitingFor "staticVar"
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if {$waitingFor == "staticVar"} {
|
|
|
if {$type == "typedef" || $type == "enum" || $type == "class" || $type == "struct"} {
|
|
|
set state "consumeUntilNextSemiColon"
|
|
|
report $fileName $line "The typedefs, enums, classes and structs should be before the static variables"
|
|
|
} elseif {$prev1 == "identifier"} {
|
|
|
if {$type == "leftparen"} {
|
|
|
if {$isStatic} {
|
|
|
set state "consumeFunction"
|
|
|
report $fileName $line "The static functions should be before the static variables"
|
|
|
} else {
|
|
|
set waitingFor "method"
|
|
|
}
|
|
|
} elseif {$type == "assign" || $type == "semicolon"} {
|
|
|
if {!$isStatic} {
|
|
|
set waitingFor "method"
|
|
|
}
|
|
|
if {$type != "semicolon"} {
|
|
|
set state "consumeUntilNextSemiColon"
|
|
|
} else {
|
|
|
set isStatic 0
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if {$waitingFor == "method"} {
|
|
|
if {$type == "typedef" || $type == "enum" || $type == "class" || $type == "struct"} {
|
|
|
set state "consumeUntilNextSemiColon"
|
|
|
report $fileName $line "The typedefs, enums, classes and structs should be before the methods"
|
|
|
} elseif {$prev2 == "identifier" && $prev1 == "operator" && $type == "assign"} {
|
|
|
# override of operator=()
|
|
|
set state "consumeFunction"
|
|
|
} elseif {$prev1 == "identifier"} {
|
|
|
if {$type == "leftparen"} {
|
|
|
if {$isStatic} {
|
|
|
report $fileName $line "The static functions should be before the methods"
|
|
|
}
|
|
|
set state "consumeFunction"
|
|
|
} elseif {$type == "assign" || $type == "semicolon"} {
|
|
|
if {$isStatic} {
|
|
|
report $fileName $line "The static variables should be before the methods"
|
|
|
} else {
|
|
|
set waitingFor "var"
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if {$waitingFor == "var"} {
|
|
|
if {$type == "typedef" || $type == "enum" || $type == "class" || $type == "struct"} {
|
|
|
set state "consumeUntilNextSemiColon"
|
|
|
report $fileName $line "The typedefs, enums, classes and structs should be before the variables"
|
|
|
} elseif {$prev1 == "identifier"} {
|
|
|
if {$type == "leftparen"} {
|
|
|
if {$isStatic} {
|
|
|
report $fileName $line "The static functions should be before the variables"
|
|
|
} else {
|
|
|
report $fileName $line "The methods should be before the variables"
|
|
|
}
|
|
|
set state "consumeFunction"
|
|
|
} elseif {$type == "assign" || $type == "semicolon"} {
|
|
|
if {$isStatic} {
|
|
|
report $fileName $line "The static variables should be before the variables"
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
} elseif {$state == "consumeUntilNextSemiColon"} {
|
|
|
set isStatic 0
|
|
|
if {$type == "semicolon"} {
|
|
|
set state "root"
|
|
|
} elseif {$type == "leftbrace"} {
|
|
|
incr bracesCounter
|
|
|
set previousState $state
|
|
|
set state "consumeBraces"
|
|
|
}
|
|
|
} elseif {$state == "consumeFunction"} {
|
|
|
set isStatic 0
|
|
|
if {$type == "semicolon"} {
|
|
|
set state "root"
|
|
|
} elseif {$type == "leftbrace"} {
|
|
|
incr bracesCounter
|
|
|
set previousState "root"
|
|
|
set state "consumeBraces"
|
|
|
}
|
|
|
} elseif {$state == "consumeBraces"} {
|
|
|
if {$type == "leftbrace"} {
|
|
|
incr bracesCounter
|
|
|
} elseif {$type == "rightbrace"} {
|
|
|
incr bracesCounter -1
|
|
|
if {$bracesCounter == 0} {
|
|
|
set state $previousState
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if {$keepMachine} {
|
|
|
lappend machinesToKeep $m
|
|
|
}
|
|
|
}
|
|
|
set machines $machinesToKeep
|
|
|
|
|
|
set prev2 $prev1
|
|
|
set prev1 $type
|
|
|
}
|
|
|
}
|