Skip to content

Commit 5fdbbf9

Browse files
committed
Merge branch 'dev'
2 parents 485b2e4 + 633b267 commit 5fdbbf9

19 files changed

+1209
-34
lines changed

README.md

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,22 @@ More information in [wiki page](https://github.com/adireddy/haxe-checkstyle/wiki
4141
"severity": "ERROR"
4242
}
4343
},
44+
{
45+
"type": "ConstantName",
46+
"props": {
47+
"severity": "ERROR",
48+
"format": "^[A-Z][A-Z0-9]*(_[A-Z0-9_]+)*$",
49+
"tokens": [ "INLINE" ]
50+
}
51+
},
52+
{
53+
"type": "ConstantName",
54+
"props": {
55+
"severity": "ERROR",
56+
"format": "^[a-z]+[a-zA-Z0-9_]*$",
57+
"tokens": [ "NOTINLINE" ]
58+
}
59+
},
4460
{
4561
"type": "EmptyLines",
4662
"props": {
@@ -88,6 +104,22 @@ More information in [wiki page](https://github.com/adireddy/haxe-checkstyle/wiki
88104
"listeners": ["addEventListener", "addListener", "on", "once"]
89105
}
90106
},
107+
{
108+
"type": "MemberName",
109+
"props": {
110+
"severity": "ERROR",
111+
"format": "^[A-Z]+[A-Z0-9_]*$",
112+
"tokens": [ "ENUM" ]
113+
}
114+
},
115+
{
116+
"type": "MemberName",
117+
"props": {
118+
"severity": "ERROR",
119+
"format": "^[a-z]+[a-zA-Z0-9_]*$",
120+
"tokens": [ "PUBLIC", "PRIVATE", "TYPEDEF" ]
121+
}
122+
},
91123
{
92124
"type": "MethodLength",
93125
"props": {
@@ -129,6 +161,13 @@ More information in [wiki page](https://github.com/adireddy/haxe-checkstyle/wiki
129161
"severity": "ERROR"
130162
}
131163
},
164+
{
165+
"type": "ParameterName",
166+
"props": {
167+
"severity": "ERROR",
168+
"format": "^[a-z]+[a-zA-Z0-9_]*$"
169+
}
170+
},
132171
{
133172
"type": "ParameterNumber",
134173
"props": {
@@ -186,6 +225,22 @@ More information in [wiki page](https://github.com/adireddy/haxe-checkstyle/wiki
186225
"severity": "ERROR"
187226
}
188227
},
228+
{
229+
"type": "TypeName",
230+
"props": {
231+
"severity": "ERROR",
232+
"format": "^I[A-Z]+[a-zA-Z0-9_]*$",
233+
"tokens": [ "INTERFACE" ]
234+
}
235+
},
236+
{
237+
"type": "TypeName",
238+
"props": {
239+
"severity": "ERROR",
240+
"format": "^[A-Z]+[a-zA-Z0-9_]*$",
241+
"tokens": [ "CLASS", "ENUM", "TYPEDEF" ]
242+
}
243+
},
189244
{
190245
"type": "VariableInitialisation",
191246
"props": {

checkstyle/ChecksInfo.hx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ class ChecksInfo {
1313
var checksClasses = CompileTime.getAllClasses(Check);
1414

1515
for (cl in checksClasses) {
16+
if (ignoreClass(cl)) continue;
1617
var name = getCheckNameFromClass(cl);
1718
var desc = getCheckDescription(cl);
1819
name2info[name] = {
@@ -23,6 +24,11 @@ class ChecksInfo {
2324
}
2425
}
2526

27+
static function ignoreClass(cl:Class<Check>) {
28+
var meta = haxe.rtti.Meta.getType(cl);
29+
return (meta.ignore != null);
30+
}
31+
2632
static function getCheckNameFromClass(cl:Class<Check>) {
2733
var meta = haxe.rtti.Meta.getType(cl);
2834
if (meta.name == null) throw '${Type.getClassName(cl)} have no @name meta.';
@@ -53,4 +59,4 @@ typedef CheckInfo = {
5359
var name:String;
5460
var description:String;
5561
var clazz:Class<Check>;
56-
}
62+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package checkstyle.checks;
2+
3+
import checkstyle.LintMessage.SeverityLevel;
4+
import haxeparser.Data;
5+
import haxe.macro.Expr;
6+
7+
@name("ConstantName")
8+
@desc("Checks on naming conventions of constants (static / static inline with initialisation)")
9+
class ConstantNameCheck extends NameCheckBase {
10+
11+
public static inline var INLINE:String = "INLINE";
12+
public static inline var NOTINLINE:String = "NOTINLINE";
13+
14+
public function new() {
15+
super();
16+
severity = "ERROR";
17+
format = "^[A-Z][A-Z0-9]*(_[A-Z0-9_]+)*$";
18+
}
19+
20+
override function checkClassType(d:Definition<ClassFlag, Array<Field>>, pos:Position) {
21+
if (ignoreExtern && (d.flags.indexOf (HExtern) > -1)) return;
22+
checkFields (d.data);
23+
}
24+
25+
override function checkEnumType(d:Definition<EnumFlag, Array<EnumConstructor>>, pos:Position) {}
26+
27+
override function checkAbstractType(d:Definition<AbstractFlag, Array<Field>>, pos:Position) {
28+
checkFields (d.data);
29+
}
30+
31+
override function checkTypedefType(d:Definition<EnumFlag, ComplexType>, pos:Position) {}
32+
33+
function checkFields(d:Array<Field>) {
34+
for (field in d) {
35+
switch (field.kind) {
36+
case FVar (t, e):
37+
checkField(field, t, e);
38+
default:
39+
}
40+
}
41+
}
42+
43+
function checkField(f:Field, t:ComplexType, e:Expr) {
44+
45+
if (e == null || e.expr == null) return;
46+
var access = getFieldAccess (f);
47+
48+
if (!access.isStatic) return;
49+
if (!hasToken (INLINE) && access.isInline) return;
50+
if (!hasToken (NOTINLINE) && !access.isInline) return;
51+
52+
matchTypeName ("const", f.name, f.pos);
53+
}
54+
}

checkstyle/checks/CyclomaticComplexityCheck.hx

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@ using Lambda;
1313
@desc("McCabe simplified cyclomatic complexity check")
1414
class CyclomaticComplexityCheck extends Check {
1515

16-
public var thresholds:Array<Threshold>;
16+
public var thresholds:Array<Threshold> = [
17+
{ severity : "WARNING", complexity : 11 },
18+
{ severity : "ERROR", complexity : 21 }
19+
];
1720

1821
override function _actualRun() {
1922
_checker.ast.decls.map(function(type:TypeDecl):Null<Definition<ClassFlag, Array<Field>>> {
@@ -39,19 +42,19 @@ class CyclomaticComplexityCheck extends Check {
3942

4043
function calculateComplexity(method:Target) {
4144
var complexity:Int = 1 + evaluateExpr(method.expr);
42-
45+
4346
var risk:Null<Threshold> = thresholds.filter(function(t:Threshold):Bool {
4447
return complexity >= t.complexity;
4548
}).pop();
46-
49+
4750
if (risk != null) {
4851
notify(method, complexity, risk);
4952
}
5053
}
51-
54+
5255
// This would not pass the cyclomatic complexity test.
5356
function evaluateExpr(e:Expr):Int {
54-
if (e == null) {
57+
if (e == null || e.expr == null) {
5558
return 0;
5659
}
5760
return switch(e.expr) {
@@ -62,9 +65,9 @@ class CyclomaticComplexityCheck extends Check {
6265
default : 0;
6366
};
6467
case ExprDef.EParenthesis(e) : evaluateExpr(e);
65-
case ExprDef.EObjectDecl(fields) :
66-
fields.map(function(f):Expr {
67-
return f.expr;
68+
case ExprDef.EObjectDecl(fields) :
69+
fields.map(function(f):Expr {
70+
return f.expr;
6871
}).fold(function(e:Expr, total:Int):Int {
6972
return total + evaluateExpr(e);
7073
}, 0);
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package checkstyle.checks;
2+
3+
import checkstyle.LintMessage.SeverityLevel;
4+
import haxeparser.Data;
5+
import haxe.macro.Expr;
6+
7+
@name("MemberName")
8+
@desc("Checks on naming conventions of non-static fields")
9+
class MemberNameCheck extends NameCheckBase {
10+
11+
public static inline var PUBLIC:String = "PUBLIC";
12+
public static inline var PRIVATE:String = "PRIVATE";
13+
public static inline var ENUM:String = "ENUM";
14+
public static inline var TYPEDEF:String = "TYPEDEF";
15+
16+
public function new() {
17+
super();
18+
severity = "ERROR";
19+
format = "^[a-z]+[a-zA-Z0-9_]*$";
20+
}
21+
22+
override function checkClassType(d:Definition<ClassFlag, Array<Field>>, pos:Position) {
23+
if (ignoreExtern && (d.flags.indexOf (HExtern) > -1)) return;
24+
checkFields (d.data);
25+
}
26+
27+
override function checkEnumType(d:Definition<EnumFlag, Array<EnumConstructor>>, pos:Position) {
28+
if (!hasToken (ENUM)) return;
29+
if (ignoreExtern && (d.flags.indexOf (EExtern) > -1)) return;
30+
checkEnumFields (d.data);
31+
}
32+
33+
override function checkAbstractType(d:Definition<AbstractFlag, Array<Field>>, pos:Position) {
34+
checkFields (d.data);
35+
}
36+
37+
override function checkTypedefType(d:Definition<EnumFlag, ComplexType>, pos:Position) {
38+
if (!hasToken (TYPEDEF)) return;
39+
if (ignoreExtern && (d.flags.indexOf (EExtern) > -1)) return;
40+
41+
switch (d.data) {
42+
case TAnonymous (f):
43+
checkTypedefFields (f);
44+
default:
45+
}
46+
}
47+
48+
function checkFields(d:Array<Field>) {
49+
for (field in d) {
50+
switch (field.kind) {
51+
case FVar (t, e):
52+
checkField (field, t, e);
53+
default:
54+
}
55+
}
56+
}
57+
58+
function checkTypedefFields(d:Array<Field>) {
59+
for (field in d) {
60+
switch (field.kind) {
61+
case FVar (t, e):
62+
checkTypedefField (field, t, e);
63+
default:
64+
}
65+
}
66+
}
67+
68+
function checkEnumFields(d:Array<EnumConstructor>) {
69+
for (field in d) {
70+
matchTypeName ("enum member", field.name, field.pos);
71+
}
72+
}
73+
74+
function checkField(f:Field, t:ComplexType, e:Expr) {
75+
var access = getFieldAccess (f);
76+
77+
if (access.isStatic) return;
78+
if (!hasToken (PUBLIC) && access.isPublic) return;
79+
if (!hasToken (PRIVATE) && access.isPrivate) return;
80+
81+
matchTypeName ("member", f.name, f.pos);
82+
}
83+
84+
function checkTypedefField(f:Field, t:ComplexType, e:Expr) {
85+
matchTypeName ("typedef member", f.name, f.pos);
86+
}
87+
}

checkstyle/checks/NameCheckBase.hx

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
package checkstyle.checks;
2+
3+
import checkstyle.LintMessage.SeverityLevel;
4+
import haxeparser.Data;
5+
import haxe.macro.Expr;
6+
7+
@ignore("Base class for name checks")
8+
class NameCheckBase extends Check {
9+
10+
public var severity:String;
11+
public var format:String;
12+
public var tokens:Array<String>;
13+
public var ignoreExtern:Bool;
14+
15+
var formatRE:EReg;
16+
17+
public function new() {
18+
super();
19+
severity = "ERROR";
20+
format = "^.*$";
21+
tokens = [];
22+
ignoreExtern = true;
23+
}
24+
25+
function hasToken(token:String):Bool {
26+
if (tokens.length == 0) return true;
27+
if (tokens.indexOf (token) > -1) return true;
28+
return false;
29+
}
30+
31+
override function _actualRun() {
32+
formatRE = new EReg (format, "");
33+
checkClassFields();
34+
}
35+
36+
function checkClassFields() {
37+
for (td in _checker.ast.decls) {
38+
switch (td.decl) {
39+
case EClass (d):
40+
checkClassType (d, td.pos);
41+
case EEnum (d):
42+
checkEnumType (d, td.pos);
43+
case EAbstract (d):
44+
checkAbstractType (d, td.pos);
45+
case ETypedef (d):
46+
checkTypedefType (d, td.pos);
47+
default:
48+
}
49+
}
50+
}
51+
52+
function checkClassType(d:Definition<ClassFlag, Array<Field>>, pos:Position) {}
53+
54+
function checkEnumType(d:Definition<EnumFlag, Array<EnumConstructor>>, pos:Position) {}
55+
56+
function checkAbstractType(d:Definition<AbstractFlag, Array<Field>>, pos:Position) {}
57+
58+
function checkTypedefType(d:Definition<EnumFlag, ComplexType>, pos:Position) {}
59+
60+
function getFieldAccess(f:Field):NameFieldAccess {
61+
var isPrivate = false;
62+
var isPublic = false;
63+
var isInline = false;
64+
var isStatic = false;
65+
66+
if (f.access.indexOf(AInline) > -1) isInline = true;
67+
if (f.access.indexOf(AStatic) > -1) isStatic = true;
68+
if (f.access.indexOf(APublic) > -1) isPublic = true;
69+
else isPrivate = true;
70+
return {
71+
isPrivate: isPrivate,
72+
isPublic: isPublic,
73+
isInline: isInline,
74+
isStatic: isStatic
75+
};
76+
}
77+
78+
function matchTypeName(type:String, name:String, pos:Position)
79+
{
80+
if (!formatRE.match (name)) {
81+
_warn(type, name, pos);
82+
}
83+
}
84+
85+
function _warn(type:String, name:String, pos:Position) {
86+
logPos('Invalid ${type} signature: ${name} (name should be ~/${format}/)', pos, Reflect.field(SeverityLevel, severity));
87+
}
88+
}
89+
90+
typedef NameFieldAccess = {
91+
var isPrivate:Bool;
92+
var isPublic:Bool;
93+
var isInline:Bool;
94+
var isStatic:Bool;
95+
};

0 commit comments

Comments
 (0)