diff --git a/analysis/builtin_property_names.d b/analysis/builtin_property_names.d new file mode 100644 index 0000000..b9bb7cc --- /dev/null +++ b/analysis/builtin_property_names.d @@ -0,0 +1,105 @@ +// Copyright Brian Schott (Sir Alaran) 2014. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +module analysis.builtin_property_names; + +import std.stdio; +import std.regex; +import std.d.ast; +import std.d.lexer; +import analysis.base; +import analysis.helpers; + +/** + * The following code should be killed with fire: + * --- + * class SomeClass + * { + * void init(); + * int init; + * string mangleof = "LOL"; + * auto init = 10; + * enum sizeof = 10; + * } + * --- + */ +class BuiltinPropertyNameCheck : BaseAnalyzer +{ + alias visit = BaseAnalyzer.visit; + + this(string fileName) + { + super(fileName); + } + + override void visit(const FunctionDeclaration fd) + { + if (depth > 0 && isBuiltinProperty(fd.name.text)) + { + addErrorMessage(fd.name.line, fd.name.column, generateErrorMessage(fd.name.text)); + } + fd.accept(this); + } + + override void visit(const AutoDeclaration ad) + { + if (depth > 0) foreach (i; ad.identifiers) + { + if (isBuiltinProperty(i.text)) + addErrorMessage(i.line, i.column, generateErrorMessage(i.text)); + } + } + + override void visit(const Declarator d) + { + if (depth > 0 && isBuiltinProperty(d.name.text)) + addErrorMessage(d.name.line, d.name.column, generateErrorMessage(d.name.text)); + } + + override void visit(const StructBody sb) + { + depth++; + sb.accept(this); + depth--; + } + +private: + + string generateErrorMessage(string name) + { + import std.string; + return format("Avoid naming members '%s'. This can" + ~ " confuse code that depends on the '.%s' property of a type.", name, name); + } + + bool isBuiltinProperty(string name) + { + import std.algorithm; + return builtinProperties.canFind(name); + } + + enum string[] builtinProperties = [ + "init", "sizeof", "mangleof", "alignof", "stringof" + ]; + int depth; +} + +unittest +{ + import analysis.config; + StaticAnalysisConfig sac; + sac.builtin_property_name_check = true; + assertAnalyzerWarnings(q{ +class SomeClass +{ + void init(); // + int init; + auto init = 10; +} + }c, sac); + + stderr.writeln("Unittest for NumberStyleCheck passed."); +} + diff --git a/analysis/config.d b/analysis/config.d index 18331cf..54e48e7 100644 --- a/analysis/config.d +++ b/analysis/config.d @@ -59,4 +59,7 @@ struct StaticAnalysisConfig @INI("Checks for subtraction from .length properties") bool length_subtraction_check; + + @INI("Checks for methods or properties whose names conflict with built-in properties") + bool builtin_property_names_check; } diff --git a/analysis/run.d b/analysis/run.d index 3203e8f..d562154 100644 --- a/analysis/run.d +++ b/analysis/run.d @@ -26,6 +26,7 @@ import analysis.unused; import analysis.duplicate_attribute; import analysis.opequals_without_tohash; import analysis.length_subtraction; +import analysis.builtin_property_names; void messageFunction(string fileName, size_t line, size_t column, string message, bool isError) @@ -96,6 +97,7 @@ string[] analyze(string fileName, ubyte[] code, StaticAnalysisConfig analysisCon if (analysisConfig.duplicate_attribute) checks ~= new DuplicateAttributeCheck(fileName); if (analysisConfig.opequals_tohash_check) checks ~= new OpEqualsWithoutToHashCheck(fileName); if (analysisConfig.length_subtraction_check) checks ~= new LengthSubtractionCheck(fileName); + if (analysisConfig.builtin_property_names_check) checks ~= new BuiltinPropertyNameCheck(fileName); foreach (check; checks) { diff --git a/analysis/unused.d b/analysis/unused.d index 56e2e9d..ade4c75 100644 --- a/analysis/unused.d +++ b/analysis/unused.d @@ -307,7 +307,7 @@ class UnusedVariableCheck : BaseAnalyzer if (!uu.isRef) addErrorMessage(uu.line, uu.column, (uu.isParameter ? "Parameter " : "Variable ") - ~ uu.name ~ " is never used"); + ~ uu.name ~ " is never used."); } tree = tree[0 .. $ - 1]; } diff --git a/libdparse b/libdparse index 98ab5c7..04241f7 160000 --- a/libdparse +++ b/libdparse @@ -1 +1 @@ -Subproject commit 98ab5c704d336da3af507563c676d9c022f21e70 +Subproject commit 04241f78cda7d9a784893d287ec0bb1304cbd6db