Use DMD in RedundantStorageClassCheck (#84)

This commit is contained in:
Vladiwostok 2024-01-15 16:40:17 +02:00 committed by Eduard Staniloiu
parent 28703e9304
commit 7f22d69b47
2 changed files with 43 additions and 52 deletions

View file

@ -5,74 +5,68 @@
module dscanner.analysis.redundant_storage_class; module dscanner.analysis.redundant_storage_class;
import std.stdio;
import std.string; import std.string;
import dparse.ast;
import dparse.lexer;
import dscanner.analysis.base; import dscanner.analysis.base;
import dscanner.analysis.helpers;
import dsymbol.scope_ : Scope;
/** /**
* Checks for redundant storage classes such immutable and __gshared, static and __gshared * Checks for redundant storage classes such immutable and __gshared, static and __gshared
*/ */
final class RedundantStorageClassCheck : BaseAnalyzer extern (C++) class RedundantStorageClassCheck(AST) : BaseAnalyzerDmd
{ {
alias visit = BaseAnalyzer.visit; alias visit = BaseAnalyzerDmd.visit;
enum string REDUNDANT_VARIABLE_ATTRIBUTES = "Variable declaration for `%s` has redundant attributes (%-(`%s`%|, %)).";
mixin AnalyzerInfo!"redundant_storage_classes"; mixin AnalyzerInfo!"redundant_storage_classes";
this(BaseAnalyzerArguments args) private enum KEY = "dscanner.unnecessary.duplicate_attribute";
private enum string REDUNDANT_VARIABLE_ATTRIBUTES = "Variable declaration for `%s` has redundant attributes (%-(`%s`%|, %)).";
extern (D) this(string fileName, bool skipTests = false)
{ {
super(args); super(fileName, skipTests);
} }
override void visit(const Declaration node) override void visit(AST.VarDeclaration varDecl)
{ {
checkAttributes(node); import dmd.astenums : STC;
node.accept(this);
if (varDecl.storage_class & STC.immutable_ && varDecl.storage_class & STC.shared_)
addErrorFor(varDecl, "immutable", "shared");
if (varDecl.storage_class & STC.immutable_ && varDecl.storage_class & STC.gshared)
addErrorFor(varDecl, "immutable", "__gshared");
if (varDecl.storage_class & STC.static_ && varDecl.storage_class & STC.gshared)
addErrorFor(varDecl, "static", "__gshared");
} }
void checkAttributes(const Declaration node) extern (D) private void addErrorFor(AST.VarDeclaration varDecl, string attr1, string attr2)
{ {
if (node.variableDeclaration !is null && node.attributes !is null) auto lineNum = cast(ulong) varDecl.loc.linnum;
checkVariableDeclaration(node.variableDeclaration, node.attributes); auto charNum = cast(ulong) varDecl.loc.charnum;
} auto varName = varDecl.ident.toString();
auto errorMsg = REDUNDANT_VARIABLE_ATTRIBUTES.format(varName, [
void checkVariableDeclaration(const VariableDeclaration vd, const Attribute[] attributes) attr1, attr2
{ ]);
import std.algorithm.comparison : among; addErrorMessage(lineNum, charNum, KEY, errorMsg);
import std.algorithm.searching: all;
string[] globalAttributes;
foreach (attrib; attributes)
{
if (attrib.attribute.type.among(tok!"shared", tok!"static", tok!"__gshared", tok!"immutable"))
globalAttributes ~= attrib.attribute.type.str;
}
if (globalAttributes.length > 1)
{
if (globalAttributes.length == 2 && (
globalAttributes.all!(a => a.among("shared", "static")) ||
globalAttributes.all!(a => a.among("static", "immutable"))
))
return;
auto t = vd.declarators[0].name;
string message = REDUNDANT_VARIABLE_ATTRIBUTES.format(t.text, globalAttributes);
addErrorMessage(t, "dscanner.unnecessary.duplicate_attribute", message);
}
} }
} }
unittest unittest
{ {
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig; import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import dscanner.analysis.helpers : assertAnalyzerWarningsDMD;
import std.stdio : stderr;
import std.format : format;
StaticAnalysisConfig sac = disabledConfig(); StaticAnalysisConfig sac = disabledConfig();
sac.redundant_storage_classes = Check.enabled; sac.redundant_storage_classes = Check.enabled;
enum string erorMsg = "Variable declaration for `%s` has redundant attributes (%-(`%s`%|, %)).";
auto immutableSharedMsg = erorMsg.format("a", ["immutable", "shared"]);
auto immutableGSharedMsg = erorMsg.format("a", ["immutable", "__gshared"]);
auto staticGSharedMsg = erorMsg.format("a", ["static", "__gshared"]);
// https://github.com/dlang-community/D-Scanner/issues/438 // https://github.com/dlang-community/D-Scanner/issues/438
assertAnalyzerWarnings(q{ assertAnalyzerWarningsDMD(q{
immutable int a; immutable int a;
immutable shared int a; // [warn]: %s immutable shared int a; // [warn]: %s
@ -91,13 +85,8 @@ unittest
enum int a; enum int a;
extern(C++) immutable int a; extern(C++) immutable int a;
immutable int function(immutable int, shared int) a; immutable int function(immutable int, shared int) a;
}c.format( }c.format(immutableSharedMsg, immutableSharedMsg, immutableGSharedMsg,
RedundantStorageClassCheck.REDUNDANT_VARIABLE_ATTRIBUTES.format("a", ["immutable", "shared"]), immutableGSharedMsg, staticGSharedMsg), sac);
RedundantStorageClassCheck.REDUNDANT_VARIABLE_ATTRIBUTES.format("a", ["shared", "immutable"]),
RedundantStorageClassCheck.REDUNDANT_VARIABLE_ATTRIBUTES.format("a", ["immutable", "__gshared"]),
RedundantStorageClassCheck.REDUNDANT_VARIABLE_ATTRIBUTES.format("a", ["__gshared", "immutable"]),
RedundantStorageClassCheck.REDUNDANT_VARIABLE_ATTRIBUTES.format("a", ["__gshared", "static"]),
), sac);
stderr.writeln("Unittest for RedundantStorageClassCheck passed."); stderr.writeln("Unittest for RedundantStorageClassCheck passed.");
} }

View file

@ -913,10 +913,6 @@ private BaseAnalyzer[] getAnalyzersForModuleAndConfig(string fileName,
checks ~= new IfConstraintsIndentCheck(args.setSkipTests( checks ~= new IfConstraintsIndentCheck(args.setSkipTests(
analysisConfig.if_constraints_indent == Check.skipTests && !ut)); analysisConfig.if_constraints_indent == Check.skipTests && !ut));
if (moduleName.shouldRun!RedundantStorageClassCheck(analysisConfig))
checks ~= new RedundantStorageClassCheck(args.setSkipTests(
analysisConfig.redundant_storage_classes == Check.skipTests && !ut));
if (moduleName.shouldRun!UnusedResultChecker(analysisConfig)) if (moduleName.shouldRun!UnusedResultChecker(analysisConfig))
checks ~= new UnusedResultChecker(args.setSkipTests( checks ~= new UnusedResultChecker(args.setSkipTests(
analysisConfig.unused_result == Check.skipTests && !ut)); analysisConfig.unused_result == Check.skipTests && !ut));
@ -1344,6 +1340,12 @@ MessageSet analyzeDmd(string fileName, ASTCodegen.Module m, const char[] moduleN
config.asm_style_check == Check.skipTests && !ut config.asm_style_check == Check.skipTests && !ut
); );
if (moduleName.shouldRunDmd!(RedundantStorageClassCheck!ASTCodegen)(config))
visitors ~= new RedundantStorageClassCheck!ASTCodegen(
fileName,
config.redundant_storage_classes == Check.skipTests && !ut
);
foreach (visitor; visitors) foreach (visitor; visitors)
{ {
m.accept(visitor); m.accept(visitor);