fix #312 - spurious warnings about non-const toString inside const block (#505)

This commit is contained in:
Basile Burg 2017-07-28 00:30:03 +02:00 committed by GitHub
parent ce6056d4bc
commit 7b91483943
1 changed files with 38 additions and 10 deletions

View File

@ -21,6 +21,7 @@ class ObjectConstCheck : BaseAnalyzer
{ {
alias visit = BaseAnalyzer.visit; alias visit = BaseAnalyzer.visit;
///
this(string fileName, const(Scope)* sc, bool skipTests = false) this(string fileName, const(Scope)* sc, bool skipTests = false)
{ {
super(fileName, sc, skipTests); super(fileName, sc, skipTests);
@ -31,24 +32,40 @@ class ObjectConstCheck : BaseAnalyzer
mixin visitTemplate!UnionDeclaration; mixin visitTemplate!UnionDeclaration;
mixin visitTemplate!StructDeclaration; mixin visitTemplate!StructDeclaration;
override void visit(const AttributeDeclaration d)
{
if (d.attribute.attribute == tok!"const" && inAggregate)
{
constColon = true;
}
d.accept(this);
}
override void visit(const Declaration d) override void visit(const Declaration d)
{ {
if (inAggregate && d.functionDeclaration !is null import std.algorithm : any;
&& isInteresting(d.functionDeclaration.name.text) && (!hasConst(d.attributes) bool setConstBlock;
&& !hasConst(d.functionDeclaration.memberFunctionAttributes))) if (inAggregate && d.attributes && d.attributes.any!(a => a.attribute == tok!"const"))
{
setConstBlock = true;
constBlock = true;
}
if (inAggregate && d.functionDeclaration !is null && !constColon && !constBlock
&& isInteresting(d.functionDeclaration.name.text)
&& !hasConst(d.functionDeclaration.memberFunctionAttributes))
{ {
addErrorMessage(d.functionDeclaration.name.line, addErrorMessage(d.functionDeclaration.name.line,
d.functionDeclaration.name.column, "dscanner.suspicious.object_const", d.functionDeclaration.name.column, "dscanner.suspicious.object_const",
"Methods 'opCmp', 'toHash', 'opEquals', 'opCast', and/or 'toString' are non-const."); "Methods 'opCmp', 'toHash', 'opEquals', 'opCast', and/or 'toString' are non-const.");
} }
d.accept(this); d.accept(this);
}
private static bool hasConst(const Attribute[] attributes) if (!inAggregate)
{ constColon = false;
import std.algorithm : any; if (setConstBlock)
constBlock = false;
return attributes.any!(a => a.attribute == tok!"const");
} }
private static bool hasConst(const MemberFunctionAttribute[] attributes) private static bool hasConst(const MemberFunctionAttribute[] attributes)
@ -65,7 +82,8 @@ class ObjectConstCheck : BaseAnalyzer
|| name == "toString" || name == "opCast"; || name == "toString" || name == "opCast";
} }
private bool looking; private bool constBlock;
private bool constColon;
} }
@ -102,6 +120,16 @@ unittest
} }
} }
class Bat
{
const: override string toString() { return "foo"; } // ok
}
class Fox
{
const{ override string toString() { return "foo"; }} // ok
}
// Will warn, because none are const // Will warn, because none are const
class Dog class Dog
{ {