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:
Sebastian Wilzbach 2017-06-25 14:05:03 +02:00 committed by Petar Kirov
parent 721f2bc907
commit 61d52156aa
14 changed files with 116 additions and 23 deletions

91
.dscanner.ini Normal file
View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
} }

View File

@ -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;

View File

@ -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)

View File

@ -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;

View File

@ -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)

View File

@ -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;

View File

@ -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)
{ {

View File

@ -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";
} }

View File

@ -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);

View File

@ -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;