/*******************************************************************************
* Copyright (c) 2012 VMWare, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* VMWare, Inc. - initial API and implementation
*******************************************************************************/
package org.grails.ide.eclipse.search;
import java.util.ArrayList;
import java.util.List;
import org.codehaus.groovy.ast.FieldNode;
import org.codehaus.groovy.ast.expr.ClosureExpression;
import org.codehaus.groovy.ast.expr.ConstantExpression;
import org.codehaus.groovy.ast.expr.Expression;
import org.codehaus.groovy.ast.expr.MapEntryExpression;
import org.codehaus.groovy.ast.expr.MethodCallExpression;
import org.codehaus.groovy.ast.expr.NamedArgumentListExpression;
import org.codehaus.groovy.ast.expr.TupleExpression;
import org.codehaus.groovy.ast.stmt.BlockStatement;
import org.codehaus.groovy.ast.stmt.Statement;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.search.IJavaSearchConstants;
import org.eclipse.jdt.core.search.IJavaSearchScope;
import org.eclipse.jdt.internal.ui.search.JavaSearchScopeFactory;
import org.eclipse.jdt.ui.search.ElementQuerySpecification;
import org.eclipse.jdt.ui.search.QuerySpecification;
/**
* @author Kris De Volder
*
* @since 2.9
*/
public class SearchUtil {
/**
* @return true if the query is asking for results to include references.
*/
public static boolean wantsReferences(ElementQuerySpecification q) {
int limit = q.getLimitTo();
return limit == IJavaSearchConstants.REFERENCES || limit == IJavaSearchConstants.ALL_OCCURRENCES;
}
/**
* For a call of the form
* <exp>(..., <name>:<value>)
*retrieves the <key>:<value> node with given name.
*@return the value or null if the call doesn't follow the expected pattern or doesn't have an argument with that
*name.
*/
public static MapEntryExpression getNamedArgument(MethodCallExpression call, String name) {
Expression args = call.getArguments();
if (args!=null && args instanceof TupleExpression) {
TupleExpression argsTuple = (TupleExpression) args;
List<Expression> exps = argsTuple.getExpressions();
if (exps!=null && exps.size()==1) {
Expression theArg = exps.get(0);
if (theArg instanceof NamedArgumentListExpression) {
NamedArgumentListExpression namedArgs = (NamedArgumentListExpression) theArg;
for (MapEntryExpression pair : namedArgs.getMapEntryExpressions()) {
String key = SearchUtil.getStringValue(pair.getKeyExpression());
if (name.equals(key)) {
return pair; //Found!
}
}
}
}
}
return null;
}
/**
* @return the value of an expression as a String, if the expression is a String constant.
* Otherwise returns null.
*/
public static String getStringValue(Expression exp) {
if (exp instanceof ConstantExpression) {
ConstantExpression konst = (ConstantExpression) exp;
Object value = konst.getValue();
if (value instanceof String) {
return (String) value;
}
}
return null;
}
public static QuerySpecification createReferencesQuery(IJavaElement element)
throws JavaModelException {
//This code based on code in org.eclipse.jdt.ui.actions.FindReferencesAction.createQuery(IJavaElement)
//So it emulates the behavior of query created by the 'References' search in the JDT UI.
JavaSearchScopeFactory factory= JavaSearchScopeFactory.getInstance();
boolean isInsideJRE = factory.isInsideJRE(element);
IJavaSearchScope scope= factory.createWorkspaceScope(isInsideJRE);
String description= factory.getWorkspaceScopeDescription(isInsideJRE);
return new ElementQuerySpecification(element, IJavaSearchConstants.REFERENCES , scope, description);
}
public static ClosureExpression getClosureValue(FieldNode node) {
Expression valueExp = node.getInitialExpression();
if (valueExp instanceof ClosureExpression) {
return (ClosureExpression) valueExp;
}
return null;
}
public static Expression getNamedArgumentWithValue(MethodCallExpression call, String argName, String expectedValue) {
MapEntryExpression arg = SearchUtil.getNamedArgument(call, argName);
if (arg!=null) {
final Expression valueExpression = arg.getValueExpression();
String argValue = SearchUtil.getStringValue(valueExpression);
if (expectedValue.equals(argValue)) {
return valueExpression;
}
}
return null;
}
public static List<Statement> getStatements(ClosureExpression closure) {
List<Statement> result = new ArrayList<Statement>();
collectStatements(closure.getCode(), result);
return result;
}
private static void collectStatements(Statement code, List<Statement> result) {
if (code instanceof BlockStatement) {
BlockStatement block = (BlockStatement) code;
for (Statement statement : ((BlockStatement) code).getStatements()) {
collectStatements(statement, result);
}
} else {
result.add(code);
}
}
}