mirror of
https://github.com/dlang-community/D-Scanner.git
synced 2025-04-26 05:10:03 +03:00
Respect @nolint user attribute (#158)
* Respect @nolint in UnmodifiedFinder * Respect @nolint in UselessInitializerChecker * Respect @nolint in StaticIfElse * Fix visibility in base.d
This commit is contained in:
parent
c965cfd5c0
commit
8e836fc6bc
4 changed files with 111 additions and 36 deletions
|
@ -9,6 +9,7 @@ import std.container;
|
|||
import std.meta : AliasSeq;
|
||||
import std.string;
|
||||
import std.sumtype;
|
||||
import dmd.attrib : UserAttributeDeclaration;
|
||||
import dmd.visitor.transitive;
|
||||
import dmd.visitor;
|
||||
import dmd.func;
|
||||
|
@ -984,4 +985,26 @@ protected:
|
|||
extern (D) string fileName;
|
||||
|
||||
extern (D) MessageSet _messages;
|
||||
|
||||
extern (D) bool shouldIgnoreDecl(UserAttributeDeclaration userAtt, string key)
|
||||
{
|
||||
import std.algorithm : startsWith;
|
||||
import std.string : indexOf;
|
||||
|
||||
if (userAtt is null)
|
||||
return false;
|
||||
|
||||
auto atts = userAtt.atts;
|
||||
if (atts !is null && (*(atts)).length > 0)
|
||||
{
|
||||
if (auto att = (*(atts))[0].isStringExp())
|
||||
{
|
||||
string attStr = cast(string) att.toStringz();
|
||||
if (attStr.startsWith("nolint") && attStr.indexOf(key) > 0)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,22 @@ extern(C++) class StaticIfElse(AST) : BaseAnalyzerDmd
|
|||
super(fileName, skipTests);
|
||||
}
|
||||
|
||||
override void visit(AST.UserAttributeDeclaration userAttribute)
|
||||
{
|
||||
if (shouldIgnoreDecl(userAttribute, KEY))
|
||||
return;
|
||||
|
||||
super.visit(userAttribute);
|
||||
}
|
||||
|
||||
override void visit(AST.Module mod)
|
||||
{
|
||||
if (shouldIgnoreDecl(mod.userAttribDecl(), KEY))
|
||||
return;
|
||||
|
||||
super.visit(mod);
|
||||
}
|
||||
|
||||
override void visit(AST.ConditionalStatement s)
|
||||
{
|
||||
import dmd.astenums : STMT;
|
||||
|
|
|
@ -36,6 +36,22 @@ extern (C++) class UnmodifiedFinder(AST) : BaseAnalyzerDmd
|
|||
pushScope();
|
||||
}
|
||||
|
||||
override void visit(AST.UserAttributeDeclaration userAttribute)
|
||||
{
|
||||
if (shouldIgnoreDecl(userAttribute, KEY))
|
||||
return;
|
||||
|
||||
super.visit(userAttribute);
|
||||
}
|
||||
|
||||
override void visit(AST.Module mod)
|
||||
{
|
||||
if (shouldIgnoreDecl(mod.userAttribDecl(), KEY))
|
||||
return;
|
||||
|
||||
super.visit(mod);
|
||||
}
|
||||
|
||||
override void visit(AST.CompoundStatement compoundStatement)
|
||||
{
|
||||
pushScope();
|
||||
|
@ -324,5 +340,12 @@ unittest
|
|||
}
|
||||
}c, sac);
|
||||
|
||||
assertAnalyzerWarningsDMD(q{
|
||||
@("nolint(dscanner.suspicious.unmodified)")
|
||||
void foo(){
|
||||
int i = 1;
|
||||
}
|
||||
}, sac);
|
||||
|
||||
stderr.writeln("Unittest for UnmodifiedFinder passed.");
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@ Limitations:
|
|||
* Check that detects the initializers that are
|
||||
* not different from the implcit initializer.
|
||||
*/
|
||||
// TODO: Fix NoLint
|
||||
extern (C++) class UselessInitializerChecker(AST) : BaseAnalyzerDmd
|
||||
{
|
||||
alias visit = BaseAnalyzerDmd.visit;
|
||||
|
@ -44,6 +43,22 @@ extern (C++) class UselessInitializerChecker(AST) : BaseAnalyzerDmd
|
|||
super(fileName, skipTests);
|
||||
}
|
||||
|
||||
override void visit(AST.UserAttributeDeclaration userAttribute)
|
||||
{
|
||||
if (shouldIgnoreDecl(userAttribute, KEY))
|
||||
return;
|
||||
|
||||
super.visit(userAttribute);
|
||||
}
|
||||
|
||||
override void visit(AST.Module mod)
|
||||
{
|
||||
if (shouldIgnoreDecl(mod.userAttribDecl(), KEY))
|
||||
return;
|
||||
|
||||
super.visit(mod);
|
||||
}
|
||||
|
||||
override void visit(AST.UnitTestDeclaration unitTestDecl)
|
||||
{
|
||||
if (skipTests)
|
||||
|
@ -303,43 +318,41 @@ extern (C++) class UselessInitializerChecker(AST) : BaseAnalyzerDmd
|
|||
}, sac);
|
||||
|
||||
// passes
|
||||
//assertAnalyzerWarnings(q{
|
||||
// @("nolint(dscanner.useless-initializer)")
|
||||
// int a = 0;
|
||||
// int a = 0; /+
|
||||
// ^ [warn]: X +/
|
||||
//
|
||||
// @("nolint(dscanner.useless-initializer)")
|
||||
// int f() {
|
||||
// int a = 0;
|
||||
// }
|
||||
//
|
||||
// struct nolint { string s; }
|
||||
//
|
||||
// @nolint("dscanner.useless-initializer")
|
||||
// int a = 0;
|
||||
// int a = 0; /+
|
||||
// ^ [warn]: X +/
|
||||
//
|
||||
// @("nolint(other_check, dscanner.useless-initializer, another_one)")
|
||||
// int a = 0;
|
||||
//
|
||||
// @nolint("other_check", "another_one", "dscanner.useless-initializer")
|
||||
// int a = 0;
|
||||
//
|
||||
//}, sac);
|
||||
assertAnalyzerWarningsDMD(q{
|
||||
@("nolint(dscanner.useless-initializer)")
|
||||
int x = 0;
|
||||
int a = 0; // [warn]: %s
|
||||
|
||||
@("nolint(dscanner.useless-initializer)")
|
||||
int f() {
|
||||
int a = 0;
|
||||
}
|
||||
|
||||
struct nolint { string s; }
|
||||
|
||||
@("nolint(dscanner.useless-initializer)")
|
||||
int c = 0;
|
||||
int s = 0; // [warn]: %s
|
||||
|
||||
@("nolint(other_check, dscanner.useless-initializer, another_one)")
|
||||
int e = 0;
|
||||
|
||||
@("nolint(other_check, another_one, dscanner.useless-initializer)")
|
||||
int f = 0;
|
||||
|
||||
}c.format(msgA, msgS), sac);
|
||||
|
||||
// passes (disable check at module level)
|
||||
//assertAnalyzerWarnings(q{
|
||||
// @("nolint(dscanner.useless-initializer)")
|
||||
// module my_module;
|
||||
//
|
||||
// int a = 0;
|
||||
//
|
||||
// int f() {
|
||||
// int a = 0;
|
||||
// }
|
||||
//}, sac);
|
||||
assertAnalyzerWarningsDMD(q{
|
||||
@("nolint(dscanner.useless-initializer)")
|
||||
module my_module;
|
||||
|
||||
int a = 0;
|
||||
|
||||
int f() {
|
||||
int a = 0;
|
||||
}
|
||||
}c, sac);
|
||||
|
||||
stderr.writeln("Unittest for UselessInitializerChecker passed.");
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue