Merge remote-tracking branch 'upstream/master' into phobos

This commit is contained in:
Sebastian Wilzbach 2018-03-24 12:32:53 +01:00
commit b4ddbd95b7
68 changed files with 611 additions and 284 deletions

View File

@ -1,5 +1,5 @@
; Configure which static analysis checks are enabled
[analysis.config.StaticAnalysisConfig]
[dscanner.analysis.config.StaticAnalysisConfig]
; Check variable, class, struct, interface, union, and function names against t
; he Phobos style guide
style_check="disabled"

3
.gitignore vendored
View File

@ -15,8 +15,7 @@
.svn/
# D Scanner binaries
dscanner
dscanner.o
/bin
# Static analysis reports
dscanner-report.json

View File

@ -140,6 +140,7 @@ Note that the "--skipTests" option is the equivalent of changing each
* Redundant visibility attributes
* Public declarations without a documented unittest. By default disabled.
* Asserts without an explanatory message. By default disabled.
* Indentation of if constraints
#### Wishlist

View File

@ -17,8 +17,8 @@ set LIBDDOC=
set STDXALLOCATOR=
set STDXALLOCATORBLOCKS=
for %%x in (src\*.d) do set CORE=!CORE! %%x
for %%x in (src\analysis\*.d) do set ANALYSIS=!ANALYSIS! %%x
for %%x in (src\dscanner\*.d) do set CORE=!CORE! %%x
for %%x in (src\dscanner\analysis\*.d) do set ANALYSIS=!ANALYSIS! %%x
for %%x in (libdparse\src\dparse\*.d) do set LIBDPARSE=!LIBDPARSE! %%x
for %%x in (libdparse\src\std\experimental\*.d) do set LIBDPARSE=!LIBDPARSE! %%x
for %%x in (libddoc\src\ddoc\*.d) do set LIBDDOC=!LIBDDOC! %%x

View File

@ -1,6 +0,0 @@
module analysis;
public import analysis.style;
public import analysis.enumarrayliteral;
public import analysis.pokemon;
public import analysis.base;

View File

@ -3,11 +3,11 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module analysis.alias_syntax_check;
module dscanner.analysis.alias_syntax_check;
import dparse.ast;
import dparse.lexer;
import analysis.base;
import dscanner.analysis.base;
/**
* Checks for uses of the old alias syntax.
@ -39,8 +39,8 @@ private:
unittest
{
import analysis.helpers : assertAnalyzerWarnings;
import analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import dscanner.analysis.helpers : assertAnalyzerWarnings;
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import std.stdio : stderr;
StaticAnalysisConfig sac = disabledConfig();

View File

@ -2,11 +2,11 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module analysis.allman;
module dscanner.analysis.allman;
import dparse.lexer;
import dparse.ast;
import analysis.base : BaseAnalyzer;
import dscanner.analysis.base : BaseAnalyzer;
import dsymbol.scope_ : Scope;
import std.algorithm;
@ -65,8 +65,8 @@ class AllManCheck : BaseAnalyzer
unittest
{
import analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import analysis.helpers : assertAnalyzerWarnings;
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import dscanner.analysis.helpers : assertAnalyzerWarnings;
import std.format : format;
import std.stdio : stderr;

View File

@ -3,13 +3,13 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module analysis.asm_style;
module dscanner.analysis.asm_style;
import std.stdio;
import dparse.ast;
import dparse.lexer;
import analysis.base;
import analysis.helpers;
import dscanner.analysis.base;
import dscanner.analysis.helpers;
import dsymbol.scope_ : Scope;
/**
@ -39,7 +39,7 @@ class AsmStyleCheck : BaseAnalyzer
unittest
{
import analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
StaticAnalysisConfig sac = disabledConfig();
sac.asm_style_check = Check.enabled;

View File

@ -2,9 +2,9 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module analysis.assert_without_msg;
module dscanner.analysis.assert_without_msg;
import analysis.base : BaseAnalyzer;
import dscanner.analysis.base : BaseAnalyzer;
import dsymbol.scope_ : Scope;
import dparse.lexer;
import dparse.ast;
@ -92,8 +92,8 @@ unittest
{
import std.stdio : stderr;
import std.format : format;
import analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import analysis.helpers : assertAnalyzerWarnings;
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import dscanner.analysis.helpers : assertAnalyzerWarnings;
StaticAnalysisConfig sac = disabledConfig();
sac.assert_without_msg = Check.enabled;

View File

@ -3,10 +3,10 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module analysis.auto_function;
module dscanner.analysis.auto_function;
import analysis.base;
import analysis.helpers;
import dscanner.analysis.base;
import dscanner.analysis.helpers;
import dparse.ast;
import dparse.lexer;
@ -157,8 +157,8 @@ unittest
{
import std.stdio : stderr;
import std.format : format;
import analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import analysis.helpers : assertAnalyzerWarnings;
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import dscanner.analysis.helpers : assertAnalyzerWarnings;
StaticAnalysisConfig sac = disabledConfig();
sac.auto_function_check = Check.enabled;

View File

@ -3,11 +3,11 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module analysis.auto_ref_assignment;
module dscanner.analysis.auto_ref_assignment;
import dparse.lexer;
import dparse.ast;
import analysis.base;
import dscanner.analysis.base;
/**
* Checks for assignment to auto-ref function parameters.
@ -113,8 +113,8 @@ unittest
{
import std.stdio : stderr;
import std.format : format;
import analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import analysis.helpers : assertAnalyzerWarnings;
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import dscanner.analysis.helpers : assertAnalyzerWarnings;
StaticAnalysisConfig sac = disabledConfig();
sac.auto_ref_assignment_check = Check.enabled;

View File

@ -1,4 +1,4 @@
module analysis.base;
module dscanner.analysis.base;
import std.container;
import std.string;

View File

@ -3,14 +3,14 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module analysis.builtin_property_names;
module dscanner.analysis.builtin_property_names;
import std.stdio;
import std.regex;
import dparse.ast;
import dparse.lexer;
import analysis.base;
import analysis.helpers;
import dscanner.analysis.base;
import dscanner.analysis.helpers;
import dsymbol.scope_;
import std.algorithm : map;
@ -102,7 +102,7 @@ private:
unittest
{
import analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
StaticAnalysisConfig sac = disabledConfig();
sac.builtin_property_names_check = Check.enabled;

View File

@ -3,11 +3,11 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module analysis.comma_expression;
module dscanner.analysis.comma_expression;
import dparse.ast;
import dparse.lexer;
import analysis.base;
import dscanner.analysis.base;
import dsymbol.scope_;
/**

View File

@ -3,7 +3,7 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module analysis.config;
module dscanner.analysis.config;
import inifiled;
@ -192,6 +192,9 @@ struct StaticAnalysisConfig
@INI("Check for asserts without an explanatory message")
string assert_without_msg = Check.disabled;
@INI("Check indent of if constraints")
string if_constraints_indent = Check.disabled;
@INI("Module-specific filters")
ModuleFilters filters;
}

View File

@ -1,10 +1,10 @@
module analysis.constructors;
module dscanner.analysis.constructors;
import dparse.ast;
import dparse.lexer;
import std.stdio;
import analysis.base;
import analysis.helpers;
import dscanner.analysis.base;
import dscanner.analysis.helpers;
import dsymbol.scope_ : Scope;
class ConstructorCheck : BaseAnalyzer
@ -90,7 +90,7 @@ private:
unittest
{
import analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
StaticAnalysisConfig sac = disabledConfig();
sac.constructor_check = Check.enabled;

View File

@ -3,12 +3,12 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module analysis.del;
module dscanner.analysis.del;
import std.stdio;
import dparse.ast;
import dparse.lexer;
import analysis.base;
import dscanner.analysis.base;
import dsymbol.scope_;
/**
@ -33,8 +33,8 @@ class DeleteCheck : BaseAnalyzer
unittest
{
import analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import analysis.helpers : assertAnalyzerWarnings;
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import dscanner.analysis.helpers : assertAnalyzerWarnings;
StaticAnalysisConfig sac = disabledConfig();
sac.delete_check = Check.enabled;

View File

@ -3,14 +3,14 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module analysis.duplicate_attribute;
module dscanner.analysis.duplicate_attribute;
import std.stdio;
import std.string;
import dparse.ast;
import dparse.lexer;
import analysis.base;
import analysis.helpers;
import dscanner.analysis.base;
import dscanner.analysis.helpers;
import dsymbol.scope_ : Scope;
/**
@ -153,7 +153,7 @@ class DuplicateAttributeCheck : BaseAnalyzer
unittest
{
import analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
StaticAnalysisConfig sac = disabledConfig();
sac.duplicate_attribute = Check.enabled;

View File

@ -3,11 +3,11 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module analysis.enumarrayliteral;
module dscanner.analysis.enumarrayliteral;
import dparse.ast;
import dparse.lexer;
import analysis.base;
import dscanner.analysis.base;
import std.algorithm : canFind, map;
import dsymbol.scope_ : Scope;

View File

@ -2,11 +2,11 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module analysis.explicitly_annotated_unittests;
module dscanner.analysis.explicitly_annotated_unittests;
import dparse.lexer;
import dparse.ast;
import analysis.base : BaseAnalyzer;
import dscanner.analysis.base : BaseAnalyzer;
import std.stdio;
@ -56,8 +56,8 @@ unittest
{
import std.stdio : stderr;
import std.format : format;
import analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import analysis.helpers : assertAnalyzerWarnings;
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import dscanner.analysis.helpers : assertAnalyzerWarnings;
StaticAnalysisConfig sac = disabledConfig();
sac.explicitly_annotated_unittests = Check.enabled;

View File

@ -3,10 +3,10 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module analysis.final_attribute;
module dscanner.analysis.final_attribute;
import analysis.base;
import analysis.helpers;
import dscanner.analysis.base;
import dscanner.analysis.helpers;
import dparse.ast;
import dparse.lexer;
@ -245,8 +245,8 @@ public:
@system unittest
{
import analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import analysis.helpers : assertAnalyzerWarnings;
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import dscanner.analysis.helpers : assertAnalyzerWarnings;
import std.stdio : stderr;
import std.format : format;

View File

@ -3,13 +3,13 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module analysis.fish;
module dscanner.analysis.fish;
import std.stdio;
import dparse.ast;
import dparse.lexer;
import analysis.base;
import analysis.helpers;
import dscanner.analysis.base;
import dscanner.analysis.helpers;
import dsymbol.scope_ : Scope;
/**
@ -42,7 +42,7 @@ class FloatOperatorCheck : BaseAnalyzer
unittest
{
import analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
StaticAnalysisConfig sac = disabledConfig();
sac.float_operator_check = Check.enabled;

View File

@ -3,9 +3,9 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module analysis.function_attributes;
module dscanner.analysis.function_attributes;
import analysis.base;
import dscanner.analysis.base;
import dparse.ast;
import dparse.lexer;
import std.stdio;

View File

@ -2,9 +2,9 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module analysis.has_public_example;
module dscanner.analysis.has_public_example;
import analysis.base;
import dscanner.analysis.base;
import dsymbol.scope_ : Scope;
import dparse.ast;
import dparse.lexer;
@ -166,8 +166,8 @@ unittest
{
import std.stdio : stderr;
import std.format : format;
import analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import analysis.helpers : assertAnalyzerWarnings;
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import dscanner.analysis.helpers : assertAnalyzerWarnings;
StaticAnalysisConfig sac = disabledConfig();
sac.has_public_example = Check.enabled;

View File

@ -3,7 +3,7 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module analysis.helpers;
module dscanner.analysis.helpers;
import core.exception : AssertError;
import std.string;
@ -13,9 +13,9 @@ import std.stdio;
import dparse.ast;
import dparse.rollback_allocator;
import dsymbol.modulecache : ModuleCache;
import analysis.config;
import analysis.run;
import analysis.base;
import dscanner.analysis.config;
import dscanner.analysis.run;
import dscanner.analysis.base;
import stdx.allocator.mallocator;
import stdx.allocator;
@ -48,13 +48,13 @@ S after(S)(S value, S separator) if (isSomeString!S)
void assertAnalyzerWarnings(string code, const StaticAnalysisConfig config,
string file = __FILE__, size_t line = __LINE__)
{
import analysis.run : parseModule;
import dscanner.analysis.run : parseModule;
import dparse.lexer : StringCache, Token;
StringCache cache = StringCache(StringCache.defaultBucketCount);
RollbackAllocator r;
const(Token)[] tokens;
const(Module) m = parseModule(file, cast(ubyte[]) code, &r, cache, false, tokens);
const(Module) m = parseModule(file, cast(ubyte[]) code, &r, defaultErrorFormat, cache, false, tokens);
auto moduleCache = ModuleCache(new CAllocatorImpl!Mallocator);

View File

@ -0,0 +1,233 @@
// 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)
module dscanner.analysis.if_constraints_indent;
import dparse.lexer;
import dparse.ast;
import dscanner.analysis.base : BaseAnalyzer, Message;
import dsymbol.scope_ : Scope;
import std.algorithm.iteration : filter;
import std.range;
/**
Checks whether all if constraints have the same indention as their declaration.
*/
class IfConstraintsIndentCheck : BaseAnalyzer
{
///
this(string fileName, const(Token)[] tokens, bool skipTests = false)
{
super(fileName, null, skipTests);
// libdparse columns start at 1
foreach (t; tokens)
{
while (firstSymbolAtLine.length < t.line - 1)
firstSymbolAtLine ~= Pos(1);
if (firstSymbolAtLine.length < t.line)
firstSymbolAtLine ~= Pos(t.column, t.type == tok!"if");
}
}
override void visit(const FunctionDeclaration decl)
{
if (decl.constraint !is null)
checkConstraintSpace(decl.constraint, decl.name);
}
override void visit(const InterfaceDeclaration decl)
{
if (decl.constraint !is null)
checkConstraintSpace(decl.constraint, decl.name);
}
override void visit(const ClassDeclaration decl)
{
if (decl.constraint !is null)
checkConstraintSpace(decl.constraint, decl.name);
}
override void visit(const TemplateDeclaration decl)
{
if (decl.constraint !is null)
checkConstraintSpace(decl.constraint, decl.name);
}
override void visit(const UnionDeclaration decl)
{
if (decl.constraint !is null)
checkConstraintSpace(decl.constraint, decl.name);
}
override void visit(const StructDeclaration decl)
{
if (decl.constraint !is null)
checkConstraintSpace(decl.constraint, decl.name);
}
override void visit(const Constructor decl)
{
if (decl.constraint !is null)
checkConstraintSpace(decl.constraint, decl.line);
}
alias visit = ASTVisitor.visit;
private:
enum string KEY = "dscanner.style.if_constraints_indent";
enum string MESSAGE = "If constraints should have the same indentation as the function";
Pos[] firstSymbolAtLine;
static struct Pos
{
size_t column;
bool isIf;
}
/**
Check indentation of constraints
*/
void checkConstraintSpace(const Constraint constraint, const Token token)
{
checkConstraintSpace(constraint, token.line);
}
void checkConstraintSpace(const Constraint constraint, size_t line)
{
// dscanner lines start at 1
auto pDecl = firstSymbolAtLine[line - 1];
// search for constraint if (might not be on the same line as the expression)
auto r = firstSymbolAtLine[line .. constraint.expression.line].retro.filter!(s => s.isIf);
// no hit = constraint is on the same line
if (r.empty)
addErrorMessage(constraint.expression.line, constraint.expression.column, KEY, MESSAGE);
else if (pDecl.column != r.front.column)
addErrorMessage(constraint.expression.line, constraint.expression.column, KEY, MESSAGE);
}
}
unittest
{
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import dscanner.analysis.helpers : assertAnalyzerWarnings;
import std.format : format;
import std.stdio : stderr;
StaticAnalysisConfig sac = disabledConfig();
sac.if_constraints_indent = Check.enabled;
assertAnalyzerWarnings(q{
void foo(R)(R r)
if (R == int)
{}
void foo(R)(R r)
if (R == int) // [warn]: %s
{}
}c.format(
IfConstraintsIndentCheck.MESSAGE,
), sac);
assertAnalyzerWarnings(q{
void foo(R)(R r)
if (R == int)
{}
void foo(R)(R r)
if (R == int) // [warn]: %s
{}
void foo(R)(R r)
if (R == int) // [warn]: %s
{}
}c.format(
IfConstraintsIndentCheck.MESSAGE,
IfConstraintsIndentCheck.MESSAGE,
), sac);
assertAnalyzerWarnings(q{
struct Foo(R)
if (R == int)
{}
struct Foo(R)
if (R == int) // [warn]: %s
{}
struct Foo(R)
if (R == int) // [warn]: %s
{}
}c.format(
IfConstraintsIndentCheck.MESSAGE,
IfConstraintsIndentCheck.MESSAGE,
), sac);
// test example from Phobos
assertAnalyzerWarnings(q{
Num abs(Num)(Num x) @safe pure nothrow
if (is(typeof(Num.init >= 0)) && is(typeof(-Num.init)) &&
!(is(Num* : const(ifloat*)) || is(Num* : const(idouble*))
|| is(Num* : const(ireal*))))
{
static if (isFloatingPoint!(Num))
return fabs(x);
else
return x >= 0 ? x : -x;
}
}, sac);
// weird constraint formatting
assertAnalyzerWarnings(q{
struct Foo(R)
if
(R == int)
{}
struct Foo(R)
if
(R == int)
{}
struct Foo(R)
if
(R == int) // [warn]: %s
{}
struct Foo(R)
if (
R == int)
{}
struct Foo(R)
if (
R == int
)
{}
struct Foo(R)
if (
R == int // [warn]: %s
) {}
}c.format(
IfConstraintsIndentCheck.MESSAGE,
IfConstraintsIndentCheck.MESSAGE,
), sac);
// constraint on the same line
assertAnalyzerWarnings(q{
struct CRC(uint N, ulong P) if (N == 32 || N == 64) // [warn]: %s
{}
}c.format(
IfConstraintsIndentCheck.MESSAGE,
), sac);
stderr.writeln("Unittest for IfConstraintsIndentCheck passed.");
}

View File

@ -2,12 +2,12 @@
// 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)
module analysis.if_statements;
module dscanner.analysis.if_statements;
import dparse.ast;
import dparse.lexer;
import dparse.formatter;
import analysis.base;
import dscanner.analysis.base;
import dsymbol.scope_ : Scope;
class IfStatementCheck : BaseAnalyzer

View File

@ -3,13 +3,13 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module analysis.ifelsesame;
module dscanner.analysis.ifelsesame;
import std.stdio;
import dparse.ast;
import dparse.lexer;
import analysis.base;
import analysis.helpers;
import dscanner.analysis.base;
import dscanner.analysis.helpers;
import dsymbol.scope_ : Scope;
/**
@ -76,7 +76,7 @@ class IfElseSameCheck : BaseAnalyzer
unittest
{
import analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
StaticAnalysisConfig sac = disabledConfig();
sac.if_else_same_check = Check.enabled;

View File

@ -2,9 +2,9 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module analysis.imports_sortedness;
module dscanner.analysis.imports_sortedness;
import analysis.base : BaseAnalyzer;
import dscanner.analysis.base : BaseAnalyzer;
import dparse.lexer;
import dparse.ast;
@ -99,8 +99,8 @@ unittest
{
import std.stdio : stderr;
import std.format : format;
import analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import analysis.helpers : assertAnalyzerWarnings;
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import dscanner.analysis.helpers : assertAnalyzerWarnings;
StaticAnalysisConfig sac = disabledConfig();
sac.imports_sortedness = Check.enabled;

View File

@ -3,10 +3,10 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module analysis.incorrect_infinite_range;
module dscanner.analysis.incorrect_infinite_range;
import analysis.base;
import analysis.helpers;
import dscanner.analysis.base;
import dscanner.analysis.helpers;
import dparse.ast;
import dparse.lexer;
@ -89,7 +89,7 @@ private:
unittest
{
import std.stdio : stderr;
import analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import std.format : format;
StaticAnalysisConfig sac = disabledConfig();

View File

@ -2,13 +2,13 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module analysis.label_var_same_name_check;
module dscanner.analysis.label_var_same_name_check;
import dparse.ast;
import dparse.lexer;
import dsymbol.scope_ : Scope;
import analysis.base;
import analysis.helpers;
import dscanner.analysis.base;
import dscanner.analysis.helpers;
/**
* Checks for labels and variables that have the same name.
@ -167,7 +167,7 @@ private:
unittest
{
import analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import std.stdio : stderr;
StaticAnalysisConfig sac = disabledConfig();

View File

@ -3,11 +3,11 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module analysis.lambda_return_check;
module dscanner.analysis.lambda_return_check;
import dparse.ast;
import dparse.lexer;
import analysis.base;
import dscanner.analysis.base;
class LambdaReturnCheck : BaseAnalyzer
{
@ -47,8 +47,8 @@ private:
version(Windows) {/*because of newline in code*/} else
unittest
{
import analysis.helpers : assertAnalyzerWarnings;
import analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import dscanner.analysis.helpers : assertAnalyzerWarnings;
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import std.stdio : stderr;
StaticAnalysisConfig sac = disabledConfig();

View File

@ -3,14 +3,14 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module analysis.length_subtraction;
module dscanner.analysis.length_subtraction;
import std.stdio;
import dparse.ast;
import dparse.lexer;
import analysis.base;
import analysis.helpers;
import dscanner.analysis.base;
import dscanner.analysis.helpers;
import dsymbol.scope_;
/**
@ -58,7 +58,7 @@ class LengthSubtractionCheck : BaseAnalyzer
unittest
{
import analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
StaticAnalysisConfig sac = disabledConfig();
sac.length_subtraction_check = Check.enabled;

View File

@ -3,9 +3,9 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module analysis.line_length;
module dscanner.analysis.line_length;
import analysis.base : BaseAnalyzer;
import dscanner.analysis.base : BaseAnalyzer;
import dparse.ast;
import dparse.lexer;
@ -161,8 +161,8 @@ private:
@system unittest
{
import analysis.config : Check, StaticAnalysisConfig, disabledConfig;
import analysis.helpers : assertAnalyzerWarnings;
import dscanner.analysis.config : Check, StaticAnalysisConfig, disabledConfig;
import dscanner.analysis.helpers : assertAnalyzerWarnings;
import std.stdio : stderr;
StaticAnalysisConfig sac = disabledConfig();

View File

@ -3,13 +3,13 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module analysis.local_imports;
module dscanner.analysis.local_imports;
import std.stdio;
import dparse.ast;
import dparse.lexer;
import analysis.base;
import analysis.helpers;
import dscanner.analysis.base;
import dscanner.analysis.helpers;
import dsymbol.scope_;
/**
@ -84,7 +84,7 @@ private:
unittest
{
import analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
StaticAnalysisConfig sac = disabledConfig();
sac.local_import_check = Check.enabled;

View File

@ -3,13 +3,13 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module analysis.logic_precedence;
module dscanner.analysis.logic_precedence;
import std.stdio;
import dparse.ast;
import dparse.lexer;
import analysis.base;
import analysis.helpers;
import dscanner.analysis.base;
import dscanner.analysis.helpers;
import dsymbol.scope_;
/**
@ -48,7 +48,7 @@ class LogicPrecedenceCheck : BaseAnalyzer
unittest
{
import analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
StaticAnalysisConfig sac = disabledConfig();
sac.logical_precedence_check = Check.enabled;

View File

@ -1,6 +1,6 @@
module analysis.mismatched_args;
module dscanner.analysis.mismatched_args;
import analysis.base : BaseAnalyzer;
import dscanner.analysis.base : BaseAnalyzer;
import dsymbol.scope_;
import dsymbol.symbol;
import dparse.ast;

View File

@ -3,14 +3,14 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module analysis.numbers;
module dscanner.analysis.numbers;
import std.stdio;
import std.regex;
import dparse.ast;
import dparse.lexer;
import analysis.base;
import analysis.helpers;
import dscanner.analysis.base;
import dscanner.analysis.helpers;
import dsymbol.scope_ : Scope;
/**
@ -49,7 +49,7 @@ private:
unittest
{
import analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
StaticAnalysisConfig sac = disabledConfig();
sac.number_style_check = Check.enabled;

View File

@ -3,14 +3,14 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module analysis.objectconst;
module dscanner.analysis.objectconst;
import std.stdio;
import std.regex;
import dparse.ast;
import dparse.lexer;
import analysis.base;
import analysis.helpers;
import dscanner.analysis.base;
import dscanner.analysis.helpers;
import dsymbol.scope_ : Scope;
/**
@ -89,7 +89,7 @@ class ObjectConstCheck : BaseAnalyzer
unittest
{
import analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
StaticAnalysisConfig sac = disabledConfig();
sac.object_const_check = Check.enabled;

View File

@ -3,13 +3,13 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module analysis.opequals_without_tohash;
module dscanner.analysis.opequals_without_tohash;
import std.stdio;
import dparse.ast;
import dparse.lexer;
import analysis.base;
import analysis.helpers;
import dscanner.analysis.base;
import dscanner.analysis.helpers;
import dsymbol.scope_ : Scope;
/**
@ -89,7 +89,7 @@ class OpEqualsWithoutToHashCheck : BaseAnalyzer
unittest
{
import analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
StaticAnalysisConfig sac = disabledConfig();
sac.opequals_tohash_check = Check.enabled;

View File

@ -0,0 +1,6 @@
module dscanner.analysis;
public import dscanner.analysis.style;
public import dscanner.analysis.enumarrayliteral;
public import dscanner.analysis.pokemon;
public import dscanner.analysis.base;

View File

@ -3,13 +3,13 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module analysis.pokemon;
module dscanner.analysis.pokemon;
import std.stdio;
import dparse.ast;
import dparse.lexer;
import analysis.base;
import analysis.helpers;
import dscanner.analysis.base;
import dscanner.analysis.helpers;
import dsymbol.scope_ : Scope;
/**
@ -84,7 +84,7 @@ class PokemonExceptionCheck : BaseAnalyzer
unittest
{
import analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
StaticAnalysisConfig sac = disabledConfig();
sac.exception_check = Check.enabled;

View File

@ -2,11 +2,11 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module analysis.properly_documented_public_functions;
module dscanner.analysis.properly_documented_public_functions;
import dparse.lexer;
import dparse.ast;
import analysis.base : BaseAnalyzer;
import dscanner.analysis.base : BaseAnalyzer;
import std.format : format;
import std.range.primitives;
@ -286,8 +286,8 @@ version(unittest)
{
import std.stdio : stderr;
import std.format : format;
import analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import analysis.helpers : assertAnalyzerWarnings;
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import dscanner.analysis.helpers : assertAnalyzerWarnings;
}
// missing params

View File

@ -3,13 +3,13 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module analysis.range;
module dscanner.analysis.range;
import std.stdio;
import dparse.ast;
import dparse.lexer;
import analysis.base;
import analysis.helpers;
import dscanner.analysis.base;
import dscanner.analysis.helpers;
import dsymbol.scope_ : Scope;
/**
@ -158,7 +158,7 @@ private:
unittest
{
import analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
StaticAnalysisConfig sac = disabledConfig();
sac.backwards_range_check = Check.enabled;

View File

@ -2,13 +2,13 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module analysis.redundant_attributes;
module dscanner.analysis.redundant_attributes;
import dparse.ast;
import dparse.lexer;
import dsymbol.scope_ : Scope;
import analysis.base;
import analysis.helpers;
import dscanner.analysis.base;
import dscanner.analysis.helpers;
import std.algorithm;
import std.conv : to, text;
@ -178,7 +178,7 @@ private:
version(unittest)
{
import analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import std.stdio : stderr;
}

View File

@ -3,11 +3,11 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module analysis.redundant_parens;
module dscanner.analysis.redundant_parens;
import dparse.ast;
import dparse.lexer;
import analysis.base;
import dscanner.analysis.base;
import dsymbol.scope_ : Scope;
/**

View File

@ -3,7 +3,7 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module analysis.run;
module dscanner.analysis.run;
import std.stdio;
import std.array;
@ -23,54 +23,55 @@ import stdx.allocator.mallocator : Mallocator;
import stdx.allocator.building_blocks.region : Region;
import stdx.allocator.building_blocks.allocator_list : AllocatorList;
import analysis.config;
import analysis.base;
import analysis.style;
import analysis.enumarrayliteral;
import analysis.pokemon;
import analysis.del;
import analysis.fish;
import analysis.numbers;
import analysis.objectconst;
import analysis.range;
import analysis.ifelsesame;
import analysis.constructors;
import analysis.unused;
import analysis.unused_label;
import analysis.duplicate_attribute;
import analysis.opequals_without_tohash;
import analysis.length_subtraction;
import analysis.builtin_property_names;
import analysis.asm_style;
import analysis.logic_precedence;
import analysis.stats_collector;
import analysis.undocumented;
import analysis.comma_expression;
import analysis.function_attributes;
import analysis.local_imports;
import analysis.unmodified;
import analysis.if_statements;
import analysis.redundant_parens;
import analysis.mismatched_args;
import analysis.label_var_same_name_check;
import analysis.line_length;
import analysis.auto_ref_assignment;
import analysis.incorrect_infinite_range;
import analysis.useless_assert;
import analysis.alias_syntax_check;
import analysis.static_if_else;
import analysis.lambda_return_check;
import analysis.auto_function;
import analysis.imports_sortedness;
import analysis.explicitly_annotated_unittests;
import analysis.properly_documented_public_functions;
import analysis.final_attribute;
import analysis.vcall_in_ctor;
import analysis.useless_initializer;
import analysis.allman;
import analysis.redundant_attributes;
import analysis.has_public_example;
import analysis.assert_without_msg;
import dscanner.analysis.config;
import dscanner.analysis.base;
import dscanner.analysis.style;
import dscanner.analysis.enumarrayliteral;
import dscanner.analysis.pokemon;
import dscanner.analysis.del;
import dscanner.analysis.fish;
import dscanner.analysis.numbers;
import dscanner.analysis.objectconst;
import dscanner.analysis.range;
import dscanner.analysis.ifelsesame;
import dscanner.analysis.constructors;
import dscanner.analysis.unused;
import dscanner.analysis.unused_label;
import dscanner.analysis.duplicate_attribute;
import dscanner.analysis.opequals_without_tohash;
import dscanner.analysis.length_subtraction;
import dscanner.analysis.builtin_property_names;
import dscanner.analysis.asm_style;
import dscanner.analysis.logic_precedence;
import dscanner.analysis.stats_collector;
import dscanner.analysis.undocumented;
import dscanner.analysis.comma_expression;
import dscanner.analysis.function_attributes;
import dscanner.analysis.local_imports;
import dscanner.analysis.unmodified;
import dscanner.analysis.if_statements;
import dscanner.analysis.redundant_parens;
import dscanner.analysis.mismatched_args;
import dscanner.analysis.label_var_same_name_check;
import dscanner.analysis.line_length;
import dscanner.analysis.auto_ref_assignment;
import dscanner.analysis.incorrect_infinite_range;
import dscanner.analysis.useless_assert;
import dscanner.analysis.alias_syntax_check;
import dscanner.analysis.static_if_else;
import dscanner.analysis.lambda_return_check;
import dscanner.analysis.auto_function;
import dscanner.analysis.imports_sortedness;
import dscanner.analysis.explicitly_annotated_unittests;
import dscanner.analysis.properly_documented_public_functions;
import dscanner.analysis.final_attribute;
import dscanner.analysis.vcall_in_ctor;
import dscanner.analysis.useless_initializer;
import dscanner.analysis.allman;
import dscanner.analysis.redundant_attributes;
import dscanner.analysis.has_public_example;
import dscanner.analysis.assert_without_msg;
import dscanner.analysis.if_constraints_indent;
import dsymbol.string_interning : internString;
import dsymbol.scope_;
@ -80,16 +81,31 @@ import dsymbol.conversion.first;
import dsymbol.conversion.second;
import dsymbol.modulecache : ModuleCache;
import readers;
import dscanner.readers;
bool first = true;
private alias ASTAllocator = CAllocatorImpl!(
AllocatorList!(n => Region!Mallocator(1024 * 128), Mallocator));
immutable string defaultErrorFormat = "{filepath}({line}:{column})[{type}]: {message}";
void messageFunctionFormat(string format, string fileName, size_t line, size_t column, string 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("{type}", isError ? "error" : "warn");
s = s.replace("{message}", message);
writefln("%s", s);
}
void messageFunction(string fileName, size_t line, size_t column, string message, bool isError)
{
writefln("%s(%d:%d)[%s]: %s", fileName, line, column, isError ? "error" : "warn", message);
messageFunctionFormat(defaultErrorFormat, fileName, line, column, message, isError);
}
void messageFunctionJSON(string fileName, size_t line, size_t column, string message, bool)
@ -112,10 +128,10 @@ void writeJSON(string key, string fileName, size_t line, size_t column, string m
write(" }");
}
bool syntaxCheck(string[] fileNames, ref StringCache stringCache, ref ModuleCache moduleCache)
bool syntaxCheck(string[] fileNames, string errorFormat, ref StringCache stringCache, ref ModuleCache moduleCache)
{
StaticAnalysisConfig config = defaultStaticAnalysisConfig();
return analyze(fileNames, config, stringCache, moduleCache, false);
return analyze(fileNames, config, errorFormat, stringCache, moduleCache, false);
}
void generateReport(string[] fileNames, const StaticAnalysisConfig config,
@ -134,7 +150,7 @@ void generateReport(string[] fileNames, const StaticAnalysisConfig config,
continue;
RollbackAllocator r;
const(Token)[] tokens;
const Module m = parseModule(fileName, code, &r, cache, true, tokens, &lineOfCodeCount);
const Module m = parseModule(fileName, code, &r, defaultErrorFormat, cache, true, tokens, &lineOfCodeCount);
stats.visit(m);
MessageSet results = analyze(fileName, m, config, moduleCache, tokens, true);
foreach (result; results[])
@ -160,7 +176,7 @@ void generateReport(string[] fileNames, const StaticAnalysisConfig config,
*
* Returns: true if there were errors or if there were warnings and `staticAnalyze` was true.
*/
bool analyze(string[] fileNames, const StaticAnalysisConfig config,
bool analyze(string[] fileNames, const StaticAnalysisConfig config, string errorFormat,
ref StringCache cache, ref ModuleCache moduleCache, bool staticAnalyze = true)
{
bool hasErrors;
@ -174,7 +190,7 @@ bool analyze(string[] fileNames, const StaticAnalysisConfig config,
uint errorCount;
uint warningCount;
const(Token)[] tokens;
const Module m = parseModule(fileName, code, &r, cache, false, tokens,
const Module m = parseModule(fileName, code, &r, errorFormat, cache, false, tokens,
null, &errorCount, &warningCount);
assert(m);
if (errorCount > 0 || (staticAnalyze && warningCount > 0))
@ -185,18 +201,21 @@ bool analyze(string[] fileNames, const StaticAnalysisConfig config,
foreach (result; results[])
{
hasErrors = true;
writefln("%s(%d:%d)[warn]: %s", result.fileName, result.line,
result.column, result.message);
messageFunctionFormat(errorFormat, result.fileName, result.line, result.column, result.message, false);
}
}
return hasErrors;
}
const(Module) parseModule(string fileName, ubyte[] code, RollbackAllocator* p,
ref StringCache cache, bool report, ref const(Token)[] tokens,
string errorFormat, ref StringCache cache, bool report, ref const(Token)[] tokens,
ulong* linesOfCode = null, uint* errorCount = null, uint* warningCount = null)
{
import stats : isLineOfCode;
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);
};
LexerConfig config;
config.fileName = fileName;
@ -205,7 +224,7 @@ const(Module) parseModule(string fileName, ubyte[] code, RollbackAllocator* p,
if (linesOfCode !is null)
(*linesOfCode) += count!(a => isLineOfCode(a.type))(tokens);
return dparse.parser.parseModule(tokens, fileName, p,
report ? toDelegate(&messageFunctionJSON) : toDelegate(&messageFunction),
report ? toDelegate(&messageFunctionJSON) : writeMessages,
errorCount, warningCount);
}
@ -488,6 +507,10 @@ MessageSet analyze(string fileName, const Module m, const StaticAnalysisConfig a
checks ~= new AssertWithoutMessageCheck(fileName, moduleScope,
analysisConfig.assert_without_msg == Check.skipTests && !ut);
if (moduleName.shouldRun!"if_constraints_indent"(analysisConfig))
checks ~= new IfConstraintsIndentCheck(fileName, tokens,
analysisConfig.if_constraints_indent == Check.skipTests && !ut);
version (none)
if (moduleName.shouldRun!"redundant_if_check"(analysisConfig))
checks ~= new IfStatementCheck(fileName, moduleScope,

View File

@ -3,11 +3,11 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module analysis.static_if_else;
module dscanner.analysis.static_if_else;
import dparse.ast;
import dparse.lexer;
import analysis.base;
import dscanner.analysis.base;
/**
* Checks for potentially mistaken static if / else if.
@ -65,8 +65,8 @@ class StaticIfElse : BaseAnalyzer
unittest
{
import analysis.helpers : assertAnalyzerWarnings;
import analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import dscanner.analysis.helpers : assertAnalyzerWarnings;
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import std.stdio : stderr;
StaticAnalysisConfig sac = disabledConfig();

View File

@ -3,11 +3,11 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module analysis.stats_collector;
module dscanner.analysis.stats_collector;
import dparse.ast;
import dparse.lexer;
import analysis.base;
import dscanner.analysis.base;
class StatsCollector : BaseAnalyzer
{

View File

@ -3,7 +3,7 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module analysis.style;
module dscanner.analysis.style;
import std.stdio;
import dparse.ast;
@ -12,8 +12,8 @@ import std.regex;
import std.array;
import std.conv;
import std.format;
import analysis.helpers;
import analysis.base;
import dscanner.analysis.helpers;
import dscanner.analysis.base;
import dsymbol.scope_ : Scope;
final class StyleChecker : BaseAnalyzer
@ -158,7 +158,7 @@ final class StyleChecker : BaseAnalyzer
unittest
{
import analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
StaticAnalysisConfig sac = disabledConfig();
sac.style_check = Check.enabled;

View File

@ -3,9 +3,9 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module analysis.undocumented;
module dscanner.analysis.undocumented;
import analysis.base;
import dscanner.analysis.base;
import dsymbol.scope_ : Scope;
import dparse.ast;
import dparse.lexer;
@ -299,8 +299,8 @@ unittest
{
import std.stdio : stderr;
import std.format : format;
import analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import analysis.helpers : assertAnalyzerWarnings;
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import dscanner.analysis.helpers : assertAnalyzerWarnings;
StaticAnalysisConfig sac = disabledConfig();
sac.undocumented_declaration_check = Check.enabled;

View File

@ -2,9 +2,9 @@
// 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)
module analysis.unmodified;
module dscanner.analysis.unmodified;
import analysis.base;
import dscanner.analysis.base;
import dsymbol.scope_ : Scope;
import std.container;
import dparse.ast;
@ -334,8 +334,8 @@ bool isValueTypeSimple(const Type type) pure nothrow @nogc
@system unittest
{
import analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import analysis.helpers : assertAnalyzerWarnings;
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import dscanner.analysis.helpers : assertAnalyzerWarnings;
import std.stdio : stderr;
import std.format : format;

View File

@ -2,11 +2,11 @@
// 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)
module analysis.unused;
module dscanner.analysis.unused;
import dparse.ast;
import dparse.lexer;
import analysis.base;
import dscanner.analysis.base;
import std.container;
import std.regex : Regex, regex, matchAll;
import dsymbol.scope_ : Scope;
@ -234,11 +234,16 @@ class UnusedVariableCheck : BaseAnalyzer
{
foreach (part; matchAll(primary.primary.text, re))
{
immutable size_t treeIndex = tree.length - 1;
auto uu = UnUsed(part.hit);
auto r = tree[treeIndex].equalRange(&uu);
if (!r.empty)
r.front.uncertain = true;
void checkTree(in size_t treeIndex)
{
auto uu = UnUsed(part.hit);
auto r = tree[treeIndex].equalRange(&uu);
if (!r.empty)
r.front.uncertain = true;
}
checkTree(tree.length - 1);
if (tree.length >= 2)
checkTree(tree.length - 2);
}
}
}
@ -407,6 +412,8 @@ private:
{
if (!uu.isRef && tree.length > 1)
{
if (uu.uncertain)
continue;
immutable string certainty = uu.uncertain ? " might not be used."
: " is never used.";
immutable string errorMessage = (uu.isParameter ? "Parameter " : "Variable ")
@ -451,8 +458,8 @@ private:
@system unittest
{
import std.stdio : stderr;
import analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import analysis.helpers : assertAnalyzerWarnings;
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import dscanner.analysis.helpers : assertAnalyzerWarnings;
StaticAnalysisConfig sac = disabledConfig();
sac.unused_variable_check = Check.enabled;
@ -526,6 +533,11 @@ private:
auto cb2 = delegate(size_t a) {}; // [warn]: Parameter a is never used.
cb2(3);
}
bool hasDittos(int decl)
{
mixin("decl++;");
}
}c, sac);
stderr.writeln("Unittest for UnusedVariableCheck passed.");

View File

@ -2,10 +2,10 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module analysis.unused_label;
module dscanner.analysis.unused_label;
import analysis.base;
import analysis.helpers;
import dscanner.analysis.base;
import dscanner.analysis.helpers;
import dparse.ast;
import dparse.lexer;
import dsymbol.scope_ : Scope;
@ -168,7 +168,7 @@ private:
unittest
{
import analysis.config : Check, StaticAnalysisConfig, disabledConfig;
import dscanner.analysis.config : Check, StaticAnalysisConfig, disabledConfig;
import std.stdio : stderr;
StaticAnalysisConfig sac = disabledConfig();

View File

@ -3,10 +3,10 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module analysis.useless_assert;
module dscanner.analysis.useless_assert;
import analysis.base;
import analysis.helpers;
import dscanner.analysis.base;
import dscanner.analysis.helpers;
import dparse.ast;
import dparse.lexer;
@ -103,7 +103,7 @@ private:
unittest
{
import std.stdio : stderr;
import analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import std.format : format;
StaticAnalysisConfig sac = disabledConfig();

View File

@ -2,9 +2,9 @@
// 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)
module analysis.useless_initializer;
module dscanner.analysis.useless_initializer;
import analysis.base;
import dscanner.analysis.base;
import containers.dynamicarray;
import containers.hashmap;
import dparse.ast;
@ -257,8 +257,8 @@ public:
@system unittest
{
import analysis.config : Check, disabledConfig, StaticAnalysisConfig;
import analysis.helpers: assertAnalyzerWarnings;
import dscanner.analysis.config : Check, disabledConfig, StaticAnalysisConfig;
import dscanner.analysis.helpers: assertAnalyzerWarnings;
import std.stdio : stderr;
StaticAnalysisConfig sac = disabledConfig;

View File

@ -2,9 +2,9 @@
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//
module analysis.vcall_in_ctor;
module dscanner.analysis.vcall_in_ctor;
import analysis.base;
import dscanner.analysis.base;
import dparse.ast, dparse.lexer;
import std.algorithm: among;
import std.algorithm.iteration : filter;
@ -279,8 +279,8 @@ public:
unittest
{
import analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import analysis.helpers : assertAnalyzerWarnings;
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import dscanner.analysis.helpers : assertAnalyzerWarnings;
import std.stdio : stderr;
import std.format : format;

View File

@ -3,6 +3,8 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module dscanner.astprinter;
import dparse.lexer;
import dparse.ast;
import dparse.formatter;

View File

@ -3,7 +3,7 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module ctags;
module dscanner.ctags;
import dparse.parser;
import dparse.lexer;

View File

@ -3,7 +3,7 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module dscanner_version;
module dscanner.dscanner_version;
/**
* Human-readable version number

View File

@ -4,7 +4,7 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module etags;
module dscanner.etags;
import dparse.parser;
import dparse.lexer;

View File

@ -3,7 +3,7 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module highlighter;
module dscanner.highlighter;
import std.stdio;
import std.array;

View File

@ -3,7 +3,7 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module imports;
module dscanner.imports;
import dparse.ast;
import dparse.lexer;
@ -12,7 +12,7 @@ import dparse.rollback_allocator;
import std.stdio;
import std.container.rbtree;
import std.functional : toDelegate;
import readers;
import dscanner.readers;
/**
* AST visitor that collects modules imported to an R-B tree.

View File

@ -3,7 +3,7 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module main;
module dscanner.main;
import std.algorithm;
import std.array;
@ -20,18 +20,18 @@ import dparse.lexer;
import dparse.parser;
import dparse.rollback_allocator;
import highlighter;
import stats;
import ctags;
import etags;
import astprinter;
import imports;
import outliner;
import symbol_finder;
import analysis.run;
import analysis.config;
import dscanner_version;
import readers;
import dscanner.highlighter;
import dscanner.stats;
import dscanner.ctags;
import dscanner.etags;
import dscanner.astprinter;
import dscanner.imports;
import dscanner.outliner;
import dscanner.symbol_finder;
import dscanner.analysis.run;
import dscanner.analysis.config;
import dscanner.dscanner_version;
import dscanner.readers;
import inifiled;
@ -67,6 +67,8 @@ else
string[] importPaths;
bool printVersion;
bool explore;
string errorFormat;
bool patchConfig;
try
{
@ -94,7 +96,9 @@ else
"version", &printVersion,
"muffinButton", &muffin,
"explore", &explore,
"skipTests", &skipTests);
"skipTests", &skipTests,
"errorFormat|f", &errorFormat,
"patchConfig", &patchConfig);
//dfmt on
}
catch (ConvException e)
@ -141,6 +145,9 @@ else
return 0;
}
if (!errorFormat.length)
errorFormat = defaultErrorFormat;
const(string[]) absImportPaths = importPaths.map!(a => a.absolutePath()
.buildNormalizedPath()).array();
@ -188,7 +195,7 @@ else
if (highlight)
{
auto tokens = byToken(bytes, config, &cache);
highlighter.highlight(tokens, args.length == 1 ? "stdin" : args[1]);
dscanner.highlighter.highlight(tokens, args.length == 1 ? "stdin" : args[1]);
return 0;
}
else if (tokenDump)
@ -228,17 +235,21 @@ else
StaticAnalysisConfig config = defaultStaticAnalysisConfig();
string s = configLocation is null ? getConfigurationLocation() : configLocation;
if (s.exists())
{
if (hasWrongIniFileSection(s, patchConfig))
return 0;
readINIFile(config, s);
}
if (skipTests)
config.enabled2SkipTests;
if (report)
generateReport(expandArgs(args), config, cache, moduleCache);
else
return analyze(expandArgs(args), config, cache, moduleCache, true) ? 1 : 0;
return analyze(expandArgs(args), config, errorFormat, cache, moduleCache, true) ? 1 : 0;
}
else if (syntaxCheck)
{
return .syntaxCheck(usingStdin ? ["stdin"] : expandArgs(args), cache, moduleCache) ? 1 : 0;
return .syntaxCheck(usingStdin ? ["stdin"] : expandArgs(args), errorFormat, cache, moduleCache) ? 1 : 0;
}
else
{
@ -382,7 +393,10 @@ Options:
Generates a default configuration file for the static analysis checks,
--skipTests
Does not analyze in the unittests. Only works if --styleCheck.`,
Does not analyze in the unittests. Only works if --styleCheck.,
--patchConfig
Patches the configuration file passed as parameter for v0.5.0.`,
programName);
}
@ -458,3 +472,41 @@ string getConfigurationLocation()
return getDefaultConfigurationLocation();
}
/// Patch the INI file to v0.5.0 format.
//TODO: remove this from v0.6.0
bool hasWrongIniFileSection(string confiFilename, bool patch)
{
import std.string : indexOf;
import std.array : replace;
bool result;
static immutable v1 = "analysis.config.StaticAnalysisConfig";
static immutable v2 = "dscanner.analysis.config.StaticAnalysisConfig";
char[] c = cast(char[]) readFile(confiFilename);
try if (const ptrdiff_t i = c.indexOf(v1))
{
if (!patch)
{
writeln("warning, the configuration file `", confiFilename, "` contains an outdated property");
writeln("change manually [", v1, "] to [", v2, "]" );
writeln("or restart D-Scanner with the `--patchConfig` option");
result = true;
}
else
{
c = replace(c, v1, v2);
std.file.write(confiFilename, c);
writeln("the configuration file `", confiFilename, "` has been updated correctly");
}
}
catch(Exception e)
{
stderr.writeln("error encountered when trying to verify the INI file compatibility");
throw e;
}
return result;
}

View File

@ -3,6 +3,8 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module dscanner.outliner;
import dparse.lexer;
import dparse.ast;
import dparse.formatter;

View File

@ -1,4 +1,4 @@
module readers;
module dscanner.readers;
import std.array : appender, uninitializedArray;
import std.stdio : stdin, stderr, File;

View File

@ -3,7 +3,7 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module stats;
module dscanner.stats;
import std.stdio;
import std.algorithm;

View File

@ -3,7 +3,7 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module symbol_finder;
module dscanner.symbol_finder;
import std.stdio : File;
import dparse.lexer;