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