Added pure and nothrow to the duplicate attribute checker.
This commit is contained in:
parent
fad096cdff
commit
657ef65952
|
|
@ -12,10 +12,10 @@ import std.d.lexer;
|
|||
import analysis.base;
|
||||
import analysis.helpers;
|
||||
|
||||
// FIXME: Make it work with pure, nothrow
|
||||
|
||||
/**
|
||||
* Checks for duplicate attributes such as @property, @safe, @trusted, @system
|
||||
* Checks for duplicate attributes such as @property, @safe,
|
||||
* @trusted, @system, pure, and nothrow
|
||||
*/
|
||||
class DuplicateAttributeCheck : BaseAnalyzer
|
||||
{
|
||||
|
|
@ -38,23 +38,24 @@ class DuplicateAttributeCheck : BaseAnalyzer
|
|||
bool hasSafe = false;
|
||||
bool hasTrusted = false;
|
||||
bool hasSystem = false;
|
||||
bool hasPure = false;
|
||||
bool hasNoThrow = false;
|
||||
|
||||
// Check the attributes
|
||||
foreach (attribute; node.attributes)
|
||||
{
|
||||
// Just skip if missing child nodes
|
||||
if (!attribute
|
||||
|| !attribute.storageClass
|
||||
|| !attribute.storageClass.atAttribute
|
||||
|| attribute.storageClass.atAttribute.identifier is Token.init)
|
||||
continue;
|
||||
size_t line, column;
|
||||
string attributeName = getAttributeName(attribute, line, column);
|
||||
if (!attributeName || line==0 || column==0)
|
||||
return;
|
||||
|
||||
// Check for the attributes
|
||||
auto iden = attribute.storageClass.atAttribute.identifier;
|
||||
checkDuplicateAttribute(iden, "property", hasProperty);
|
||||
checkDuplicateAttribute(iden, "safe", hasSafe);
|
||||
checkDuplicateAttribute(iden, "trusted", hasTrusted);
|
||||
checkDuplicateAttribute(iden, "system", hasSystem);
|
||||
checkDuplicateAttribute(attributeName, "property", line, column, hasProperty);
|
||||
checkDuplicateAttribute(attributeName, "safe", line, column, hasSafe);
|
||||
checkDuplicateAttribute(attributeName, "trusted", line, column, hasTrusted);
|
||||
checkDuplicateAttribute(attributeName, "system", line, column, hasSystem);
|
||||
checkDuplicateAttribute(attributeName, "pure", line, column, hasPure);
|
||||
checkDuplicateAttribute(attributeName, "nothrow", line, column, hasNoThrow);
|
||||
}
|
||||
|
||||
// Just return if missing function nodes
|
||||
|
|
@ -65,38 +66,96 @@ class DuplicateAttributeCheck : BaseAnalyzer
|
|||
// Check the functions
|
||||
foreach (memberFunctionAttribute; node.functionDeclaration.memberFunctionAttributes)
|
||||
{
|
||||
// Just skip if missing child nodes
|
||||
if (!memberFunctionAttribute
|
||||
|| !memberFunctionAttribute.atAttribute
|
||||
|| memberFunctionAttribute.atAttribute.identifier is Token.init)
|
||||
continue;
|
||||
size_t line, column;
|
||||
string attributeName = getAttributeName(memberFunctionAttribute, line, column);
|
||||
if (!attributeName || line==0 || column==0)
|
||||
return;
|
||||
|
||||
// Check for the attributes
|
||||
auto iden = memberFunctionAttribute.atAttribute.identifier;
|
||||
checkDuplicateAttribute(iden, "property", hasProperty);
|
||||
checkDuplicateAttribute(iden, "safe", hasSafe);
|
||||
checkDuplicateAttribute(iden, "trusted", hasTrusted);
|
||||
checkDuplicateAttribute(iden, "system", hasSystem);
|
||||
checkDuplicateAttribute(attributeName, "property", line, column, hasProperty);
|
||||
checkDuplicateAttribute(attributeName, "safe", line, column, hasSafe);
|
||||
checkDuplicateAttribute(attributeName, "trusted", line, column, hasTrusted);
|
||||
checkDuplicateAttribute(attributeName, "system", line, column, hasSystem);
|
||||
checkDuplicateAttribute(attributeName, "pure", line, column, hasPure);
|
||||
checkDuplicateAttribute(attributeName, "nothrow", line, column, hasNoThrow);
|
||||
}
|
||||
}
|
||||
|
||||
void checkDuplicateAttribute(const Token token, const string attributeName, ref bool hasAttribute)
|
||||
void checkDuplicateAttribute(const string attributeName, const string attributeDesired, size_t line, size_t column, ref bool hasAttribute)
|
||||
{
|
||||
// Just return if not an attribute
|
||||
if (token.type != tok!"identifier"
|
||||
|| token.text != attributeName)
|
||||
if (attributeName != attributeDesired)
|
||||
return;
|
||||
|
||||
// Already has that attribute
|
||||
if (hasAttribute)
|
||||
{
|
||||
string message = "The attribute '%s' is duplicated.".format(token.text);
|
||||
addErrorMessage(token.line, token.column, message);
|
||||
string message = "The attribute '%s' is duplicated.".format(attributeName);
|
||||
addErrorMessage(line, column, message);
|
||||
}
|
||||
|
||||
// Mark it as having that attribute
|
||||
hasAttribute = true;
|
||||
}
|
||||
|
||||
string getAttributeName(const Attribute attribute, ref size_t line, ref size_t column)
|
||||
{
|
||||
// Get the name from the attribute identifier
|
||||
if (attribute
|
||||
&& attribute.storageClass
|
||||
&& attribute.storageClass.atAttribute
|
||||
&& attribute.storageClass.atAttribute.identifier !is Token.init
|
||||
&& attribute.storageClass.atAttribute.identifier.text
|
||||
&& attribute.storageClass.atAttribute.identifier.text.length)
|
||||
{
|
||||
auto token = attribute.storageClass.atAttribute.identifier;
|
||||
line = token.line;
|
||||
column = token.column;
|
||||
return token.text;
|
||||
}
|
||||
|
||||
// Get the attribute from the storage class token
|
||||
if (attribute
|
||||
&& attribute.storageClass
|
||||
&& attribute.storageClass.token !is Token.init)
|
||||
{
|
||||
auto token = attribute.storageClass.token;
|
||||
line = token.line;
|
||||
column = token.column;
|
||||
return token.type.str;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
string getAttributeName(const MemberFunctionAttribute memberFunctionAttribute, ref size_t line, ref size_t column)
|
||||
{
|
||||
// Get the name from the tokenType
|
||||
if (memberFunctionAttribute
|
||||
&& memberFunctionAttribute.tokenType !is IdType.init
|
||||
&& memberFunctionAttribute.tokenType.str
|
||||
&& memberFunctionAttribute.tokenType.str.length)
|
||||
{
|
||||
// FIXME: How do we get the line/column number?
|
||||
return memberFunctionAttribute.tokenType.str;
|
||||
}
|
||||
|
||||
// Get the name from the attribute identifier
|
||||
if (memberFunctionAttribute
|
||||
&& memberFunctionAttribute.atAttribute
|
||||
&& memberFunctionAttribute.atAttribute.identifier !is Token.init
|
||||
&& memberFunctionAttribute.atAttribute.identifier.type == tok!"identifier"
|
||||
&& memberFunctionAttribute.atAttribute.identifier.text
|
||||
&& memberFunctionAttribute.atAttribute.identifier.text.length)
|
||||
{
|
||||
auto iden = memberFunctionAttribute.atAttribute.identifier;
|
||||
line = iden.line;
|
||||
column = iden.column;
|
||||
return iden.text;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
unittest
|
||||
|
|
@ -133,6 +192,36 @@ unittest
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class ExamplePureNoThrow
|
||||
{
|
||||
pure nothrow bool aaa() // ok
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
pure pure bool bbb() // [warn]: The attribute 'pure' is duplicated.
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// FIXME: There is no way to get the line/column number of the attribute like this
|
||||
bool ccc() pure pure // FIXME: [warn]: The attribute 'pure' is duplicated.
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
nothrow nothrow bool ddd() // [warn]: The attribute 'nothrow' is duplicated.
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// FIXME: There is no way to get the line/column number of the attribute like this
|
||||
bool eee() nothrow nothrow // FIXME: [warn]: The attribute 'nothrow' is duplicated.
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}c, analysis.run.AnalyzerCheck.duplicate_attribute);
|
||||
|
||||
stderr.writeln("Unittest for DuplicateAttributeCheck passed.");
|
||||
|
|
|
|||
Loading…
Reference in New Issue