D-Scanner/src/analysis/function_attributes.d

86 lines
2.1 KiB
D

// Copyright Brian Schott (Hackerpilot) 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
module analysis.function_attributes;
import std.d.ast;
import std.d.lexer;
import analysis.base;
import std.stdio;
/**
* Prefer
* ---
* int getStuff() const {}
* ---
* to
* ---
* const int getStuff() {}
* ---
*/
class FunctionAttributeCheck : BaseAnalyzer
{
alias visit = BaseAnalyzer.visit;
this(string fileName)
{
super(fileName);
}
override void visit(const InterfaceDeclaration dec)
{
inInterface++;
dec.accept(this);
inInterface--;
}
override void visit(const AttributeDeclaration dec)
{
if (inInterface > 0 && dec.attribute.storageClass !is null
&& dec.attribute.storageClass.token == tok!"abstract")
{
addErrorMessage(dec.attribute.storageClass.token.line,
dec.attribute.storageClass.token.column, KEY, ABSTRACT_MESSAGE);
}
}
override void visit(const Declaration dec)
{
if (dec.attributes.length == 0)
goto end;
foreach (attr; dec.attributes)
{
if (attr.storageClass is null)
continue;
if (attr.storageClass.token == tok!"abstract" && inInterface > 0)
{
addErrorMessage(attr.storageClass.token.line,
attr.storageClass.token.column, KEY, ABSTRACT_MESSAGE);
continue;
}
if (dec.functionDeclaration !is null
&& (attr.storageClass.token == tok!"const"
|| attr.storageClass.token == tok!"inout"
|| attr.storageClass.token == tok!"immutable"))
{
import std.string : format;
immutable string attrString = str(attr.storageClass.token.type);
addErrorMessage(dec.functionDeclaration.name.line,
dec.functionDeclaration.name.column, KEY,
format("'%s' is not an attribute of the return type."
~ " Place it after the parameter list to clarify.", attrString));
}
}
end:
dec.accept(this);
}
int inInterface;
private enum ABSTRACT_MESSAGE = "'abstract' attribute is redundant in interface declarations";
private enum KEY = "dscanner.confusing.function_attributes";
}