Starting work on 0.3.0

This commit is contained in:
Hackerpilot 2015-05-26 00:24:21 -07:00
parent 327e629867
commit a3c4a5384a
35 changed files with 212 additions and 99 deletions

6
.gitmodules vendored
View file

@ -5,3 +5,9 @@
[submodule "inifiled"] [submodule "inifiled"]
path = inifiled path = inifiled
url = https://github.com/burner/inifiled.git url = https://github.com/burner/inifiled.git
[submodule "containers"]
path = containers
url = https://github.com/economicmodeling/containers.git
[submodule "dsymbol"]
path = dsymbol
url = https://github.com/Hackerpilot/dsymbol.git

1
containers Submodule

@ -0,0 +1 @@
Subproject commit d732a67e76f60fd037547c3ffe8776c6deda6bab

1
dsymbol Submodule

@ -0,0 +1 @@
Subproject commit ddf8c97753471388303d64a47bdade85cc4de003

@ -1 +1 @@
Subproject commit 32f6d638e38888e1bb11cf43e93fe2d11132a98f Subproject commit 0dccfca0e2a132b3c862a62da1c323ccd24e622d

View file

@ -7,12 +7,21 @@ SRC = src/*.d\
src/analysis/*.d\ src/analysis/*.d\
libdparse/src/std/*.d\ libdparse/src/std/*.d\
libdparse/src/std/d/*.d\ libdparse/src/std/d/*.d\
inifiled/source/*.d inifiled/source/*.d\
INCLUDE_PATHS = -Ilibdparse/src $(shell find dsymbol/src -name "*.d")\
containers/src/containers/ttree.d\
containers/src/containers/unrolledlist.d\
containers/src/containers/hashset.d\
containers/src/containers/internal/hash.d\
containers/src/containers/internal/node.d\
containers/src/containers/internal/storage_type.d\
containers/src/memory/allocators.d\
containers/src/memory/appender.d
INCLUDE_PATHS = -Ilibdparse/src -Idsymbol/src -Icontainers/src
VERSIONS = VERSIONS =
DEBUG_VERSIONS = -version=std_parser_verbose DEBUG_VERSIONS = -version=std_parser_verbose
DMD_FLAGS = -w -O -release -inline #DMD_FLAGS = -w -O -release -inline
#DMD_FLAGS = -w DMD_FLAGS = -w
all: dmdbuild all: dmdbuild
ldc: ldcbuild ldc: ldcbuild

View file

@ -10,6 +10,7 @@ import std.d.ast;
import std.d.lexer; import std.d.lexer;
import analysis.base; import analysis.base;
import analysis.helpers; import analysis.helpers;
import dsymbol.scope_ : Scope;
/** /**
* Checks for confusing asm expressions. * Checks for confusing asm expressions.
@ -19,9 +20,9 @@ class AsmStyleCheck : BaseAnalyzer
{ {
alias visit = BaseAnalyzer.visit; alias visit = BaseAnalyzer.visit;
this(string fileName) this(string fileName, const(Scope)* sc)
{ {
super(fileName); super(fileName, sc);
} }
override void visit(const AsmBrExp brExp) override void visit(const AsmBrExp brExp)

View file

@ -4,6 +4,7 @@ import std.container;
import std.string; import std.string;
import std.d.ast; import std.d.ast;
import std.array; import std.array;
import dsymbol.scope_ : Scope;
struct Message struct Message
{ {
@ -26,8 +27,9 @@ alias MessageSet = RedBlackTree!(Message, comparitor, true);
abstract class BaseAnalyzer : ASTVisitor abstract class BaseAnalyzer : ASTVisitor
{ {
public: public:
this(string fileName) this(string fileName, const Scope* sc)
{ {
this.sc = sc;
this.fileName = fileName; this.fileName = fileName;
_messages = new MessageSet; _messages = new MessageSet;
} }
@ -61,6 +63,8 @@ protected:
*/ */
string fileName; string fileName;
const(Scope)* sc;
MessageSet _messages; MessageSet _messages;
} }

View file

@ -11,6 +11,7 @@ import std.d.ast;
import std.d.lexer; import std.d.lexer;
import analysis.base; import analysis.base;
import analysis.helpers; import analysis.helpers;
import dsymbol.scope_;
/** /**
* The following code should be killed with fire: * The following code should be killed with fire:
@ -29,9 +30,9 @@ class BuiltinPropertyNameCheck : BaseAnalyzer
{ {
alias visit = BaseAnalyzer.visit; alias visit = BaseAnalyzer.visit;
this(string fileName) this(string fileName, const(Scope)* sc)
{ {
super(fileName); super(fileName, sc);
} }
override void visit(const FunctionDeclaration fd) override void visit(const FunctionDeclaration fd)

View file

@ -8,6 +8,7 @@ module analysis.comma_expression;
import std.d.ast; import std.d.ast;
import std.d.lexer; import std.d.lexer;
import analysis.base; import analysis.base;
import dsymbol.scope_;
/** /**
* Check for uses of the comma expression. * Check for uses of the comma expression.
@ -16,9 +17,9 @@ class CommaExpressionCheck : BaseAnalyzer
{ {
alias visit = BaseAnalyzer.visit; alias visit = BaseAnalyzer.visit;
this(string fileName) this(string fileName, const(Scope)* sc)
{ {
super(fileName); super(fileName, sc);
} }
override void visit(const Expression ex) override void visit(const Expression ex)

View file

@ -5,15 +5,16 @@ import std.d.lexer;
import std.stdio; import std.stdio;
import analysis.base; import analysis.base;
import analysis.helpers; import analysis.helpers;
import dsymbol.scope_ : Scope;
class ConstructorCheck : BaseAnalyzer class ConstructorCheck : BaseAnalyzer
{ {
alias visit = BaseAnalyzer.visit; alias visit = BaseAnalyzer.visit;
this(string fileName) this(string fileName, const(Scope)* sc)
{ {
super(fileName); super(fileName, sc);
} }
override void visit(const ClassDeclaration classDeclaration) override void visit(const ClassDeclaration classDeclaration)

View file

@ -10,6 +10,7 @@ import std.d.ast;
import std.d.lexer; import std.d.lexer;
import analysis.base; import analysis.base;
import analysis.helpers; import analysis.helpers;
import dsymbol.scope_;
/** /**
* Checks for use of the deprecated 'delete' keyword * Checks for use of the deprecated 'delete' keyword
@ -18,9 +19,9 @@ class DeleteCheck : BaseAnalyzer
{ {
alias visit = BaseAnalyzer.visit; alias visit = BaseAnalyzer.visit;
this(string fileName) this(string fileName, const(Scope)* sc)
{ {
super(fileName); super(fileName, sc);
} }
override void visit(const DeleteExpression d) override void visit(const DeleteExpression d)

View file

@ -11,6 +11,7 @@ import std.d.ast;
import std.d.lexer; import std.d.lexer;
import analysis.base; import analysis.base;
import analysis.helpers; import analysis.helpers;
import dsymbol.scope_ : Scope;
/** /**
@ -21,9 +22,9 @@ class DuplicateAttributeCheck : BaseAnalyzer
{ {
alias visit = BaseAnalyzer.visit; alias visit = BaseAnalyzer.visit;
this(string fileName) this(string fileName, const(Scope)* sc)
{ {
super(fileName); super(fileName, sc);
} }
override void visit(const Declaration node) override void visit(const Declaration node)

View file

@ -9,6 +9,7 @@ import std.d.ast;
import std.d.lexer; import std.d.lexer;
import analysis.base; import analysis.base;
import std.algorithm : canFind; import std.algorithm : canFind;
import dsymbol.scope_ : Scope;
void doNothing(string, size_t, size_t, string, bool) {} void doNothing(string, size_t, size_t, string, bool) {}
@ -16,9 +17,9 @@ class EnumArrayLiteralCheck : BaseAnalyzer
{ {
alias visit = BaseAnalyzer.visit; alias visit = BaseAnalyzer.visit;
this(string fileName) this(string fileName, const(Scope)* sc)
{ {
super(fileName); super(fileName, sc);
} }
bool looking = false; bool looking = false;

View file

@ -10,6 +10,7 @@ import std.d.ast;
import std.d.lexer; import std.d.lexer;
import analysis.base; import analysis.base;
import analysis.helpers; import analysis.helpers;
import dsymbol.scope_ : Scope;
/** /**
* Checks for use of the deprecated floating point comparison operators. * Checks for use of the deprecated floating point comparison operators.
@ -20,9 +21,9 @@ class FloatOperatorCheck : BaseAnalyzer
enum string KEY = "dscanner.deprecated.floating_point_operators"; enum string KEY = "dscanner.deprecated.floating_point_operators";
this(string fileName) this(string fileName, const(Scope)* sc)
{ {
super(fileName); super(fileName, sc);
} }
override void visit(const RelExpression r) override void visit(const RelExpression r)

View file

@ -5,11 +5,11 @@
module analysis.function_attributes; module analysis.function_attributes;
import analysis.base;
import std.d.ast; import std.d.ast;
import std.d.lexer; import std.d.lexer;
import analysis.base;
import std.stdio; import std.stdio;
import dsymbol.scope_;
/** /**
* Prefer * Prefer
@ -25,9 +25,9 @@ class FunctionAttributeCheck : BaseAnalyzer
{ {
alias visit = BaseAnalyzer.visit; alias visit = BaseAnalyzer.visit;
this(string fileName) this(string fileName, const(Scope)* sc)
{ {
super(fileName); super(fileName, sc);
} }
override void visit(const InterfaceDeclaration dec) override void visit(const InterfaceDeclaration dec)

View file

@ -8,15 +8,14 @@ import std.d.ast;
import std.d.lexer; import std.d.lexer;
import std.d.formatter; import std.d.formatter;
import analysis.base; import analysis.base;
import dsymbol.scope_ : Scope;
class IfStatementCheck : BaseAnalyzer class IfStatementCheck : BaseAnalyzer
{ {
alias visit = BaseAnalyzer.visit; alias visit = BaseAnalyzer.visit;
this(string fileName) this(string fileName, const(Scope)* sc)
{ {
import std.container.binaryheap : heapify; super(fileName, sc);
super(fileName);
} }
override void visit(const IfStatement ifStatement) override void visit(const IfStatement ifStatement)

View file

@ -6,12 +6,11 @@
module analysis.ifelsesame; module analysis.ifelsesame;
import std.stdio; import std.stdio;
import std.d.ast; import std.d.ast;
import std.d.lexer; import std.d.lexer;
import analysis.base; import analysis.base;
import analysis.helpers; import analysis.helpers;
import dsymbol.scope_ : Scope;
/** /**
* Checks for duplicated code in conditional and logical expressions. * Checks for duplicated code in conditional and logical expressions.
@ -25,9 +24,9 @@ class IfElseSameCheck : BaseAnalyzer
{ {
alias visit = BaseAnalyzer.visit; alias visit = BaseAnalyzer.visit;
this(string fileName) this(string fileName, const(Scope)* sc)
{ {
super(fileName); super(fileName, sc);
} }
override void visit(const IfStatement ifStatement) override void visit(const IfStatement ifStatement)

View file

@ -11,6 +11,7 @@ import std.d.ast;
import std.d.lexer; import std.d.lexer;
import analysis.base; import analysis.base;
import analysis.helpers; import analysis.helpers;
import dsymbol.scope_;
/** /**
@ -20,9 +21,9 @@ class LengthSubtractionCheck : BaseAnalyzer
{ {
alias visit = BaseAnalyzer.visit; alias visit = BaseAnalyzer.visit;
this(string fileName) this(string fileName, const(Scope)* sc)
{ {
super(fileName); super(fileName, sc);
} }
override void visit(const AddExpression addExpression) override void visit(const AddExpression addExpression)

View file

@ -10,6 +10,7 @@ import std.d.ast;
import std.d.lexer; import std.d.lexer;
import analysis.base; import analysis.base;
import analysis.helpers; import analysis.helpers;
import dsymbol.scope_;
/** /**
* Checks for local imports that import all symbols. * Checks for local imports that import all symbols.
@ -22,9 +23,9 @@ class LocalImportCheck : BaseAnalyzer
/** /**
* Construct with the given file name. * Construct with the given file name.
*/ */
this(string fileName) this(string fileName, const(Scope)* sc)
{ {
super(fileName); super(fileName, sc);
} }
mixin visitThing!StructBody; mixin visitThing!StructBody;

View file

@ -10,6 +10,7 @@ import std.d.ast;
import std.d.lexer; import std.d.lexer;
import analysis.base; import analysis.base;
import analysis.helpers; import analysis.helpers;
import dsymbol.scope_;
/** /**
* Checks for code with confusing && and || operator precedence * Checks for code with confusing && and || operator precedence
@ -24,9 +25,9 @@ class LogicPrecedenceCheck : BaseAnalyzer
enum string KEY = "dscanner.confusing.logical_precedence"; enum string KEY = "dscanner.confusing.logical_precedence";
this(string fileName) this(string fileName, const(Scope)* sc)
{ {
super(fileName); super(fileName, sc);
} }
override void visit(const OrOrExpression orOr) override void visit(const OrOrExpression orOr)

View file

@ -0,0 +1,56 @@
module analysis.mismatched_args;
struct ArgMismatch
{
size_t argIndex;
size_t paramIndex;
}
ArgMismatch[] compareArgsToParams(const string[] params, const string[] args) pure
in
{
assert(args.length == params.length);
}
body
{
ArgMismatch[] retVal;
foreach (i, arg; args)
{
if (arg is null || arg == params[i])
continue;
foreach (j, param; params)
if (param == arg)
retVal ~= ArgMismatch(i, j);
}
return retVal;
}
string createWarningFromMismatch(ref const ArgMismatch mismatch, const string commonName) pure
{
import std.format : format;
return "Argument %d is named '%s', but this is the name of parameter %d".format(
mismatch.argIndex + 1, commonName, mismatch.paramIndex + 1);
}
unittest
{
{
string[] args = ["a", "b", "c"];
string[] params = ["a", "b", "c"];
immutable res = compareArgsToParams(params, args);
assert(res == []);
}
{
string[] args = ["a", "c", "b"];
string[] params = ["a", "b", "c"];
immutable res = compareArgsToParams(params, args);
assert(res == [ArgMismatch(1, 2), ArgMismatch(2, 1)]);
}
{
string[] args = ["a", "c", "b"];
string[] params = ["alpha", "bravo", "c"];
immutable res = compareArgsToParams(params, args);
assert(res == [ArgMismatch(1, 2)]);
}
}

View file

@ -11,6 +11,7 @@ import std.d.ast;
import std.d.lexer; import std.d.lexer;
import analysis.base; import analysis.base;
import analysis.helpers; import analysis.helpers;
import dsymbol.scope_ : Scope;
/** /**
* Checks for long and hard-to-read number literals * Checks for long and hard-to-read number literals
@ -23,9 +24,9 @@ public:
/** /**
* Constructs the style checker with the given file name. * Constructs the style checker with the given file name.
*/ */
this(string fileName) this(string fileName, const(Scope)* sc)
{ {
super(fileName); super(fileName, sc);
} }
override void visit(const Token t) override void visit(const Token t)

View file

@ -11,6 +11,7 @@ import std.d.ast;
import std.d.lexer; import std.d.lexer;
import analysis.base; import analysis.base;
import analysis.helpers; import analysis.helpers;
import dsymbol.scope_ : Scope;
/** /**
* Checks that opEquals, opCmp, toHash, and toString are either const, * Checks that opEquals, opCmp, toHash, and toString are either const,
@ -20,9 +21,9 @@ class ObjectConstCheck : BaseAnalyzer
{ {
alias visit = BaseAnalyzer.visit; alias visit = BaseAnalyzer.visit;
this(string fileName) this(string fileName, const(Scope)* sc)
{ {
super(fileName); super(fileName, sc);
} }
mixin visitTemplate!ClassDeclaration; mixin visitTemplate!ClassDeclaration;

View file

@ -10,6 +10,7 @@ import std.d.ast;
import std.d.lexer; import std.d.lexer;
import analysis.base; import analysis.base;
import analysis.helpers; import analysis.helpers;
import dsymbol.scope_ : Scope;
/** /**
* Checks for when a class/struct has the method opEquals without toHash, or * Checks for when a class/struct has the method opEquals without toHash, or
@ -19,9 +20,9 @@ class OpEqualsWithoutToHashCheck : BaseAnalyzer
{ {
alias visit = BaseAnalyzer.visit; alias visit = BaseAnalyzer.visit;
this(string fileName) this(string fileName, const(Scope)* sc)
{ {
super(fileName); super(fileName, sc);
} }
override void visit(const ClassDeclaration node) override void visit(const ClassDeclaration node)

View file

@ -10,6 +10,7 @@ import std.d.ast;
import std.d.lexer; import std.d.lexer;
import analysis.base; import analysis.base;
import analysis.helpers; import analysis.helpers;
import dsymbol.scope_ : Scope;
/** /**
@ -30,9 +31,9 @@ class PokemonExceptionCheck : BaseAnalyzer
alias visit = BaseAnalyzer.visit; alias visit = BaseAnalyzer.visit;
this(string fileName) this(string fileName, const(Scope)* sc)
{ {
super(fileName); super(fileName, sc);
} }
override void visit(const LastCatch lc) override void visit(const LastCatch lc)

View file

@ -10,6 +10,7 @@ import std.d.ast;
import std.d.lexer; import std.d.lexer;
import analysis.base; import analysis.base;
import analysis.helpers; import analysis.helpers;
import dsymbol.scope_ : Scope;
/** /**
* Checks for .. expressions where the left side is larger than the right. This * Checks for .. expressions where the left side is larger than the right. This
@ -26,9 +27,9 @@ class BackwardsRangeCheck : BaseAnalyzer
* Params: * Params:
* fileName = the name of the file being analyzed * fileName = the name of the file being analyzed
*/ */
this(string fileName) this(string fileName, const(Scope)* sc)
{ {
super(fileName); super(fileName, sc);
} }
override void visit(const ForeachStatement foreachStatement) override void visit(const ForeachStatement foreachStatement)
@ -56,7 +57,7 @@ class BackwardsRangeCheck : BaseAnalyzer
override void visit(const AddExpression add) override void visit(const AddExpression add)
{ {
auto s = state; immutable s = state;
state = State.ignore; state = State.ignore;
add.accept(this); add.accept(this);
state = s; state = s;

View file

@ -8,14 +8,15 @@ module analysis.redundant_parens;
import std.d.ast; import std.d.ast;
import std.d.lexer; import std.d.lexer;
import analysis.base; import analysis.base;
import dsymbol.scope_ : Scope;
class RedundantParenCheck : BaseAnalyzer class RedundantParenCheck : BaseAnalyzer
{ {
alias visit = BaseAnalyzer.visit; alias visit = BaseAnalyzer.visit;
this(string fileName) this(string fileName, const(Scope)* sc)
{ {
super(fileName); super(fileName, sc);
} }
override void visit(const IfStatement statement) override void visit(const IfStatement statement)

View file

@ -14,6 +14,8 @@ import std.array;
import std.d.lexer; import std.d.lexer;
import std.d.parser; import std.d.parser;
import std.d.ast; import std.d.ast;
import std.allocator : CAllocatorImpl;
import std.typecons:scoped;
import analysis.config; import analysis.config;
import analysis.base; import analysis.base;
@ -44,6 +46,11 @@ import analysis.unmodified;
import analysis.if_statements; import analysis.if_statements;
import analysis.redundant_parens; import analysis.redundant_parens;
import memory.allocators:BlockAllocator;
import dsymbol.scope_;
import dsymbol.conversion;
bool first = true; bool first = true;
void messageFunction(string fileName, size_t line, size_t column, string message, void messageFunction(string fileName, size_t line, size_t column, string message,
@ -166,33 +173,36 @@ MessageSet analyze(string fileName, const Module m,
if (!staticAnalyze) if (!staticAnalyze)
return null; return null;
auto allocator = scoped!(CAllocatorImpl!(BlockAllocator!(1024 * 16)))();
const(Scope)* moduleScope = generateAutocompleteTrees(m, allocator);
BaseAnalyzer[] checks; BaseAnalyzer[] checks;
if (analysisConfig.style_check) checks ~= new StyleChecker(fileName); if (analysisConfig.style_check) checks ~= new StyleChecker(fileName, moduleScope);
if (analysisConfig.enum_array_literal_check) checks ~= new EnumArrayLiteralCheck(fileName); if (analysisConfig.enum_array_literal_check) checks ~= new EnumArrayLiteralCheck(fileName, moduleScope);
if (analysisConfig.exception_check) checks ~= new PokemonExceptionCheck(fileName); if (analysisConfig.exception_check) checks ~= new PokemonExceptionCheck(fileName, moduleScope);
if (analysisConfig.delete_check) checks ~= new DeleteCheck(fileName); if (analysisConfig.delete_check) checks ~= new DeleteCheck(fileName, moduleScope);
if (analysisConfig.float_operator_check) checks ~= new FloatOperatorCheck(fileName); if (analysisConfig.float_operator_check) checks ~= new FloatOperatorCheck(fileName, moduleScope);
if (analysisConfig.number_style_check) checks ~= new NumberStyleCheck(fileName); if (analysisConfig.number_style_check) checks ~= new NumberStyleCheck(fileName, moduleScope);
if (analysisConfig.object_const_check) checks ~= new ObjectConstCheck(fileName); if (analysisConfig.object_const_check) checks ~= new ObjectConstCheck(fileName, moduleScope);
if (analysisConfig.backwards_range_check) checks ~= new BackwardsRangeCheck(fileName); if (analysisConfig.backwards_range_check) checks ~= new BackwardsRangeCheck(fileName, moduleScope);
if (analysisConfig.if_else_same_check) checks ~= new IfElseSameCheck(fileName); if (analysisConfig.if_else_same_check) checks ~= new IfElseSameCheck(fileName, moduleScope);
if (analysisConfig.constructor_check) checks ~= new ConstructorCheck(fileName); if (analysisConfig.constructor_check) checks ~= new ConstructorCheck(fileName, moduleScope);
if (analysisConfig.unused_label_check) checks ~= new UnusedLabelCheck(fileName); if (analysisConfig.unused_label_check) checks ~= new UnusedLabelCheck(fileName, moduleScope);
if (analysisConfig.unused_variable_check) checks ~= new UnusedVariableCheck(fileName); if (analysisConfig.unused_variable_check) checks ~= new UnusedVariableCheck(fileName, moduleScope);
if (analysisConfig.duplicate_attribute) checks ~= new DuplicateAttributeCheck(fileName); if (analysisConfig.duplicate_attribute) checks ~= new DuplicateAttributeCheck(fileName, moduleScope);
if (analysisConfig.opequals_tohash_check) checks ~= new OpEqualsWithoutToHashCheck(fileName); if (analysisConfig.opequals_tohash_check) checks ~= new OpEqualsWithoutToHashCheck(fileName, moduleScope);
if (analysisConfig.length_subtraction_check) checks ~= new LengthSubtractionCheck(fileName); if (analysisConfig.length_subtraction_check) checks ~= new LengthSubtractionCheck(fileName, moduleScope);
if (analysisConfig.builtin_property_names_check) checks ~= new BuiltinPropertyNameCheck(fileName); if (analysisConfig.builtin_property_names_check) checks ~= new BuiltinPropertyNameCheck(fileName, moduleScope);
if (analysisConfig.asm_style_check) checks ~= new AsmStyleCheck(fileName); if (analysisConfig.asm_style_check) checks ~= new AsmStyleCheck(fileName, moduleScope);
if (analysisConfig.logical_precedence_check) checks ~= new LogicPrecedenceCheck(fileName); if (analysisConfig.logical_precedence_check) checks ~= new LogicPrecedenceCheck(fileName, moduleScope);
if (analysisConfig.undocumented_declaration_check) checks ~= new UndocumentedDeclarationCheck(fileName); if (analysisConfig.undocumented_declaration_check) checks ~= new UndocumentedDeclarationCheck(fileName, moduleScope);
if (analysisConfig.function_attribute_check) checks ~= new FunctionAttributeCheck(fileName); if (analysisConfig.function_attribute_check) checks ~= new FunctionAttributeCheck(fileName, moduleScope);
if (analysisConfig.comma_expression_check) checks ~= new CommaExpressionCheck(fileName); if (analysisConfig.comma_expression_check) checks ~= new CommaExpressionCheck(fileName, moduleScope);
if (analysisConfig.local_import_check) checks ~= new LocalImportCheck(fileName); if (analysisConfig.local_import_check) checks ~= new LocalImportCheck(fileName, moduleScope);
if (analysisConfig.could_be_immutable_check) checks ~= new UnmodifiedFinder(fileName); if (analysisConfig.could_be_immutable_check) checks ~= new UnmodifiedFinder(fileName, moduleScope);
if (analysisConfig.redundant_parens_check) checks ~= new RedundantParenCheck(fileName); if (analysisConfig.redundant_parens_check) checks ~= new RedundantParenCheck(fileName, moduleScope);
version(none) if (analysisConfig.redundant_if_check) checks ~= new IfStatementCheck(fileName); version(none) if (analysisConfig.redundant_if_check) checks ~= new IfStatementCheck(fileName, moduleScope);
foreach (check; checks) foreach (check; checks)
{ {

View file

@ -15,7 +15,7 @@ class StatsCollector : BaseAnalyzer
this(string fileName) this(string fileName)
{ {
super(fileName); super(fileName, null);
} }
override void visit(const Statement statement) override void visit(const Statement statement)

View file

@ -13,8 +13,8 @@ import std.array;
import std.conv; import std.conv;
import std.format; import std.format;
import analysis.helpers; import analysis.helpers;
import analysis.base; import analysis.base;
import dsymbol.scope_ : Scope;
class StyleChecker : BaseAnalyzer class StyleChecker : BaseAnalyzer
{ {
@ -25,9 +25,9 @@ class StyleChecker : BaseAnalyzer
enum string moduleNameRegex = `^[\p{Ll}_\d]+$`; enum string moduleNameRegex = `^[\p{Ll}_\d]+$`;
enum string KEY = "dscanner.style.phobos_naming_convention"; enum string KEY = "dscanner.style.phobos_naming_convention";
this(string fileName) this(string fileName, const(Scope)* sc)
{ {
super(fileName); super(fileName, sc);
} }
override void visit(const ModuleDeclaration dec) override void visit(const ModuleDeclaration dec)

View file

@ -5,10 +5,10 @@
module analysis.undocumented; module analysis.undocumented;
import analysis.base;
import dsymbol.scope_ : Scope;
import std.d.ast; import std.d.ast;
import std.d.lexer; import std.d.lexer;
import analysis.base;
import std.stdio; import std.stdio;
/** /**
@ -19,9 +19,9 @@ class UndocumentedDeclarationCheck : BaseAnalyzer
{ {
alias visit = BaseAnalyzer.visit; alias visit = BaseAnalyzer.visit;
this(string fileName) this(string fileName, const(Scope)* sc)
{ {
super(fileName); super(fileName, sc);
} }
override void visit(const Module mod) override void visit(const Module mod)

View file

@ -4,10 +4,11 @@
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
module analysis.unmodified; module analysis.unmodified;
import analysis.base;
import dsymbol.scope_ : Scope;
import std.container; import std.container;
import std.d.ast; import std.d.ast;
import std.d.lexer; import std.d.lexer;
import analysis.base;
/** /**
* Checks for variables that could have been declared const or immutable * Checks for variables that could have been declared const or immutable
@ -17,9 +18,9 @@ class UnmodifiedFinder:BaseAnalyzer
alias visit = BaseAnalyzer.visit; alias visit = BaseAnalyzer.visit;
/// ///
this(string fileName) this(string fileName, const(Scope)* sc)
{ {
super(fileName); super(fileName, sc);
} }
override void visit(const Module mod) override void visit(const Module mod)
@ -41,7 +42,7 @@ class UnmodifiedFinder:BaseAnalyzer
override void visit(const StructBody structBody) override void visit(const StructBody structBody)
{ {
pushScope(); pushScope();
auto oldBlockStatementDepth = blockStatementDepth; immutable oldBlockStatementDepth = blockStatementDepth;
blockStatementDepth = 0; blockStatementDepth = 0;
structBody.accept(this); structBody.accept(this);
blockStatementDepth = oldBlockStatementDepth; blockStatementDepth = oldBlockStatementDepth;

View file

@ -10,6 +10,7 @@ import std.d.lexer;
import analysis.base; import analysis.base;
import std.container; import std.container;
import std.regex : Regex, regex, matchAll; import std.regex : Regex, regex, matchAll;
import dsymbol.scope_ : Scope;
/** /**
* Checks for unused variables. * Checks for unused variables.
@ -22,9 +23,9 @@ class UnusedVariableCheck : BaseAnalyzer
* Params: * Params:
* fileName = the name of the file being analyzed * fileName = the name of the file being analyzed
*/ */
this(string fileName) this(string fileName, const(Scope)* sc)
{ {
super(fileName); super(fileName, sc);
re = regex("[\\p{Alphabetic}_][\\w_]*"); re = regex("[\\p{Alphabetic}_][\\w_]*");
} }

View file

@ -9,14 +9,15 @@ import std.d.ast;
import std.d.lexer; import std.d.lexer;
import analysis.base; import analysis.base;
import analysis.helpers; import analysis.helpers;
import dsymbol.scope_ : Scope;
class UnusedLabelCheck : BaseAnalyzer class UnusedLabelCheck : BaseAnalyzer
{ {
alias visit = BaseAnalyzer.visit; alias visit = BaseAnalyzer.visit;
this(string fileName) this(string fileName, const(Scope)* sc)
{ {
super(fileName); super(fileName, sc);
} }
static struct Label static struct Label

View file

@ -1,4 +1,4 @@
// Copyright Brian Schott (Hackerpilot) 2012. // Copyright Brian Schott (Hackerpilot) 2012-2015.
// Distributed under the Boost Software License, Version 1.0. // Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at // (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
@ -31,6 +31,8 @@ import dscanner_version;
import inifiled; import inifiled;
import dsymbol.modulecache;
int main(string[] args) int main(string[] args)
{ {
version (unittest) version (unittest)
@ -65,6 +67,7 @@ int run(string[] args)
string configLocation; string configLocation;
bool printVersion; bool printVersion;
bool explore; bool explore;
string[] importPaths;
try try
{ {
@ -75,7 +78,7 @@ int run(string[] args)
"ast|xml", &ast, "imports|i", &imports, "outline|o", &outline, "ast|xml", &ast, "imports|i", &imports, "outline|o", &outline,
"tokenDump", &tokenDump, "styleCheck|S", &styleCheck, "tokenDump", &tokenDump, "styleCheck|S", &styleCheck,
"defaultConfig", &defaultConfig, "declaration|d", &symbolName, "defaultConfig", &defaultConfig, "declaration|d", &symbolName,
"config", &configLocation, "report", &report, "config", &configLocation, "report", &report, "I", &importPaths,
"version", &printVersion, "muffinButton", &muffin, "explore", &explore); "version", &printVersion, "muffinButton", &muffin, "explore", &explore);
} }
catch (ConvException e) catch (ConvException e)
@ -121,7 +124,13 @@ int run(string[] args)
return 0; return 0;
} }
auto optionCount = count!"a"([sloc, highlight, ctags, tokenCount, const(string[]) absImportPaths = importPaths.map!(
a => a.absolutePath().buildNormalizedPath()).array();
if (absImportPaths.length)
ModuleCache.addImportPaths(absImportPaths);
immutable optionCount = count!"a"([sloc, highlight, ctags, tokenCount,
syntaxCheck, ast, imports, outline, tokenDump, styleCheck, defaultConfig, syntaxCheck, ast, imports, outline, tokenDump, styleCheck, defaultConfig,
report, symbolName !is null, etags, etagsAll]); report, symbolName !is null, etags, etagsAll]);
if (optionCount > 1) if (optionCount > 1)
@ -274,7 +283,6 @@ int run(string[] args)
return 0; return 0;
} }
string[] expandArgs(string[] args) string[] expandArgs(string[] args)
{ {
// isFile can throw if it's a broken symlink. // isFile can throw if it's a broken symlink.
@ -289,7 +297,7 @@ string[] expandArgs(string[] args)
return false; return false;
} }
} }
string[] rVal; string[] rVal;
if (args.length == 1) if (args.length == 1)
args ~= "."; args ~= ".";