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:
Vladiwostok 2024-10-15 09:36:54 +03:00 committed by Vladiwostok
parent c965cfd5c0
commit 8e836fc6bc
4 changed files with 111 additions and 36 deletions

View file

@ -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;
}
}

View file

@ -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;

View file

@ -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.");
}

View file

@ -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.");
}