mirror of
https://github.com/dlang-community/D-Scanner.git
synced 2025-04-27 13:50:02 +03:00
UDA to disable linting: handle check status in NoLint struct
This commit is contained in:
parent
43c93e2537
commit
7fc1081630
4 changed files with 65 additions and 77 deletions
|
@ -1,8 +1,8 @@
|
|||
module dscanner.analysis.base;
|
||||
|
||||
import dscanner.analysis.nolint;
|
||||
import dparse.ast;
|
||||
import dparse.lexer : IdType, str, Token, tok;
|
||||
import dscanner.analysis.nolint;
|
||||
import dsymbol.scope_ : Scope;
|
||||
import std.array;
|
||||
import std.container;
|
||||
|
@ -413,8 +413,9 @@ public:
|
|||
*/
|
||||
override void visit(const(ModuleDeclaration) moduleDeclaration)
|
||||
{
|
||||
if(stopLinting(moduleDeclaration))
|
||||
return;
|
||||
auto currNoLint = NoLintFactory.fromModuleDeclaration(moduleDeclaration);
|
||||
noLint.push(currNoLint);
|
||||
scope(exit) noLint.pop(currNoLint);
|
||||
|
||||
moduleDeclaration.accept(this);
|
||||
}
|
||||
|
@ -426,12 +427,11 @@ public:
|
|||
*/
|
||||
override void visit(const(Declaration) decl)
|
||||
{
|
||||
const msgDisabled = maybeDisableErrorMessage(decl);
|
||||
auto currNoLint = NoLintFactory.fromDeclaration(decl);
|
||||
noLint.push(currNoLint);
|
||||
scope(exit) noLint.pop(currNoLint);
|
||||
|
||||
decl.accept(this);
|
||||
|
||||
if(msgDisabled)
|
||||
reenableErrorMessage();
|
||||
}
|
||||
|
||||
AutoFix.CodeReplacement[] resolveAutoFix(
|
||||
|
@ -452,7 +452,7 @@ protected:
|
|||
|
||||
bool inAggregate;
|
||||
bool skipTests;
|
||||
int errorMsgDisabled;
|
||||
NoLint noLint;
|
||||
|
||||
template visitTemplate(T)
|
||||
{
|
||||
|
@ -467,42 +467,42 @@ protected:
|
|||
deprecated("Use the overload taking start and end locations or a Node instead")
|
||||
void addErrorMessage(size_t line, size_t column, string key, string message)
|
||||
{
|
||||
if(!errorMsgEnabled())
|
||||
if(noLint.containsCheck(this.getName()))
|
||||
return;
|
||||
_messages.insert(Message(fileName, line, column, key, message, getName()));
|
||||
}
|
||||
|
||||
void addErrorMessage(const BaseNode node, string key, string message, AutoFix[] autofixes = null)
|
||||
{
|
||||
if(!errorMsgEnabled())
|
||||
if(noLint.containsCheck(this.getName()))
|
||||
return;
|
||||
addErrorMessage(Message.Diagnostic.from(fileName, node, message), key, autofixes);
|
||||
}
|
||||
|
||||
void addErrorMessage(const Token token, string key, string message, AutoFix[] autofixes = null)
|
||||
{
|
||||
if(!errorMsgEnabled())
|
||||
if(noLint.containsCheck(this.getName()))
|
||||
return;
|
||||
addErrorMessage(Message.Diagnostic.from(fileName, token, message), key, autofixes);
|
||||
}
|
||||
|
||||
void addErrorMessage(const Token[] tokens, string key, string message, AutoFix[] autofixes = null)
|
||||
{
|
||||
if(!errorMsgEnabled())
|
||||
if(noLint.containsCheck(this.getName()))
|
||||
return;
|
||||
addErrorMessage(Message.Diagnostic.from(fileName, tokens, message), key, autofixes);
|
||||
}
|
||||
|
||||
void addErrorMessage(size_t[2] index, size_t line, size_t[2] columns, string key, string message, AutoFix[] autofixes = null)
|
||||
{
|
||||
if(!errorMsgEnabled())
|
||||
if(noLint.containsCheck(this.getName()))
|
||||
return;
|
||||
addErrorMessage(index, [line, line], columns, key, message, autofixes);
|
||||
}
|
||||
|
||||
void addErrorMessage(size_t[2] index, size_t[2] lines, size_t[2] columns, string key, string message, AutoFix[] autofixes = null)
|
||||
{
|
||||
if(!errorMsgEnabled())
|
||||
if(noLint.containsCheck(this.getName()))
|
||||
return;
|
||||
auto d = Message.Diagnostic.from(fileName, index, lines, columns, message);
|
||||
_messages.insert(Message(d, key, getName(), autofixes));
|
||||
|
@ -510,57 +510,18 @@ protected:
|
|||
|
||||
void addErrorMessage(Message.Diagnostic diagnostic, string key, AutoFix[] autofixes = null)
|
||||
{
|
||||
if(!errorMsgEnabled())
|
||||
if(noLint.containsCheck(this.getName()))
|
||||
return;
|
||||
_messages.insert(Message(diagnostic, key, getName(), autofixes));
|
||||
}
|
||||
|
||||
void addErrorMessage(Message.Diagnostic diagnostic, Message.Diagnostic[] supplemental, string key, AutoFix[] autofixes = null)
|
||||
{
|
||||
if(!errorMsgEnabled())
|
||||
if(noLint.containsCheck(this.getName()))
|
||||
return;
|
||||
_messages.insert(Message(diagnostic, supplemental, key, getName(), autofixes));
|
||||
}
|
||||
|
||||
void reenableErrorMessage()
|
||||
in(this.errorMsgDisabled > 0)
|
||||
{
|
||||
this.errorMsgDisabled--;
|
||||
}
|
||||
|
||||
bool errorMsgEnabled() const
|
||||
{
|
||||
return this.errorMsgDisabled == 0;
|
||||
}
|
||||
|
||||
// Disable error message if declaration contains UDA :
|
||||
// @("nolint(..)") and @nolint(".."), ..
|
||||
// that indicates to skip linting on this declaration
|
||||
// Return wheter the message is actually disabled or not
|
||||
bool maybeDisableErrorMessage(const Declaration decl)
|
||||
{
|
||||
if(stopLinting(decl))
|
||||
{
|
||||
this.errorMsgDisabled++;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool stopLinting(AstNode)(const AstNode node)
|
||||
{
|
||||
import std.typecons: Nullable;
|
||||
Nullable!NoLint noLint;
|
||||
|
||||
static if(is(AstNode == ModuleDeclaration))
|
||||
noLint = NoLintFactory.fromModuleDeclaration(node);
|
||||
else static if(is(AstNode == Declaration))
|
||||
noLint = NoLintFactory.fromDeclaration(node);
|
||||
|
||||
return !noLint.isNull && noLint.get.containsCheck(this.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* The file name
|
||||
*/
|
||||
|
|
|
@ -13,28 +13,47 @@ struct NoLint
|
|||
{
|
||||
bool containsCheck(in string check) const
|
||||
{
|
||||
return disabledChecks.canFind(check);
|
||||
return (check in disabledChecks) !is null &&
|
||||
disabledChecks[check] > 0;
|
||||
}
|
||||
|
||||
package:
|
||||
const(string[]) getDisabledChecks() const
|
||||
const(int[string]) getDisabledChecks() const
|
||||
{
|
||||
return this.disabledChecks;
|
||||
}
|
||||
|
||||
void addCheck(in string check)
|
||||
void pushCheck(in string check)
|
||||
{
|
||||
disabledChecks ~= check;
|
||||
disabledChecks[check]++;
|
||||
}
|
||||
|
||||
void merge(in Nullable!NoLint other)
|
||||
void push(in Nullable!NoLint other)
|
||||
{
|
||||
if(!other.isNull)
|
||||
this.disabledChecks ~= other.get.getDisabledChecks();
|
||||
if(other.isNull)
|
||||
return;
|
||||
|
||||
foreach(item; other.get.getDisabledChecks.byKeyValue)
|
||||
this.disabledChecks[item.key] += item.value;
|
||||
}
|
||||
|
||||
void pop(in Nullable!NoLint other)
|
||||
{
|
||||
if(other.isNull)
|
||||
return;
|
||||
|
||||
foreach(item; other.get.getDisabledChecks.byKeyValue)
|
||||
{
|
||||
assert((item.key in disabledChecks) !is null &&
|
||||
this.disabledChecks[item.key] >= item.value);
|
||||
|
||||
this.disabledChecks[item.key] -= item.value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
string[] disabledChecks;
|
||||
int[string] disabledChecks;
|
||||
}
|
||||
|
||||
struct NoLintFactory
|
||||
|
@ -44,7 +63,7 @@ struct NoLintFactory
|
|||
NoLint noLint;
|
||||
|
||||
foreach(atAttribute; moduleDeclaration.atAttributes)
|
||||
noLint.merge(NoLintFactory.fromAtAttribute(atAttribute));
|
||||
noLint.push(NoLintFactory.fromAtAttribute(atAttribute));
|
||||
|
||||
if(!noLint.getDisabledChecks.length)
|
||||
return nullNoLint;
|
||||
|
@ -56,7 +75,7 @@ struct NoLintFactory
|
|||
{
|
||||
NoLint noLint;
|
||||
foreach(attribute; declaration.attributes)
|
||||
noLint.merge(NoLintFactory.fromAttribute(attribute));
|
||||
noLint.push(NoLintFactory.fromAttribute(attribute));
|
||||
|
||||
if(!noLint.getDisabledChecks.length)
|
||||
return nullNoLint;
|
||||
|
@ -115,7 +134,7 @@ private:
|
|||
if(primaryExpression.primary != tok!"stringLiteral")
|
||||
continue;
|
||||
|
||||
noLint.addCheck(primaryExpression.primary.text.strip("\""));
|
||||
noLint.pushCheck(primaryExpression.primary.text.strip("\""));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -144,7 +163,7 @@ private:
|
|||
|
||||
auto str = primaryExpression.primary.text.strip("\"");
|
||||
Nullable!NoLint currNoLint = NoLintFactory.fromString(str);
|
||||
noLint.merge(currNoLint);
|
||||
noLint.push(currNoLint);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -175,7 +194,7 @@ private:
|
|||
|
||||
while(matches)
|
||||
{
|
||||
noLint.addCheck(matches.hit);
|
||||
noLint.pushCheck(matches.hit);
|
||||
matches.popFront;
|
||||
}
|
||||
|
||||
|
@ -195,8 +214,14 @@ unittest
|
|||
const s3 = " nolint ( abc , efg ) ";
|
||||
const s4 = "OtherUda(abc)";
|
||||
|
||||
assert(NoLintFactory.fromString(s1).get == NoLint(["abc"]));
|
||||
assert(NoLintFactory.fromString(s2).get == NoLint(["abc", "efg", "hij"]));
|
||||
assert(NoLintFactory.fromString(s3).get == NoLint(["abc", "efg"]));
|
||||
assert(NoLintFactory.fromString(s1).get.containsCheck("abc"));
|
||||
|
||||
assert(NoLintFactory.fromString(s2).get.containsCheck("abc"));
|
||||
assert(NoLintFactory.fromString(s2).get.containsCheck("efg"));
|
||||
assert(NoLintFactory.fromString(s2).get.containsCheck("hij"));
|
||||
|
||||
assert(NoLintFactory.fromString(s3).get.containsCheck("abc"));
|
||||
assert(NoLintFactory.fromString(s3).get.containsCheck("efg"));
|
||||
|
||||
assert(NoLintFactory.fromString(s4).isNull);
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import std.conv;
|
|||
import std.format;
|
||||
import dscanner.analysis.helpers;
|
||||
import dscanner.analysis.base;
|
||||
import dscanner.analysis.nolint;
|
||||
import dsymbol.scope_ : Scope;
|
||||
|
||||
final class StyleChecker : BaseAnalyzer
|
||||
|
@ -33,8 +34,9 @@ final class StyleChecker : BaseAnalyzer
|
|||
|
||||
override void visit(const ModuleDeclaration dec)
|
||||
{
|
||||
if(stopLinting(dec))
|
||||
return;
|
||||
auto currNoLint = NoLintFactory.fromModuleDeclaration(dec);
|
||||
noLint.push(currNoLint);
|
||||
scope(exit) noLint.pop(currNoLint);
|
||||
|
||||
foreach (part; dec.moduleName.identifiers)
|
||||
{
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
module dscanner.analysis.useless_initializer;
|
||||
|
||||
import dscanner.analysis.base;
|
||||
import dscanner.analysis.nolint;
|
||||
import dscanner.utils : safeAccess;
|
||||
import containers.dynamicarray;
|
||||
import containers.hashmap;
|
||||
|
@ -93,13 +94,12 @@ public:
|
|||
{
|
||||
_inStruct.insert(decl.structDeclaration !is null);
|
||||
|
||||
const msgDisabled = maybeDisableErrorMessage(decl);
|
||||
auto currNoLint = NoLintFactory.fromDeclaration(decl);
|
||||
noLint.push(currNoLint);
|
||||
scope(exit) noLint.pop(currNoLint);
|
||||
|
||||
decl.accept(this);
|
||||
|
||||
if(msgDisabled)
|
||||
reenableErrorMessage();
|
||||
|
||||
if (_inStruct.length > 1 && _inStruct[$-2] && decl.constructor &&
|
||||
((decl.constructor.parameters && decl.constructor.parameters.parameters.length == 0) ||
|
||||
!decl.constructor.parameters))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue