/*******************************************************************************
* Copyright (c) 2015 Jeff Martin.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser General Public
* License v3.0 which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/lgpl.html
*
* Contributors:
* Jeff Martin - initial API and implementation
******************************************************************************/
package cuchaz.enigma.analysis;
import com.strobel.assembler.metadata.MemberReference;
import com.strobel.assembler.metadata.MethodDefinition;
import com.strobel.assembler.metadata.MethodReference;
import com.strobel.assembler.metadata.ParameterDefinition;
import com.strobel.assembler.metadata.TypeReference;
import com.strobel.decompiler.languages.TextLocation;
import com.strobel.decompiler.languages.java.ast.*;
import cuchaz.enigma.mapping.*;
public class SourceIndexBehaviorVisitor extends SourceIndexVisitor
{
private BehaviorEntry m_behaviorEntry;
public SourceIndexBehaviorVisitor(BehaviorEntry behaviorEntry)
{
m_behaviorEntry = behaviorEntry;
}
@Override
public Void visitInvocationExpression(InvocationExpression node,
SourceIndex index)
{
MemberReference ref = node.getUserData(Keys.MEMBER_REFERENCE);
// get the behavior entry
ClassEntry classEntry =
new ClassEntry(ref.getDeclaringType().getInternalName());
BehaviorEntry behaviorEntry = null;
if(ref instanceof MethodReference)
{
MethodReference methodRef = (MethodReference)ref;
if(methodRef.isConstructor())
behaviorEntry =
new ConstructorEntry(classEntry, new Signature(
ref.getErasedSignature()));
else if(methodRef.isTypeInitializer())
behaviorEntry = new ConstructorEntry(classEntry);
else
behaviorEntry =
new MethodEntry(classEntry, ref.getName(), new Signature(
ref.getErasedSignature()));
}
if(behaviorEntry != null)
{
// get the node for the token
AstNode tokenNode = null;
if(node.getTarget() instanceof MemberReferenceExpression)
tokenNode =
((MemberReferenceExpression)node.getTarget())
.getMemberNameToken();
else if(node.getTarget() instanceof SuperReferenceExpression)
tokenNode = node.getTarget();
else if(node.getTarget() instanceof ThisReferenceExpression)
tokenNode = node.getTarget();
if(tokenNode != null)
index.addReference(tokenNode, behaviorEntry, m_behaviorEntry);
}
return recurse(node, index);
}
@Override
public Void visitMemberReferenceExpression(MemberReferenceExpression node,
SourceIndex index)
{
MemberReference ref = node.getUserData(Keys.MEMBER_REFERENCE);
if(ref != null)
{
// make sure this is actually a field
if(ref.getErasedSignature().indexOf('(') >= 0)
throw new Error("Expected a field here! got " + ref);
ClassEntry classEntry =
new ClassEntry(ref.getDeclaringType().getInternalName());
FieldEntry fieldEntry =
new FieldEntry(classEntry, ref.getName(), new Type(
ref.getErasedSignature()));
index.addReference(node.getMemberNameToken(), fieldEntry,
m_behaviorEntry);
}
return recurse(node, index);
}
@Override
public Void visitSimpleType(SimpleType node, SourceIndex index)
{
TypeReference ref = node.getUserData(Keys.TYPE_REFERENCE);
if(node.getIdentifierToken().getStartLocation() != TextLocation.EMPTY)
{
ClassEntry classEntry = new ClassEntry(ref.getInternalName());
index.addReference(node.getIdentifierToken(), classEntry,
m_behaviorEntry);
}
return recurse(node, index);
}
@Override
public Void visitParameterDeclaration(ParameterDeclaration node,
SourceIndex index)
{
ParameterDefinition def = node.getUserData(Keys.PARAMETER_DEFINITION);
if(def.getMethod() instanceof MethodDefinition)
{
MethodDefinition methodDef = (MethodDefinition)def.getMethod();
BehaviorEntry behaviorEntry =
ProcyonEntryFactory.getBehaviorEntry(methodDef);
ArgumentEntry argumentEntry =
new ArgumentEntry(behaviorEntry, def.getPosition(),
node.getName());
index.addDeclaration(node.getNameToken(), argumentEntry);
}
return recurse(node, index);
}
@Override
public Void visitIdentifierExpression(IdentifierExpression node,
SourceIndex index)
{
MemberReference ref = node.getUserData(Keys.MEMBER_REFERENCE);
if(ref != null)
{
ClassEntry classEntry =
new ClassEntry(ref.getDeclaringType().getInternalName());
FieldEntry fieldEntry =
new FieldEntry(classEntry, ref.getName(), new Type(
ref.getErasedSignature()));
index.addReference(node.getIdentifierToken(), fieldEntry,
m_behaviorEntry);
}
return recurse(node, index);
}
@Override
public Void visitObjectCreationExpression(ObjectCreationExpression node,
SourceIndex index)
{
MemberReference ref = node.getUserData(Keys.MEMBER_REFERENCE);
if(ref != null)
{
ClassEntry classEntry =
new ClassEntry(ref.getDeclaringType().getInternalName());
ConstructorEntry constructorEntry =
new ConstructorEntry(classEntry, new Signature(
ref.getErasedSignature()));
if(node.getType() instanceof SimpleType)
{
SimpleType simpleTypeNode = (SimpleType)node.getType();
index.addReference(simpleTypeNode.getIdentifierToken(),
constructorEntry, m_behaviorEntry);
}
}
return recurse(node, index);
}
}