From 3b9d608866cd5a9045bc9f94ee9f199fed8be733 Mon Sep 17 00:00:00 2001 From: Eugene Wissner Date: Tue, 9 Jul 2019 12:16:25 +0200 Subject: [PATCH] Track check name for error messages (#769) * Track check name for error messages * Assert BaseAnalyzer.getName() is implemented --- src/dscanner/analysis/alias_syntax_check.d | 2 + src/dscanner/analysis/allman.d | 4 +- src/dscanner/analysis/asm_style.d | 2 + src/dscanner/analysis/assert_without_msg.d | 3 +- src/dscanner/analysis/auto_function.d | 2 + src/dscanner/analysis/auto_ref_assignment.d | 2 + src/dscanner/analysis/base.d | 19 ++- .../analysis/builtin_property_names.d | 2 + src/dscanner/analysis/comma_expression.d | 2 + src/dscanner/analysis/constructors.d | 2 + src/dscanner/analysis/del.d | 2 + src/dscanner/analysis/duplicate_attribute.d | 2 + src/dscanner/analysis/enumarrayliteral.d | 2 + .../analysis/explicitly_annotated_unittests.d | 3 +- src/dscanner/analysis/final_attribute.d | 2 + src/dscanner/analysis/fish.d | 1 + src/dscanner/analysis/function_attributes.d | 2 + src/dscanner/analysis/has_public_example.d | 2 + src/dscanner/analysis/if_constraints_indent.d | 4 +- src/dscanner/analysis/if_statements.d | 2 + src/dscanner/analysis/ifelsesame.d | 2 + src/dscanner/analysis/imports_sortedness.d | 3 +- .../analysis/incorrect_infinite_range.d | 2 + .../analysis/label_var_same_name_check.d | 2 + src/dscanner/analysis/lambda_return_check.d | 2 + src/dscanner/analysis/length_subtraction.d | 2 + src/dscanner/analysis/line_length.d | 4 +- src/dscanner/analysis/local_imports.d | 2 + src/dscanner/analysis/logic_precedence.d | 1 + src/dscanner/analysis/mismatched_args.d | 4 +- src/dscanner/analysis/numbers.d | 2 + src/dscanner/analysis/objectconst.d | 2 + .../analysis/opequals_without_tohash.d | 2 + src/dscanner/analysis/pokemon.d | 1 + .../properly_documented_public_functions.d | 4 +- src/dscanner/analysis/range.d | 2 + src/dscanner/analysis/redundant_attributes.d | 2 + src/dscanner/analysis/redundant_parens.d | 2 + .../analysis/redundant_storage_class.d | 1 + src/dscanner/analysis/run.d | 151 +++++++++--------- src/dscanner/analysis/static_if_else.d | 2 + src/dscanner/analysis/style.d | 1 + src/dscanner/analysis/trust_too_much.d | 2 + src/dscanner/analysis/undocumented.d | 2 + src/dscanner/analysis/unmodified.d | 2 + src/dscanner/analysis/unused_label.d | 2 + src/dscanner/analysis/unused_parameter.d | 3 + src/dscanner/analysis/unused_variable.d | 3 + src/dscanner/analysis/useless_assert.d | 2 + src/dscanner/analysis/useless_initializer.d | 2 + src/dscanner/analysis/vcall_in_ctor.d | 2 + 51 files changed, 195 insertions(+), 83 deletions(-) diff --git a/src/dscanner/analysis/alias_syntax_check.d b/src/dscanner/analysis/alias_syntax_check.d index 8989ffa..e8c1ab2 100644 --- a/src/dscanner/analysis/alias_syntax_check.d +++ b/src/dscanner/analysis/alias_syntax_check.d @@ -16,6 +16,8 @@ final class AliasSyntaxCheck : BaseAnalyzer { alias visit = BaseAnalyzer.visit; + mixin AnalyzerInfo!"alias_syntax_check"; + this(string fileName, bool skipTests = false) { super(fileName, null, skipTests); diff --git a/src/dscanner/analysis/allman.d b/src/dscanner/analysis/allman.d index 239faf0..2cbd9cc 100644 --- a/src/dscanner/analysis/allman.d +++ b/src/dscanner/analysis/allman.d @@ -6,7 +6,7 @@ module dscanner.analysis.allman; import dparse.lexer; import dparse.ast; -import dscanner.analysis.base : BaseAnalyzer; +import dscanner.analysis.base; import dsymbol.scope_ : Scope; import std.algorithm; @@ -27,6 +27,8 @@ if (param < 0) */ final class AllManCheck : BaseAnalyzer { + mixin AnalyzerInfo!"allman_braces_check"; + /// this(string fileName, const(Token)[] tokens, bool skipTests = false) { diff --git a/src/dscanner/analysis/asm_style.d b/src/dscanner/analysis/asm_style.d index 48da513..de54c77 100644 --- a/src/dscanner/analysis/asm_style.d +++ b/src/dscanner/analysis/asm_style.d @@ -20,6 +20,8 @@ final class AsmStyleCheck : BaseAnalyzer { alias visit = BaseAnalyzer.visit; + mixin AnalyzerInfo!"asm_style_check"; + this(string fileName, const(Scope)* sc, bool skipTests = false) { super(fileName, sc, skipTests); diff --git a/src/dscanner/analysis/assert_without_msg.d b/src/dscanner/analysis/assert_without_msg.d index 6ee8f93..e24c989 100644 --- a/src/dscanner/analysis/assert_without_msg.d +++ b/src/dscanner/analysis/assert_without_msg.d @@ -4,7 +4,7 @@ module dscanner.analysis.assert_without_msg; -import dscanner.analysis.base : BaseAnalyzer; +import dscanner.analysis.base; import dscanner.utils : safeAccess; import dsymbol.scope_ : Scope; import dparse.lexer; @@ -20,6 +20,7 @@ final class AssertWithoutMessageCheck : BaseAnalyzer { enum string KEY = "dscanner.style.assert_without_msg"; enum string MESSAGE = "An assert should have an explanatory message"; + mixin AnalyzerInfo!"assert_without_msg"; /// this(string fileName, const(Scope)* sc, bool skipTests = false) diff --git a/src/dscanner/analysis/auto_function.d b/src/dscanner/analysis/auto_function.d index 5bb9a5d..659dbff 100644 --- a/src/dscanner/analysis/auto_function.d +++ b/src/dscanner/analysis/auto_function.d @@ -36,6 +36,8 @@ public: alias visit = BaseAnalyzer.visit; + mixin AnalyzerInfo!"auto_function_check"; + /// this(string fileName, bool skipTests = false) { diff --git a/src/dscanner/analysis/auto_ref_assignment.d b/src/dscanner/analysis/auto_ref_assignment.d index b4185c7..dbd5760 100644 --- a/src/dscanner/analysis/auto_ref_assignment.d +++ b/src/dscanner/analysis/auto_ref_assignment.d @@ -14,6 +14,8 @@ import dscanner.analysis.base; */ final class AutoRefAssignmentCheck : BaseAnalyzer { + mixin AnalyzerInfo!"auto_ref_assignment_check"; + /// this(string fileName, bool skipTests = false) { diff --git a/src/dscanner/analysis/base.d b/src/dscanner/analysis/base.d index fd7ac4d..0b92a5c 100644 --- a/src/dscanner/analysis/base.d +++ b/src/dscanner/analysis/base.d @@ -18,12 +18,24 @@ struct Message string key; /// Warning message string message; + /// Check name + string checkName; } enum comparitor = q{ a.line < b.line || (a.line == b.line && a.column < b.column) }; alias MessageSet = RedBlackTree!(Message, comparitor, true); +mixin template AnalyzerInfo(string checkName) +{ + enum string name = checkName; + + override protected string getName() + { + return name; + } +} + abstract class BaseAnalyzer : ASTVisitor { public: @@ -35,6 +47,11 @@ public: _messages = new MessageSet; } + protected string getName() + { + assert(0); + } + Message[] messages() { return _messages[].array; @@ -71,7 +88,7 @@ protected: void addErrorMessage(size_t line, size_t column, string key, string message) { - _messages.insert(Message(fileName, line, column, key, message)); + _messages.insert(Message(fileName, line, column, key, message, getName())); } /** diff --git a/src/dscanner/analysis/builtin_property_names.d b/src/dscanner/analysis/builtin_property_names.d index d7de74a..cadc220 100644 --- a/src/dscanner/analysis/builtin_property_names.d +++ b/src/dscanner/analysis/builtin_property_names.d @@ -31,6 +31,8 @@ final class BuiltinPropertyNameCheck : BaseAnalyzer { alias visit = BaseAnalyzer.visit; + mixin AnalyzerInfo!"builtin_property_names_check"; + this(string fileName, const(Scope)* sc, bool skipTests = false) { super(fileName, sc, skipTests); diff --git a/src/dscanner/analysis/comma_expression.d b/src/dscanner/analysis/comma_expression.d index 9ce4589..45c7d68 100644 --- a/src/dscanner/analysis/comma_expression.d +++ b/src/dscanner/analysis/comma_expression.d @@ -17,6 +17,8 @@ final class CommaExpressionCheck : BaseAnalyzer { alias visit = BaseAnalyzer.visit; + mixin AnalyzerInfo!"comma_expression_check"; + this(string fileName, const(Scope)* sc, bool skipTests = false) { super(fileName, sc, skipTests); diff --git a/src/dscanner/analysis/constructors.d b/src/dscanner/analysis/constructors.d index 7efbd4d..2a65e06 100644 --- a/src/dscanner/analysis/constructors.d +++ b/src/dscanner/analysis/constructors.d @@ -11,6 +11,8 @@ final class ConstructorCheck : BaseAnalyzer { alias visit = BaseAnalyzer.visit; + mixin AnalyzerInfo!"constructor_check"; + this(string fileName, const(Scope)* sc, bool skipTests = false) { super(fileName, sc, skipTests); diff --git a/src/dscanner/analysis/del.d b/src/dscanner/analysis/del.d index 6162470..99ca640 100644 --- a/src/dscanner/analysis/del.d +++ b/src/dscanner/analysis/del.d @@ -18,6 +18,8 @@ final class DeleteCheck : BaseAnalyzer { alias visit = BaseAnalyzer.visit; + mixin AnalyzerInfo!"delete_check"; + this(string fileName, const(Scope)* sc, bool skipTests = false) { super(fileName, sc, skipTests); diff --git a/src/dscanner/analysis/duplicate_attribute.d b/src/dscanner/analysis/duplicate_attribute.d index c1292fc..539da98 100644 --- a/src/dscanner/analysis/duplicate_attribute.d +++ b/src/dscanner/analysis/duplicate_attribute.d @@ -21,6 +21,8 @@ final class DuplicateAttributeCheck : BaseAnalyzer { alias visit = BaseAnalyzer.visit; + mixin AnalyzerInfo!"duplicate_attribute"; + this(string fileName, const(Scope)* sc, bool skipTests = false) { super(fileName, sc, skipTests); diff --git a/src/dscanner/analysis/enumarrayliteral.d b/src/dscanner/analysis/enumarrayliteral.d index 68e25ca..c52c726 100644 --- a/src/dscanner/analysis/enumarrayliteral.d +++ b/src/dscanner/analysis/enumarrayliteral.d @@ -19,6 +19,8 @@ final class EnumArrayLiteralCheck : BaseAnalyzer { alias visit = BaseAnalyzer.visit; + mixin AnalyzerInfo!"enum_array_literal_check"; + this(string fileName, const(Scope)* sc, bool skipTests = false) { super(fileName, sc, skipTests); diff --git a/src/dscanner/analysis/explicitly_annotated_unittests.d b/src/dscanner/analysis/explicitly_annotated_unittests.d index 87e830d..c5afc01 100644 --- a/src/dscanner/analysis/explicitly_annotated_unittests.d +++ b/src/dscanner/analysis/explicitly_annotated_unittests.d @@ -6,7 +6,7 @@ module dscanner.analysis.explicitly_annotated_unittests; import dparse.lexer; import dparse.ast; -import dscanner.analysis.base : BaseAnalyzer; +import dscanner.analysis.base; import std.stdio; @@ -17,6 +17,7 @@ final class ExplicitlyAnnotatedUnittestCheck : BaseAnalyzer { enum string KEY = "dscanner.style.explicitly_annotated_unittest"; enum string MESSAGE = "A unittest should be annotated with at least @safe or @system"; + mixin AnalyzerInfo!"explicitly_annotated_unittests"; /// this(string fileName, bool skipTests = false) diff --git a/src/dscanner/analysis/final_attribute.d b/src/dscanner/analysis/final_attribute.d index e899b27..8df2adb 100644 --- a/src/dscanner/analysis/final_attribute.d +++ b/src/dscanner/analysis/final_attribute.d @@ -66,6 +66,8 @@ public: alias visit = BaseAnalyzer.visit; + mixin AnalyzerInfo!"final_attribute_check"; + enum pushPopPrivate = q{ const bool wasPrivate = _private; _private = false; diff --git a/src/dscanner/analysis/fish.d b/src/dscanner/analysis/fish.d index d09f4e2..0417e48 100644 --- a/src/dscanner/analysis/fish.d +++ b/src/dscanner/analysis/fish.d @@ -20,6 +20,7 @@ final class FloatOperatorCheck : BaseAnalyzer alias visit = BaseAnalyzer.visit; enum string KEY = "dscanner.deprecated.floating_point_operators"; + mixin AnalyzerInfo!"float_operator_check"; this(string fileName, const(Scope)* sc, bool skipTests = false) { diff --git a/src/dscanner/analysis/function_attributes.d b/src/dscanner/analysis/function_attributes.d index 2c5ce9a..e6dc515 100644 --- a/src/dscanner/analysis/function_attributes.d +++ b/src/dscanner/analysis/function_attributes.d @@ -25,6 +25,8 @@ final class FunctionAttributeCheck : BaseAnalyzer { alias visit = BaseAnalyzer.visit; + mixin AnalyzerInfo!"function_attribute_check"; + this(string fileName, const(Scope)* sc, bool skipTests = false) { super(fileName, sc, skipTests); diff --git a/src/dscanner/analysis/has_public_example.d b/src/dscanner/analysis/has_public_example.d index cdbe6dc..0d82977 100644 --- a/src/dscanner/analysis/has_public_example.d +++ b/src/dscanner/analysis/has_public_example.d @@ -20,6 +20,8 @@ final class HasPublicExampleCheck : BaseAnalyzer { alias visit = BaseAnalyzer.visit; + mixin AnalyzerInfo!"has_public_example"; + this(string fileName, const(Scope)* sc, bool skipTests = false) { super(fileName, sc, skipTests); diff --git a/src/dscanner/analysis/if_constraints_indent.d b/src/dscanner/analysis/if_constraints_indent.d index 8391f7a..8517553 100644 --- a/src/dscanner/analysis/if_constraints_indent.d +++ b/src/dscanner/analysis/if_constraints_indent.d @@ -6,7 +6,7 @@ module dscanner.analysis.if_constraints_indent; import dparse.lexer; import dparse.ast; -import dscanner.analysis.base : BaseAnalyzer, Message; +import dscanner.analysis.base; import dsymbol.scope_ : Scope; import std.algorithm.iteration : filter; @@ -17,6 +17,8 @@ Checks whether all if constraints have the same indention as their declaration. */ final class IfConstraintsIndentCheck : BaseAnalyzer { + mixin AnalyzerInfo!"if_constraints_indent"; + /// this(string fileName, const(Token)[] tokens, bool skipTests = false) { diff --git a/src/dscanner/analysis/if_statements.d b/src/dscanner/analysis/if_statements.d index 7358d37..a70aec5 100644 --- a/src/dscanner/analysis/if_statements.d +++ b/src/dscanner/analysis/if_statements.d @@ -13,6 +13,8 @@ import dsymbol.scope_ : Scope; final class IfStatementCheck : BaseAnalyzer { alias visit = BaseAnalyzer.visit; + mixin AnalyzerInfo!"redundant_if_check"; + this(string fileName, const(Scope)* sc, bool skipTests = false) { super(fileName, sc, skipTests); diff --git a/src/dscanner/analysis/ifelsesame.d b/src/dscanner/analysis/ifelsesame.d index 0247816..e757b91 100644 --- a/src/dscanner/analysis/ifelsesame.d +++ b/src/dscanner/analysis/ifelsesame.d @@ -24,6 +24,8 @@ final class IfElseSameCheck : BaseAnalyzer { alias visit = BaseAnalyzer.visit; + mixin AnalyzerInfo!"if_else_same_check"; + this(string fileName, const(Scope)* sc, bool skipTests = false) { super(fileName, sc, skipTests); diff --git a/src/dscanner/analysis/imports_sortedness.d b/src/dscanner/analysis/imports_sortedness.d index 0d7cd3b..4f33fd4 100644 --- a/src/dscanner/analysis/imports_sortedness.d +++ b/src/dscanner/analysis/imports_sortedness.d @@ -4,7 +4,7 @@ module dscanner.analysis.imports_sortedness; -import dscanner.analysis.base : BaseAnalyzer; +import dscanner.analysis.base; import dparse.lexer; import dparse.ast; @@ -17,6 +17,7 @@ final class ImportSortednessCheck : BaseAnalyzer { enum string KEY = "dscanner.style.imports_sortedness"; enum string MESSAGE = "The imports are not sorted in alphabetical order"; + mixin AnalyzerInfo!"imports_sortedness"; /// this(string fileName, bool skipTests = false) diff --git a/src/dscanner/analysis/incorrect_infinite_range.d b/src/dscanner/analysis/incorrect_infinite_range.d index be52b10..1df6b3e 100644 --- a/src/dscanner/analysis/incorrect_infinite_range.d +++ b/src/dscanner/analysis/incorrect_infinite_range.d @@ -17,6 +17,8 @@ final class IncorrectInfiniteRangeCheck : BaseAnalyzer { alias visit = BaseAnalyzer.visit; + mixin AnalyzerInfo!"incorrect_infinite_range_check"; + /// this(string fileName, bool skipTests = false) { diff --git a/src/dscanner/analysis/label_var_same_name_check.d b/src/dscanner/analysis/label_var_same_name_check.d index 1e1f298..dc85bdb 100644 --- a/src/dscanner/analysis/label_var_same_name_check.d +++ b/src/dscanner/analysis/label_var_same_name_check.d @@ -15,6 +15,8 @@ import dscanner.analysis.helpers; */ final class LabelVarNameCheck : BaseAnalyzer { + mixin AnalyzerInfo!"label_var_same_name_check"; + this(string fileName, const(Scope)* sc, bool skipTests = false) { super(fileName, sc, skipTests); diff --git a/src/dscanner/analysis/lambda_return_check.d b/src/dscanner/analysis/lambda_return_check.d index b4b9189..e0b0b47 100644 --- a/src/dscanner/analysis/lambda_return_check.d +++ b/src/dscanner/analysis/lambda_return_check.d @@ -14,6 +14,8 @@ final class LambdaReturnCheck : BaseAnalyzer { alias visit = BaseAnalyzer.visit; + mixin AnalyzerInfo!"lambda_return_check"; + this(string fileName, bool skipTests = false) { super(fileName, null, skipTests); diff --git a/src/dscanner/analysis/length_subtraction.d b/src/dscanner/analysis/length_subtraction.d index 4c7a0d1..a788ec7 100644 --- a/src/dscanner/analysis/length_subtraction.d +++ b/src/dscanner/analysis/length_subtraction.d @@ -20,6 +20,8 @@ final class LengthSubtractionCheck : BaseAnalyzer { alias visit = BaseAnalyzer.visit; + mixin AnalyzerInfo!"length_subtraction_check"; + this(string fileName, const(Scope)* sc, bool skipTests = false) { super(fileName, sc, skipTests); diff --git a/src/dscanner/analysis/line_length.d b/src/dscanner/analysis/line_length.d index 97d3f07..f10c3d2 100644 --- a/src/dscanner/analysis/line_length.d +++ b/src/dscanner/analysis/line_length.d @@ -5,7 +5,7 @@ module dscanner.analysis.line_length; -import dscanner.analysis.base : BaseAnalyzer; +import dscanner.analysis.base; import dparse.ast; import dparse.lexer; @@ -17,6 +17,8 @@ import std.typecons : tuple, Tuple; */ final class LineLengthCheck : BaseAnalyzer { + mixin AnalyzerInfo!"long_line_check"; + /// this(string fileName, const(Token)[] tokens, bool skipTests = false) { diff --git a/src/dscanner/analysis/local_imports.d b/src/dscanner/analysis/local_imports.d index 0da9840..4489ce7 100644 --- a/src/dscanner/analysis/local_imports.d +++ b/src/dscanner/analysis/local_imports.d @@ -20,6 +20,8 @@ final class LocalImportCheck : BaseAnalyzer { alias visit = BaseAnalyzer.visit; + mixin AnalyzerInfo!"local_import_check"; + /** * Construct with the given file name. */ diff --git a/src/dscanner/analysis/logic_precedence.d b/src/dscanner/analysis/logic_precedence.d index 7e474d3..35d3633 100644 --- a/src/dscanner/analysis/logic_precedence.d +++ b/src/dscanner/analysis/logic_precedence.d @@ -24,6 +24,7 @@ final class LogicPrecedenceCheck : BaseAnalyzer alias visit = BaseAnalyzer.visit; enum string KEY = "dscanner.confusing.logical_precedence"; + mixin AnalyzerInfo!"logical_precedence_check"; this(string fileName, const(Scope)* sc, bool skipTests = false) { diff --git a/src/dscanner/analysis/mismatched_args.d b/src/dscanner/analysis/mismatched_args.d index 718b34d..a25ce0e 100644 --- a/src/dscanner/analysis/mismatched_args.d +++ b/src/dscanner/analysis/mismatched_args.d @@ -1,6 +1,6 @@ module dscanner.analysis.mismatched_args; -import dscanner.analysis.base : BaseAnalyzer; +import dscanner.analysis.base; import dscanner.utils : safeAccess; import dsymbol.scope_; import dsymbol.symbol; @@ -11,6 +11,8 @@ import dsymbol.builtin.names; /// Checks for mismatched argument and parameter names final class MismatchedArgumentCheck : BaseAnalyzer { + mixin AnalyzerInfo!"mismatched_args_check"; + /// this(string fileName, const(Scope)* sc, bool skipTests = false) { diff --git a/src/dscanner/analysis/numbers.d b/src/dscanner/analysis/numbers.d index 6e7b86b..8e8d55d 100644 --- a/src/dscanner/analysis/numbers.d +++ b/src/dscanner/analysis/numbers.d @@ -21,6 +21,8 @@ final class NumberStyleCheck : BaseAnalyzer public: alias visit = BaseAnalyzer.visit; + mixin AnalyzerInfo!"number_style_check"; + /** * Constructs the style checker with the given file name. */ diff --git a/src/dscanner/analysis/objectconst.d b/src/dscanner/analysis/objectconst.d index c089e76..7de6182 100644 --- a/src/dscanner/analysis/objectconst.d +++ b/src/dscanner/analysis/objectconst.d @@ -21,6 +21,8 @@ final class ObjectConstCheck : BaseAnalyzer { alias visit = BaseAnalyzer.visit; + mixin AnalyzerInfo!"object_const_check"; + /// this(string fileName, const(Scope)* sc, bool skipTests = false) { diff --git a/src/dscanner/analysis/opequals_without_tohash.d b/src/dscanner/analysis/opequals_without_tohash.d index 6517ccd..f3b854d 100644 --- a/src/dscanner/analysis/opequals_without_tohash.d +++ b/src/dscanner/analysis/opequals_without_tohash.d @@ -20,6 +20,8 @@ final class OpEqualsWithoutToHashCheck : BaseAnalyzer { alias visit = BaseAnalyzer.visit; + mixin AnalyzerInfo!"opequals_tohash_check"; + this(string fileName, const(Scope)* sc, bool skipTests = false) { super(fileName, sc, skipTests); diff --git a/src/dscanner/analysis/pokemon.d b/src/dscanner/analysis/pokemon.d index ef594ae..c3dbb11 100644 --- a/src/dscanner/analysis/pokemon.d +++ b/src/dscanner/analysis/pokemon.d @@ -27,6 +27,7 @@ final class PokemonExceptionCheck : BaseAnalyzer { enum MESSAGE = "Catching Error or Throwable is almost always a bad idea."; enum string KEY = "dscanner.suspicious.catch_em_all"; + mixin AnalyzerInfo!"exception_check"; alias visit = BaseAnalyzer.visit; diff --git a/src/dscanner/analysis/properly_documented_public_functions.d b/src/dscanner/analysis/properly_documented_public_functions.d index a711b85..70c2d2a 100644 --- a/src/dscanner/analysis/properly_documented_public_functions.d +++ b/src/dscanner/analysis/properly_documented_public_functions.d @@ -7,7 +7,7 @@ module dscanner.analysis.properly_documented_public_functions; import dparse.lexer; import dparse.ast; import dparse.formatter : astFmt = format; -import dscanner.analysis.base : BaseAnalyzer; +import dscanner.analysis.base; import dscanner.utils : safeAccess; import std.format : format; @@ -38,6 +38,8 @@ final class ProperlyDocumentedPublicFunctions : BaseAnalyzer enum string MISSING_THROW_KEY = "dscanner.style.doc_missing_throw"; enum string MISSING_THROW_MESSAGE = "An instance of `%s` is thrown but not documented in the `Throws` section"; + mixin AnalyzerInfo!"properly_documented_public_functions"; + /// this(string fileName, bool skipTests = false) { diff --git a/src/dscanner/analysis/range.d b/src/dscanner/analysis/range.d index bfc5581..f7a6f65 100644 --- a/src/dscanner/analysis/range.d +++ b/src/dscanner/analysis/range.d @@ -20,6 +20,8 @@ final class BackwardsRangeCheck : BaseAnalyzer { alias visit = BaseAnalyzer.visit; + mixin AnalyzerInfo!"backwards_range_check"; + /// Key for this check in the report output enum string KEY = "dscanner.bugs.backwards_slices"; diff --git a/src/dscanner/analysis/redundant_attributes.d b/src/dscanner/analysis/redundant_attributes.d index d7bfab2..0b3a467 100644 --- a/src/dscanner/analysis/redundant_attributes.d +++ b/src/dscanner/analysis/redundant_attributes.d @@ -19,6 +19,8 @@ import std.range : empty, front, walkLength; */ final class RedundantAttributesCheck : BaseAnalyzer { + mixin AnalyzerInfo!"redundant_attributes_check"; + this(string fileName, const(Scope)* sc, bool skipTests = false) { super(fileName, sc, skipTests); diff --git a/src/dscanner/analysis/redundant_parens.d b/src/dscanner/analysis/redundant_parens.d index b2bf1bd..8f2c56f 100644 --- a/src/dscanner/analysis/redundant_parens.d +++ b/src/dscanner/analysis/redundant_parens.d @@ -17,6 +17,8 @@ final class RedundantParenCheck : BaseAnalyzer { alias visit = BaseAnalyzer.visit; + mixin AnalyzerInfo!"redundant_parens_check"; + /// this(string fileName, const(Scope)* sc, bool skipTests = false) { diff --git a/src/dscanner/analysis/redundant_storage_class.d b/src/dscanner/analysis/redundant_storage_class.d index af90b9c..b03a876 100644 --- a/src/dscanner/analysis/redundant_storage_class.d +++ b/src/dscanner/analysis/redundant_storage_class.d @@ -20,6 +20,7 @@ final class RedundantStorageClassCheck : BaseAnalyzer { alias visit = BaseAnalyzer.visit; enum string REDUNDANT_VARIABLE_ATTRIBUTES = "Variable declaration for `%s` has redundant attributes (%-(`%s`%|, %))."; + mixin AnalyzerInfo!"redundant_storage_classes"; this(string fileName, bool skipTests = false) { diff --git a/src/dscanner/analysis/run.d b/src/dscanner/analysis/run.d index 6f19b54..ba53ed6 100644 --- a/src/dscanner/analysis/run.d +++ b/src/dscanner/analysis/run.d @@ -95,41 +95,45 @@ private alias ASTAllocator = CAllocatorImpl!( immutable string defaultErrorFormat = "{filepath}({line}:{column})[{type}]: {message}"; -void messageFunctionFormat(string format, string fileName, size_t line, size_t column, string message, bool isError) +void messageFunctionFormat(string format, Message message, bool isError) { auto s = format; - s = s.replace("{filepath}", fileName); - s = s.replace("{line}", to!string(line)); - s = s.replace("{column}", to!string(column)); + s = s.replace("{filepath}", message.fileName); + s = s.replace("{line}", to!string(message.line)); + s = s.replace("{column}", to!string(message.column)); s = s.replace("{type}", isError ? "error" : "warn"); - s = s.replace("{message}", message); + s = s.replace("{message}", message.message); writefln("%s", s); } -void messageFunction(string fileName, size_t line, size_t column, string message, bool isError) +void messageFunction(Message message, bool isError) { - messageFunctionFormat(defaultErrorFormat, fileName, line, column, message, isError); + messageFunctionFormat(defaultErrorFormat, message, isError); } void messageFunctionJSON(string fileName, size_t line, size_t column, string message, bool) { - writeJSON("dscanner.syntax", fileName, line, column, message); + writeJSON(Message(fileName, line, column, "dscanner.syntax", message)); } -void writeJSON(string key, string fileName, size_t line, size_t column, string message) +void writeJSON(Message message) { if (!first) writeln(","); else first = false; writeln(" {"); - writeln(` "key": "`, key, `",`); - writeln(` "fileName": "`, fileName.replace("\\", "\\\\").replace(`"`, `\"`), `",`); - writeln(` "line": `, line, `,`); - writeln(` "column": `, column, `,`); - writeln(` "message": "`, message.replace("\\", "\\\\").replace(`"`, `\"`), `"`); + writeln(` "key": "`, message.key, `",`); + if (message.checkName !is null) + { + writeln(` "name": "`, message.checkName, `",`); + } + writeln(` "fileName": "`, message.fileName.replace("\\", "\\\\").replace(`"`, `\"`), `",`); + writeln(` "line": `, message.line, `,`); + writeln(` "column": `, message.column, `,`); + writeln(` "message": "`, message.message.replace("\\", "\\\\").replace(`"`, `\"`), `"`); write(" }"); } @@ -160,7 +164,7 @@ void generateReport(string[] fileNames, const StaticAnalysisConfig config, MessageSet results = analyze(fileName, m, config, moduleCache, tokens, true); foreach (result; results[]) { - writeJSON(result.key, result.fileName, result.line, result.column, result.message); + writeJSON(result); } } writeln(); @@ -206,7 +210,7 @@ bool analyze(string[] fileNames, const StaticAnalysisConfig config, string error foreach (result; results[]) { hasErrors = true; - messageFunctionFormat(errorFormat, result.fileName, result.line, result.column, result.message, false); + messageFunctionFormat(errorFormat, result, false); } } return hasErrors; @@ -219,7 +223,7 @@ const(Module) parseModule(string fileName, ubyte[] code, RollbackAllocator* p, import dscanner.stats : isLineOfCode; auto writeMessages = delegate(string fileName, size_t line, size_t column, string message, bool isError){ - return messageFunctionFormat(errorFormat, fileName, line, column, message, isError); + return messageFunctionFormat(errorFormat, Message(fileName, line, column, message), isError); }; LexerConfig config; @@ -239,8 +243,10 @@ The user can specify a comma-separated list of filters, everyone needs to start either a '+' (inclusion) or '-' (exclusion). If no includes are specified, all modules are included. */ -bool shouldRun(string a)(string moduleName, const ref StaticAnalysisConfig config) +bool shouldRun(check : BaseAnalyzer)(string moduleName, const ref StaticAnalysisConfig config) { + enum string a = check.name; + if (mixin("config." ~ a) == Check.disabled) return false; @@ -279,7 +285,7 @@ unittest config.asm_style_check = Check.enabled; // this is done automatically by inifiled config.filters.asm_style_check = filters.split(","); - return shouldRun!"asm_style_check"(moduleName, config); + return shouldRun!AsmStyleCheck(moduleName, config); } // test inclusion @@ -337,213 +343,210 @@ MessageSet analyze(string fileName, const Module m, const StaticAnalysisConfig a GC.disable; - with(analysisConfig) - if (moduleName.shouldRun!"asm_style_check"(analysisConfig)) + if (moduleName.shouldRun!AsmStyleCheck(analysisConfig)) checks ~= new AsmStyleCheck(fileName, moduleScope, - asm_style_check == Check.skipTests && !ut); + analysisConfig.asm_style_check == Check.skipTests && !ut); - if (moduleName.shouldRun!"backwards_range_check"(analysisConfig)) + if (moduleName.shouldRun!BackwardsRangeCheck(analysisConfig)) checks ~= new BackwardsRangeCheck(fileName, moduleScope, analysisConfig.backwards_range_check == Check.skipTests && !ut); - if (moduleName.shouldRun!"builtin_property_names_check"(analysisConfig)) + if (moduleName.shouldRun!BuiltinPropertyNameCheck(analysisConfig)) checks ~= new BuiltinPropertyNameCheck(fileName, moduleScope, analysisConfig.builtin_property_names_check == Check.skipTests && !ut); - if (moduleName.shouldRun!"comma_expression_check"(analysisConfig)) + if (moduleName.shouldRun!CommaExpressionCheck(analysisConfig)) checks ~= new CommaExpressionCheck(fileName, moduleScope, analysisConfig.comma_expression_check == Check.skipTests && !ut); - if (moduleName.shouldRun!"constructor_check"(analysisConfig)) + if (moduleName.shouldRun!ConstructorCheck(analysisConfig)) checks ~= new ConstructorCheck(fileName, moduleScope, analysisConfig.constructor_check == Check.skipTests && !ut); - if (moduleName.shouldRun!"could_be_immutable_check"(analysisConfig)) + if (moduleName.shouldRun!UnmodifiedFinder(analysisConfig)) checks ~= new UnmodifiedFinder(fileName, moduleScope, analysisConfig.could_be_immutable_check == Check.skipTests && !ut); - if (moduleName.shouldRun!"delete_check"(analysisConfig)) + if (moduleName.shouldRun!DeleteCheck(analysisConfig)) checks ~= new DeleteCheck(fileName, moduleScope, analysisConfig.delete_check == Check.skipTests && !ut); - if (moduleName.shouldRun!"duplicate_attribute"(analysisConfig)) + if (moduleName.shouldRun!DuplicateAttributeCheck(analysisConfig)) checks ~= new DuplicateAttributeCheck(fileName, moduleScope, analysisConfig.duplicate_attribute == Check.skipTests && !ut); - if (moduleName.shouldRun!"enum_array_literal_check"(analysisConfig)) + if (moduleName.shouldRun!EnumArrayLiteralCheck(analysisConfig)) checks ~= new EnumArrayLiteralCheck(fileName, moduleScope, analysisConfig.enum_array_literal_check == Check.skipTests && !ut); - if (moduleName.shouldRun!"exception_check"(analysisConfig)) + if (moduleName.shouldRun!PokemonExceptionCheck(analysisConfig)) checks ~= new PokemonExceptionCheck(fileName, moduleScope, analysisConfig.exception_check == Check.skipTests && !ut); - if (moduleName.shouldRun!"float_operator_check"(analysisConfig)) + if (moduleName.shouldRun!FloatOperatorCheck(analysisConfig)) checks ~= new FloatOperatorCheck(fileName, moduleScope, analysisConfig.float_operator_check == Check.skipTests && !ut); - if (moduleName.shouldRun!"function_attribute_check"(analysisConfig)) + if (moduleName.shouldRun!FunctionAttributeCheck(analysisConfig)) checks ~= new FunctionAttributeCheck(fileName, moduleScope, analysisConfig.function_attribute_check == Check.skipTests && !ut); - if (moduleName.shouldRun!"if_else_same_check"(analysisConfig)) + if (moduleName.shouldRun!IfElseSameCheck(analysisConfig)) checks ~= new IfElseSameCheck(fileName, moduleScope, analysisConfig.if_else_same_check == Check.skipTests&& !ut); - if (moduleName.shouldRun!"label_var_same_name_check"(analysisConfig)) + if (moduleName.shouldRun!LabelVarNameCheck(analysisConfig)) checks ~= new LabelVarNameCheck(fileName, moduleScope, analysisConfig.label_var_same_name_check == Check.skipTests && !ut); - if (moduleName.shouldRun!"length_subtraction_check"(analysisConfig)) + if (moduleName.shouldRun!LengthSubtractionCheck(analysisConfig)) checks ~= new LengthSubtractionCheck(fileName, moduleScope, analysisConfig.length_subtraction_check == Check.skipTests && !ut); - if (moduleName.shouldRun!"local_import_check"(analysisConfig)) + if (moduleName.shouldRun!LocalImportCheck(analysisConfig)) checks ~= new LocalImportCheck(fileName, moduleScope, analysisConfig.local_import_check == Check.skipTests && !ut); - if (moduleName.shouldRun!"logical_precedence_check"(analysisConfig)) + if (moduleName.shouldRun!LogicPrecedenceCheck(analysisConfig)) checks ~= new LogicPrecedenceCheck(fileName, moduleScope, analysisConfig.logical_precedence_check == Check.skipTests && !ut); - if (moduleName.shouldRun!"mismatched_args_check"(analysisConfig)) + if (moduleName.shouldRun!MismatchedArgumentCheck(analysisConfig)) checks ~= new MismatchedArgumentCheck(fileName, moduleScope, analysisConfig.mismatched_args_check == Check.skipTests && !ut); - if (moduleName.shouldRun!"number_style_check"(analysisConfig)) + if (moduleName.shouldRun!NumberStyleCheck(analysisConfig)) checks ~= new NumberStyleCheck(fileName, moduleScope, analysisConfig.number_style_check == Check.skipTests && !ut); - if (moduleName.shouldRun!"object_const_check"(analysisConfig)) + if (moduleName.shouldRun!ObjectConstCheck(analysisConfig)) checks ~= new ObjectConstCheck(fileName, moduleScope, analysisConfig.object_const_check == Check.skipTests && !ut); - if (moduleName.shouldRun!"opequals_tohash_check"(analysisConfig)) + if (moduleName.shouldRun!OpEqualsWithoutToHashCheck(analysisConfig)) checks ~= new OpEqualsWithoutToHashCheck(fileName, moduleScope, analysisConfig.opequals_tohash_check == Check.skipTests && !ut); - if (moduleName.shouldRun!"redundant_parens_check"(analysisConfig)) + if (moduleName.shouldRun!RedundantParenCheck(analysisConfig)) checks ~= new RedundantParenCheck(fileName, moduleScope, analysisConfig.redundant_parens_check == Check.skipTests && !ut); - if (moduleName.shouldRun!"style_check"(analysisConfig)) + if (moduleName.shouldRun!StyleChecker(analysisConfig)) checks ~= new StyleChecker(fileName, moduleScope, analysisConfig.style_check == Check.skipTests && !ut); - if (moduleName.shouldRun!"undocumented_declaration_check"(analysisConfig)) + if (moduleName.shouldRun!UndocumentedDeclarationCheck(analysisConfig)) checks ~= new UndocumentedDeclarationCheck(fileName, moduleScope, analysisConfig.undocumented_declaration_check == Check.skipTests && !ut); - if (moduleName.shouldRun!"unused_label_check"(analysisConfig)) + if (moduleName.shouldRun!UnusedLabelCheck(analysisConfig)) checks ~= new UnusedLabelCheck(fileName, moduleScope, analysisConfig.unused_label_check == Check.skipTests && !ut); - if (moduleName.shouldRun!"unused_variable_check"(analysisConfig)) + if (moduleName.shouldRun!UnusedVariableCheck(analysisConfig)) checks ~= new UnusedVariableCheck(fileName, moduleScope, analysisConfig.unused_variable_check == Check.skipTests && !ut); - if (moduleName.shouldRun!"unused_parameter_check"(analysisConfig)) + if (moduleName.shouldRun!UnusedParameterCheck(analysisConfig)) checks ~= new UnusedParameterCheck(fileName, moduleScope, analysisConfig.unused_parameter_check == Check.skipTests && !ut); - if (moduleName.shouldRun!"long_line_check"(analysisConfig)) + if (moduleName.shouldRun!LineLengthCheck(analysisConfig)) checks ~= new LineLengthCheck(fileName, tokens, analysisConfig.long_line_check == Check.skipTests && !ut); - if (moduleName.shouldRun!"auto_ref_assignment_check"(analysisConfig)) + if (moduleName.shouldRun!AutoRefAssignmentCheck(analysisConfig)) checks ~= new AutoRefAssignmentCheck(fileName, analysisConfig.auto_ref_assignment_check == Check.skipTests && !ut); - if (moduleName.shouldRun!"incorrect_infinite_range_check"(analysisConfig)) + if (moduleName.shouldRun!IncorrectInfiniteRangeCheck(analysisConfig)) checks ~= new IncorrectInfiniteRangeCheck(fileName, analysisConfig.incorrect_infinite_range_check == Check.skipTests && !ut); - if (moduleName.shouldRun!"useless_assert_check"(analysisConfig)) + if (moduleName.shouldRun!UselessAssertCheck(analysisConfig)) checks ~= new UselessAssertCheck(fileName, analysisConfig.useless_assert_check == Check.skipTests && !ut); - if (moduleName.shouldRun!"alias_syntax_check"(analysisConfig)) + if (moduleName.shouldRun!AliasSyntaxCheck(analysisConfig)) checks ~= new AliasSyntaxCheck(fileName, analysisConfig.alias_syntax_check == Check.skipTests && !ut); - if (moduleName.shouldRun!"static_if_else_check"(analysisConfig)) + if (moduleName.shouldRun!StaticIfElse(analysisConfig)) checks ~= new StaticIfElse(fileName, analysisConfig.static_if_else_check == Check.skipTests && !ut); - if (moduleName.shouldRun!"lambda_return_check"(analysisConfig)) + if (moduleName.shouldRun!LambdaReturnCheck(analysisConfig)) checks ~= new LambdaReturnCheck(fileName, analysisConfig.lambda_return_check == Check.skipTests && !ut); - if (moduleName.shouldRun!"auto_function_check"(analysisConfig)) + if (moduleName.shouldRun!AutoFunctionChecker(analysisConfig)) checks ~= new AutoFunctionChecker(fileName, analysisConfig.auto_function_check == Check.skipTests && !ut); - if (moduleName.shouldRun!"imports_sortedness"(analysisConfig)) + if (moduleName.shouldRun!ImportSortednessCheck(analysisConfig)) checks ~= new ImportSortednessCheck(fileName, analysisConfig.imports_sortedness == Check.skipTests && !ut); - if (moduleName.shouldRun!"explicitly_annotated_unittests"(analysisConfig)) + if (moduleName.shouldRun!ExplicitlyAnnotatedUnittestCheck(analysisConfig)) checks ~= new ExplicitlyAnnotatedUnittestCheck(fileName, analysisConfig.explicitly_annotated_unittests == Check.skipTests && !ut); - if (moduleName.shouldRun!"properly_documented_public_functions"(analysisConfig)) + if (moduleName.shouldRun!ProperlyDocumentedPublicFunctions(analysisConfig)) checks ~= new ProperlyDocumentedPublicFunctions(fileName, analysisConfig.properly_documented_public_functions == Check.skipTests && !ut); - if (moduleName.shouldRun!"final_attribute_check"(analysisConfig)) + if (moduleName.shouldRun!FinalAttributeChecker(analysisConfig)) checks ~= new FinalAttributeChecker(fileName, analysisConfig.final_attribute_check == Check.skipTests && !ut); - if (moduleName.shouldRun!"vcall_in_ctor"(analysisConfig)) + if (moduleName.shouldRun!VcallCtorChecker(analysisConfig)) checks ~= new VcallCtorChecker(fileName, analysisConfig.vcall_in_ctor == Check.skipTests && !ut); - if (moduleName.shouldRun!"useless_initializer"(analysisConfig)) + if (moduleName.shouldRun!UselessInitializerChecker(analysisConfig)) checks ~= new UselessInitializerChecker(fileName, analysisConfig.useless_initializer == Check.skipTests && !ut); - if (moduleName.shouldRun!"allman_braces_check"(analysisConfig)) + if (moduleName.shouldRun!AllManCheck(analysisConfig)) checks ~= new AllManCheck(fileName, tokens, analysisConfig.allman_braces_check == Check.skipTests && !ut); - if (moduleName.shouldRun!"redundant_attributes_check"(analysisConfig)) + if (moduleName.shouldRun!RedundantAttributesCheck(analysisConfig)) checks ~= new RedundantAttributesCheck(fileName, moduleScope, analysisConfig.redundant_attributes_check == Check.skipTests && !ut); - if (moduleName.shouldRun!"has_public_example"(analysisConfig)) + if (moduleName.shouldRun!HasPublicExampleCheck(analysisConfig)) checks ~= new HasPublicExampleCheck(fileName, moduleScope, analysisConfig.has_public_example == Check.skipTests && !ut); - if (moduleName.shouldRun!"assert_without_msg"(analysisConfig)) + if (moduleName.shouldRun!AssertWithoutMessageCheck(analysisConfig)) checks ~= new AssertWithoutMessageCheck(fileName, moduleScope, analysisConfig.assert_without_msg == Check.skipTests && !ut); - if (moduleName.shouldRun!"if_constraints_indent"(analysisConfig)) + if (moduleName.shouldRun!IfConstraintsIndentCheck(analysisConfig)) checks ~= new IfConstraintsIndentCheck(fileName, tokens, analysisConfig.if_constraints_indent == Check.skipTests && !ut); - if (moduleName.shouldRun!"trust_too_much"(analysisConfig)) + if (moduleName.shouldRun!TrustTooMuchCheck(analysisConfig)) checks ~= new TrustTooMuchCheck(fileName, analysisConfig.trust_too_much == Check.skipTests && !ut); - if (moduleName.shouldRun!"redundant_storage_classes"(analysisConfig)) + if (moduleName.shouldRun!RedundantStorageClassCheck(analysisConfig)) checks ~= new RedundantStorageClassCheck(fileName, analysisConfig.redundant_storage_classes == Check.skipTests && !ut); version (none) - if (moduleName.shouldRun!"redundant_if_check"(analysisConfig)) + if (moduleName.shouldRun!IfStatementCheck(analysisConfig)) checks ~= new IfStatementCheck(fileName, moduleScope, analysisConfig.redundant_if_check == Check.skipTests && !ut); + MessageSet set = new MessageSet; foreach (check; checks) { check.visit(m); - } - - MessageSet set = new MessageSet; - foreach (check; checks) foreach (message; check.messages) set.insert(message); + } GC.enable; diff --git a/src/dscanner/analysis/static_if_else.d b/src/dscanner/analysis/static_if_else.d index df7db9d..17966da 100644 --- a/src/dscanner/analysis/static_if_else.d +++ b/src/dscanner/analysis/static_if_else.d @@ -26,6 +26,8 @@ final class StaticIfElse : BaseAnalyzer { alias visit = BaseAnalyzer.visit; + mixin AnalyzerInfo!"static_if_else_check"; + this(string fileName, bool skipTests = false) { super(fileName, null, skipTests); diff --git a/src/dscanner/analysis/style.d b/src/dscanner/analysis/style.d index 5a948a0..96de04b 100644 --- a/src/dscanner/analysis/style.d +++ b/src/dscanner/analysis/style.d @@ -24,6 +24,7 @@ final class StyleChecker : BaseAnalyzer enum string aggregateNameRegex = `^\p{Lu}[\w\d]*$`; enum string moduleNameRegex = `^[\p{Ll}_\d]+$`; enum string KEY = "dscanner.style.phobos_naming_convention"; + mixin AnalyzerInfo!"style_check"; this(string fileName, const(Scope)* sc, bool skipTests = false) { diff --git a/src/dscanner/analysis/trust_too_much.d b/src/dscanner/analysis/trust_too_much.d index ee3850b..f9eddf4 100644 --- a/src/dscanner/analysis/trust_too_much.d +++ b/src/dscanner/analysis/trust_too_much.d @@ -28,6 +28,8 @@ public: alias visit = BaseAnalyzer.visit; + mixin AnalyzerInfo!"trust_too_much"; + /// this(string fileName, bool skipTests = false) { diff --git a/src/dscanner/analysis/undocumented.d b/src/dscanner/analysis/undocumented.d index 439c237..46e3f76 100644 --- a/src/dscanner/analysis/undocumented.d +++ b/src/dscanner/analysis/undocumented.d @@ -21,6 +21,8 @@ final class UndocumentedDeclarationCheck : BaseAnalyzer { alias visit = BaseAnalyzer.visit; + mixin AnalyzerInfo!"undocumented_declaration_check"; + this(string fileName, const(Scope)* sc, bool skipTests = false) { super(fileName, sc, skipTests); diff --git a/src/dscanner/analysis/unmodified.d b/src/dscanner/analysis/unmodified.d index f73c173..7bd9ef3 100644 --- a/src/dscanner/analysis/unmodified.d +++ b/src/dscanner/analysis/unmodified.d @@ -18,6 +18,8 @@ final class UnmodifiedFinder : BaseAnalyzer { alias visit = BaseAnalyzer.visit; + mixin AnalyzerInfo!"could_be_immutable_check"; + /// this(string fileName, const(Scope)* sc, bool skipTests = false) { diff --git a/src/dscanner/analysis/unused_label.d b/src/dscanner/analysis/unused_label.d index 86e961f..ed02880 100644 --- a/src/dscanner/analysis/unused_label.d +++ b/src/dscanner/analysis/unused_label.d @@ -18,6 +18,8 @@ final class UnusedLabelCheck : BaseAnalyzer { alias visit = BaseAnalyzer.visit; + mixin AnalyzerInfo!"unused_label_check"; + /// this(string fileName, const(Scope)* sc, bool skipTests = false) { diff --git a/src/dscanner/analysis/unused_parameter.d b/src/dscanner/analysis/unused_parameter.d index 01f3b29..b8454d7 100644 --- a/src/dscanner/analysis/unused_parameter.d +++ b/src/dscanner/analysis/unused_parameter.d @@ -6,6 +6,7 @@ module dscanner.analysis.unused_parameter; import dparse.ast; import dparse.lexer; +import dscanner.analysis.base; import dscanner.analysis.unused; import dsymbol.scope_ : Scope; @@ -16,6 +17,8 @@ final class UnusedParameterCheck : UnusedIdentifierCheck { alias visit = UnusedIdentifierCheck.visit; + mixin AnalyzerInfo!"unused_parameter_check"; + /** * Params: * fileName = the name of the file being analyzed diff --git a/src/dscanner/analysis/unused_variable.d b/src/dscanner/analysis/unused_variable.d index 8b03cb1..782e9df 100644 --- a/src/dscanner/analysis/unused_variable.d +++ b/src/dscanner/analysis/unused_variable.d @@ -5,6 +5,7 @@ module dscanner.analysis.unused_variable; import dparse.ast; +import dscanner.analysis.base; import dscanner.analysis.unused; import dsymbol.scope_ : Scope; import std.algorithm.iteration : map; @@ -16,6 +17,8 @@ final class UnusedVariableCheck : UnusedIdentifierCheck { alias visit = UnusedIdentifierCheck.visit; + mixin AnalyzerInfo!"unused_variable_check"; + /** * Params: * fileName = the name of the file being analyzed diff --git a/src/dscanner/analysis/useless_assert.d b/src/dscanner/analysis/useless_assert.d index 2339f9c..0b75ff2 100644 --- a/src/dscanner/analysis/useless_assert.d +++ b/src/dscanner/analysis/useless_assert.d @@ -27,6 +27,8 @@ final class UselessAssertCheck : BaseAnalyzer { alias visit = BaseAnalyzer.visit; + mixin AnalyzerInfo!"useless_assert_check"; + /// this(string fileName, bool skipTests = false) { diff --git a/src/dscanner/analysis/useless_initializer.d b/src/dscanner/analysis/useless_initializer.d index f3f2af1..2dc5394 100644 --- a/src/dscanner/analysis/useless_initializer.d +++ b/src/dscanner/analysis/useless_initializer.d @@ -29,6 +29,8 @@ final class UselessInitializerChecker : BaseAnalyzer { alias visit = BaseAnalyzer.visit; + mixin AnalyzerInfo!"useless_initializer"; + private: enum key = "dscanner.useless-initializer"; diff --git a/src/dscanner/analysis/vcall_in_ctor.d b/src/dscanner/analysis/vcall_in_ctor.d index b83859e..820b4de 100644 --- a/src/dscanner/analysis/vcall_in_ctor.d +++ b/src/dscanner/analysis/vcall_in_ctor.d @@ -20,6 +20,8 @@ final class VcallCtorChecker : BaseAnalyzer { alias visit = BaseAnalyzer.visit; + mixin AnalyzerInfo!"vcall_in_ctor"; + private: enum string KEY = "dscanner.vcall_ctor";