Skip to content

Commit a4a5734

Browse files
committed
UDA to disable linting: handle check status in NoLint struct
1 parent 156ea55 commit a4a5734

File tree

4 files changed

+65
-77
lines changed

4 files changed

+65
-77
lines changed

src/dscanner/analysis/base.d

Lines changed: 16 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
module dscanner.analysis.base;
22

3-
import dscanner.analysis.nolint;
43
import dparse.ast;
54
import dparse.lexer : IdType, str, Token, tok;
5+
import dscanner.analysis.nolint;
66
import dsymbol.scope_ : Scope;
77
import std.array;
88
import std.container;
@@ -413,8 +413,9 @@ public:
413413
*/
414414
override void visit(const(ModuleDeclaration) moduleDeclaration)
415415
{
416-
if(stopLinting(moduleDeclaration))
417-
return;
416+
auto currNoLint = NoLintFactory.fromModuleDeclaration(moduleDeclaration);
417+
noLint.push(currNoLint);
418+
scope(exit) noLint.pop(currNoLint);
418419

419420
moduleDeclaration.accept(this);
420421
}
@@ -426,12 +427,11 @@ public:
426427
*/
427428
override void visit(const(Declaration) decl)
428429
{
429-
const msgDisabled = maybeDisableErrorMessage(decl);
430+
auto currNoLint = NoLintFactory.fromDeclaration(decl);
431+
noLint.push(currNoLint);
432+
scope(exit) noLint.pop(currNoLint);
430433

431434
decl.accept(this);
432-
433-
if(msgDisabled)
434-
reenableErrorMessage();
435435
}
436436

437437
AutoFix.CodeReplacement[] resolveAutoFix(
@@ -452,7 +452,7 @@ protected:
452452

453453
bool inAggregate;
454454
bool skipTests;
455-
int errorMsgDisabled;
455+
NoLint noLint;
456456

457457
template visitTemplate(T)
458458
{
@@ -467,100 +467,61 @@ protected:
467467
deprecated("Use the overload taking start and end locations or a Node instead")
468468
void addErrorMessage(size_t line, size_t column, string key, string message)
469469
{
470-
if(!errorMsgEnabled())
470+
if(noLint.containsCheck(this.getName()))
471471
return;
472472
_messages.insert(Message(fileName, line, column, key, message, getName()));
473473
}
474474

475475
void addErrorMessage(const BaseNode node, string key, string message, AutoFix[] autofixes = null)
476476
{
477-
if(!errorMsgEnabled())
477+
if(noLint.containsCheck(this.getName()))
478478
return;
479479
addErrorMessage(Message.Diagnostic.from(fileName, node, message), key, autofixes);
480480
}
481481

482482
void addErrorMessage(const Token token, string key, string message, AutoFix[] autofixes = null)
483483
{
484-
if(!errorMsgEnabled())
484+
if(noLint.containsCheck(this.getName()))
485485
return;
486486
addErrorMessage(Message.Diagnostic.from(fileName, token, message), key, autofixes);
487487
}
488488

489489
void addErrorMessage(const Token[] tokens, string key, string message, AutoFix[] autofixes = null)
490490
{
491-
if(!errorMsgEnabled())
491+
if(noLint.containsCheck(this.getName()))
492492
return;
493493
addErrorMessage(Message.Diagnostic.from(fileName, tokens, message), key, autofixes);
494494
}
495495

496496
void addErrorMessage(size_t[2] index, size_t line, size_t[2] columns, string key, string message, AutoFix[] autofixes = null)
497497
{
498-
if(!errorMsgEnabled())
498+
if(noLint.containsCheck(this.getName()))
499499
return;
500500
addErrorMessage(index, [line, line], columns, key, message, autofixes);
501501
}
502502

503503
void addErrorMessage(size_t[2] index, size_t[2] lines, size_t[2] columns, string key, string message, AutoFix[] autofixes = null)
504504
{
505-
if(!errorMsgEnabled())
505+
if(noLint.containsCheck(this.getName()))
506506
return;
507507
auto d = Message.Diagnostic.from(fileName, index, lines, columns, message);
508508
_messages.insert(Message(d, key, getName(), autofixes));
509509
}
510510

511511
void addErrorMessage(Message.Diagnostic diagnostic, string key, AutoFix[] autofixes = null)
512512
{
513-
if(!errorMsgEnabled())
513+
if(noLint.containsCheck(this.getName()))
514514
return;
515515
_messages.insert(Message(diagnostic, key, getName(), autofixes));
516516
}
517517

518518
void addErrorMessage(Message.Diagnostic diagnostic, Message.Diagnostic[] supplemental, string key, AutoFix[] autofixes = null)
519519
{
520-
if(!errorMsgEnabled())
520+
if(noLint.containsCheck(this.getName()))
521521
return;
522522
_messages.insert(Message(diagnostic, supplemental, key, getName(), autofixes));
523523
}
524524

525-
void reenableErrorMessage()
526-
in(this.errorMsgDisabled > 0)
527-
{
528-
this.errorMsgDisabled--;
529-
}
530-
531-
bool errorMsgEnabled() const
532-
{
533-
return this.errorMsgDisabled == 0;
534-
}
535-
536-
// Disable error message if declaration contains UDA :
537-
// @("nolint(..)") and @nolint(".."), ..
538-
// that indicates to skip linting on this declaration
539-
// Return wheter the message is actually disabled or not
540-
bool maybeDisableErrorMessage(const Declaration decl)
541-
{
542-
if(stopLinting(decl))
543-
{
544-
this.errorMsgDisabled++;
545-
return true;
546-
}
547-
else
548-
return false;
549-
}
550-
551-
bool stopLinting(AstNode)(const AstNode node)
552-
{
553-
import std.typecons: Nullable;
554-
Nullable!NoLint noLint;
555-
556-
static if(is(AstNode == ModuleDeclaration))
557-
noLint = NoLintFactory.fromModuleDeclaration(node);
558-
else static if(is(AstNode == Declaration))
559-
noLint = NoLintFactory.fromDeclaration(node);
560-
561-
return !noLint.isNull && noLint.get.containsCheck(this.getName());
562-
}
563-
564525
/**
565526
* The file name
566527
*/

src/dscanner/analysis/nolint.d

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,28 +13,47 @@ struct NoLint
1313
{
1414
bool containsCheck(in string check) const
1515
{
16-
return disabledChecks.canFind(check);
16+
return (check in disabledChecks) !is null &&
17+
disabledChecks[check] > 0;
1718
}
1819

1920
package:
20-
const(string[]) getDisabledChecks() const
21+
const(int[string]) getDisabledChecks() const
2122
{
2223
return this.disabledChecks;
2324
}
2425

25-
void addCheck(in string check)
26+
void pushCheck(in string check)
2627
{
27-
disabledChecks ~= check;
28+
disabledChecks[check]++;
2829
}
2930

30-
void merge(in Nullable!NoLint other)
31+
void push(in Nullable!NoLint other)
3132
{
32-
if(!other.isNull)
33-
this.disabledChecks ~= other.get.getDisabledChecks();
33+
if(other.isNull)
34+
return;
35+
36+
foreach(item; other.get.getDisabledChecks.byKeyValue)
37+
this.disabledChecks[item.key] += item.value;
38+
}
39+
40+
void pop(in Nullable!NoLint other)
41+
{
42+
if(other.isNull)
43+
return;
44+
45+
foreach(item; other.get.getDisabledChecks.byKeyValue)
46+
{
47+
assert((item.key in disabledChecks) !is null &&
48+
this.disabledChecks[item.key] >= item.value);
49+
50+
this.disabledChecks[item.key] -= item.value;
51+
}
3452
}
3553

54+
3655
private:
37-
string[] disabledChecks;
56+
int[string] disabledChecks;
3857
}
3958

4059
struct NoLintFactory
@@ -44,7 +63,7 @@ struct NoLintFactory
4463
NoLint noLint;
4564

4665
foreach(atAttribute; moduleDeclaration.atAttributes)
47-
noLint.merge(NoLintFactory.fromAtAttribute(atAttribute));
66+
noLint.push(NoLintFactory.fromAtAttribute(atAttribute));
4867

4968
if(!noLint.getDisabledChecks.length)
5069
return nullNoLint;
@@ -56,7 +75,7 @@ struct NoLintFactory
5675
{
5776
NoLint noLint;
5877
foreach(attribute; declaration.attributes)
59-
noLint.merge(NoLintFactory.fromAttribute(attribute));
78+
noLint.push(NoLintFactory.fromAttribute(attribute));
6079

6180
if(!noLint.getDisabledChecks.length)
6281
return nullNoLint;
@@ -115,7 +134,7 @@ private:
115134
if(primaryExpression.primary != tok!"stringLiteral")
116135
continue;
117136

118-
noLint.addCheck(primaryExpression.primary.text.strip("\""));
137+
noLint.pushCheck(primaryExpression.primary.text.strip("\""));
119138
}
120139
}
121140

@@ -144,7 +163,7 @@ private:
144163

145164
auto str = primaryExpression.primary.text.strip("\"");
146165
Nullable!NoLint currNoLint = NoLintFactory.fromString(str);
147-
noLint.merge(currNoLint);
166+
noLint.push(currNoLint);
148167
}
149168
}
150169

@@ -175,7 +194,7 @@ private:
175194

176195
while(matches)
177196
{
178-
noLint.addCheck(matches.hit);
197+
noLint.pushCheck(matches.hit);
179198
matches.popFront;
180199
}
181200

@@ -195,8 +214,14 @@ unittest
195214
const s3 = " nolint ( abc , efg ) ";
196215
const s4 = "OtherUda(abc)";
197216

198-
assert(NoLintFactory.fromString(s1).get == NoLint(["abc"]));
199-
assert(NoLintFactory.fromString(s2).get == NoLint(["abc", "efg", "hij"]));
200-
assert(NoLintFactory.fromString(s3).get == NoLint(["abc", "efg"]));
217+
assert(NoLintFactory.fromString(s1).get.containsCheck("abc"));
218+
219+
assert(NoLintFactory.fromString(s2).get.containsCheck("abc"));
220+
assert(NoLintFactory.fromString(s2).get.containsCheck("efg"));
221+
assert(NoLintFactory.fromString(s2).get.containsCheck("hij"));
222+
223+
assert(NoLintFactory.fromString(s3).get.containsCheck("abc"));
224+
assert(NoLintFactory.fromString(s3).get.containsCheck("efg"));
225+
201226
assert(NoLintFactory.fromString(s4).isNull);
202227
}

src/dscanner/analysis/style.d

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import std.conv;
1414
import std.format;
1515
import dscanner.analysis.helpers;
1616
import dscanner.analysis.base;
17+
import dscanner.analysis.nolint;
1718
import dsymbol.scope_ : Scope;
1819

1920
final class StyleChecker : BaseAnalyzer
@@ -33,8 +34,9 @@ final class StyleChecker : BaseAnalyzer
3334

3435
override void visit(const ModuleDeclaration dec)
3536
{
36-
if(stopLinting(dec))
37-
return;
37+
auto currNoLint = NoLintFactory.fromModuleDeclaration(dec);
38+
noLint.push(currNoLint);
39+
scope(exit) noLint.pop(currNoLint);
3840

3941
foreach (part; dec.moduleName.identifiers)
4042
{

src/dscanner/analysis/useless_initializer.d

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
module dscanner.analysis.useless_initializer;
66

77
import dscanner.analysis.base;
8+
import dscanner.analysis.nolint;
89
import dscanner.utils : safeAccess;
910
import containers.dynamicarray;
1011
import containers.hashmap;
@@ -93,13 +94,12 @@ public:
9394
{
9495
_inStruct.insert(decl.structDeclaration !is null);
9596

96-
const msgDisabled = maybeDisableErrorMessage(decl);
97+
auto currNoLint = NoLintFactory.fromDeclaration(decl);
98+
noLint.push(currNoLint);
99+
scope(exit) noLint.pop(currNoLint);
97100

98101
decl.accept(this);
99102

100-
if(msgDisabled)
101-
reenableErrorMessage();
102-
103103
if (_inStruct.length > 1 && _inStruct[$-2] && decl.constructor &&
104104
((decl.constructor.parameters && decl.constructor.parameters.parameters.length == 0) ||
105105
!decl.constructor.parameters))

0 commit comments

Comments
 (0)