This commit is contained in:
Hackerpilot 2015-09-18 11:47:28 -07:00
parent 27a423e3fa
commit dffed0ab24
1 changed files with 56 additions and 13 deletions

View File

@ -44,35 +44,52 @@ class LabelVarNameCheck : BaseAnalyzer
override void visit(const VariableDeclaration var) override void visit(const VariableDeclaration var)
{ {
foreach (dec; var.declarators) foreach (dec; var.declarators)
duplicateCheck(dec.name, false); duplicateCheck(dec.name, false, conditionalDepth > 0);
} }
override void visit(const LabeledStatement labeledStatement) override void visit(const LabeledStatement labeledStatement)
{ {
duplicateCheck(labeledStatement.identifier, true); duplicateCheck(labeledStatement.identifier, true, conditionalDepth > 0);
if (labeledStatement.declarationOrStatement !is null) if (labeledStatement.declarationOrStatement !is null)
labeledStatement.declarationOrStatement.accept(this); labeledStatement.declarationOrStatement.accept(this);
} }
override void visit(const ConditionalDeclaration condition)
{
if (condition.falseDeclaration)
++conditionalDepth;
condition.accept(this);
if (condition.falseDeclaration)
--conditionalDepth;
}
alias visit = BaseAnalyzer.visit; alias visit = BaseAnalyzer.visit;
private: private:
Thing[string][] stack; Thing[string][] stack;
void duplicateCheck(const Token name, bool fromLabel) void duplicateCheck(const Token name, bool fromLabel, bool isConditional)
{ {
import std.conv : to; import std.conv : to;
const(Thing)* thing = name.text in currentScope; import std.range : retro;
if (thing is null)
currentScope[name.text] = Thing(name.text, name.line, name.column, false); size_t i = 0;
else foreach (s; retro(stack))
{ {
immutable thisKind = fromLabel ? "Label" : "Variable"; const(Thing)* thing = name.text in s;
immutable otherKind = thing.isVar ? "variable" : "label"; if (thing is null)
addErrorMessage(name.line, name.column, "dscanner.suspicious.label_var_same_name", currentScope[name.text] = Thing(name.text, name.line, name.column,
thisKind ~ " \"" ~ name.text ~ "\" has the same name as a " !fromLabel/+, isConditional+/);
~ otherKind ~ " defined on line " ~ to!string(thing.line) ~ "."); else if (i != 0 || !isConditional)
{
immutable thisKind = fromLabel ? "Label" : "Variable";
immutable otherKind = thing.isVar ? "variable" : "label";
addErrorMessage(name.line, name.column, "dscanner.suspicious.label_var_same_name",
thisKind ~ " \"" ~ name.text ~ "\" has the same name as a "
~ otherKind ~ " defined on line " ~ to!string(thing.line) ~ ".");
}
++i;
} }
} }
@ -82,6 +99,7 @@ private:
size_t line; size_t line;
size_t column; size_t column;
bool isVar; bool isVar;
//bool isConditional;
} }
ref currentScope() @property ref currentScope() @property
@ -98,6 +116,8 @@ private:
{ {
stack.length--; stack.length--;
} }
int conditionalDepth;
} }
unittest unittest
@ -114,6 +134,29 @@ blah:
int blah; // [warn]: Variable "blah" has the same name as a label defined on line 4. int blah; // [warn]: Variable "blah" has the same name as a label defined on line 4.
} }
int blah; int blah;
}c, sac); unittest
{
static if (stuff)
int a;
int a; // [warn]: Variable "a" has the same name as a variable defined on line 11.
}
unittest
{
static if (stuff)
int a = 10;
else
int a = 20;
}
unittest
{
static if (stuff)
int a = 10;
else
int a = 20;
int a; // [warn]: Variable "a" has the same name as a variable defined on line 28.
}
}c, sac);
stderr.writeln("Unittest for LabelVarNameCheck passed."); stderr.writeln("Unittest for LabelVarNameCheck passed.");
} }