fix all cases of mixed tabs and spaces
This commit is contained in:
parent
af0bebd891
commit
4231deb046
|
@ -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";
|
||||||
|
|
|
@ -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.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue