From a3c4a5384a21d2a2f694c13af7bfa6a621048134 Mon Sep 17 00:00:00 2001 From: Hackerpilot Date: Tue, 26 May 2015 00:24:21 -0700 Subject: [PATCH] Starting work on 0.3.0 --- .gitmodules | 6 +++ containers | 1 + dsymbol | 1 + libdparse | 2 +- makefile | 17 ++++++-- src/analysis/asm_style.d | 5 ++- src/analysis/base.d | 6 ++- src/analysis/builtin_property_names.d | 5 ++- src/analysis/comma_expression.d | 5 ++- src/analysis/constructors.d | 5 ++- src/analysis/del.d | 5 ++- src/analysis/duplicate_attribute.d | 5 ++- src/analysis/enumarrayliteral.d | 5 ++- src/analysis/fish.d | 5 ++- src/analysis/function_attributes.d | 8 ++-- src/analysis/if_statements.d | 7 ++- src/analysis/ifelsesame.d | 7 ++- src/analysis/length_subtraction.d | 5 ++- src/analysis/local_imports.d | 5 ++- src/analysis/logic_precedence.d | 5 ++- src/analysis/mismatched_args.d | 56 ++++++++++++++++++++++++ src/analysis/numbers.d | 5 ++- src/analysis/objectconst.d | 5 ++- src/analysis/opequals_without_tohash.d | 5 ++- src/analysis/pokemon.d | 5 ++- src/analysis/range.d | 7 +-- src/analysis/redundant_parens.d | 5 ++- src/analysis/run.d | 60 +++++++++++++++----------- src/analysis/stats_collector.d | 2 +- src/analysis/style.d | 6 +-- src/analysis/undocumented.d | 8 ++-- src/analysis/unmodified.d | 9 ++-- src/analysis/unused.d | 5 ++- src/analysis/unused_label.d | 5 ++- src/main.d | 18 +++++--- 35 files changed, 212 insertions(+), 99 deletions(-) create mode 160000 containers create mode 160000 dsymbol create mode 100644 src/analysis/mismatched_args.d diff --git a/.gitmodules b/.gitmodules index 85595f2..c977bf8 100644 --- a/.gitmodules +++ b/.gitmodules @@ -5,3 +5,9 @@ [submodule "inifiled"] path = inifiled 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 diff --git a/containers b/containers new file mode 160000 index 0000000..d732a67 --- /dev/null +++ b/containers @@ -0,0 +1 @@ +Subproject commit d732a67e76f60fd037547c3ffe8776c6deda6bab diff --git a/dsymbol b/dsymbol new file mode 160000 index 0000000..ddf8c97 --- /dev/null +++ b/dsymbol @@ -0,0 +1 @@ +Subproject commit ddf8c97753471388303d64a47bdade85cc4de003 diff --git a/libdparse b/libdparse index 32f6d63..0dccfca 160000 --- a/libdparse +++ b/libdparse @@ -1 +1 @@ -Subproject commit 32f6d638e38888e1bb11cf43e93fe2d11132a98f +Subproject commit 0dccfca0e2a132b3c862a62da1c323ccd24e622d diff --git a/makefile b/makefile index 3d2f11e..8ead467 100644 --- a/makefile +++ b/makefile @@ -7,12 +7,21 @@ SRC = src/*.d\ src/analysis/*.d\ libdparse/src/std/*.d\ libdparse/src/std/d/*.d\ - inifiled/source/*.d -INCLUDE_PATHS = -Ilibdparse/src + inifiled/source/*.d\ + $(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 = DEBUG_VERSIONS = -version=std_parser_verbose -DMD_FLAGS = -w -O -release -inline -#DMD_FLAGS = -w +#DMD_FLAGS = -w -O -release -inline +DMD_FLAGS = -w all: dmdbuild ldc: ldcbuild diff --git a/src/analysis/asm_style.d b/src/analysis/asm_style.d index 063b48c..6b2344c 100644 --- a/src/analysis/asm_style.d +++ b/src/analysis/asm_style.d @@ -10,6 +10,7 @@ import std.d.ast; import std.d.lexer; import analysis.base; import analysis.helpers; +import dsymbol.scope_ : Scope; /** * Checks for confusing asm expressions. @@ -19,9 +20,9 @@ class AsmStyleCheck : BaseAnalyzer { alias visit = BaseAnalyzer.visit; - this(string fileName) + this(string fileName, const(Scope)* sc) { - super(fileName); + super(fileName, sc); } override void visit(const AsmBrExp brExp) diff --git a/src/analysis/base.d b/src/analysis/base.d index f984ef3..adfd3f2 100644 --- a/src/analysis/base.d +++ b/src/analysis/base.d @@ -4,6 +4,7 @@ import std.container; import std.string; import std.d.ast; import std.array; +import dsymbol.scope_ : Scope; struct Message { @@ -26,8 +27,9 @@ alias MessageSet = RedBlackTree!(Message, comparitor, true); abstract class BaseAnalyzer : ASTVisitor { public: - this(string fileName) + this(string fileName, const Scope* sc) { + this.sc = sc; this.fileName = fileName; _messages = new MessageSet; } @@ -61,6 +63,8 @@ protected: */ string fileName; + const(Scope)* sc; + MessageSet _messages; } diff --git a/src/analysis/builtin_property_names.d b/src/analysis/builtin_property_names.d index c5d62b0..62a14a3 100644 --- a/src/analysis/builtin_property_names.d +++ b/src/analysis/builtin_property_names.d @@ -11,6 +11,7 @@ import std.d.ast; import std.d.lexer; import analysis.base; import analysis.helpers; +import dsymbol.scope_; /** * The following code should be killed with fire: @@ -29,9 +30,9 @@ class BuiltinPropertyNameCheck : BaseAnalyzer { alias visit = BaseAnalyzer.visit; - this(string fileName) + this(string fileName, const(Scope)* sc) { - super(fileName); + super(fileName, sc); } override void visit(const FunctionDeclaration fd) diff --git a/src/analysis/comma_expression.d b/src/analysis/comma_expression.d index f55e5ec..d628ec7 100644 --- a/src/analysis/comma_expression.d +++ b/src/analysis/comma_expression.d @@ -8,6 +8,7 @@ module analysis.comma_expression; import std.d.ast; import std.d.lexer; import analysis.base; +import dsymbol.scope_; /** * Check for uses of the comma expression. @@ -16,9 +17,9 @@ class CommaExpressionCheck : BaseAnalyzer { alias visit = BaseAnalyzer.visit; - this(string fileName) + this(string fileName, const(Scope)* sc) { - super(fileName); + super(fileName, sc); } override void visit(const Expression ex) diff --git a/src/analysis/constructors.d b/src/analysis/constructors.d index 3d9eb09..724565e 100644 --- a/src/analysis/constructors.d +++ b/src/analysis/constructors.d @@ -5,15 +5,16 @@ import std.d.lexer; import std.stdio; import analysis.base; import analysis.helpers; +import dsymbol.scope_ : Scope; class ConstructorCheck : BaseAnalyzer { alias visit = BaseAnalyzer.visit; - this(string fileName) + this(string fileName, const(Scope)* sc) { - super(fileName); + super(fileName, sc); } override void visit(const ClassDeclaration classDeclaration) diff --git a/src/analysis/del.d b/src/analysis/del.d index c6ee938..be14ad5 100644 --- a/src/analysis/del.d +++ b/src/analysis/del.d @@ -10,6 +10,7 @@ import std.d.ast; import std.d.lexer; import analysis.base; import analysis.helpers; +import dsymbol.scope_; /** * Checks for use of the deprecated 'delete' keyword @@ -18,9 +19,9 @@ class DeleteCheck : BaseAnalyzer { alias visit = BaseAnalyzer.visit; - this(string fileName) + this(string fileName, const(Scope)* sc) { - super(fileName); + super(fileName, sc); } override void visit(const DeleteExpression d) diff --git a/src/analysis/duplicate_attribute.d b/src/analysis/duplicate_attribute.d index 1c1eb6c..8beab67 100644 --- a/src/analysis/duplicate_attribute.d +++ b/src/analysis/duplicate_attribute.d @@ -11,6 +11,7 @@ import std.d.ast; import std.d.lexer; import analysis.base; import analysis.helpers; +import dsymbol.scope_ : Scope; /** @@ -21,9 +22,9 @@ class DuplicateAttributeCheck : BaseAnalyzer { alias visit = BaseAnalyzer.visit; - this(string fileName) + this(string fileName, const(Scope)* sc) { - super(fileName); + super(fileName, sc); } override void visit(const Declaration node) diff --git a/src/analysis/enumarrayliteral.d b/src/analysis/enumarrayliteral.d index f15ada3..9dd4e82 100644 --- a/src/analysis/enumarrayliteral.d +++ b/src/analysis/enumarrayliteral.d @@ -9,6 +9,7 @@ import std.d.ast; import std.d.lexer; import analysis.base; import std.algorithm : canFind; +import dsymbol.scope_ : Scope; void doNothing(string, size_t, size_t, string, bool) {} @@ -16,9 +17,9 @@ class EnumArrayLiteralCheck : BaseAnalyzer { alias visit = BaseAnalyzer.visit; - this(string fileName) + this(string fileName, const(Scope)* sc) { - super(fileName); + super(fileName, sc); } bool looking = false; diff --git a/src/analysis/fish.d b/src/analysis/fish.d index 2bc5dea..6453b06 100644 --- a/src/analysis/fish.d +++ b/src/analysis/fish.d @@ -10,6 +10,7 @@ import std.d.ast; import std.d.lexer; import analysis.base; import analysis.helpers; +import dsymbol.scope_ : Scope; /** * 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"; - this(string fileName) + this(string fileName, const(Scope)* sc) { - super(fileName); + super(fileName, sc); } override void visit(const RelExpression r) diff --git a/src/analysis/function_attributes.d b/src/analysis/function_attributes.d index 8087310..6da57c0 100644 --- a/src/analysis/function_attributes.d +++ b/src/analysis/function_attributes.d @@ -5,11 +5,11 @@ module analysis.function_attributes; +import analysis.base; import std.d.ast; import std.d.lexer; -import analysis.base; - import std.stdio; +import dsymbol.scope_; /** * Prefer @@ -25,9 +25,9 @@ class FunctionAttributeCheck : BaseAnalyzer { alias visit = BaseAnalyzer.visit; - this(string fileName) + this(string fileName, const(Scope)* sc) { - super(fileName); + super(fileName, sc); } override void visit(const InterfaceDeclaration dec) diff --git a/src/analysis/if_statements.d b/src/analysis/if_statements.d index 73bb8b0..8316ea1 100644 --- a/src/analysis/if_statements.d +++ b/src/analysis/if_statements.d @@ -8,15 +8,14 @@ import std.d.ast; import std.d.lexer; import std.d.formatter; import analysis.base; +import dsymbol.scope_ : Scope; class IfStatementCheck : BaseAnalyzer { alias visit = BaseAnalyzer.visit; - this(string fileName) + this(string fileName, const(Scope)* sc) { - import std.container.binaryheap : heapify; - - super(fileName); + super(fileName, sc); } override void visit(const IfStatement ifStatement) diff --git a/src/analysis/ifelsesame.d b/src/analysis/ifelsesame.d index f260da0..8d11e95 100644 --- a/src/analysis/ifelsesame.d +++ b/src/analysis/ifelsesame.d @@ -6,12 +6,11 @@ module analysis.ifelsesame; import std.stdio; - import std.d.ast; import std.d.lexer; import analysis.base; import analysis.helpers; - +import dsymbol.scope_ : Scope; /** * Checks for duplicated code in conditional and logical expressions. @@ -25,9 +24,9 @@ class IfElseSameCheck : BaseAnalyzer { alias visit = BaseAnalyzer.visit; - this(string fileName) + this(string fileName, const(Scope)* sc) { - super(fileName); + super(fileName, sc); } override void visit(const IfStatement ifStatement) diff --git a/src/analysis/length_subtraction.d b/src/analysis/length_subtraction.d index 0fbef2b..f557bca 100644 --- a/src/analysis/length_subtraction.d +++ b/src/analysis/length_subtraction.d @@ -11,6 +11,7 @@ import std.d.ast; import std.d.lexer; import analysis.base; import analysis.helpers; +import dsymbol.scope_; /** @@ -20,9 +21,9 @@ class LengthSubtractionCheck : BaseAnalyzer { alias visit = BaseAnalyzer.visit; - this(string fileName) + this(string fileName, const(Scope)* sc) { - super(fileName); + super(fileName, sc); } override void visit(const AddExpression addExpression) diff --git a/src/analysis/local_imports.d b/src/analysis/local_imports.d index 002eda9..9670411 100644 --- a/src/analysis/local_imports.d +++ b/src/analysis/local_imports.d @@ -10,6 +10,7 @@ import std.d.ast; import std.d.lexer; import analysis.base; import analysis.helpers; +import dsymbol.scope_; /** * Checks for local imports that import all symbols. @@ -22,9 +23,9 @@ class LocalImportCheck : BaseAnalyzer /** * Construct with the given file name. */ - this(string fileName) + this(string fileName, const(Scope)* sc) { - super(fileName); + super(fileName, sc); } mixin visitThing!StructBody; diff --git a/src/analysis/logic_precedence.d b/src/analysis/logic_precedence.d index c78dc6a..15948dc 100644 --- a/src/analysis/logic_precedence.d +++ b/src/analysis/logic_precedence.d @@ -10,6 +10,7 @@ import std.d.ast; import std.d.lexer; import analysis.base; import analysis.helpers; +import dsymbol.scope_; /** * Checks for code with confusing && and || operator precedence @@ -24,9 +25,9 @@ class LogicPrecedenceCheck : BaseAnalyzer 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) diff --git a/src/analysis/mismatched_args.d b/src/analysis/mismatched_args.d new file mode 100644 index 0000000..7848b04 --- /dev/null +++ b/src/analysis/mismatched_args.d @@ -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)]); + } +} diff --git a/src/analysis/numbers.d b/src/analysis/numbers.d index bc67da3..9cb1041 100644 --- a/src/analysis/numbers.d +++ b/src/analysis/numbers.d @@ -11,6 +11,7 @@ import std.d.ast; import std.d.lexer; import analysis.base; import analysis.helpers; +import dsymbol.scope_ : Scope; /** * Checks for long and hard-to-read number literals @@ -23,9 +24,9 @@ public: /** * 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) diff --git a/src/analysis/objectconst.d b/src/analysis/objectconst.d index f46d1a6..0e7778c 100644 --- a/src/analysis/objectconst.d +++ b/src/analysis/objectconst.d @@ -11,6 +11,7 @@ import std.d.ast; import std.d.lexer; import analysis.base; import analysis.helpers; +import dsymbol.scope_ : Scope; /** * Checks that opEquals, opCmp, toHash, and toString are either const, @@ -20,9 +21,9 @@ class ObjectConstCheck : BaseAnalyzer { alias visit = BaseAnalyzer.visit; - this(string fileName) + this(string fileName, const(Scope)* sc) { - super(fileName); + super(fileName, sc); } mixin visitTemplate!ClassDeclaration; diff --git a/src/analysis/opequals_without_tohash.d b/src/analysis/opequals_without_tohash.d index 290a805..e9fd138 100644 --- a/src/analysis/opequals_without_tohash.d +++ b/src/analysis/opequals_without_tohash.d @@ -10,6 +10,7 @@ import std.d.ast; import std.d.lexer; import analysis.base; import analysis.helpers; +import dsymbol.scope_ : Scope; /** * Checks for when a class/struct has the method opEquals without toHash, or @@ -19,9 +20,9 @@ class OpEqualsWithoutToHashCheck : BaseAnalyzer { alias visit = BaseAnalyzer.visit; - this(string fileName) + this(string fileName, const(Scope)* sc) { - super(fileName); + super(fileName, sc); } override void visit(const ClassDeclaration node) diff --git a/src/analysis/pokemon.d b/src/analysis/pokemon.d index 7d61571..b20e41e 100644 --- a/src/analysis/pokemon.d +++ b/src/analysis/pokemon.d @@ -10,6 +10,7 @@ import std.d.ast; import std.d.lexer; import analysis.base; import analysis.helpers; +import dsymbol.scope_ : Scope; /** @@ -30,9 +31,9 @@ class PokemonExceptionCheck : BaseAnalyzer alias visit = BaseAnalyzer.visit; - this(string fileName) + this(string fileName, const(Scope)* sc) { - super(fileName); + super(fileName, sc); } override void visit(const LastCatch lc) diff --git a/src/analysis/range.d b/src/analysis/range.d index 1d2644e..1d656fd 100644 --- a/src/analysis/range.d +++ b/src/analysis/range.d @@ -10,6 +10,7 @@ import std.d.ast; import std.d.lexer; import analysis.base; import analysis.helpers; +import dsymbol.scope_ : Scope; /** * Checks for .. expressions where the left side is larger than the right. This @@ -26,9 +27,9 @@ class BackwardsRangeCheck : BaseAnalyzer * Params: * 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) @@ -56,7 +57,7 @@ class BackwardsRangeCheck : BaseAnalyzer override void visit(const AddExpression add) { - auto s = state; + immutable s = state; state = State.ignore; add.accept(this); state = s; diff --git a/src/analysis/redundant_parens.d b/src/analysis/redundant_parens.d index 88c8c5f..a036d6f 100644 --- a/src/analysis/redundant_parens.d +++ b/src/analysis/redundant_parens.d @@ -8,14 +8,15 @@ module analysis.redundant_parens; import std.d.ast; import std.d.lexer; import analysis.base; +import dsymbol.scope_ : Scope; class RedundantParenCheck : BaseAnalyzer { alias visit = BaseAnalyzer.visit; - this(string fileName) + this(string fileName, const(Scope)* sc) { - super(fileName); + super(fileName, sc); } override void visit(const IfStatement statement) diff --git a/src/analysis/run.d b/src/analysis/run.d index 2d1a9e6..647e607 100644 --- a/src/analysis/run.d +++ b/src/analysis/run.d @@ -14,6 +14,8 @@ import std.array; import std.d.lexer; import std.d.parser; import std.d.ast; +import std.allocator : CAllocatorImpl; +import std.typecons:scoped; import analysis.config; import analysis.base; @@ -44,6 +46,11 @@ import analysis.unmodified; import analysis.if_statements; import analysis.redundant_parens; +import memory.allocators:BlockAllocator; + +import dsymbol.scope_; +import dsymbol.conversion; + bool first = true; 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) return null; + auto allocator = scoped!(CAllocatorImpl!(BlockAllocator!(1024 * 16)))(); + const(Scope)* moduleScope = generateAutocompleteTrees(m, allocator); + BaseAnalyzer[] checks; - if (analysisConfig.style_check) checks ~= new StyleChecker(fileName); - if (analysisConfig.enum_array_literal_check) checks ~= new EnumArrayLiteralCheck(fileName); - if (analysisConfig.exception_check) checks ~= new PokemonExceptionCheck(fileName); - if (analysisConfig.delete_check) checks ~= new DeleteCheck(fileName); - if (analysisConfig.float_operator_check) checks ~= new FloatOperatorCheck(fileName); - if (analysisConfig.number_style_check) checks ~= new NumberStyleCheck(fileName); - if (analysisConfig.object_const_check) checks ~= new ObjectConstCheck(fileName); - if (analysisConfig.backwards_range_check) checks ~= new BackwardsRangeCheck(fileName); - if (analysisConfig.if_else_same_check) checks ~= new IfElseSameCheck(fileName); - if (analysisConfig.constructor_check) checks ~= new ConstructorCheck(fileName); - if (analysisConfig.unused_label_check) checks ~= new UnusedLabelCheck(fileName); - if (analysisConfig.unused_variable_check) checks ~= new UnusedVariableCheck(fileName); - if (analysisConfig.duplicate_attribute) checks ~= new DuplicateAttributeCheck(fileName); - if (analysisConfig.opequals_tohash_check) checks ~= new OpEqualsWithoutToHashCheck(fileName); - if (analysisConfig.length_subtraction_check) checks ~= new LengthSubtractionCheck(fileName); - if (analysisConfig.builtin_property_names_check) checks ~= new BuiltinPropertyNameCheck(fileName); - if (analysisConfig.asm_style_check) checks ~= new AsmStyleCheck(fileName); - if (analysisConfig.logical_precedence_check) checks ~= new LogicPrecedenceCheck(fileName); - if (analysisConfig.undocumented_declaration_check) checks ~= new UndocumentedDeclarationCheck(fileName); - if (analysisConfig.function_attribute_check) checks ~= new FunctionAttributeCheck(fileName); - if (analysisConfig.comma_expression_check) checks ~= new CommaExpressionCheck(fileName); - if (analysisConfig.local_import_check) checks ~= new LocalImportCheck(fileName); - if (analysisConfig.could_be_immutable_check) checks ~= new UnmodifiedFinder(fileName); - if (analysisConfig.redundant_parens_check) checks ~= new RedundantParenCheck(fileName); - version(none) if (analysisConfig.redundant_if_check) checks ~= new IfStatementCheck(fileName); + if (analysisConfig.style_check) checks ~= new StyleChecker(fileName, moduleScope); + if (analysisConfig.enum_array_literal_check) checks ~= new EnumArrayLiteralCheck(fileName, moduleScope); + if (analysisConfig.exception_check) checks ~= new PokemonExceptionCheck(fileName, moduleScope); + if (analysisConfig.delete_check) checks ~= new DeleteCheck(fileName, moduleScope); + if (analysisConfig.float_operator_check) checks ~= new FloatOperatorCheck(fileName, moduleScope); + if (analysisConfig.number_style_check) checks ~= new NumberStyleCheck(fileName, moduleScope); + if (analysisConfig.object_const_check) checks ~= new ObjectConstCheck(fileName, moduleScope); + if (analysisConfig.backwards_range_check) checks ~= new BackwardsRangeCheck(fileName, moduleScope); + if (analysisConfig.if_else_same_check) checks ~= new IfElseSameCheck(fileName, moduleScope); + if (analysisConfig.constructor_check) checks ~= new ConstructorCheck(fileName, moduleScope); + if (analysisConfig.unused_label_check) checks ~= new UnusedLabelCheck(fileName, moduleScope); + if (analysisConfig.unused_variable_check) checks ~= new UnusedVariableCheck(fileName, moduleScope); + if (analysisConfig.duplicate_attribute) checks ~= new DuplicateAttributeCheck(fileName, moduleScope); + if (analysisConfig.opequals_tohash_check) checks ~= new OpEqualsWithoutToHashCheck(fileName, moduleScope); + if (analysisConfig.length_subtraction_check) checks ~= new LengthSubtractionCheck(fileName, moduleScope); + if (analysisConfig.builtin_property_names_check) checks ~= new BuiltinPropertyNameCheck(fileName, moduleScope); + if (analysisConfig.asm_style_check) checks ~= new AsmStyleCheck(fileName, moduleScope); + if (analysisConfig.logical_precedence_check) checks ~= new LogicPrecedenceCheck(fileName, moduleScope); + if (analysisConfig.undocumented_declaration_check) checks ~= new UndocumentedDeclarationCheck(fileName, moduleScope); + if (analysisConfig.function_attribute_check) checks ~= new FunctionAttributeCheck(fileName, moduleScope); + if (analysisConfig.comma_expression_check) checks ~= new CommaExpressionCheck(fileName, moduleScope); + if (analysisConfig.local_import_check) checks ~= new LocalImportCheck(fileName, moduleScope); + if (analysisConfig.could_be_immutable_check) checks ~= new UnmodifiedFinder(fileName, moduleScope); + if (analysisConfig.redundant_parens_check) checks ~= new RedundantParenCheck(fileName, moduleScope); + version(none) if (analysisConfig.redundant_if_check) checks ~= new IfStatementCheck(fileName, moduleScope); foreach (check; checks) { diff --git a/src/analysis/stats_collector.d b/src/analysis/stats_collector.d index c3cc6fd..f33be48 100644 --- a/src/analysis/stats_collector.d +++ b/src/analysis/stats_collector.d @@ -15,7 +15,7 @@ class StatsCollector : BaseAnalyzer this(string fileName) { - super(fileName); + super(fileName, null); } override void visit(const Statement statement) diff --git a/src/analysis/style.d b/src/analysis/style.d index 6d30e80..47b13bb 100644 --- a/src/analysis/style.d +++ b/src/analysis/style.d @@ -13,8 +13,8 @@ import std.array; import std.conv; import std.format; import analysis.helpers; - import analysis.base; +import dsymbol.scope_ : Scope; class StyleChecker : BaseAnalyzer { @@ -25,9 +25,9 @@ class StyleChecker : BaseAnalyzer enum string moduleNameRegex = `^[\p{Ll}_\d]+$`; 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) diff --git a/src/analysis/undocumented.d b/src/analysis/undocumented.d index 165f807..e844464 100644 --- a/src/analysis/undocumented.d +++ b/src/analysis/undocumented.d @@ -5,10 +5,10 @@ module analysis.undocumented; +import analysis.base; +import dsymbol.scope_ : Scope; import std.d.ast; import std.d.lexer; -import analysis.base; - import std.stdio; /** @@ -19,9 +19,9 @@ class UndocumentedDeclarationCheck : BaseAnalyzer { alias visit = BaseAnalyzer.visit; - this(string fileName) + this(string fileName, const(Scope)* sc) { - super(fileName); + super(fileName, sc); } override void visit(const Module mod) diff --git a/src/analysis/unmodified.d b/src/analysis/unmodified.d index b5621ce..ce9998d 100644 --- a/src/analysis/unmodified.d +++ b/src/analysis/unmodified.d @@ -4,10 +4,11 @@ // http://www.boost.org/LICENSE_1_0.txt) module analysis.unmodified; +import analysis.base; +import dsymbol.scope_ : Scope; import std.container; import std.d.ast; import std.d.lexer; -import analysis.base; /** * Checks for variables that could have been declared const or immutable @@ -17,9 +18,9 @@ class UnmodifiedFinder:BaseAnalyzer alias visit = BaseAnalyzer.visit; /// - this(string fileName) + this(string fileName, const(Scope)* sc) { - super(fileName); + super(fileName, sc); } override void visit(const Module mod) @@ -41,7 +42,7 @@ class UnmodifiedFinder:BaseAnalyzer override void visit(const StructBody structBody) { pushScope(); - auto oldBlockStatementDepth = blockStatementDepth; + immutable oldBlockStatementDepth = blockStatementDepth; blockStatementDepth = 0; structBody.accept(this); blockStatementDepth = oldBlockStatementDepth; diff --git a/src/analysis/unused.d b/src/analysis/unused.d index 7b23dbe..49853b4 100644 --- a/src/analysis/unused.d +++ b/src/analysis/unused.d @@ -10,6 +10,7 @@ import std.d.lexer; import analysis.base; import std.container; import std.regex : Regex, regex, matchAll; +import dsymbol.scope_ : Scope; /** * Checks for unused variables. @@ -22,9 +23,9 @@ class UnusedVariableCheck : BaseAnalyzer * Params: * 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_]*"); } diff --git a/src/analysis/unused_label.d b/src/analysis/unused_label.d index 32c0cc7..0f9ac56 100644 --- a/src/analysis/unused_label.d +++ b/src/analysis/unused_label.d @@ -9,14 +9,15 @@ import std.d.ast; import std.d.lexer; import analysis.base; import analysis.helpers; +import dsymbol.scope_ : Scope; class UnusedLabelCheck : BaseAnalyzer { alias visit = BaseAnalyzer.visit; - this(string fileName) + this(string fileName, const(Scope)* sc) { - super(fileName); + super(fileName, sc); } static struct Label diff --git a/src/main.d b/src/main.d index 69f85f2..54ae665 100644 --- a/src/main.d +++ b/src/main.d @@ -1,4 +1,4 @@ -// Copyright Brian Schott (Hackerpilot) 2012. +// Copyright Brian Schott (Hackerpilot) 2012-2015. // 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) @@ -31,6 +31,8 @@ import dscanner_version; import inifiled; +import dsymbol.modulecache; + int main(string[] args) { version (unittest) @@ -65,6 +67,7 @@ int run(string[] args) string configLocation; bool printVersion; bool explore; + string[] importPaths; try { @@ -75,7 +78,7 @@ int run(string[] args) "ast|xml", &ast, "imports|i", &imports, "outline|o", &outline, "tokenDump", &tokenDump, "styleCheck|S", &styleCheck, "defaultConfig", &defaultConfig, "declaration|d", &symbolName, - "config", &configLocation, "report", &report, + "config", &configLocation, "report", &report, "I", &importPaths, "version", &printVersion, "muffinButton", &muffin, "explore", &explore); } catch (ConvException e) @@ -121,7 +124,13 @@ int run(string[] args) 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, report, symbolName !is null, etags, etagsAll]); if (optionCount > 1) @@ -274,7 +283,6 @@ int run(string[] args) return 0; } - string[] expandArgs(string[] args) { // isFile can throw if it's a broken symlink. @@ -289,7 +297,7 @@ string[] expandArgs(string[] args) return false; } } - + string[] rVal; if (args.length == 1) args ~= ".";