1 /*******************************************************************************
2 * Copyright (c) 2003, 2006 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpeclipse.xdebug.php.model;
12 /*org.eclipse.jdt.internal.debug.ui.actions;*/
14 //import java.util.ArrayList;
15 //import java.util.Iterator;
16 import java.util.List;
18 import net.sourceforge.phpdt.internal.core.CompilationUnit;
19 //import net.sourceforge.phpdt.internal.compiler.batch.CompilationUnit;
21 import net.sourceforge.phpdt.internal.compiler.ast.ASTNode;
22 import net.sourceforge.phpdt.internal.compiler.ASTVisitor;
23 /*import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
24 import org.eclipse.jdt.core.dom.AnnotationTypeDeclaration;
25 import org.eclipse.jdt.core.dom.AnnotationTypeMemberDeclaration;
26 import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
27 import org.eclipse.jdt.core.dom.ArrayAccess;
28 import org.eclipse.jdt.core.dom.ArrayCreation;*/
29 import net.sourceforge.phpdt.internal.compiler.ast.ArrayInitializer;
30 /*import org.eclipse.jdt.core.dom.ArrayType;*/
31 import net.sourceforge.phpdt.internal.compiler.ast.AssertStatement;
32 import net.sourceforge.phpdt.internal.compiler.ast.Assignment;
33 import net.sourceforge.phpdt.internal.compiler.ast.Block;
34 import net.sourceforge.phpdt.internal.compiler.ast.ThrowStatement;
36 /*import org.eclipse.jdt.core.dom.BlockComment;
37 import org.eclipse.jdt.core.dom.BodyDeclaration;
38 import org.eclipse.jdt.core.dom.BooleanLiteral;*/
39 import net.sourceforge.phpdt.internal.compiler.ast.BreakStatement;
40 import net.sourceforge.phpdt.internal.compiler.ast.CastExpression;
41 /*import org.eclipse.jdt.core.dom.CatchClause;
42 import org.eclipse.jdt.core.dom.CharacterLiteral;
43 import org.eclipse.jdt.core.dom.ClassInstanceCreation;
44 import org.eclipse.jdt.core.dom.CompilationUnit;*/
45 import net.sourceforge.phpdt.internal.compiler.ast.ConditionalExpression;
46 /*import org.eclipse.jdt.core.dom.ConstructorInvocation;*/
47 import net.sourceforge.phpdt.internal.compiler.ast.ContinueStatement;
48 import net.sourceforge.phpdt.internal.compiler.ast.DoStatement;
49 import net.sourceforge.phpdt.internal.compiler.ast.EmptyStatement;
50 /*import org.eclipse.jdt.core.dom.EnhancedForStatement;
51 import org.eclipse.jdt.core.dom.EnumConstantDeclaration;
52 import org.eclipse.jdt.core.dom.EnumDeclaration;
53 import org.eclipse.jdt.core.dom.Expression;
54 import org.eclipse.jdt.core.dom.ExpressionStatement;
55 import org.eclipse.jdt.core.dom.FieldAccess;*/
56 import net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration;
57 import net.sourceforge.phpdt.internal.compiler.ast.ForStatement;
58 /*import org.eclipse.jdt.core.dom.IBinding;
59 import org.eclipse.jdt.core.dom.IVariableBinding;*/
60 import net.sourceforge.phpdt.internal.compiler.ast.IfStatement;
61 /*import org.eclipse.jdt.core.dom.ImportDeclaration;
62 import org.eclipse.jdt.core.dom.InfixExpression;*/
63 import net.sourceforge.phpdt.internal.compiler.ast.Initializer;
64 import net.sourceforge.phpdt.internal.compiler.ast.InstanceOfExpression;
65 /*import org.eclipse.jdt.core.dom.Javadoc;*/
66 import net.sourceforge.phpdt.internal.compiler.ast.LabeledStatement;
67 /*import org.eclipse.jdt.core.dom.LineComment;
68 import org.eclipse.jdt.core.dom.MarkerAnnotation;
69 import org.eclipse.jdt.core.dom.MemberRef;
70 import org.eclipse.jdt.core.dom.MemberValuePair;*/
71 import net.sourceforge.phpdt.internal.compiler.ast.MethodDeclaration;
72 /*import org.eclipse.jdt.core.dom.MethodInvocation;
73 import org.eclipse.jdt.core.dom.MethodRef;
74 import org.eclipse.jdt.core.dom.MethodRefParameter;
75 import org.eclipse.jdt.core.dom.Modifier;
76 import org.eclipse.jdt.core.dom.Name;
77 import org.eclipse.jdt.core.dom.NormalAnnotation;*/
78 import net.sourceforge.phpdt.internal.compiler.ast.NullLiteral;
79 import net.sourceforge.phpdt.internal.compiler.ast.NumberLiteral;
80 /*import org.eclipse.jdt.core.dom.PackageDeclaration;
81 import org.eclipse.jdt.core.dom.ParameterizedType;
82 import org.eclipse.jdt.core.dom.ParenthesizedExpression;*/
83 import net.sourceforge.phpdt.internal.compiler.ast.PostfixExpression;
84 import net.sourceforge.phpdt.internal.compiler.ast.PrefixExpression;
85 /*import org.eclipse.jdt.core.dom.PrimitiveType;
86 import org.eclipse.jdt.core.dom.QualifiedName;
87 import org.eclipse.jdt.core.dom.QualifiedType;*/
88 import net.sourceforge.phpdt.internal.compiler.ast.ReturnStatement;
89 /*import org.eclipse.jdt.core.dom.SimpleName;
90 import org.eclipse.jdt.core.dom.SimpleType;
91 import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
92 import org.eclipse.jdt.core.dom.SingleVariableDeclaration;*/
93 import net.sourceforge.phpdt.internal.compiler.ast.StringLiteral;
94 /*import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
95 import org.eclipse.jdt.core.dom.SuperFieldAccess;
96 import org.eclipse.jdt.core.dom.SuperMethodInvocation;
97 import org.eclipse.jdt.core.dom.SwitchCase;*/
98 import net.sourceforge.phpdt.internal.compiler.ast.SwitchStatement;
99 /*import org.eclipse.jdt.core.dom.SynchronizedStatement;
100 import org.eclipse.jdt.core.dom.TagElement;
101 import org.eclipse.jdt.core.dom.TextElement;
102 import org.eclipse.jdt.core.dom.ThisExpression;*/
103 import net.sourceforge.phpdt.internal.compiler.ast.ThrowStatement;
104 import net.sourceforge.phpdt.internal.compiler.ast.TryStatement;
105 import net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration;
106 /*import org.eclipse.jdt.core.dom.TypeDeclarationStatement;
107 import org.eclipse.jdt.core.dom.TypeLiteral;
108 import org.eclipse.jdt.core.dom.TypeParameter;
109 import org.eclipse.jdt.core.dom.VariableDeclarationExpression;
110 import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
111 import org.eclipse.jdt.core.dom.VariableDeclarationStatement;*/
112 import net.sourceforge.phpdt.internal.compiler.ast.WhileStatement;
113 /*import org.eclipse.jdt.core.dom.WildcardType;
114 import org.eclipse.jdt.core.dom.PrefixExpression.Operator;*/
118 * Compute a valid location where to put a breakpoint from an JDOM CompilationUnit.
119 * The result is the first valid location with a line number greater or equals than the given position.
121 public class ValidBreakpointLocationLocator extends ASTVisitor {
123 public static final int LOCATION_NOT_FOUND= 0;
124 public static final int LOCATION_LINE= 1;
125 public static final int LOCATION_METHOD= 2;
126 public static final int LOCATION_FIELD= 3;
128 private CompilationUnit fCompilationUnit;
129 private int fLineNumber;
130 private boolean fBindingsResolved;
131 private boolean fNeedBindings = false;
132 private boolean fBestMatch;
134 private int fLocationType;
135 private boolean fLocationFound;
136 private String fTypeName;
137 private int fLineLocation;
138 private int fMemberOffset;
139 private List fLabels;
142 * @param compilationUnit the JDOM CompilationUnit of the source code.
143 * @param lineNumber the line number in the source code where to put the breakpoint.
144 * @param bestMatch if <code>true</code> look for the best match, otherwise look only for a valid line
146 public ValidBreakpointLocationLocator(CompilationUnit compilationUnit, int lineNumber, boolean bindingsResolved, boolean bestMatch) {
147 fCompilationUnit= compilationUnit;
148 fLineNumber= lineNumber;
149 fBindingsResolved= bindingsResolved;
150 fBestMatch= bestMatch;
151 fLocationFound= false;
155 * Returns whether binding information would be helpful in validating a breakpoint
156 * location. If this locator makes a pass of the tree and determines that binding
157 * information would be helpful but was not available, this method returns
160 * @return whether binding information would be helpful in validating a breakpoint location
162 public boolean isBindingsRequired() {
163 return fNeedBindings;
167 * Return the type of the valid location found
168 * @return one of LOCATION_NOT_FOUND, LOCATION_LINE, LOCATION_METHOD or LOCATION_FIELD
170 public int getLocationType() {
171 return fLocationType;
175 * Return of the type where the valid location is.
177 public String getFullyQualifiedTypeName() {
182 * Return the line number of the computed valid location, if the location type is LOCATION_LINE.
184 public int getLineLocation() {
185 if (fLocationType == LOCATION_LINE) {
186 return fLineLocation;
192 * Return the offset of the member which is the valid location,
193 * if the location type is LOCATION_METHOD or LOCATION_FIELD.
195 public int getMemberOffset() {
196 return fMemberOffset;
200 * Compute the name of the type which contains this node.
201 * Result will be the name of the type or the inner type which contains this node, but not of the local or anonymous type.
203 /*static protected String computeTypeName(ASTNode node) {
204 String typeName = null;
205 while (!(node instanceof CompilationUnit)) {
206 if (node instanceof AbstractTypeDeclaration) {
207 String identifier= ((AbstractTypeDeclaration)node).getName().getIdentifier();
208 if (typeName == null) {
209 typeName= identifier;
211 typeName= identifier + "$" + typeName; //$NON-NLS-1$
214 node= node.getParent();
216 PackageDeclaration packageDecl= ((CompilationUnit)node).getPackage();
217 String packageIdentifier= ""; //$NON-NLS-1$
218 if (packageDecl != null) {
219 Name packageName= packageDecl.getName();
220 while (packageName.isQualifiedName()) {
221 QualifiedName qualifiedName= (QualifiedName) packageName;
222 packageIdentifier= qualifiedName.getName().getIdentifier() + "." + packageIdentifier; //$NON-NLS-1$
223 packageName= qualifiedName.getQualifier();
225 packageIdentifier= ((SimpleName)packageName).getIdentifier() + "." + packageIdentifier; //$NON-NLS-1$
227 return packageIdentifier + typeName;
231 * Return <code>true</code> if this node children may contain a valid location
232 * for the breakpoint.
233 * @param node the node.
234 * @param isCode true indicated that the first line of the given node always
235 * contains some executable code, even if split in multiple lines.
237 /*private boolean visit(ASTNode node, boolean isCode) {
238 // if we already found a correct location
239 // no need to check the element inside.
240 if (fLocationFound) {
243 int startPosition= node.getStartPosition();
244 int endLine= lineNumber(startPosition + node.getLength() - 1);
245 // if the position is not in this part of the code
246 // no need to check the element inside.
247 if (endLine < fLineNumber) {
250 // if the first line of this node always represents some executable code and the
251 // breakpoint is requested on this line or on a previous line, this is a valid
253 int startLine = lineNumber(startPosition);
254 if (isCode && (fLineNumber <= startLine)) {
255 fLineLocation= startLine;
256 fLocationFound= true;
257 fLocationType= LOCATION_LINE;
258 fTypeName= computeTypeName(node);
264 /*private boolean isReplacedByConstantValue(Expression node) {
265 switch (node.getNodeType()) {
266 // litterals are constant
267 case ASTNode.BOOLEAN_LITERAL:
268 case ASTNode.CHARACTER_LITERAL:
269 case ASTNode.NUMBER_LITERAL:
270 case ASTNode.STRING_LITERAL:
272 case ASTNode.SIMPLE_NAME:
273 case ASTNode.QUALIFIED_NAME:
274 return isReplacedByConstantValue((Name)node);
275 case ASTNode.FIELD_ACCESS:
276 return isReplacedByConstantValue((FieldAccess)node);
277 case ASTNode.SUPER_FIELD_ACCESS:
278 return isReplacedByConstantValue((SuperFieldAccess)node);
279 case ASTNode.INFIX_EXPRESSION:
280 return isReplacedByConstantValue((InfixExpression)node);
281 case ASTNode.PREFIX_EXPRESSION:
282 return isReplacedByConstantValue((PrefixExpression)node);
283 case ASTNode.CAST_EXPRESSION:
284 return isReplacedByConstantValue(((CastExpression)node).getExpression());
290 /*private boolean isReplacedByConstantValue(InfixExpression node) {
291 // if all operands are constant value, the expression is replaced by a constant value
292 if (!(isReplacedByConstantValue(node.getLeftOperand()) && isReplacedByConstantValue(node.getRightOperand()))) {
295 if (node.hasExtendedOperands()) {
296 for (Iterator iter = node.extendedOperands().iterator(); iter.hasNext(); ) {
297 if (!isReplacedByConstantValue((Expression) iter.next())) {
305 /*private boolean isReplacedByConstantValue(PrefixExpression node) {
306 // for '-', '+', '~' and '!', if the operand is a constant value,
307 // the expression is replaced by a constant value
308 Operator operator = node.getOperator();
309 if (operator != PrefixExpression.Operator.INCREMENT && operator != PrefixExpression.Operator.DECREMENT) {
310 return isReplacedByConstantValue(node.getOperand());
315 /*private boolean isReplacedByConstantValue(Name node) {
316 if (!fBindingsResolved) {
317 fNeedBindings = true;
320 // if node is a variable with a constant value (static final field)
321 IBinding binding= node.resolveBinding();
322 if (binding != null && binding.getKind() == IBinding.VARIABLE) {
323 return ((IVariableBinding)binding).getConstantValue() != null;
328 /*private boolean isReplacedByConstantValue(FieldAccess node) {
329 if (!fBindingsResolved) {
330 fNeedBindings = true;
333 // if the node is 'this.<field>', and the field is static final
334 Expression expression= node.getExpression();
335 IVariableBinding binding= node.resolveFieldBinding();
336 if (binding != null && expression.getNodeType() == ASTNode.THIS_EXPRESSION) {
337 return binding.getConstantValue() != null;
342 /*private boolean isReplacedByConstantValue(SuperFieldAccess node) {
343 if (!fBindingsResolved) {
344 fNeedBindings = true;
347 // if the field is static final
348 IVariableBinding binding= node.resolveFieldBinding();
349 if (binding != null) {
350 return binding.getConstantValue() != null;
356 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.AnnotationTypeDeclaration)
358 /*public boolean visit(AnnotationTypeDeclaration node) {
363 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.AnnotationTypeMemberDeclaration)
365 /*public boolean visit(AnnotationTypeMemberDeclaration node) {
370 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.AnonymousClassDeclaration)
372 /*public boolean visit(AnonymousClassDeclaration node) {
373 return visit(node, false);
377 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ArrayAccess)
379 /*public boolean visit(ArrayAccess node) {
380 return visit(node, true);
384 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ArrayCreation)
386 /*public boolean visit(ArrayCreation node) {
387 return visit(node, node.getInitializer() == null);
391 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ArrayInitializer)
393 /*public boolean visit(ArrayInitializer node) {
394 return visit(node, true);
398 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ArrayType)
400 /*public boolean visit(ArrayType node) {
405 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.AssertStatement)
407 /*public boolean visit(AssertStatement node) {
408 return visit(node, true);
412 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.Assignment)
414 /*public boolean visit(Assignment node) {
415 if (visit(node, false)) {
416 // if the left hand side represent a local variable, or a static field
417 // and the breakpoint was requested on a line before the line where
418 // starts the assigment, set the location to be the first executable
419 // instruction of the right hand side, as it will be the first part of
420 // this assigment to be executed
421 Expression leftHandSide= node.getLeftHandSide();
422 if (leftHandSide instanceof Name) {
423 int startLine = lineNumber(node.getStartPosition());
424 if (fLineNumber < startLine) {
425 if (fBindingsResolved) {
426 IVariableBinding binding= (IVariableBinding)((Name)leftHandSide).resolveBinding();
427 if (binding != null && (!binding.isField() || Modifier.isStatic(binding.getModifiers()))) {
428 node.getRightHandSide().accept(this);
431 fNeedBindings = true;
441 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.Block)
443 /*public boolean visit(Block node) {
444 if (visit(node, false)) {
445 if (node.statements().isEmpty() && node.getParent().getNodeType() == ASTNode.METHOD_DECLARATION) {
446 // in case of an empty method, set the breakpoint on the last line of the empty block.
447 fLineLocation= lineNumber(node.getStartPosition() + node.getLength() - 1);
448 fLocationFound= true;
449 fLocationType= LOCATION_LINE;
450 fTypeName= computeTypeName(node);
459 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.BlockComment)
461 /*public boolean visit(BlockComment node) {
466 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.BooleanLiteral)
468 /*public boolean visit(BooleanLiteral node) {
469 return visit(node, true);
473 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.BreakStatement)
475 /*public boolean visit(BreakStatement node) {
476 return visit(node, true);
480 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.CastExpression)
482 /*public boolean visit(CastExpression node) {
483 return visit(node, true);
487 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.CatchClause)
489 /*public boolean visit(CatchClause node) {
490 return visit(node, false);
494 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.CharacterLiteral)
496 /*public boolean visit(CharacterLiteral node) {
497 return visit(node, true);
501 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ClassInstanceCreation)
503 /*public boolean visit(ClassInstanceCreation node) {
504 return visit(node, true);
508 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.CompilationUnit)
510 /*public boolean visit(CompilationUnit node) {
511 return visit(node, false);
515 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ConditionalExpression)
517 /*public boolean visit(ConditionalExpression node) {
518 return visit(node, true);
522 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ConstructorInvocation)
524 /*public boolean visit(ConstructorInvocation node) {
525 return visit(node, true);
529 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ContinueStatement)
531 /*public boolean visit(ContinueStatement node) {
532 return visit(node, true);
536 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.DoStatement)
538 /*public boolean visit(DoStatement node) {
539 return visit(node, false);
543 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.EmptyStatement)
545 public boolean visit(EmptyStatement node) {
550 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.EnhancedForStatement)
552 /*public boolean visit(EnhancedForStatement node) {
553 if (visit(node, false)) {
554 node.getExpression().accept(this);
555 node.getBody().accept(this);
561 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.EnumConstantDeclaration)
563 /*public boolean visit(EnumConstantDeclaration node) {
564 if (visit(node, false)) {
565 List arguments= node.arguments();
566 for (Iterator iter= arguments.iterator(); iter.hasNext();) {
567 ((Expression)iter.next()).accept(this);
569 AnonymousClassDeclaration decl= node.getAnonymousClassDeclaration();
578 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.EnumDeclaration)
580 /*public boolean visit(EnumDeclaration node) {
581 if (visit(node, false)) {
582 List enumConstants= node.enumConstants();
583 for (Iterator iter = enumConstants.iterator(); iter.hasNext();) {
584 ((EnumConstantDeclaration) iter.next()).accept(this);
586 List bodyDeclaration= node.bodyDeclarations();
587 for (Iterator iter= bodyDeclaration.iterator(); iter.hasNext();) {
588 ((BodyDeclaration)iter.next()).accept(this);
595 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ExpressionStatement)
597 /*public boolean visit(ExpressionStatement node) {
598 return visit(node, false);
602 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.FieldAccess)
604 /*public boolean visit(FieldAccess node) {
605 return visit(node, false);
609 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.FieldDeclaration)
611 /*public boolean visit(FieldDeclaration node) {
612 if (visit(node, false)) {
614 // check if the line contains a single field declaration.
615 List fragments = node.fragments();
616 if (fragments.size() == 1) {
617 int offset= ((VariableDeclarationFragment)fragments.get(0)).getName().getStartPosition();
618 // check if the breakpoint is to be set on the line which contains the name of the field
619 if (lineNumber(offset) == fLineNumber) {
620 fMemberOffset= offset;
621 fLocationType= LOCATION_FIELD;
622 fLocationFound= true;
627 // visit only the variable declaration fragments, no the variable names.
628 List fragments= node.fragments();
629 for (Iterator iter= fragments.iterator(); iter.hasNext();) {
630 ((VariableDeclarationFragment)iter.next()).accept(this);
637 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ForStatement)
639 /*public boolean visit(ForStatement node) {
640 // in case on a "for(;;)", the breakpoint can be set on the first token of the node.
641 return visit(node, node.initializers().isEmpty() && node.getExpression() == null && node.updaters().isEmpty());
645 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.IfStatement)
647 /*public boolean visit(IfStatement node) {
648 return visit(node, false);
652 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ImportDeclaration)
654 /*public boolean visit(ImportDeclaration node) {
659 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.InfixExpression)
661 /*public boolean visit(InfixExpression node) {
662 // if the breakpoint is to be set on a constant operand, the breakpoint needs to be
663 // set on the first constant operand after the previous non-constant operand
664 // (or the beginning of the expression, if there is no non-constant operand before).
665 // ex: foo() + // previous non-constant operand
666 // 1 + // breakpoint set here
667 // 2 // breakpoint asked to be set here
668 if (visit(node, false)) {
669 Expression leftOperand= node.getLeftOperand();
670 Expression firstConstant= null;
671 if (visit(leftOperand, false)) {
672 leftOperand.accept(this);
675 if (isReplacedByConstantValue(leftOperand)) {
676 firstConstant= leftOperand;
678 Expression rightOperand= node.getRightOperand();
679 if (visit(rightOperand, false)) {
680 if (firstConstant == null || !isReplacedByConstantValue(rightOperand)) {
681 rightOperand.accept(this);
685 if (isReplacedByConstantValue(rightOperand)) {
686 if (firstConstant == null) {
687 firstConstant= rightOperand;
692 List extendedOperands= node.extendedOperands();
693 for (Iterator iter= extendedOperands.iterator(); iter.hasNext();) {
694 Expression operand= (Expression) iter.next();
695 if (visit(operand, false)) {
696 if (firstConstant == null || !isReplacedByConstantValue(operand)) {
697 operand.accept(this);
702 if (isReplacedByConstantValue(operand)) {
703 if (firstConstant == null) {
704 firstConstant= operand;
712 fLineLocation= lineNumber(firstConstant.getStartPosition());
713 fLocationFound= true;
714 fLocationType= LOCATION_LINE;
715 fTypeName= computeTypeName(firstConstant);
721 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.Initializer)
723 /*public boolean visit(Initializer node) {
724 return visit(node, false);
728 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.InstanceofExpression)
730 /*public boolean visit(InstanceofExpression node) {
731 return visit(node, true);
735 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.Javadoc)
737 /*public boolean visit(Javadoc node) {
742 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.LabeledStatement)
744 /*public boolean visit(LabeledStatement node) {
745 nestLabel(node.getLabel().getFullyQualifiedName());
746 return visit(node, false);
750 * @see org.eclipse.jdt.core.dom.ASTVisitor#endVisit(org.eclipse.jdt.core.dom.LabeledStatement)
752 /*public void endVisit(LabeledStatement node) {
754 super.endVisit(node);
757 private String getLabel() {
758 if (fLabels == null || fLabels.isEmpty()) {
761 return (String) fLabels.get(fLabels.size() - 1);
764 // private void nestLabel(String label) {
765 // if (fLabels == null) {
766 // fLabels = new ArrayList();
768 // fLabels.add(label);
771 // private void popLabel() {
772 // if (fLabels == null || fLabels.isEmpty()) {
775 // fLabels.remove(fLabels.size() - 1);
779 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.LineComment)
781 /*public boolean visit(LineComment node) {
786 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MarkerAnnotation)
788 /*public boolean visit(MarkerAnnotation node) {
793 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MemberRef)
795 /*public boolean visit(MemberRef node) {
800 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MemberValuePair)
802 /*public boolean visit(MemberValuePair node) {
807 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MethodDeclaration)
809 public boolean visit(MethodDeclaration node) {
810 if (visit(node/*, false*/)) {
812 // check if we are on the line which contains the method name
813 int nameOffset= node.sourceStart; // node.getName().getStartPosition();
814 if (lineNumber(nameOffset) == fLineNumber) {
815 fMemberOffset= nameOffset;
816 fLocationType= LOCATION_METHOD;
817 fLocationFound= true;
821 // visit only the body
822 /*Block body = node.getBody();
823 if (body != null) { // body is null for abstract methods
831 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MethodInvocation)
833 /*public boolean visit(MethodInvocation node) {
834 return visit(node, true);
838 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MethodRef)
840 /*public boolean visit(MethodRef node) {
845 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MethodRefParameter)
847 /*public boolean visit(MethodRefParameter node) {
852 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.Modifier)
854 /*public boolean visit(Modifier node) {
859 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.NormalAnnotation)
861 /*public boolean visit(NormalAnnotation node) {
866 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.NullLiteral)
868 /*public boolean visit(NullLiteral node) {
869 return visit(node, true);
873 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.NumberLiteral)
875 /*public boolean visit(NumberLiteral node) {
876 return visit(node, true);
880 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.PackageDeclaration)
882 /*public boolean visit(PackageDeclaration node) {
887 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ParameterizedType)
889 /*public boolean visit(ParameterizedType node) {
894 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ParenthesizedExpression)
896 /*public boolean visit(ParenthesizedExpression node) {
897 return visit(node, false);
901 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.PostfixExpression)
903 /*public boolean visit(PostfixExpression node) {
904 return visit(node, true);
908 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.PrefixExpression)
910 /*public boolean visit(PrefixExpression node) {
911 if (visit(node, false)) {
912 if (isReplacedByConstantValue(node)) {
913 fLineLocation= lineNumber(node.getStartPosition());
914 fLocationFound= true;
915 fLocationType= LOCATION_LINE;
916 fTypeName= computeTypeName(node);
925 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.PrimitiveType)
927 /*public boolean visit(PrimitiveType node) {
932 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.QualifiedName)
934 /*public boolean visit(QualifiedName node) {
940 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.QualifiedType)
942 /*public boolean visit(QualifiedType node) {
947 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ReturnStatement)
949 /*public boolean visit(ReturnStatement node) {
950 return visit(node, true);
954 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.SimpleName)
956 /*public boolean visit(SimpleName node) {
957 // the name is only code if its not the current label (if any)
958 return visit(node, !node.getFullyQualifiedName().equals(getLabel()));
962 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.SimpleType)
964 /*public boolean visit(SimpleType node) {
969 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.SingleMemberAnnotation)
971 /*public boolean visit(SingleMemberAnnotation node) {
976 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.SingleVariableDeclaration)
978 /*public boolean visit(SingleVariableDeclaration node) {
979 return visit(node, false);
983 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.StringLiteral)
985 /*public boolean visit(StringLiteral node) {
986 return visit(node, true);
990 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.SuperConstructorInvocation)
992 /*public boolean visit(SuperConstructorInvocation node) {
993 return visit(node, true);
997 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.SuperFieldAccess)
999 /*public boolean visit(SuperFieldAccess node) {
1000 return visit(node, true);
1004 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.SuperMethodInvocation)
1006 /*public boolean visit(SuperMethodInvocation node) {
1007 return visit(node, true);
1014 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.SwitchCase)
1016 /*public boolean visit(SwitchCase node) {
1021 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.SwitchStatement)
1023 /*public boolean visit(SwitchStatement node) {
1024 return visit(node, false);
1028 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.SynchronizedStatement)
1030 /*public boolean visit(SynchronizedStatement node) {
1031 return visit(node, false);
1035 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.TagElement)
1037 /*public boolean visit(TagElement node) {
1042 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.TextElement)
1044 /*public boolean visit(TextElement node) {
1049 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ThisExpression)
1051 /*public boolean visit(ThisExpression node) {
1052 return visit(node, true);
1056 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ThrowStatement)
1058 /*public boolean visit(ThrowStatement node) {
1059 return visit(node, true);
1063 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.TryStatement)
1065 /*public boolean visit(TryStatement node) {
1066 return visit(node, false);
1070 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.TypeDeclaration)
1072 /*public boolean visit(TypeDeclaration node) {
1073 if (visit(node, false)) {
1074 // visit only the elements of the type declaration
1075 List bodyDeclaration= node.bodyDeclarations();
1076 for (Iterator iter= bodyDeclaration.iterator(); iter.hasNext();) {
1077 ((BodyDeclaration)iter.next()).accept(this);
1084 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.TypeDeclarationStatement)
1086 /*public boolean visit(TypeDeclarationStatement node) {
1087 return visit(node, false);
1091 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.TypeParameter)
1093 /*public boolean visit(TypeParameter node) {
1098 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.TypeLiteral)
1100 /*public boolean visit(TypeLiteral node) {
1105 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.VariableDeclarationExpression)
1107 /*public boolean visit(VariableDeclarationExpression node) {
1108 return visit(node, false);
1112 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.VariableDeclarationFragment)
1114 /*public boolean visit(VariableDeclarationFragment node) {
1115 Expression initializer = node.getInitializer();
1116 if (visit(node, false) && initializer != null) {
1117 int startLine = lineNumber(node.getName().getStartPosition());
1119 if (fLineNumber == startLine) {
1120 fLineLocation= startLine;
1121 fLocationFound= true;
1122 fLocationType= LOCATION_LINE;
1123 fTypeName= computeTypeName(node);
1126 initializer.accept(this);
1131 private int lineNumber(int offset) {
1132 //int lineNumber = fCompilationUnit.getLineNumber(offset);
1133 return 10; //lineNumber < 1 ? 1 : lineNumber;
1138 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.WildcardType)
1140 /*public boolean visit(WildcardType node) {
1145 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.VariableDeclarationStatement)
1147 /*public boolean visit(VariableDeclarationStatement node) {
1148 return visit(node, false);
1152 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.WhileStatement)
1154 /*public boolean visit(WhileStatement node) {
1155 return visit(node, false);