我正在尝试使用CheckStyle在给定源文件中找到的所有方法中检索所有参数名称。这是相关代码:
public int[] getDefaultTokens()
{
return new int[] { TokenTypes.METHOD_DEF};
}
public void visitToken(DetailAST aDetailAST)
{
String returnType; // The return type of the method.
int numberOfParameters; // The number of parameters in the method's parameter list... not returned in log.
String [] parameterNames; // The names of all method parameters.
int openingBraceLine; // The line number of the opening method bracket.
returnType = aDetailAST.findFirstToken(TokenTypes.TYPE).getFirstChild().getText(); // get the return type.
numberOfParameters = aDetailAST.findFirstToken(TokenTypes.PARAMETERS).getChildCount(TokenTypes.PARAMETER_DEF); // get num of parameters.
parameterNames = new String[numberOfParameters]; // create array to store the parameter names.
if (numberOfParameters > 0) // only bother if parameters existed.
{
List <DetailAST> parameters = DetailASTUtil.getDetailASTsForTypeInBranch // Get all PARAMETER_DEF nodes.
(aDetailAST.findFirstToken(TokenTypes.PARAMETERS)
, TokenTypes.PARAMETER_DEF);
int i = 0;
for (DetailAST currentParameter: parameters) // iterate through all parameters.
{
parameterNames[i] = currentParameter.findFirstToken(TokenTypes.IDENT).getText();
// Get the parameter name, store it in the array.
i++; // iterate to next parameter name array storage index.
}
}
// parameterNames now contains all parameter names in the parameter list. Format it for log message.
String formattedParameterNames = "";
if (numberOfParameters > 1) // if more than one parameter was present, then create comma list.
{
for (int i = 0; i < parameterNames.length-1; i++) // put all names in comma-separated string except for last.
{
formattedParameterNames += parameterNames[i] + ", ";
}
formattedParameterNames += parameterNames[numberOfParameters-1]; // add the last element of the comma list.
}
else if (numberOfParameters == 1) // only one parameter -- don't comma-delimit.
{
formattedParameterNames = parameterNames[0];
}
if (numberOfParameters == 2) // debug to see if string formatting is messing up the parameter names or if tree traversal is bad.
{
formattedParameterNames = "Param 1: " + parameterNames[0] + " Param 2: " + parameterNames[1];
}
log(aDetailAST.getLineNo(), "[" + returnType + "]" + ", [" + formattedParameterNames + "], ");
// will be further parsed in actual applet since I don't think there's a way to get individual lines of code via CheckStyle... I would like if a getTextForLineofCode(lineNumber) func existed with CheckStyle, but I don't think it does.
}
public static List<DetailAST> getDetailASTsForTypeInBranch(DetailAST expr,
int tokenType) {
return getDetailASTsForTypeInBranch(expr, tokenType, null);
}
private static List<DetailAST> getDetailASTsForTypeInBranch(DetailAST expr,
int tokenType, List<DetailAST> list) {
if (list == null)
list = new ArrayList<DetailAST>();
DetailAST child = (DetailAST) expr.getFirstChild();
while (child != null) {
if (child.getType() == tokenType) {
list.add(child);
} else {
list = getDetailASTsForTypeInBranch(child, tokenType, list);
}
child = (DetailAST) child.getNextSibling();
}
return list;
}
当我在主小程序中检索到此日志消息时,带有无/单个参数列表的函数似乎很好,但是双参数函数根本没有注册,或者返回消息“ secondParmeterNameHere]”,其中secondParameterNameHere是特定功能的第二个参数名称。
关于获取所有参数名称的算法有什么问题的任何想法?谢谢。
我花了两美分来优化代码。
您可以使用递归帮助器方法替换
DetailAST child = (DetailAST) expr.getFirstChild();
while (child != null) {
if (child.getType() == tokenType) {
list.add(child);
} else {
list = getDetailASTsForTypeInBranch(child, tokenType, list);
}
child = (DetailAST) child.getNextSibling();
}
作者
for(DetailAST child = (DetailAST) expr.getFirstChild(); child != null; child = (DetailAST) child.getNextSibling()) {
if (child.getType() == tokenType) {
list.add(child);
} else {
list = getDetailASTsForTypeInBranch(child, tokenType, list);
}
}
这是某种“分配重复:
list = getDetailASTsForTypeInBranch(child, tokenType, list);
您正在通过引用传递“列表”。在递归过程中,您将对此引用(list.add(..))进行操作。但您仍然稍后会将此列表作为返回值返回。并在递归中将此返回值重新分配给原始输入变量,尽管在递归过程中已对其进行了修改?!
您应该使用返回值,并且不要将列表作为输入参数传递。或者,您可以传递列表,但是您的方法则不应具有返回值。
变量parameterNames已过时,因为您仅使用它来再次对其进行迭代并连接一个String。您的字符串连接也重复且效率低下。我将提出以下解决方案:
StringBuilder formattedParameterNames = new StringBuilder();
for (Iterator<DetailAST> iterator = parameters.iterator(); iterator.hasNext();) {
DetailAST detailAST = iterator.next();
formattedParameterNames.append(detailAST.findFirstToken(TokenTypes.IDENT).getText());
if(iterator.hasNext()) {
formattedParameterNames.append(", ");
}
}
您可以在StringBuilder上调用toString()来获取日志记录语句。
希望下面的代码片段将对您有所帮助
@Override
public int[] getDefaultTokens() {
return new int[] { TokenTypes.METHOD_DEF};
}
@Override
public void visitToken(DetailAST ast) {
String methodName = null;
String returnType = null;
int numberOfParameters = 0;
methodName = ast.findFirstToken(TokenTypes.IDENT).getText();
DetailAST typeElt = ast.findFirstToken(TokenTypes.TYPE);
returnType = typeElt.getFirstChild().getText();
DetailAST parametersElt = ast.findFirstToken(TokenTypes.PARAMETERS);
numberOfParameters = parametersElt.getChildCount(TokenTypes.PARAMETER_DEF);
log(ast,"Method Name : "+methodName);
log(ast,"Return Type : "+returnType);
log(ast,"No Of Parameters : "+numberOfParameters);
DetailAST paraElt = parametersElt.findFirstToken(TokenTypes.PARAMETER_DEF);
int i=1;
while(paraElt != null){
if(paraElt.getType() == TokenTypes.PARAMETER_DEF){
String dataType = paraElt.findFirstToken(TokenTypes.TYPE).getFirstChild().getText();
String paraName = paraElt.findFirstToken(TokenTypes.IDENT).getText();
log(ast,"Parameter "+i+" ("+dataType+" "+paraName+")");
i++;
}
paraElt = paraElt.getNextSibling();
}
}
输出将类似于
[ERROR] path\Test.java:8:9: Method Name : add [ListMethodParameters]
[ERROR] path\Test.java:8:9: No Of Parameters : 0 [ListMethodParameters]
[ERROR] path\Test.java:8:9: Return Type : void [ListMethodParameters]
[ERROR] path\Test.java:12:9: Method Name : sub [ListMethodParameters]
[ERROR] path\Test.java:12:9: No Of Parameters : 3 [ListMethodParameters]
[ERROR] path\Test.java:12:9: Parameter 1 (int a) [ListMethodParameters]
[ERROR] path\Test.java:12:9: Parameter 2 (int b) [ListMethodParameters]
[ERROR] path\Test.java:12:9: Parameter 3 (int c) [ListMethodParameters]
[ERROR] path\Test.java:12:9: Return Type : int [ListMethodParameters]
Java文件用于测试上面的代码
public class Test {
public void add(){
name.length();
}
public int sub(int a,int b,int c){
return a+b+c;
}
}