blob: 9242b1037b3f081bf3b1caff41112e3c454d5827 [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.FieldDeclaration;
import org.eclipse.jdt.core.dom.Name;
import org.eclipse.jdt.core.dom.PackageDeclaration;
import org.eclipse.jdt.core.dom.QualifiedName;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
/**
* Compute the name of field declared at a given position from an JDOM CompilationUnit.
*/
public class BreakpointFieldLocator extends ASTVisitor {
private int fPosition;
private String fTypeName;
private String fFieldName;
private boolean fFound;
/**
* Constructor
* @param position the position in the compilation unit.
*/
public BreakpointFieldLocator(int position) {
fPosition= position;
fFound= false;
}
/**
* Return the name of the field declared at the given position.
* Return <code>null</code> if there is no field declaration at the given position.
*/
public String getFieldName() {
return fFieldName;
}
/**
* Return the name of type in which the field is declared.
* Return <code>null</code> if there is no field declaration at the given position.
*/
public String getTypeName() {
return fTypeName;
}
private boolean containsPosition(ASTNode node) {
int startPosition= node.getStartPosition();
int endPosition = startPosition + node.getLength();
return startPosition <= fPosition && fPosition <= endPosition;
}
/**
* @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(FieldDeclaration node) {
if (containsPosition(node)) {
// visit only the variable declaration fragments
List<VariableDeclarationFragment> fragments = node.fragments();
if (fragments.size() == 1) {
fFieldName= fragments.get(0).getName().getIdentifier();
fTypeName= computeTypeName(node);
fFound= true;
return false;
}
for (Iterator<VariableDeclarationFragment> iter = fragments.iterator(); iter.hasNext() && !fFound;) {
iter.next().accept(this);
}
}
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 field declarations
FieldDeclaration[] fields = node.getFields();
for (int i = 0, length = fields.length; i < length && !fFound; i++) {
fields[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;
}
/**
* @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.VariableDeclarationFragment)
*/
@Override
public boolean visit(VariableDeclarationFragment node) {
if (containsPosition(node)) {
fFieldName= node.getName().getIdentifier();
fTypeName= computeTypeName(node);
fFound= true;
}
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;
}
}