Run DScanner on itself (#479)
* Enable DScanner checking on Travis * Fix linter warnings * Set opequals_tohash_check to disabled * Set could_be_immutable to 'disabled' * Split expression back into multiple lines * Set style to disabled * Fix Makefile target
This commit is contained in:
parent
721f2bc907
commit
61d52156aa
|
@ -0,0 +1,91 @@
|
||||||
|
; Configure which static analysis checks are enabled
|
||||||
|
[analysis.config.StaticAnalysisConfig]
|
||||||
|
; Check variable, class, struct, interface, union, and function names against t
|
||||||
|
; he Phobos style guide
|
||||||
|
style_check="disabled"
|
||||||
|
; Check for array literals that cause unnecessary allocation
|
||||||
|
enum_array_literal_check="enabled"
|
||||||
|
; Check for poor exception handling practices
|
||||||
|
exception_check="enabled"
|
||||||
|
; Check for use of the deprecated 'delete' keyword
|
||||||
|
delete_check="enabled"
|
||||||
|
; Check for use of the deprecated floating point operators
|
||||||
|
float_operator_check="enabled"
|
||||||
|
; Check number literals for readability
|
||||||
|
number_style_check="enabled"
|
||||||
|
; Checks that opEquals, opCmp, toHash, and toString are either const, immutable
|
||||||
|
; , or inout.
|
||||||
|
object_const_check="enabled"
|
||||||
|
; Checks for .. expressions where the left side is larger than the right.
|
||||||
|
backwards_range_check="enabled"
|
||||||
|
; Checks for if statements whose 'then' block is the same as the 'else' block
|
||||||
|
if_else_same_check="enabled"
|
||||||
|
; Checks for some problems with constructors
|
||||||
|
constructor_check="enabled"
|
||||||
|
; Checks for unused variables and function parameters
|
||||||
|
unused_variable_check="enabled"
|
||||||
|
; Checks for unused labels
|
||||||
|
unused_label_check="enabled"
|
||||||
|
; Checks for duplicate attributes
|
||||||
|
duplicate_attribute="enabled"
|
||||||
|
; Checks that opEquals and toHash are both defined or neither are defined
|
||||||
|
opequals_tohash_check="disabled"
|
||||||
|
; Checks for subtraction from .length properties
|
||||||
|
length_subtraction_check="disabled"
|
||||||
|
; Checks for methods or properties whose names conflict with built-in propertie
|
||||||
|
; s
|
||||||
|
builtin_property_names_check="enabled"
|
||||||
|
; Checks for confusing code in inline asm statements
|
||||||
|
asm_style_check="enabled"
|
||||||
|
; Checks for confusing logical operator precedence
|
||||||
|
logical_precedence_check="enabled"
|
||||||
|
; Checks for undocumented public declarations
|
||||||
|
undocumented_declaration_check="disabled"
|
||||||
|
; Checks for poor placement of function attributes
|
||||||
|
function_attribute_check="disabled"
|
||||||
|
; Checks for use of the comma operator
|
||||||
|
comma_expression_check="enabled"
|
||||||
|
; Checks for local imports that are too broad
|
||||||
|
local_import_check="enabled"
|
||||||
|
; Checks for variables that could be declared immutable
|
||||||
|
could_be_immutable_check="disabled"
|
||||||
|
; Checks for redundant expressions in if statements
|
||||||
|
redundant_if_check="enabled"
|
||||||
|
; Checks for redundant parenthesis
|
||||||
|
redundant_parens_check="enabled"
|
||||||
|
; Checks for mismatched argument and parameter names
|
||||||
|
mismatched_args_check="enabled"
|
||||||
|
; Checks for labels with the same name as variables
|
||||||
|
label_var_same_name_check="enabled"
|
||||||
|
; Checks for lines longer than 120 characters
|
||||||
|
long_line_check="disabled"
|
||||||
|
; Checks for assignment to auto-ref function parameters
|
||||||
|
auto_ref_assignment_check="enabled"
|
||||||
|
; Checks for incorrect infinite range definitions
|
||||||
|
incorrect_infinite_range_check="enabled"
|
||||||
|
; Checks for asserts that are always true
|
||||||
|
useless_assert_check="enabled"
|
||||||
|
; Check for uses of the old-style alias syntax
|
||||||
|
alias_syntax_check="enabled"
|
||||||
|
; Checks for else if that should be else static if
|
||||||
|
static_if_else_check="enabled"
|
||||||
|
; Check for unclear lambda syntax
|
||||||
|
lambda_return_check="enabled"
|
||||||
|
; Check for auto function without return statement
|
||||||
|
auto_function_check="enabled"
|
||||||
|
; Check for sortedness of imports
|
||||||
|
imports_sortedness="disabled"
|
||||||
|
; Check for explicitly annotated unittests
|
||||||
|
explicitly_annotated_unittests="disabled"
|
||||||
|
; Check for properly documented public functions (Returns, Params)
|
||||||
|
properly_documented_public_functions="disabled"
|
||||||
|
; Check for useless usage of the final attribute
|
||||||
|
final_attribute_check="enabled"
|
||||||
|
; Check for virtual calls in the class constructors
|
||||||
|
vcall_in_ctor="enabled"
|
||||||
|
; Check for useless user defined initializers
|
||||||
|
useless_initializer="enabled"
|
||||||
|
; Check allman brace style
|
||||||
|
allman_braces_check="disabled"
|
||||||
|
; Check for redundant attributes
|
||||||
|
redundant_attributes_check="enabled"
|
|
@ -10,4 +10,5 @@ elif [[ $DC == ldc2 ]]; then
|
||||||
else
|
else
|
||||||
git submodule update --init --recursive
|
git submodule update --init --recursive
|
||||||
make test
|
make test
|
||||||
|
make lint
|
||||||
fi
|
fi
|
||||||
|
|
3
makefile
3
makefile
|
@ -51,6 +51,9 @@ test: githash
|
||||||
./bin/dscanner-unittest
|
./bin/dscanner-unittest
|
||||||
rm -f bin/dscanner-unittest
|
rm -f bin/dscanner-unittest
|
||||||
|
|
||||||
|
lint: dmdbuild
|
||||||
|
./bin/dscanner --config .dscanner.ini --styleCheck src
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf dsc
|
rm -rf dsc
|
||||||
rm -rf bin
|
rm -rf bin
|
||||||
|
|
|
@ -33,8 +33,8 @@ class AllManCheck : BaseAnalyzer
|
||||||
super(fileName, null, skipTests);
|
super(fileName, null, skipTests);
|
||||||
foreach (i; 1 .. tokens.length - 1)
|
foreach (i; 1 .. tokens.length - 1)
|
||||||
{
|
{
|
||||||
auto curLine = tokens[i].line;
|
const curLine = tokens[i].line;
|
||||||
auto prevTokenLine = tokens[i-1].line;
|
const prevTokenLine = tokens[i-1].line;
|
||||||
if (tokens[i].type == tok!"{" && curLine == prevTokenLine)
|
if (tokens[i].type == tok!"{" && curLine == prevTokenLine)
|
||||||
{
|
{
|
||||||
// ignore struct initialization
|
// ignore struct initialization
|
||||||
|
|
|
@ -93,10 +93,10 @@ private:
|
||||||
{
|
{
|
||||||
import std.algorithm : canFind;
|
import std.algorithm : canFind;
|
||||||
|
|
||||||
return builtinProperties.canFind(name);
|
return BuiltinProperties.canFind(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum string[] builtinProperties = ["init", "sizeof", "mangleof", "alignof", "stringof"];
|
enum string[] BuiltinProperties = ["init", "sizeof", "mangleof", "alignof", "stringof"];
|
||||||
int depth;
|
int depth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ class FunctionAttributeCheck : BaseAnalyzer
|
||||||
|
|
||||||
override void visit(const InterfaceDeclaration dec)
|
override void visit(const InterfaceDeclaration dec)
|
||||||
{
|
{
|
||||||
auto t = inInterface;
|
const t = inInterface;
|
||||||
inInterface = true;
|
inInterface = true;
|
||||||
dec.accept(this);
|
dec.accept(this);
|
||||||
inInterface = t;
|
inInterface = t;
|
||||||
|
@ -40,7 +40,7 @@ class FunctionAttributeCheck : BaseAnalyzer
|
||||||
|
|
||||||
override void visit(const ClassDeclaration dec)
|
override void visit(const ClassDeclaration dec)
|
||||||
{
|
{
|
||||||
auto t = inInterface;
|
const t = inInterface;
|
||||||
inInterface = false;
|
inInterface = false;
|
||||||
dec.accept(this);
|
dec.accept(this);
|
||||||
inInterface = t;
|
inInterface = t;
|
||||||
|
|
|
@ -66,7 +66,7 @@ class ImportSortednessCheck : BaseAnalyzer
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
int level = 0;
|
int level;
|
||||||
string[][int] imports;
|
string[][int] imports;
|
||||||
|
|
||||||
template ScopedVisit(NodeType)
|
template ScopedVisit(NodeType)
|
||||||
|
|
|
@ -78,7 +78,7 @@ private:
|
||||||
import std.conv : to;
|
import std.conv : to;
|
||||||
import std.range : retro;
|
import std.range : retro;
|
||||||
|
|
||||||
size_t i = 0;
|
size_t i;
|
||||||
foreach (s; retro(stack))
|
foreach (s; retro(stack))
|
||||||
{
|
{
|
||||||
const(Thing)* thing = name.text in s;
|
const(Thing)* thing = name.text in s;
|
||||||
|
|
|
@ -26,7 +26,7 @@ class LineLengthCheck : BaseAnalyzer
|
||||||
|
|
||||||
override void visit(const Module)
|
override void visit(const Module)
|
||||||
{
|
{
|
||||||
size_t endColumn = 0;
|
size_t endColumn;
|
||||||
lastErrorLine = ulong.max;
|
lastErrorLine = ulong.max;
|
||||||
foreach (i, token; tokens)
|
foreach (i, token; tokens)
|
||||||
{
|
{
|
||||||
|
@ -89,7 +89,6 @@ private:
|
||||||
|
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
import std.stdio;
|
|
||||||
assert(new LineLengthCheck(null, null).checkMultiLineToken(Token(tok!"stringLiteral", " ", 0, 0, 0)) == 8);
|
assert(new LineLengthCheck(null, null).checkMultiLineToken(Token(tok!"stringLiteral", " ", 0, 0, 0)) == 8);
|
||||||
assert(new LineLengthCheck(null, null).checkMultiLineToken(Token(tok!"stringLiteral", " \na", 0, 0, 0)) == 2);
|
assert(new LineLengthCheck(null, null).checkMultiLineToken(Token(tok!"stringLiteral", " \na", 0, 0, 0)) == 2);
|
||||||
assert(new LineLengthCheck(null, null).checkMultiLineToken(Token(tok!"stringLiteral", " \n ", 0, 0, 0)) == 5);
|
assert(new LineLengthCheck(null, null).checkMultiLineToken(Token(tok!"stringLiteral", " \n ", 0, 0, 0)) == 5);
|
||||||
|
@ -123,8 +122,8 @@ private:
|
||||||
{
|
{
|
||||||
import std.utf : byDchar;
|
import std.utf : byDchar;
|
||||||
|
|
||||||
size_t length = 0;
|
size_t length;
|
||||||
bool newLine = tok.line > prevLine;
|
const newLine = tok.line > prevLine;
|
||||||
bool multiLine;
|
bool multiLine;
|
||||||
|
|
||||||
if (tok.text is null)
|
if (tok.text is null)
|
||||||
|
|
|
@ -71,7 +71,7 @@ private:
|
||||||
{
|
{
|
||||||
override void visit(const T thing)
|
override void visit(const T thing)
|
||||||
{
|
{
|
||||||
auto b = interesting;
|
const b = interesting;
|
||||||
interesting = true;
|
interesting = true;
|
||||||
thing.accept(this);
|
thing.accept(this);
|
||||||
interesting = b;
|
interesting = b;
|
||||||
|
|
|
@ -67,7 +67,7 @@ class PokemonExceptionCheck : BaseAnalyzer
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto identOrTemplate = type2.symbol.identifierOrTemplateChain
|
const identOrTemplate = type2.symbol.identifierOrTemplateChain
|
||||||
.identifiersOrTemplateInstances[0];
|
.identifiersOrTemplateInstances[0];
|
||||||
if (identOrTemplate.templateInstance !is null)
|
if (identOrTemplate.templateInstance !is null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -43,7 +43,7 @@ class RedundantAttributesCheck : BaseAnalyzer
|
||||||
// new scope: private { }
|
// new scope: private { }
|
||||||
if (decl.declarations.length > 0)
|
if (decl.declarations.length > 0)
|
||||||
{
|
{
|
||||||
auto prev = currentAttributes[];
|
const prev = currentAttributes[];
|
||||||
// append to current scope and reset once block is left
|
// append to current scope and reset once block is left
|
||||||
foreach (attr; attributes)
|
foreach (attr; attributes)
|
||||||
addAttribute(attr);
|
addAttribute(attr);
|
||||||
|
@ -113,7 +113,7 @@ private:
|
||||||
void removeOverwrite(const Attribute attr)
|
void removeOverwrite(const Attribute attr)
|
||||||
{
|
{
|
||||||
import std.array : array;
|
import std.array : array;
|
||||||
auto group = getAttributeGroup(attr);
|
const group = getAttributeGroup(attr);
|
||||||
if (currentAttributes.filter!(a => getAttributeGroup(a) == group
|
if (currentAttributes.filter!(a => getAttributeGroup(a) == group
|
||||||
&& !isIdenticalAttribute(a, attr)).walkLength > 0)
|
&& !isIdenticalAttribute(a, attr)).walkLength > 0)
|
||||||
{
|
{
|
||||||
|
@ -172,7 +172,6 @@ private:
|
||||||
stack.length--;
|
stack.length--;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
enum string KEY = "dscanner.suspicious.redundant_attributes";
|
enum string KEY = "dscanner.suspicious.redundant_attributes";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -168,8 +168,8 @@ bool analyze(string[] fileNames, const StaticAnalysisConfig config,
|
||||||
if (code.length == 0)
|
if (code.length == 0)
|
||||||
continue;
|
continue;
|
||||||
RollbackAllocator r;
|
RollbackAllocator r;
|
||||||
uint errorCount = 0;
|
uint errorCount;
|
||||||
uint warningCount = 0;
|
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, cache, false, tokens,
|
||||||
null, &errorCount, &warningCount);
|
null, &errorCount, &warningCount);
|
||||||
|
|
|
@ -97,7 +97,7 @@ final class EtagsPrinter : ASTVisitor
|
||||||
override void visit(const ModuleDeclaration dec)
|
override void visit(const ModuleDeclaration dec)
|
||||||
{
|
{
|
||||||
auto tok0 = dec.moduleName.identifiers[0];
|
auto tok0 = dec.moduleName.identifiers[0];
|
||||||
auto was = context;
|
const was = context;
|
||||||
context = "";
|
context = "";
|
||||||
maketag(moduleName, tok0.index, tok0.line);
|
maketag(moduleName, tok0.index, tok0.line);
|
||||||
context = was;
|
context = was;
|
||||||
|
@ -115,7 +115,7 @@ final class EtagsPrinter : ASTVisitor
|
||||||
|
|
||||||
// visibility needs to be restored to what it was when changed by
|
// visibility needs to be restored to what it was when changed by
|
||||||
// attribute.
|
// attribute.
|
||||||
auto was = visibility;
|
const was = visibility;
|
||||||
foreach (attr; dec.attributes)
|
foreach (attr; dec.attributes)
|
||||||
{
|
{
|
||||||
updateVisibility(attr.attribute.type);
|
updateVisibility(attr.attribute.type);
|
||||||
|
@ -217,7 +217,7 @@ final class EtagsPrinter : ASTVisitor
|
||||||
|
|
||||||
override void visit(const Unittest dec)
|
override void visit(const Unittest dec)
|
||||||
{
|
{
|
||||||
bool was = inUnittest;
|
const was = inUnittest;
|
||||||
inUnittest = true;
|
inUnittest = true;
|
||||||
dec.accept(this);
|
dec.accept(this);
|
||||||
inUnittest = was;
|
inUnittest = was;
|
||||||
|
@ -287,7 +287,7 @@ private:
|
||||||
void acceptInContext(const ASTNode dec, string name)
|
void acceptInContext(const ASTNode dec, string name)
|
||||||
{
|
{
|
||||||
// nest context before journeying on
|
// nest context before journeying on
|
||||||
auto c = context;
|
const c = context;
|
||||||
context ~= name ~ ".";
|
context ~= name ~ ".";
|
||||||
dec.accept(this);
|
dec.accept(this);
|
||||||
context = c;
|
context = c;
|
||||||
|
|
Loading…
Reference in New Issue