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 ; 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 ; Check variable, class, struct, interface, union, and function names against t
; he Phobos style guide ; he Phobos style guide
style_check="disabled" style_check="disabled"

3
.gitignore vendored
View File

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

View File

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

View File

@ -17,8 +17,8 @@ set LIBDDOC=
set STDXALLOCATOR= set STDXALLOCATOR=
set STDXALLOCATORBLOCKS= set STDXALLOCATORBLOCKS=
for %%x in (src\*.d) do set CORE=!CORE! %%x for %%x in (src\dscanner\*.d) do set CORE=!CORE! %%x
for %%x in (src\analysis\*.d) do set ANALYSIS=!ANALYSIS! %%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\dparse\*.d) do set LIBDPARSE=!LIBDPARSE! %%x
for %%x in (libdparse\src\std\experimental\*.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 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 // (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
module analysis.alias_syntax_check; module dscanner.analysis.alias_syntax_check;
import dparse.ast; import dparse.ast;
import dparse.lexer; import dparse.lexer;
import analysis.base; import dscanner.analysis.base;
/** /**
* Checks for uses of the old alias syntax. * Checks for uses of the old alias syntax.
@ -39,8 +39,8 @@ private:
unittest unittest
{ {
import analysis.helpers : assertAnalyzerWarnings; import dscanner.analysis.helpers : assertAnalyzerWarnings;
import analysis.config : StaticAnalysisConfig, Check, disabledConfig; import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import std.stdio : stderr; import std.stdio : stderr;
StaticAnalysisConfig sac = disabledConfig(); StaticAnalysisConfig sac = disabledConfig();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -3,7 +3,7 @@
// (See accompanying file LICENSE_1_0.txt or copy at // (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
module analysis.helpers; module dscanner.analysis.helpers;
import core.exception : AssertError; import core.exception : AssertError;
import std.string; import std.string;
@ -13,9 +13,9 @@ import std.stdio;
import dparse.ast; import dparse.ast;
import dparse.rollback_allocator; import dparse.rollback_allocator;
import dsymbol.modulecache : ModuleCache; import dsymbol.modulecache : ModuleCache;
import analysis.config; import dscanner.analysis.config;
import analysis.run; import dscanner.analysis.run;
import analysis.base; import dscanner.analysis.base;
import stdx.allocator.mallocator; import stdx.allocator.mallocator;
import stdx.allocator; import stdx.allocator;
@ -48,13 +48,13 @@ S after(S)(S value, S separator) if (isSomeString!S)
void assertAnalyzerWarnings(string code, const StaticAnalysisConfig config, void assertAnalyzerWarnings(string code, const StaticAnalysisConfig config,
string file = __FILE__, size_t line = __LINE__) string file = __FILE__, size_t line = __LINE__)
{ {
import analysis.run : parseModule; import dscanner.analysis.run : parseModule;
import dparse.lexer : StringCache, Token; import dparse.lexer : StringCache, Token;
StringCache cache = StringCache(StringCache.defaultBucketCount); StringCache cache = StringCache(StringCache.defaultBucketCount);
RollbackAllocator r; RollbackAllocator r;
const(Token)[] tokens; 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); 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. // Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at // (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
module analysis.if_statements; module dscanner.analysis.if_statements;
import dparse.ast; import dparse.ast;
import dparse.lexer; import dparse.lexer;
import dparse.formatter; import dparse.formatter;
import analysis.base; import dscanner.analysis.base;
import dsymbol.scope_ : Scope; import dsymbol.scope_ : Scope;
class IfStatementCheck : BaseAnalyzer class IfStatementCheck : BaseAnalyzer

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2,9 +2,9 @@
// Distributed under the Boost Software License, Version 1.0. // Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at // (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
module analysis.unmodified; module dscanner.analysis.unmodified;
import analysis.base; import dscanner.analysis.base;
import dsymbol.scope_ : Scope; import dsymbol.scope_ : Scope;
import std.container; import std.container;
import dparse.ast; import dparse.ast;
@ -334,8 +334,8 @@ bool isValueTypeSimple(const Type type) pure nothrow @nogc
@system unittest @system unittest
{ {
import analysis.config : StaticAnalysisConfig, Check, disabledConfig; import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import analysis.helpers : assertAnalyzerWarnings; import dscanner.analysis.helpers : assertAnalyzerWarnings;
import std.stdio : stderr; import std.stdio : stderr;
import std.format : format; import std.format : format;

View File

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

View File

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

View File

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

View File

@ -2,9 +2,9 @@
// Distributed under the Boost Software License, Version 1.0. // Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at // (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
module analysis.useless_initializer; module dscanner.analysis.useless_initializer;
import analysis.base; import dscanner.analysis.base;
import containers.dynamicarray; import containers.dynamicarray;
import containers.hashmap; import containers.hashmap;
import dparse.ast; import dparse.ast;
@ -257,8 +257,8 @@ public:
@system unittest @system unittest
{ {
import analysis.config : Check, disabledConfig, StaticAnalysisConfig; import dscanner.analysis.config : Check, disabledConfig, StaticAnalysisConfig;
import analysis.helpers: assertAnalyzerWarnings; import dscanner.analysis.helpers: assertAnalyzerWarnings;
import std.stdio : stderr; import std.stdio : stderr;
StaticAnalysisConfig sac = disabledConfig; StaticAnalysisConfig sac = disabledConfig;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -3,7 +3,7 @@
// (See accompanying file LICENSE_1_0.txt or copy at // (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
module imports; module dscanner.imports;
import dparse.ast; import dparse.ast;
import dparse.lexer; import dparse.lexer;
@ -12,7 +12,7 @@ import dparse.rollback_allocator;
import std.stdio; import std.stdio;
import std.container.rbtree; import std.container.rbtree;
import std.functional : toDelegate; import std.functional : toDelegate;
import readers; import dscanner.readers;
/** /**
* AST visitor that collects modules imported to an R-B tree. * 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 // (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
module main; module dscanner.main;
import std.algorithm; import std.algorithm;
import std.array; import std.array;
@ -20,18 +20,18 @@ import dparse.lexer;
import dparse.parser; import dparse.parser;
import dparse.rollback_allocator; import dparse.rollback_allocator;
import highlighter; import dscanner.highlighter;
import stats; import dscanner.stats;
import ctags; import dscanner.ctags;
import etags; import dscanner.etags;
import astprinter; import dscanner.astprinter;
import imports; import dscanner.imports;
import outliner; import dscanner.outliner;
import symbol_finder; import dscanner.symbol_finder;
import analysis.run; import dscanner.analysis.run;
import analysis.config; import dscanner.analysis.config;
import dscanner_version; import dscanner.dscanner_version;
import readers; import dscanner.readers;
import inifiled; import inifiled;
@ -67,6 +67,8 @@ else
string[] importPaths; string[] importPaths;
bool printVersion; bool printVersion;
bool explore; bool explore;
string errorFormat;
bool patchConfig;
try try
{ {
@ -94,7 +96,9 @@ else
"version", &printVersion, "version", &printVersion,
"muffinButton", &muffin, "muffinButton", &muffin,
"explore", &explore, "explore", &explore,
"skipTests", &skipTests); "skipTests", &skipTests,
"errorFormat|f", &errorFormat,
"patchConfig", &patchConfig);
//dfmt on //dfmt on
} }
catch (ConvException e) catch (ConvException e)
@ -141,6 +145,9 @@ else
return 0; return 0;
} }
if (!errorFormat.length)
errorFormat = defaultErrorFormat;
const(string[]) absImportPaths = importPaths.map!(a => a.absolutePath() const(string[]) absImportPaths = importPaths.map!(a => a.absolutePath()
.buildNormalizedPath()).array(); .buildNormalizedPath()).array();
@ -188,7 +195,7 @@ else
if (highlight) if (highlight)
{ {
auto tokens = byToken(bytes, config, &cache); 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; return 0;
} }
else if (tokenDump) else if (tokenDump)
@ -228,17 +235,21 @@ else
StaticAnalysisConfig config = defaultStaticAnalysisConfig(); StaticAnalysisConfig config = defaultStaticAnalysisConfig();
string s = configLocation is null ? getConfigurationLocation() : configLocation; string s = configLocation is null ? getConfigurationLocation() : configLocation;
if (s.exists()) if (s.exists())
{
if (hasWrongIniFileSection(s, patchConfig))
return 0;
readINIFile(config, s); readINIFile(config, s);
}
if (skipTests) if (skipTests)
config.enabled2SkipTests; config.enabled2SkipTests;
if (report) if (report)
generateReport(expandArgs(args), config, cache, moduleCache); generateReport(expandArgs(args), config, cache, moduleCache);
else 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) 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 else
{ {
@ -382,7 +393,10 @@ Options:
Generates a default configuration file for the static analysis checks, Generates a default configuration file for the static analysis checks,
--skipTests --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); programName);
} }
@ -458,3 +472,41 @@ string getConfigurationLocation()
return getDefaultConfigurationLocation(); 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 // (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
module dscanner.outliner;
import dparse.lexer; import dparse.lexer;
import dparse.ast; import dparse.ast;
import dparse.formatter; import dparse.formatter;

View File

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

View File

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

View File

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