/*
* Copyright (c) 2014, the Dart project authors.
*
* Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.eclipse.org/legal/epl-v10.html
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.dart.java2dart.engine;
import com.google.common.collect.Maps;
import com.google.dart.engine.ast.ArgumentList;
import com.google.dart.engine.ast.CompilationUnit;
import com.google.dart.engine.ast.Expression;
import com.google.dart.engine.ast.ExpressionFunctionBody;
import com.google.dart.engine.ast.FormalParameter;
import com.google.dart.engine.ast.FormalParameterList;
import com.google.dart.engine.ast.MethodDeclaration;
import com.google.dart.engine.ast.MethodInvocation;
import com.google.dart.engine.ast.NullLiteral;
import com.google.dart.engine.ast.SimpleIdentifier;
import com.google.dart.engine.ast.visitor.RecursiveAstVisitor;
import com.google.dart.java2dart.Context;
import com.google.dart.java2dart.processor.SemanticProcessor;
import static com.google.dart.java2dart.util.AstFactory.expressionFunctionBody;
import static com.google.dart.java2dart.util.AstFactory.formalParameterList;
import static com.google.dart.java2dart.util.AstFactory.functionExpression;
import static com.google.dart.java2dart.util.AstFactory.functionExpressionInvocation;
import static com.google.dart.java2dart.util.AstFactory.identifier;
import static com.google.dart.java2dart.util.AstFactory.isExpression;
import static com.google.dart.java2dart.util.AstFactory.simpleFormalParameter;
import static com.google.dart.java2dart.util.AstFactory.typeName;
import static com.google.dart.java2dart.util.TokenFactory.token;
import org.eclipse.jdt.core.dom.IBinding;
import org.eclipse.jdt.core.dom.IVariableBinding;
import java.util.List;
import java.util.Map;
/**
* Replace <code>isInstanceOf(Object, Type)</code> invocations with a predicate invocation.
*/
public class EngineInstanceOfProcessor extends SemanticProcessor {
public EngineInstanceOfProcessor(Context context) {
super(context);
}
@Override
public void process(CompilationUnit unit) {
unit.accept(new RecursiveAstVisitor<Void>() {
String replace_isInstanceOf_arg = null;
Map<String, String> replaceIdentifiersMap = Maps.newHashMap();
@Override
public Void visitMethodDeclaration(MethodDeclaration node) {
replaceIdentifiersMap.clear();
FormalParameterList parameterList = node.getParameters();
if (parameterList != null) {
List<FormalParameter> parameters = parameterList.getParameters();
if (isMethodInClass(node, "getAncestor", "com.google.dart.engine.ast.AstNode")
|| isMethodInClass(
node,
"getNodeMatching",
"com.google.dart.engine.internal.element.ElementImpl")
&& parameters.size() == 1
|| isMethodInClass(
node,
"getAncestor",
"com.google.dart.engine.internal.element.ElementImpl")
|| isMethodInClass(node, "getAncestor", "com.google.dart.engine.element.Element")) {
parameterList.getParameters().set(
0,
simpleFormalParameter(typeName("Predicate", typeName("AstNode")), "predicate"));
replace_isInstanceOf_arg = "node";
}
if (isMethodInClass(node, "getAncestor", "com.google.dart.engine.element.Element")) {
parameterList.getParameters().set(
0,
simpleFormalParameter(typeName("Predicate", typeName("Element")), "predicate"));
replace_isInstanceOf_arg = "ancestor";
}
if (isMethodInClass(node, "assertInstanceOf", "com.google.dart.engine.EngineTestCase")) {
parameterList.getParameters().add(
0,
simpleFormalParameter(typeName("Predicate", typeName("Object")), "predicate"));
replace_isInstanceOf_arg = "object";
}
if (isMethodInClass(
node,
"assertLocate",
"com.google.dart.engine.ast.visitor.NodeLocatorTest") && parameters.size() == 4) {
parameterList.getParameters().add(
3,
simpleFormalParameter(typeName("Predicate", typeName("AstNode")), "predicate"));
replace_isInstanceOf_arg = "node";
}
if (isMethodInClass(node, "findNode", "com.google.dart.engine.EngineTestCase")
|| isMethodInClass(
node,
"assertLocate",
"com.google.dart.engine.ast.visitor.NodeLocatorTest") && parameters.size() == 4) {
parameterList.getParameters().set(
3,
simpleFormalParameter(typeName("Predicate", typeName("AstNode")), "predicate"));
replace_isInstanceOf_arg = "node";
}
if (isMethodInClass(
node,
"checkResolved",
"com.google.dart.engine.internal.resolver.ResolutionVerifier")) {
parameterList.getParameters().set(
2,
simpleFormalParameter(typeName("Predicate", typeName("Element")), "predicate"));
replace_isInstanceOf_arg = "element";
replaceIdentifiersMap.put("expectedClass", "predicate");
}
}
try {
return super.visitMethodDeclaration(node);
} finally {
replace_isInstanceOf_arg = null;
replaceIdentifiersMap.clear();
}
}
@Override
public Void visitMethodInvocation(MethodInvocation node) {
String name = node.getMethodName().getName();
ArgumentList argumentList = node.getArgumentList();
List<Expression> arguments = argumentList.getArguments();
if (replace_isInstanceOf_arg != null && name.equals("isInstanceOf")) {
replaceNode(
node,
functionExpressionInvocation(
identifier("predicate"),
identifier(replace_isInstanceOf_arg)));
}
int typeLiteralIndex = -1;
String predicateArgumentName = "_";
if (isMethodInClass(node, "getAncestor", "com.google.dart.engine.ast.AstNode")
|| isMethodInClass(
node,
"getNodeMatching",
"com.google.dart.engine.internal.element.ElementImpl") && arguments.size() == 1) {
typeLiteralIndex = 0;
predicateArgumentName = "node";
}
if (isMethodInClass(
node,
"getAncestor",
"com.google.dart.engine.internal.element.ElementImpl")
|| isMethodInClass(node, "getAncestor", "com.google.dart.engine.element.Element")) {
typeLiteralIndex = 0;
predicateArgumentName = "element";
}
if (isMethodInClass(node, "assertInstanceOf", "com.google.dart.engine.EngineTestCase")) {
arguments.add(0, arguments.get(0));
typeLiteralIndex = 0;
predicateArgumentName = "obj";
}
if (isMethodInClass(
node,
"assertLocate",
"com.google.dart.engine.ast.visitor.NodeLocatorTest") && arguments.size() == 4) {
arguments.add(3, arguments.get(3));
typeLiteralIndex = 3;
predicateArgumentName = "node";
}
if (isMethodInClass(node, "findNode", "com.google.dart.engine.EngineTestCase")) {
typeLiteralIndex = 3;
predicateArgumentName = "node";
}
if (isMethodInClass(
node,
"checkResolved",
"com.google.dart.engine.internal.resolver.ResolutionVerifier")) {
typeLiteralIndex = 2;
predicateArgumentName = "node";
}
if (typeLiteralIndex != -1) {
Expression argument = arguments.get(typeLiteralIndex);
IBinding argumentBinding = context.getNodeBinding(argument);
if (argument instanceof NullLiteral) {
} else if (argumentBinding instanceof IVariableBinding) {
replaceNode(argumentList, argument, identifier("predicate"));
} else {
SimpleIdentifier typeLiteralName = (SimpleIdentifier) argument;
ExpressionFunctionBody body = expressionFunctionBody(isExpression(
identifier(predicateArgumentName),
false,
typeName(typeLiteralName)));
body.setSemicolon(null);
replaceNode(
argumentList,
argument,
functionExpression(
formalParameterList(simpleFormalParameter(predicateArgumentName)),
body));
}
}
return super.visitMethodInvocation(node);
}
@Override
public Void visitSimpleIdentifier(SimpleIdentifier node) {
String name = node.getName();
String newName = replaceIdentifiersMap.get(name);
if (newName != null) {
node.setToken(token(newName));
}
return super.visitSimpleIdentifier(node);
}
});
}
}