mirror of
https://github.com/dlang-community/D-Scanner.git
synced 2025-04-27 22:00:17 +03:00
Use DMD in RedundantStorageClassCheck (#84)
This commit is contained in:
parent
28703e9304
commit
7f22d69b47
2 changed files with 43 additions and 52 deletions
|
@ -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.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue