Menu
Home
Create new Paste
Log in
unused vars detector
Code
Theme: cobalt
Theme: eclipse
Theme: elegant
Theme: monokai
Theme: neat
Theme: night
Theme: rubyblue
import std.stdio; import std.regex; import std.string : strip, format; import std.file : readText; import std.conv : to; import std.algorithm; import std.array; static import std.ascii; /** * Types */ enum : string { PrimitiveTypes = r"((?:void|bool|string|char|double|float)|u?(?:byte|short|int|long|cent)(?:\[.*?\])*)(?:\s*\*)?\s+(?:\s*\*\s*)?([a-zA-Z]+.*?)\;" } /** * Assign variants */ enum : string { DirectAssign = r"%s\s*(?:\+|-|\*|\/|~|&|\|)?=\s*.+?;", IncDecBinAssign = r"%s\s*(?:\+\+|--)", IncDecUnAssign = r"(?:\+\+|--)\s*.*?%s", ByRefAssign = "&%s", TenCondUse = r"\!?\s*%s.*?\?.+?" } /** * Stores Variable Information */ class Var { public: const string Type; const string Name; const uint LineNr; const uint ScopeBegin; const uint ScopeEnd; /** * Is var used? */ bool Assigned; this(string type, string name, uint line, uint begin, uint end) { Type = strip(type); Name = strip(name); LineNr = line; ScopeBegin = begin; ScopeEnd = end; } } /** * Stores Information about a single line */ class Line { public: /** * Line content */ const string Content; /** * Line Number */ const uint Index; this(string line, uint line_nr) { Content = strip(line); Index = line_nr; } } void main(string[] args) { string buffer = readText(args[1]); /// read content and split into lines string[] lines = split(buffer, std.ascii.newline); Line[][string] scopes; Line[][uint] temp_scopes; /// Line numbers of beginning scopes uint[] open_brackets = [0]; /// scan file content foreach (uint line_nr, string line; lines) { if (match(line, r".*?\{.*?")) { debug writeln("Open -> ", line_nr); open_brackets ~= line_nr; debug writeln(open_brackets); continue; } if (match(line, r".*?\}.*?")) { debug writeln("Close -> ", line_nr); /// After found scope end, store temporay fields permanent if (open_brackets.back !in temp_scopes) { continue; } foreach (Line tline; temp_scopes[open_brackets.back]) { debug assert(tline !is null); scopes[to!(string)(open_brackets.back) ~ "~" ~ to!(string)(line_nr)] ~= tline; } /// clear scope temporary field temp_scopes[open_brackets.back] = []; /// pop back last scope bracket open_brackets.popBack(); debug writeln(open_brackets); continue; } /// Stores first in temporay field temp_scopes[open_brackets.back] ~= new Line(line, line_nr); } Var[] all_vars; bool comment; /// walk through scopes foreach (string scope_nr, Line[] scope_content; scopes.rehash) { foreach (uint index, Line line; scope_content) { /// multi line comment if (match(line.Content, r"\/\*+")) { comment = true; } if (match(line.Content, r"\*+\/")) { comment = false; } if (comment) { continue; } /// single comment if (match(line.Content, r"^\s*\/\/")) { continue; } /// search for all variables which are not directly assigned if (auto m = match(line.Content, PrimitiveTypes)) { auto c = m.captures; string[] variables = split(c[2], ","); string[2] scope_args = split(scope_nr, "~"); const uint begin = to!(uint)(scope_args[0]); const uint end = to!(uint)(scope_args[1]); if (variables.length == 1) { string[] assign = split(c[2], "="); if (assign.length == 1) { all_vars ~= new Var(c[1], c[2], line.Index, begin, end); debug writefln(" >> Found Var %s of type %s on line %d", c[2], c[1], line.Index); } } else { foreach (string var; variables) { debug writeln(" --> ", var); string[] assign = split(var, "="); if (assign.length == 1) { all_vars ~= new Var(c[1], var, line.Index, begin, end); debug writefln(" >> Found Var %s of type %s on line %d", var, c[1], line.Index); } } } } } } /// walk through the scopes foreach (string scope_nr, Line[] content; scopes.rehash) { string[2] scope_args = split(scope_nr, "~"); const uint s_begin = to!(uint)(scope_args[0]); const uint s_end = to!(uint)(scope_args[1]); foreach (Var var; all_vars) { /// correct scope? if (var.ScopeEnd < s_begin || var.ScopeBegin > s_end) { //writeln(" ---------------> ", content); continue; } foreach (Line line; content) { /// multi line comment if (match(line.Content, r"\/\*+")) { comment = true; } if (match(line.Content, r"\*+\/")) { comment = false; } if (comment) { continue; } /// single comment if (match(line.Content, r"\/\/")) { continue; } /// is variable assigned? if (match(line.Content, format(DirectAssign, var.Name)) || match(line.Content, format(IncDecBinAssign, var.Name)) || match(line.Content, format(IncDecUnAssign, var.Name)) || match(line.Content, format(TenCondUse, var.Name)) || match(line.Content, format(ByRefAssign, var.Name))) { debug writeln(" ==> ", var.Name, ", ", var.LineNr + 1, " is used!"); var.Assigned = true; } } } } writeln("----"); uint counter = 0; /// step through founded variables and check if they was assigned foreach (Var var; all_vars) { if (!var.Assigned) { counter++; writefln("Variable %s of type %s on line %d is unused.", var.Name, var.Type, var.LineNr + 1); } } writefln("----\nYou have %d unused variables.", counter); }
Result:
Compilation error
/
Return code: 9 (Killed)
/
Compilation time:
5.068
seconds
Username
Message
Add comment
Paste info
Author:
Namespace
Views:
201
Private:
no
Expires:
Never
Uploaded:
30.07.12 18:40
Votes
:
0
Tweet
Compilation
Compiler:
DMD 2.062
Pointer size:
m64
Actions
Download
Fork
Raw
×
Confirm
Are you sure you want to delete this paste?
There's no way back!
×
Confirm
Reason