package org.rubypeople.rdt.internal.debug.ui.actions;
import org.jruby.ast.DefnNode;
import org.jruby.ast.Node;
import org.jruby.ast.RootNode;
import org.rubypeople.rdt.internal.core.parser.InOrderVisitor;
public class ValidBreakpointLocationLocator extends InOrderVisitor
{
public static final int LOCATION_NOT_FOUND = 0;
public static final int LOCATION_LINE = 1;
public static final int LOCATION_METHOD = 2;
public static final int LOCATION_FIELD = 3;
private RootNode fCompilationUnit;
private int fLineNumber;
private boolean fBestMatch;
private int fLocationType;
private boolean fLocationFound;
private int fLineLocation;
/**
* @param compilationUnit
* the JDOM CompilationUnit of the source code.
* @param lineNumber
* the line number in the source code where to put the breakpoint.
* @param bestMatch
* if <code>true</code> look for the best match, otherwise look only for a valid line
*/
public ValidBreakpointLocationLocator(RootNode compilationUnit, int lineNumber, boolean bestMatch)
{
fCompilationUnit = compilationUnit;
fLineNumber = lineNumber;
fBestMatch = bestMatch;
fLocationFound = false;
}
public int getLocationType()
{
return fLocationType;
}
@Override
public Object visitDefnNode(DefnNode node)
{
if (visit(node, false))
{
if (fBestMatch)
{
// check if we are on the line which contains the method name
int nameStartLine = node.getNameNode().getPosition().getStartLine();
if (nameStartLine == fLineNumber)
{
// fMemberOffset= nameOffset;
fLocationType = LOCATION_METHOD;
fLocationFound = true;
return false;
}
}
super.visitDefnNode(node);
}
return false;
}
/**
* Return <code>true</code> if this node children may contain a valid location for the breakpoint.
*
* @param node
* the node.
* @param isCode
* true indicated that the first line of the given node always contains some executable code, even if
* split in multiple lines.
*/
private boolean visit(Node node, boolean isCode)
{
// if we already found a correct location
// no need to check the element inside.
if (fLocationFound)
{
return false;
}
int startPosition = node.getPosition().getStartOffset();
int endLine = node.getPosition().getEndLine();
// if the position is not in this part of the code
// no need to check the element inside.
if (endLine < fLineNumber)
{
return false;
}
// if the first line of this node always represents some executable code and the
// breakpoint is requested on this line or on a previous line, this is a valid
// location
int startLine = node.getPosition().getStartLine();
if (isCode && (fLineNumber <= startLine))
{
fLineLocation = startLine;
fLocationFound = true;
fLocationType = LOCATION_LINE;
// fTypeName= computeTypeName(node);
return false;
}
return true;
}
}