118 lines
3.3 KiB
D
118 lines
3.3 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 dscanner.analysis.base;
|
|
|
|
/**
|
|
* The following code should be killed with fire:
|
|
* ---
|
|
* class SomeClass
|
|
* {
|
|
* void init();
|
|
* int init;
|
|
* string mangleof = "LOL";
|
|
* auto init = 10;
|
|
* enum sizeof = 10;
|
|
* }
|
|
* ---
|
|
*/
|
|
|
|
extern(C++) class BuiltinPropertyNameCheck(AST) : BaseAnalyzerDmd
|
|
{
|
|
alias visit = BaseAnalyzerDmd.visit;
|
|
mixin AnalyzerInfo!"builtin_property_names_check";
|
|
|
|
extern(D) this(string fileName)
|
|
{
|
|
super(fileName);
|
|
}
|
|
|
|
mixin AggregateVisit!(AST.StructDeclaration);
|
|
mixin AggregateVisit!(AST.ClassDeclaration);
|
|
mixin AggregateVisit!(AST.InterfaceDeclaration);
|
|
mixin AggregateVisit!(AST.UnionDeclaration);
|
|
|
|
override void visit(AST.VarDeclaration vd)
|
|
{
|
|
if (inAggregate && isBuiltinProperty(vd.ident.toString()))
|
|
addErrorMessage(cast(ulong) vd.loc.linnum, cast(ulong) vd.loc.charnum,
|
|
KEY, generateErrorMessage(vd.ident.toString()));
|
|
}
|
|
|
|
override void visit(AST.FuncDeclaration fd)
|
|
{
|
|
if (inAggregate && isBuiltinProperty(fd.ident.toString()))
|
|
addErrorMessage(cast(ulong) fd.loc.linnum, cast(ulong) fd.loc.charnum,
|
|
KEY, generateErrorMessage(fd.ident.toString()));
|
|
}
|
|
|
|
override void visit(AST.AliasDeclaration ad)
|
|
{
|
|
if (inAggregate && isBuiltinProperty(ad.ident.toString()))
|
|
addErrorMessage(cast(ulong) ad.loc.linnum, cast(ulong) ad.loc.charnum,
|
|
KEY, generateErrorMessage(ad.ident.toString()));
|
|
}
|
|
|
|
override void visit(AST.TemplateDeclaration td)
|
|
{
|
|
if (inAggregate && isBuiltinProperty(td.ident.toString()))
|
|
addErrorMessage(cast(ulong) td.loc.linnum, cast(ulong) td.loc.charnum,
|
|
KEY, generateErrorMessage(td.ident.toString()));
|
|
}
|
|
|
|
private:
|
|
enum string KEY = "dscanner.confusing.builtin_property_names";
|
|
|
|
template AggregateVisit(NodeType)
|
|
{
|
|
override void visit(NodeType n)
|
|
{
|
|
inAggregate++;
|
|
super.visit(n);
|
|
inAggregate--;
|
|
}
|
|
}
|
|
|
|
extern(D) string generateErrorMessage(const(char)[] 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);
|
|
}
|
|
|
|
extern(D) bool isBuiltinProperty(const(char)[] name)
|
|
{
|
|
import std.algorithm : canFind;
|
|
|
|
return BuiltinProperties.canFind(name);
|
|
}
|
|
|
|
enum string[] BuiltinProperties = ["init", "sizeof", "mangleof", "alignof", "stringof"];
|
|
int inAggregate;
|
|
}
|
|
|
|
unittest
|
|
{
|
|
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
|
|
import dscanner.analysis.helpers : assertAnalyzerWarnings = assertAnalyzerWarningsDMD;
|
|
import std.stdio : stderr;
|
|
|
|
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 BuiltinPropertyNamesCheck passed.");
|
|
}
|