Skip to content

Commit e48a205

Browse files
committed
unused imports now checks string interpolation for types (#274)
prevent stacktrace when calling checkstyle with an invalid config file
1 parent c60a025 commit e48a205

File tree

3 files changed

+60
-5
lines changed

3 files changed

+60
-5
lines changed

src/checkstyle/Main.hx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,8 @@ class Main {
109109
excludePath = DEFAULT_EXCLUDE_CONFIG;
110110
}
111111

112-
if (configPath == null) addAllChecks();
113-
else loadConfig(configPath);
112+
if (configPath != null && FileSystem.exists(configPath) && !FileSystem.isDirectory(configPath)) loadConfig(configPath);
113+
else addAllChecks();
114114

115115
if (excludePath != null) loadExcludeConfig(excludePath);
116116
else start();

src/checkstyle/checks/imports/UnusedImportCheck.hx

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,22 @@ class UnusedImportCheck extends Check {
3232
var imports:Array<TokenTree> = root.filter([Kwd(KwdImport)], ALL);
3333
var idents:Array<TokenTree> = root.filterCallback(function(token:TokenTree, depth:Int):FilterResult {
3434
switch (token.tok) {
35-
case Const(CIdent(name)):
35+
case Const(CIdent(_)):
3636
if (TokenTreeCheckUtils.isImport(token)) return GO_DEEPER;
3737
return FOUND_GO_DEEPER;
3838
default:
3939
}
4040
return GO_DEEPER;
4141
});
42+
var stringLiterals:Array<TokenTree> = root.filterCallback(function(token:TokenTree, depth:Int):FilterResult {
43+
switch (token.tok) {
44+
case Const(CString(text)):
45+
if (checker.file.content.substr(token.pos.min, 1) != "'") return GO_DEEPER;
46+
if (~/\$\{[^\}]+\.[^\}]+\}/.match (text)) return FOUND_GO_DEEPER;
47+
default:
48+
}
49+
return GO_DEEPER;
50+
});
4251
for (imp in imports) {
4352
var typeName:String = detectTypeName(imp);
4453
var moduleName:String = detectModuleName(imp);
@@ -60,7 +69,7 @@ class UnusedImportCheck extends Check {
6069
continue;
6170
}
6271
seenModules.push(moduleName);
63-
checkUsage(typeName, moduleName, imp, idents);
72+
checkUsage(typeName, moduleName, imp, idents, stringLiterals);
6473
}
6574
}
6675

@@ -119,7 +128,7 @@ class UnusedImportCheck extends Check {
119128
return null;
120129
}
121130

122-
function checkUsage(typeName:String, moduleName:String, importTok:TokenTree, idents:Array<TokenTree>) {
131+
function checkUsage(typeName:String, moduleName:String, importTok:TokenTree, idents:Array<TokenTree>, stringLiterals:Array<TokenTree>) {
123132
for (ident in idents) {
124133
var name:String = TokenDefPrinter.print(ident.tok);
125134
if (!checkName(typeName, moduleName, name)) continue;
@@ -129,9 +138,35 @@ class UnusedImportCheck extends Check {
129138
default: return;
130139
}
131140
}
141+
for (literal in stringLiterals) {
142+
var names : Array<String> = extractLiteralNames(TokenDefPrinter.print (literal.tok));
143+
for (name in names) {
144+
if (checkName(typeName, moduleName, name)) return;
145+
}
146+
}
132147
logPos('Unused import "$moduleName" detected', importTok.pos);
133148
}
134149

150+
function extractLiteralNames(text : String):Array<String> {
151+
var names : Array<String> = [];
152+
var interpols : Array<String> = [];
153+
var interpolRegEx : EReg = ~/\$\{([^\}]+)\}/g;
154+
while (true) {
155+
if (!interpolRegEx.match(text)) break;
156+
interpols.push(interpolRegEx.matched(1));
157+
text = interpolRegEx.matchedRight();
158+
}
159+
var namesRegEx : EReg = ~/([A-Z][A-Za-z0-9_]*)/g;
160+
for (interpol in interpols) {
161+
while (true) {
162+
if (!namesRegEx.match(interpol)) break;
163+
names.push(namesRegEx.matched(1));
164+
interpol = namesRegEx.matchedRight();
165+
}
166+
}
167+
return names;
168+
}
169+
135170
function hasMapping(moduleName:String):Bool {
136171
var mappedTypes:Array<String> = Reflect.field(moduleTypeMap, moduleName);
137172
return ((mappedTypes != null) && (mappedTypes.length > 0));

test/checks/imports/UnusedImportCheckTest.hx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@ class UnusedImportCheckTest extends CheckTestCase<UnusedImportCheckTests> {
6969
assertNoMsg(check, IMPORT_TYPE_MAP, "import.hx");
7070
assertNoMsg(check, UNUSED_IMPORT_TYPE_MAP, "import.hx");
7171
}
72+
73+
public function testStringInterpolation() {
74+
var check = new UnusedImportCheck();
75+
assertMsg(check, STRING_INTERPOL, MSG_UNUSED);
76+
}
7277
}
7378

7479
@:enum
@@ -79,6 +84,7 @@ abstract UnusedImportCheckTests(String) to String {
7984
import haxe.checkstyle.Check;
8085
import haxe.checkstyle.Check2;
8186
import haxe.checkstyle.Check3;
87+
import haxe.checkstyle.Check5;
8288
import haxe.checkstyle.sub.*;
8389
8490
abstractAndClass Test {
@@ -88,6 +94,7 @@ abstract UnusedImportCheckTests(String) to String {
8894
new Check2();
8995
Check3.test();
9096
new Check4();
97+
trace ('${Check5.debug()} ${blah.xxx}');
9198
}
9299
}";
93100

@@ -255,4 +262,17 @@ abstract UnusedImportCheckTests(String) to String {
255262
return new OtherCheck ();
256263
}
257264
}";
265+
266+
var STRING_INTERPOL = "
267+
package checkstyle.test;
268+
269+
import haxe.checkstyle.Check3;
270+
271+
abstractAndClass Test {
272+
273+
public function new() {
274+
trace ('${Check3}');
275+
}
276+
}";
277+
258278
}

0 commit comments

Comments
 (0)