fix all cases of mixed tabs and spaces

This commit is contained in:
Basile Burg 2018-04-07 21:45:55 +02:00
parent af0bebd891
commit 4231deb046
12 changed files with 463 additions and 463 deletions

View File

@ -57,7 +57,7 @@ class AllManCheck : BaseAnalyzer
addErrorMessage(tokens[i].line, tokens[i].column, KEY, MESSAGE); addErrorMessage(tokens[i].line, tokens[i].column, KEY, MESSAGE);
} }
} }
} }
enum string KEY = "dscanner.style.allman"; enum string KEY = "dscanner.style.allman";
enum string MESSAGE = "Braces should be on their own line"; enum string MESSAGE = "Braces should be on their own line";

View File

@ -30,7 +30,7 @@ private:
bool[] _returns; bool[] _returns;
size_t _mixinDepth; size_t _mixinDepth;
string[] _literalWithReturn; string[] _literalWithReturn;
public: public:
@ -98,59 +98,59 @@ public:
import std.algorithm.searching : canFind; import std.algorithm.searching : canFind;
if (_returns.length && _mixinDepth) if (_returns.length && _mixinDepth)
{ {
if (findReturnInLiteral(exp.primary.text)) if (findReturnInLiteral(exp.primary.text))
_returns[$-1] = true; _returns[$-1] = true;
else if (exp.identifierOrTemplateInstance && else if (exp.identifierOrTemplateInstance &&
_literalWithReturn.canFind(exp.identifierOrTemplateInstance.identifier.text)) _literalWithReturn.canFind(exp.identifierOrTemplateInstance.identifier.text))
_returns[$-1] = true; _returns[$-1] = true;
} }
} }
bool findReturnInLiteral(const(string) value) bool findReturnInLiteral(const(string) value)
{ {
import std.algorithm.searching : find; import std.algorithm.searching : find;
import std.range : empty; import std.range : empty;
return value == "return" || !value.find("return ").empty; return value == "return" || !value.find("return ").empty;
} }
bool stringliteralHasReturn(const(NonVoidInitializer) nvi) bool stringliteralHasReturn(const(NonVoidInitializer) nvi)
{ {
bool result; bool result;
if (!nvi.assignExpression || (cast(UnaryExpression) nvi.assignExpression) is null) if (!nvi.assignExpression || (cast(UnaryExpression) nvi.assignExpression) is null)
return result; return result;
const(UnaryExpression) u = cast(UnaryExpression) nvi.assignExpression; const(UnaryExpression) u = cast(UnaryExpression) nvi.assignExpression;
if (u.primaryExpression && if (u.primaryExpression &&
u.primaryExpression.primary.type.isStringLiteral && u.primaryExpression.primary.type.isStringLiteral &&
findReturnInLiteral(u.primaryExpression.primary.text)) findReturnInLiteral(u.primaryExpression.primary.text))
result = true; result = true;
return result; return result;
} }
override void visit(const(AutoDeclaration) decl) override void visit(const(AutoDeclaration) decl)
{ {
decl.accept(this); decl.accept(this);
foreach(const(AutoDeclarationPart) p; decl.parts) foreach(const(AutoDeclarationPart) p; decl.parts)
if (p.initializer && if (p.initializer &&
p.initializer.nonVoidInitializer && p.initializer.nonVoidInitializer &&
stringliteralHasReturn(p.initializer.nonVoidInitializer)) stringliteralHasReturn(p.initializer.nonVoidInitializer))
_literalWithReturn ~= p.identifier.text.idup; _literalWithReturn ~= p.identifier.text.idup;
} }
override void visit(const(VariableDeclaration) decl) override void visit(const(VariableDeclaration) decl)
{ {
decl.accept(this); decl.accept(this);
foreach(const(Declarator) d; decl.declarators) foreach(const(Declarator) d; decl.declarators)
if (d.initializer && if (d.initializer &&
d.initializer.nonVoidInitializer && d.initializer.nonVoidInitializer &&
stringliteralHasReturn(d.initializer.nonVoidInitializer)) stringliteralHasReturn(d.initializer.nonVoidInitializer))
_literalWithReturn ~= d.name.text.idup; _literalWithReturn ~= d.name.text.idup;
} }
} }
unittest unittest
@ -202,24 +202,24 @@ unittest
AutoFunctionChecker.MESSAGE, AutoFunctionChecker.MESSAGE,
), sac); ), sac);
assertAnalyzerWarnings(q{ assertAnalyzerWarnings(q{
auto doStuff(){} // [warn]: %s auto doStuff(){} // [warn]: %s
extern(C) auto doStuff(); extern(C) auto doStuff();
}c.format( }c.format(
AutoFunctionChecker.MESSAGE, AutoFunctionChecker.MESSAGE,
), sac); ), sac);
assertAnalyzerWarnings(q{ assertAnalyzerWarnings(q{
auto doStuff(){} // [warn]: %s auto doStuff(){} // [warn]: %s
@disable auto doStuff(); @disable auto doStuff();
}c.format( }c.format(
AutoFunctionChecker.MESSAGE, AutoFunctionChecker.MESSAGE,
), sac); ), sac);
assertAnalyzerWarnings(q{ assertAnalyzerWarnings(q{
enum _genSave = "return true;"; enum _genSave = "return true;";
auto doStuff(){ mixin(_genSave);} auto doStuff(){ mixin(_genSave);}
}, sac); }, sac);
stderr.writeln("Unittest for AutoFunctionChecker passed."); stderr.writeln("Unittest for AutoFunctionChecker passed.");
} }

View File

@ -31,7 +31,7 @@ public:
{ {
this.sc = sc; this.sc = sc;
this.fileName = fileName; this.fileName = fileName;
this.skipTests = skipTests; this.skipTests = skipTests;
_messages = new MessageSet; _messages = new MessageSet;
} }
@ -40,24 +40,24 @@ public:
return _messages[].array; return _messages[].array;
} }
alias visit = ASTVisitor.visit; alias visit = ASTVisitor.visit;
/** /**
* Visits a unittest. * Visits a unittest.
* *
* When overriden, the protected bool "skipTests" should be handled * When overriden, the protected bool "skipTests" should be handled
* so that the content of the test is not analyzed. * so that the content of the test is not analyzed.
*/ */
override void visit(const Unittest unittest_) override void visit(const Unittest unittest_)
{ {
if (!skipTests) if (!skipTests)
unittest_.accept(this); unittest_.accept(this);
} }
protected: protected:
bool inAggregate; bool inAggregate;
bool skipTests; bool skipTests;
template visitTemplate(T) template visitTemplate(T)
{ {

View File

@ -20,387 +20,387 @@ final class FinalAttributeChecker : BaseAnalyzer
private: private:
enum string KEY = "dscanner.useless.final"; enum string KEY = "dscanner.useless.final";
enum string MSGB = "Useless final attribute, %s"; enum string MSGB = "Useless final attribute, %s";
static struct MESSAGE static struct MESSAGE
{ {
static immutable struct_i = "structs cannot be subclassed"; static immutable struct_i = "structs cannot be subclassed";
static immutable union_i = "unions cannot be subclassed"; static immutable union_i = "unions cannot be subclassed";
static immutable class_t = "templated functions declared within a class are never virtual"; static immutable class_t = "templated functions declared within a class are never virtual";
static immutable class_p = "private functions declared within a class are never virtual"; static immutable class_p = "private functions declared within a class are never virtual";
static immutable class_f = "functions declared within a final class are never virtual"; static immutable class_f = "functions declared within a final class are never virtual";
static immutable class_s = "static functions are never virtual"; static immutable class_s = "static functions are never virtual";
static immutable interface_t = "templated functions declared within an interface are never virtual"; static immutable interface_t = "templated functions declared within an interface are never virtual";
static immutable struct_f = "functions declared within a struct are never virtual"; static immutable struct_f = "functions declared within a struct are never virtual";
static immutable union_f = "functions declared within an union are never virtual"; static immutable union_f = "functions declared within an union are never virtual";
static immutable func_n = "nested functions are never virtual"; static immutable func_n = "nested functions are never virtual";
static immutable func_g = "global functions are never virtual"; static immutable func_g = "global functions are never virtual";
} }
enum Parent enum Parent
{ {
module_, module_,
struct_, struct_,
union_, union_,
class_, class_,
function_, function_,
interface_ interface_
} }
bool[] _private; bool[] _private;
bool _finalAggregate; bool _finalAggregate;
bool _alwaysStatic; bool _alwaysStatic;
bool _blockStatic; bool _blockStatic;
Parent _parent = Parent.module_; Parent _parent = Parent.module_;
void addError(T)(T t, string msg) void addError(T)(T t, string msg)
{ {
import std.format : format; import std.format : format;
const size_t lne = t.name.line; const size_t lne = t.name.line;
const size_t col = t.name.column; const size_t col = t.name.column;
addErrorMessage(lne, col, KEY, MSGB.format(msg)); addErrorMessage(lne, col, KEY, MSGB.format(msg));
} }
public: public:
alias visit = BaseAnalyzer.visit; alias visit = BaseAnalyzer.visit;
/// ///
this(string fileName, bool skipTests = false) this(string fileName, bool skipTests = false)
{ {
super(fileName, null, skipTests); super(fileName, null, skipTests);
_private.length = 1; _private.length = 1;
} }
override void visit(const(StructDeclaration) sd) override void visit(const(StructDeclaration) sd)
{ {
const Parent saved = _parent; const Parent saved = _parent;
_parent = Parent.struct_; _parent = Parent.struct_;
_private.length += 1; _private.length += 1;
_alwaysStatic = false; _alwaysStatic = false;
sd.accept(this); sd.accept(this);
_private.length -= 1; _private.length -= 1;
_parent = saved; _parent = saved;
} }
override void visit(const(InterfaceDeclaration) id) override void visit(const(InterfaceDeclaration) id)
{ {
const Parent saved = _parent; const Parent saved = _parent;
_parent = Parent.interface_; _parent = Parent.interface_;
_private.length += 1; _private.length += 1;
_alwaysStatic = false; _alwaysStatic = false;
id.accept(this); id.accept(this);
_private.length -= 1; _private.length -= 1;
_parent = saved; _parent = saved;
} }
override void visit(const(UnionDeclaration) ud) override void visit(const(UnionDeclaration) ud)
{ {
const Parent saved = _parent; const Parent saved = _parent;
_parent = Parent.union_; _parent = Parent.union_;
_private.length += 1; _private.length += 1;
_alwaysStatic = false; _alwaysStatic = false;
ud.accept(this); ud.accept(this);
_private.length -= 1; _private.length -= 1;
_parent = saved; _parent = saved;
} }
override void visit(const(ClassDeclaration) cd) override void visit(const(ClassDeclaration) cd)
{ {
const Parent saved = _parent; const Parent saved = _parent;
_parent = Parent.class_; _parent = Parent.class_;
_private.length += 1; _private.length += 1;
_alwaysStatic = false; _alwaysStatic = false;
cd.accept(this); cd.accept(this);
_private.length -= 1; _private.length -= 1;
_parent = saved; _parent = saved;
} }
override void visit(const(MixinTemplateDeclaration) mtd) override void visit(const(MixinTemplateDeclaration) mtd)
{ {
// can't really know where it'll be mixed (class |final class | struct ?) // can't really know where it'll be mixed (class |final class | struct ?)
} }
override void visit(const(TemplateDeclaration) mtd) override void visit(const(TemplateDeclaration) mtd)
{ {
// regular template are also mixable // regular template are also mixable
} }
override void visit(const(AttributeDeclaration) decl) override void visit(const(AttributeDeclaration) decl)
{ {
if (_parent == Parent.class_ && decl.attribute && if (_parent == Parent.class_ && decl.attribute &&
decl.attribute.attribute == tok!"static") decl.attribute.attribute == tok!"static")
_alwaysStatic = true; _alwaysStatic = true;
} }
override void visit(const(Declaration) d) override void visit(const(Declaration) d)
{ {
import std.algorithm.iteration : filter; import std.algorithm.iteration : filter;
import std.algorithm.searching : canFind; import std.algorithm.searching : canFind;
const Parent savedParent = _parent; const Parent savedParent = _parent;
bool undoBlockStatic; bool undoBlockStatic;
if (_parent == Parent.class_ && d.attributes && if (_parent == Parent.class_ && d.attributes &&
d.attributes.canFind!(a => a.attribute == tok!"static")) d.attributes.canFind!(a => a.attribute == tok!"static"))
{ {
_blockStatic = true; _blockStatic = true;
undoBlockStatic = true; undoBlockStatic = true;
} }
scope(exit) scope(exit)
{ {
d.accept(this); d.accept(this);
_parent = savedParent; _parent = savedParent;
if (undoBlockStatic) if (undoBlockStatic)
_blockStatic = false; _blockStatic = false;
} }
if (!d.attributeDeclaration && if (!d.attributeDeclaration &&
!d.classDeclaration && !d.classDeclaration &&
!d.structDeclaration && !d.structDeclaration &&
!d.unionDeclaration && !d.unionDeclaration &&
!d.interfaceDeclaration && !d.interfaceDeclaration &&
!d.functionDeclaration) !d.functionDeclaration)
return; return;
if (d.attributeDeclaration && d.attributeDeclaration.attribute) if (d.attributeDeclaration && d.attributeDeclaration.attribute)
{ {
const tp = d.attributeDeclaration.attribute.attribute.type; const tp = d.attributeDeclaration.attribute.attribute.type;
_private[$-1] = isProtection(tp) & (tp == tok!"private"); _private[$-1] = isProtection(tp) & (tp == tok!"private");
} }
const bool isFinal = d.attributes const bool isFinal = d.attributes
.canFind!(a => a.attribute.type == tok!"final"); .canFind!(a => a.attribute.type == tok!"final");
const bool isStaticOnce = d.attributes const bool isStaticOnce = d.attributes
.canFind!(a => a.attribute.type == tok!"static"); .canFind!(a => a.attribute.type == tok!"static");
// determine if private // determine if private
const bool changeProtectionOnce = d.attributes const bool changeProtectionOnce = d.attributes
.canFind!(a => a.attribute.type.isProtection); .canFind!(a => a.attribute.type.isProtection);
const bool isPrivateOnce = d.attributes const bool isPrivateOnce = d.attributes
.canFind!(a => a.attribute.type == tok!"private"); .canFind!(a => a.attribute.type == tok!"private");
bool isPrivate; bool isPrivate;
if (isPrivateOnce) if (isPrivateOnce)
isPrivate = true; isPrivate = true;
else if (_private[$-1] && !changeProtectionOnce) else if (_private[$-1] && !changeProtectionOnce)
isPrivate = true; isPrivate = true;
// check final aggregate type // check final aggregate type
if (d.classDeclaration || d.structDeclaration || d.unionDeclaration) if (d.classDeclaration || d.structDeclaration || d.unionDeclaration)
{ {
_finalAggregate = isFinal; _finalAggregate = isFinal;
if (_finalAggregate && savedParent == Parent.module_) if (_finalAggregate && savedParent == Parent.module_)
{ {
if (d.structDeclaration) if (d.structDeclaration)
addError(d.structDeclaration, MESSAGE.struct_i); addError(d.structDeclaration, MESSAGE.struct_i);
else if (d.unionDeclaration) else if (d.unionDeclaration)
addError(d.unionDeclaration, MESSAGE.union_i); addError(d.unionDeclaration, MESSAGE.union_i);
} }
} }
if (!d.functionDeclaration) if (!d.functionDeclaration)
return; return;
// check final functions // check final functions
_parent = Parent.function_; _parent = Parent.function_;
const(FunctionDeclaration) fd = d.functionDeclaration; const(FunctionDeclaration) fd = d.functionDeclaration;
if (isFinal) final switch(savedParent) if (isFinal) final switch(savedParent)
{ {
case Parent.class_: case Parent.class_:
if (fd.templateParameters) if (fd.templateParameters)
addError(fd, MESSAGE.class_t); addError(fd, MESSAGE.class_t);
if (isPrivate) if (isPrivate)
addError(fd, MESSAGE.class_p); addError(fd, MESSAGE.class_p);
else if (isStaticOnce || _alwaysStatic || _blockStatic) else if (isStaticOnce || _alwaysStatic || _blockStatic)
addError(fd, MESSAGE.class_s); addError(fd, MESSAGE.class_s);
else if (_finalAggregate) else if (_finalAggregate)
addError(fd, MESSAGE.class_f); addError(fd, MESSAGE.class_f);
break; break;
case Parent.interface_: case Parent.interface_:
if (fd.templateParameters) if (fd.templateParameters)
addError(fd, MESSAGE.interface_t); addError(fd, MESSAGE.interface_t);
break; break;
case Parent.struct_: case Parent.struct_:
addError(fd, MESSAGE.struct_f); addError(fd, MESSAGE.struct_f);
break; break;
case Parent.union_: case Parent.union_:
addError(fd, MESSAGE.union_f); addError(fd, MESSAGE.union_f);
break; break;
case Parent.function_: case Parent.function_:
addError(fd, MESSAGE.func_n); addError(fd, MESSAGE.func_n);
break; break;
case Parent.module_: case Parent.module_:
addError(fd, MESSAGE.func_g); addError(fd, MESSAGE.func_g);
break; break;
} }
} }
} }
@system unittest @system unittest
{ {
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig; import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import dscanner.analysis.helpers : assertAnalyzerWarnings; import dscanner.analysis.helpers : assertAnalyzerWarnings;
import std.stdio : stderr; import std.stdio : stderr;
import std.format : format; import std.format : format;
StaticAnalysisConfig sac = disabledConfig(); StaticAnalysisConfig sac = disabledConfig();
sac.final_attribute_check = Check.enabled; sac.final_attribute_check = Check.enabled;
// pass // pass
assertAnalyzerWarnings(q{ assertAnalyzerWarnings(q{
void foo(){} void foo(){}
}, sac); }, sac);
assertAnalyzerWarnings(q{ assertAnalyzerWarnings(q{
void foo(){void foo(){}} void foo(){void foo(){}}
}, sac); }, sac);
assertAnalyzerWarnings(q{ assertAnalyzerWarnings(q{
struct S{} struct S{}
}, sac); }, sac);
assertAnalyzerWarnings(q{ assertAnalyzerWarnings(q{
union U{} union U{}
}, sac); }, sac);
assertAnalyzerWarnings(q{ assertAnalyzerWarnings(q{
class Foo{public final void foo(){}} class Foo{public final void foo(){}}
}, sac); }, sac);
assertAnalyzerWarnings(q{ assertAnalyzerWarnings(q{
final class Foo{static struct Bar{}} final class Foo{static struct Bar{}}
}, sac); }, sac);
assertAnalyzerWarnings(q{ assertAnalyzerWarnings(q{
class Foo{private: public final void foo(){}} class Foo{private: public final void foo(){}}
}, sac); }, sac);
assertAnalyzerWarnings(q{ assertAnalyzerWarnings(q{
class Foo{private: public: final void foo(){}} class Foo{private: public: final void foo(){}}
}, sac); }, sac);
assertAnalyzerWarnings(q{ assertAnalyzerWarnings(q{
class Foo{private: public: final void foo(){}} class Foo{private: public: final void foo(){}}
}, sac); }, sac);
assertAnalyzerWarnings(q{ assertAnalyzerWarnings(q{
class Impl class Impl
{ {
private: private:
static if (true) static if (true)
{ {
protected final void _wrap_getSource() {} protected final void _wrap_getSource() {}
} }
} }
}, sac); }, sac);
assertAnalyzerWarnings(q{ assertAnalyzerWarnings(q{
mixin template Impl() mixin template Impl()
{ {
protected final void mixin_template_can() {} protected final void mixin_template_can() {}
} }
}, sac); }, sac);
// fail // fail
assertAnalyzerWarnings(q{ assertAnalyzerWarnings(q{
final void foo(){} // [warn]: %s final void foo(){} // [warn]: %s
}c.format( }c.format(
FinalAttributeChecker.MSGB.format(FinalAttributeChecker.MESSAGE.func_g) FinalAttributeChecker.MSGB.format(FinalAttributeChecker.MESSAGE.func_g)
), sac); ), sac);
assertAnalyzerWarnings(q{ assertAnalyzerWarnings(q{
void foo(){final void foo(){}} // [warn]: %s void foo(){final void foo(){}} // [warn]: %s
}c.format( }c.format(
FinalAttributeChecker.MSGB.format(FinalAttributeChecker.MESSAGE.func_n) FinalAttributeChecker.MSGB.format(FinalAttributeChecker.MESSAGE.func_n)
), sac); ), sac);
assertAnalyzerWarnings(q{ assertAnalyzerWarnings(q{
void foo() void foo()
{ {
static if (true) static if (true)
final class A{ private: final protected void foo(){}} // [warn]: %s final class A{ private: final protected void foo(){}} // [warn]: %s
} }
}c.format( }c.format(
FinalAttributeChecker.MSGB.format(FinalAttributeChecker.MESSAGE.class_f) FinalAttributeChecker.MSGB.format(FinalAttributeChecker.MESSAGE.class_f)
), sac); ), sac);
assertAnalyzerWarnings(q{ assertAnalyzerWarnings(q{
final struct Foo{} // [warn]: %s final struct Foo{} // [warn]: %s
}c.format( }c.format(
FinalAttributeChecker.MSGB.format(FinalAttributeChecker.MESSAGE.struct_i) FinalAttributeChecker.MSGB.format(FinalAttributeChecker.MESSAGE.struct_i)
), sac); ), sac);
assertAnalyzerWarnings(q{ assertAnalyzerWarnings(q{
final union Foo{} // [warn]: %s final union Foo{} // [warn]: %s
}c.format( }c.format(
FinalAttributeChecker.MSGB.format(FinalAttributeChecker.MESSAGE.union_i) FinalAttributeChecker.MSGB.format(FinalAttributeChecker.MESSAGE.union_i)
), sac); ), sac);
assertAnalyzerWarnings(q{ assertAnalyzerWarnings(q{
class Foo{private final void foo(){}} // [warn]: %s class Foo{private final void foo(){}} // [warn]: %s
}c.format( }c.format(
FinalAttributeChecker.MSGB.format(FinalAttributeChecker.MESSAGE.class_p) FinalAttributeChecker.MSGB.format(FinalAttributeChecker.MESSAGE.class_p)
), sac); ), sac);
assertAnalyzerWarnings(q{ assertAnalyzerWarnings(q{
class Foo{private: final void foo(){}} // [warn]: %s class Foo{private: final void foo(){}} // [warn]: %s
}c.format( }c.format(
FinalAttributeChecker.MSGB.format(FinalAttributeChecker.MESSAGE.class_p) FinalAttributeChecker.MSGB.format(FinalAttributeChecker.MESSAGE.class_p)
), sac); ), sac);
assertAnalyzerWarnings(q{ assertAnalyzerWarnings(q{
interface Foo{final void foo(T)(){}} // [warn]: %s interface Foo{final void foo(T)(){}} // [warn]: %s
}c.format( }c.format(
FinalAttributeChecker.MSGB.format(FinalAttributeChecker.MESSAGE.interface_t) FinalAttributeChecker.MSGB.format(FinalAttributeChecker.MESSAGE.interface_t)
), sac); ), sac);
assertAnalyzerWarnings(q{ assertAnalyzerWarnings(q{
final class Foo{final void foo(){}} // [warn]: %s final class Foo{final void foo(){}} // [warn]: %s
}c.format( }c.format(
FinalAttributeChecker.MSGB.format(FinalAttributeChecker.MESSAGE.class_f) FinalAttributeChecker.MSGB.format(FinalAttributeChecker.MESSAGE.class_f)
), sac); ), sac);
assertAnalyzerWarnings(q{ assertAnalyzerWarnings(q{
private: final class Foo {public: private final void foo(){}} // [warn]: %s private: final class Foo {public: private final void foo(){}} // [warn]: %s
}c.format( }c.format(
FinalAttributeChecker.MSGB.format(FinalAttributeChecker.MESSAGE.class_p) FinalAttributeChecker.MSGB.format(FinalAttributeChecker.MESSAGE.class_p)
), sac); ), sac);
assertAnalyzerWarnings(q{ assertAnalyzerWarnings(q{
class Foo {final static void foo(){}} // [warn]: %s class Foo {final static void foo(){}} // [warn]: %s
}c.format( }c.format(
FinalAttributeChecker.MSGB.format(FinalAttributeChecker.MESSAGE.class_s) FinalAttributeChecker.MSGB.format(FinalAttributeChecker.MESSAGE.class_s)
), sac); ), sac);
assertAnalyzerWarnings(q{ assertAnalyzerWarnings(q{
class Foo class Foo
{ {
void foo(){} void foo(){}
static: final void foo(){} // [warn]: %s static: final void foo(){} // [warn]: %s
} }
}c.format( }c.format(
FinalAttributeChecker.MSGB.format(FinalAttributeChecker.MESSAGE.class_s) FinalAttributeChecker.MSGB.format(FinalAttributeChecker.MESSAGE.class_s)
), sac); ), sac);
assertAnalyzerWarnings(q{ assertAnalyzerWarnings(q{
class Foo class Foo
{ {
void foo(){} void foo(){}
static{ final void foo(){}} // [warn]: %s static{ final void foo(){}} // [warn]: %s
void foo(){} void foo(){}
} }
}c.format( }c.format(
FinalAttributeChecker.MSGB.format(FinalAttributeChecker.MESSAGE.class_s) FinalAttributeChecker.MSGB.format(FinalAttributeChecker.MESSAGE.class_s)
), sac); ), sac);
stderr.writeln("Unittest for FinalAttributeChecker passed."); stderr.writeln("Unittest for FinalAttributeChecker passed.");
} }

View File

@ -174,13 +174,13 @@ if (R == int) // [warn]: %s
assertAnalyzerWarnings(q{ assertAnalyzerWarnings(q{
Num abs(Num)(Num x) @safe pure nothrow Num abs(Num)(Num x) @safe pure nothrow
if (is(typeof(Num.init >= 0)) && is(typeof(-Num.init)) && if (is(typeof(Num.init >= 0)) && is(typeof(-Num.init)) &&
!(is(Num* : const(ifloat*)) || is(Num* : const(idouble*)) !(is(Num* : const(ifloat*)) || is(Num* : const(idouble*))
|| is(Num* : const(ireal*)))) || is(Num* : const(ireal*))))
{ {
static if (isFloatingPoint!(Num)) static if (isFloatingPoint!(Num))
return fabs(x); return fabs(x);
else else
return x >= 0 ? x : -x; return x >= 0 ? x : -x;
} }
}, sac); }, sac);

View File

@ -347,8 +347,8 @@ unittest
import foo; import foo;
import foo.bar; import foo.bar;
import fooa; import fooa;
import std.range : Take; import std.range : Take;
import std.range.primitives : isInputRange, walkLength; import std.range.primitives : isInputRange, walkLength;
}, sac); }, sac);
// condition declaration // condition declaration

View File

@ -228,7 +228,7 @@ unittest
unittest unittest
{ {
version(LittleEndian) { enum string NAME = "UTF-16LE"; } version(LittleEndian) { enum string NAME = "UTF-16LE"; }
else version(BigEndian) { enum string NAME = "UTF-16BE"; } else version(BigEndian) { enum string NAME = "UTF-16BE"; }
} }
@ -267,8 +267,8 @@ unittest
unittest unittest
{ {
int aa; int aa;
struct a { int a; } struct a { int a; }
} }
}c, sac); }c, sac);

View File

@ -11,37 +11,37 @@ import dscanner.analysis.base;
class LambdaReturnCheck : BaseAnalyzer class LambdaReturnCheck : BaseAnalyzer
{ {
alias visit = BaseAnalyzer.visit; alias visit = BaseAnalyzer.visit;
this(string fileName, bool skipTests = false) this(string fileName, bool skipTests = false)
{ {
super(fileName, null, skipTests); super(fileName, null, skipTests);
} }
override void visit(const FunctionLiteralExpression fLit) override void visit(const FunctionLiteralExpression fLit)
{ {
if (fLit.assignExpression is null) if (fLit.assignExpression is null)
return; return;
const UnaryExpression unary = cast(const UnaryExpression) fLit.assignExpression; const UnaryExpression unary = cast(const UnaryExpression) fLit.assignExpression;
if (unary is null) if (unary is null)
return; return;
if (unary.primaryExpression is null) if (unary.primaryExpression is null)
return; return;
if (unary.primaryExpression.functionLiteralExpression is null) if (unary.primaryExpression.functionLiteralExpression is null)
return; return;
if (unary.primaryExpression.functionLiteralExpression.parameters !is null) if (unary.primaryExpression.functionLiteralExpression.parameters !is null)
return; return;
if (unary.primaryExpression.functionLiteralExpression.identifier != tok!"") if (unary.primaryExpression.functionLiteralExpression.identifier != tok!"")
return; return;
if (unary.primaryExpression.functionLiteralExpression.functionBody is null) if (unary.primaryExpression.functionLiteralExpression.functionBody is null)
return; return;
if (unary.primaryExpression.functionLiteralExpression.functionBody.blockStatement is null) if (unary.primaryExpression.functionLiteralExpression.functionBody.blockStatement is null)
return; return;
addErrorMessage(fLit.line, fLit.column, KEY, "This lambda returns a lambda. Add parenthesis to clarify."); addErrorMessage(fLit.line, fLit.column, KEY, "This lambda returns a lambda. Add parenthesis to clarify.");
} }
private: private:
enum KEY = "dscanner.confusing.lambda_returns_lambda"; enum KEY = "dscanner.confusing.lambda_returns_lambda";
} }
version(Windows) {/*because of newline in code*/} else version(Windows) {/*because of newline in code*/} else

View File

@ -122,12 +122,12 @@ unittest
class Bat class Bat
{ {
const: override string toString() { return "foo"; } // ok const: override string toString() { return "foo"; } // ok
} }
class Fox class Fox
{ {
const{ override string toString() { return "foo"; }} // ok const{ override string toString() { return "foo"; }} // ok
} }
// Will warn, because none are const // Will warn, because none are const

View File

@ -718,28 +718,28 @@ unittest
assertAnalyzerWarnings(q{ assertAnalyzerWarnings(q{
/++ /++
Counts elements in the given Counts elements in the given
$(REF_ALTTEXT forward range, isForwardRange, std,range,primitives) $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives)
until the given predicate is true for one of the given $(D needles). until the given predicate is true for one of the given $(D needles).
Params: Params:
val = A stupid parameter val = A stupid parameter
Returns: Awesome values. Returns: Awesome values.
+/ +/
string bar(string val){} string bar(string val){}
}c, sac); }c, sac);
assertAnalyzerWarnings(q{ assertAnalyzerWarnings(q{
/++ /++
Counts elements in the given Counts elements in the given
$(REF_ALTTEXT forward range, isForwardRange, std,range,primitives) $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives)
until the given predicate is true for one of the given $(D needles). until the given predicate is true for one of the given $(D needles).
Params: Params:
val = A stupid parameter val = A stupid parameter
Returns: Awesome values. Returns: Awesome values.
+/ +/
template bar(string val){} template bar(string val){}
}c, sac); }c, sac);
@ -835,10 +835,10 @@ unittest
Implements the homonym function (also known as `accumulate`) Implements the homonym function (also known as `accumulate`)
Returns: Returns:
the accumulated `result` the accumulated `result`
Params: Params:
fun = one or more functions fun = one or more functions
+/ +/
template reduce(fun...) template reduce(fun...)
if (fun.length >= 1) if (fun.length >= 1)

View File

@ -332,40 +332,40 @@ bool isValueTypeSimple(const Type type) pure nothrow @nogc
@system unittest @system unittest
{ {
import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig; import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig;
import dscanner.analysis.helpers : assertAnalyzerWarnings; import dscanner.analysis.helpers : assertAnalyzerWarnings;
import std.stdio : stderr; import std.stdio : stderr;
import std.format : format; import std.format : format;
StaticAnalysisConfig sac = disabledConfig(); StaticAnalysisConfig sac = disabledConfig();
sac.could_be_immutable_check = Check.enabled; sac.could_be_immutable_check = Check.enabled;
// fails // fails
assertAnalyzerWarnings(q{ assertAnalyzerWarnings(q{
void foo(){int i = 1;} // [warn]: Variable i is never modified and could have been declared const or immutable. void foo(){int i = 1;} // [warn]: Variable i is never modified and could have been declared const or immutable.
}, sac); }, sac);
// pass // pass
assertAnalyzerWarnings(q{
void foo(){const(int) i;}
}, sac);
assertAnalyzerWarnings(q{ assertAnalyzerWarnings(q{
void foo(){immutable(int)* i;} void foo(){const(int) i;}
}, sac); }, sac);
assertAnalyzerWarnings(q{ assertAnalyzerWarnings(q{
void foo(){enum i = 1;} void foo(){immutable(int)* i;}
}, sac); }, sac);
assertAnalyzerWarnings(q{ assertAnalyzerWarnings(q{
void foo(){E e = new E;} void foo(){enum i = 1;}
}, sac); }, sac);
assertAnalyzerWarnings(q{ assertAnalyzerWarnings(q{
void foo(){auto e = new E;} void foo(){E e = new E;}
}, sac); }, sac);
assertAnalyzerWarnings(q{
void foo(){auto e = new E;}
}, sac);
} }

View File

@ -186,7 +186,7 @@ if (is(M == class))
__traits(getMember, m, member) = a; __traits(getMember, m, member) = a;
} }
} }
} }
} }
/// General usage /// General usage
@safe unittest @safe unittest