125 lines
2.9 KiB
D
125 lines
2.9 KiB
D
// Copyright Brian Schott (Hackerpilot) 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 dscanner.analysis.builtin_property_names;
|
|
|
|
import std.stdio;
|
|
import std.regex;
|
|
import dparse.ast;
|
|
import dparse.lexer;
|
|
import dscanner.analysis.base;
|
|
import dscanner.analysis.helpers;
|
|
import dsymbol.scope_;
|
|
import std.algorithm : map;
|
|
|
|
/**
|
|
* The following code should be killed with fire:
|
|
* ---
|
|
* class SomeClass
|
|
* {
|
|
* void init();
|
|
* int init;
|
|
* string mangleof = "LOL";
|
|
* auto init = 10;
|
|
* enum sizeof = 10;
|
|
* }
|
|
* ---
|
|
*/
|
|
final class BuiltinPropertyNameCheck : BaseAnalyzer
|
|
{
|
|
alias visit = BaseAnalyzer.visit;
|
|
|
|
mixin AnalyzerInfo!"builtin_property_names_check";
|
|
|
|
this(string fileName, const(Scope)* sc, bool skipTests = false)
|
|
{
|
|
super(fileName, sc, skipTests);
|
|
}
|
|
|
|
override void visit(const FunctionDeclaration fd)
|
|
{
|
|
if (depth > 0 && isBuiltinProperty(fd.name.text))
|
|
{
|
|
addErrorMessage(fd.name, KEY, generateErrorMessage(fd.name.text));
|
|
}
|
|
fd.accept(this);
|
|
}
|
|
|
|
override void visit(const FunctionBody functionBody)
|
|
{
|
|
immutable int d = depth;
|
|
scope (exit)
|
|
depth = d;
|
|
depth = 0;
|
|
functionBody.accept(this);
|
|
}
|
|
|
|
override void visit(const AutoDeclaration ad)
|
|
{
|
|
if (depth > 0)
|
|
foreach (i; ad.parts.map!(a => a.identifier))
|
|
{
|
|
if (isBuiltinProperty(i.text))
|
|
addErrorMessage(i, KEY, generateErrorMessage(i.text));
|
|
}
|
|
}
|
|
|
|
override void visit(const Declarator d)
|
|
{
|
|
if (depth > 0 && isBuiltinProperty(d.name.text))
|
|
addErrorMessage(d.name, KEY, generateErrorMessage(d.name.text));
|
|
}
|
|
|
|
override void visit(const StructBody sb)
|
|
{
|
|
depth++;
|
|
sb.accept(this);
|
|
depth--;
|
|
}
|
|
|
|
private:
|
|
|
|
enum string KEY = "dscanner.confusing.builtin_property_names";
|
|
|
|
string generateErrorMessage(string name)
|
|
{
|
|
import std.string : format;
|
|
|
|
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 : canFind;
|
|
|
|
return BuiltinProperties.canFind(name);
|
|
}
|
|
|
|
enum string[] BuiltinProperties = ["init", "sizeof", "mangleof", "alignof", "stringof"];
|
|
int depth;
|
|
}
|
|
|
|
unittest
|
|
{
|
|
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
|
|
|
|
StaticAnalysisConfig sac = disabledConfig();
|
|
sac.builtin_property_names_check = Check.enabled;
|
|
assertAnalyzerWarnings(q{
|
|
class SomeClass
|
|
{
|
|
void init(); /+
|
|
^^^^ [warn]: Avoid naming members 'init'. This can confuse code that depends on the '.init' property of a type. +/
|
|
int init; /+
|
|
^^^^ [warn]: Avoid naming members 'init'. This can confuse code that depends on the '.init' property of a type. +/
|
|
auto init = 10; /+
|
|
^^^^ [warn]: Avoid naming members 'init'. This can confuse code that depends on the '.init' property of a type. +/
|
|
}
|
|
}c, sac);
|
|
|
|
stderr.writeln("Unittest for NumberStyleCheck passed.");
|
|
}
|