blob: c77c93a52291fdbe6e3eab51da85ea04543bc0e1 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2003, 2012 IBM Corporation and others.
* 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.debug.tests.breakpoints;
import java.util.Iterator;
import java.util.List;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.dom.Name;
import org.eclipse.jdt.core.dom.PackageDeclaration;
import org.eclipse.jdt.core.dom.PrimitiveType;
import org.eclipse.jdt.core.dom.QualifiedName;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.Type;
import org.eclipse.jdt.core.dom.TypeDeclaration;
/**
* Compute the name of field declared at a given position from an JDOM CompilationUnit.
*/
public class BreakpointMethodLocator extends ASTVisitor {
private int fPosition;
private String fTypeName;
private String fMethodName;
private String fMethodSignature;
private boolean fFound;
/**
* Constructor
* @param position the position in the compilation unit.
*/
public BreakpointMethodLocator(int position) {
fPosition= position;
fFound= false;
}
/**
* Return the name of the method declared at the given position.
* Return <code>null</code> if there is no method declaration at the given position.
* .
*/
public String getMethodName() {
return fMethodName;
}
/**
* Return the name of the method declared at the given position.
* Return <code>null</code> if there is no method declaration at the given position or
* if not possible to compute the signature of the method declared at the given
* position.
* @see BreakpointFieldLocator#getMethodName()
*/
public String getMethodSignature() {
return fMethodSignature;
}
/**
* Return the name of type in which the method is declared.
* Return <code>null</code> if there is no method declaration at the given position.
* @see BreakpointFieldLocator#getMethodName()
*/
public String getTypeName() {
return fTypeName;
}
private boolean containsPosition(ASTNode node) {
int startPosition= node.getStartPosition();
int endPosition = startPosition + node.getLength();
return startPosition <= fPosition && fPosition <= endPosition;
}
private String computeMethodSignature(MethodDeclaration node) {
if (node.getExtraDimensions() != 0 || Modifier.isAbstract(node.getModifiers())) {
return null;
}
StringBuffer signature= new StringBuffer();
signature.append('(');
List<SingleVariableDeclaration> parameters = node.parameters();
for (Iterator<SingleVariableDeclaration> iter = parameters.iterator(); iter.hasNext();) {
Type type = iter.next().getType();
if (type instanceof PrimitiveType) {
appendTypeLetter(signature, (PrimitiveType)type);
} else {
return null;
}
}
signature.append(')');
Type returnType;
returnType= node.getReturnType2();
if (returnType instanceof PrimitiveType) {
appendTypeLetter(signature, (PrimitiveType)returnType);
} else {
return null;
}
return signature.toString();
}
private void appendTypeLetter(StringBuffer signature, PrimitiveType type) {
PrimitiveType.Code code= type.getPrimitiveTypeCode();
if (code == PrimitiveType.BYTE) {
signature.append('B');
} else if (code == PrimitiveType.CHAR) {
signature.append('C');
} else if (code == PrimitiveType.DOUBLE) {
signature.append('D');
} else if (code == PrimitiveType.FLOAT) {
signature.append('F');
} else if (code == PrimitiveType.INT) {
signature.append('I');
} else if (code == PrimitiveType.LONG) {
signature.append('J');
} else if (code == PrimitiveType.SHORT) {
signature.append('S');
} else if (code == PrimitiveType.VOID) {
signature.append('V');
} else if (code == PrimitiveType.BOOLEAN) {
signature.append('Z');
}
}
/**
* @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.CompilationUnit)
*/
@Override
public boolean visit(CompilationUnit node) {
// visit only the type declarations
List<TypeDeclaration> types = node.types();
for (Iterator<TypeDeclaration> iter = types.iterator(); iter.hasNext() && !fFound;) {
iter.next().accept(this);
}
return false;
}
/**
* @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.FieldDeclaration)
*/
@Override
public boolean visit(MethodDeclaration node) {
if (containsPosition(node)) {
if (node.isConstructor()) {
fMethodName= "<init>"; //$NON-NLS-1$
} else {
fMethodName= node.getName().getIdentifier();
}
fMethodSignature= computeMethodSignature(node);
fTypeName= computeTypeName(node);
fFound= true;
}
return false;
}
/**
* @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.TypeDeclaration)
*/
@Override
public boolean visit(TypeDeclaration node) {
if (containsPosition(node)) {
// visit the methode declarations
MethodDeclaration[] methods = node.getMethods();
for (int i = 0, length = methods.length; i < length && !fFound; i++) {
methods[i].accept(this);
}
if (!fFound) {
// visit inner types
TypeDeclaration[] types = node.getTypes();
for (int i = 0, length = types.length; i < length && !fFound; i++) {
types[i].accept(this);
}
}
}
return false;
}
/**
* Compute the name of the type which contains this node.
* Result will be the name of the type or the inner type which contains this node, but not of the local or anonymous type.
*/
private String computeTypeName(ASTNode node) {
String typeName = null;
ASTNode newnode = node;
while (!(newnode instanceof CompilationUnit)) {
if (newnode instanceof AbstractTypeDeclaration) {
String identifier= ((AbstractTypeDeclaration)newnode).getName().getIdentifier();
if (typeName == null) {
typeName= identifier;
} else {
typeName= identifier + "$" + typeName; //$NON-NLS-1$
}
}
newnode= newnode.getParent();
}
PackageDeclaration packageDecl= ((CompilationUnit)newnode).getPackage();
String packageIdentifier= ""; //$NON-NLS-1$
if (packageDecl != null) {
Name packageName= packageDecl.getName();
while (packageName.isQualifiedName()) {
QualifiedName qualifiedName= (QualifiedName) packageName;
packageIdentifier= qualifiedName.getName().getIdentifier() + "." + packageIdentifier; //$NON-NLS-1$
packageName= qualifiedName.getQualifier();
}
packageIdentifier= ((SimpleName)packageName).getIdentifier() + "." + packageIdentifier; //$NON-NLS-1$
}
return packageIdentifier + typeName;
}
}