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,29 +44,44 @@ 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;
size_t i = 0;
foreach (s; retro(stack))
{
const(Thing)* thing = name.text in s;
if (thing is null) if (thing is null)
currentScope[name.text] = Thing(name.text, name.line, name.column, false); currentScope[name.text] = Thing(name.text, name.line, name.column,
else !fromLabel/+, isConditional+/);
else if (i != 0 || !isConditional)
{ {
immutable thisKind = fromLabel ? "Label" : "Variable"; immutable thisKind = fromLabel ? "Label" : "Variable";
immutable otherKind = thing.isVar ? "variable" : "label"; immutable otherKind = thing.isVar ? "variable" : "label";
@ -74,6 +89,8 @@ private:
thisKind ~ " \"" ~ name.text ~ "\" has the same name as a " thisKind ~ " \"" ~ name.text ~ "\" has the same name as a "
~ otherKind ~ " defined on line " ~ to!string(thing.line) ~ "."); ~ otherKind ~ " defined on line " ~ to!string(thing.line) ~ ".");
} }
++i;
}
} }
static struct Thing static struct Thing
@ -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;
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); }c, sac);
stderr.writeln("Unittest for LabelVarNameCheck passed."); stderr.writeln("Unittest for LabelVarNameCheck passed.");
} }