KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > debug > ui > actions > ValidBreakpointLocationLocator


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
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.debug.ui.actions;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.Iterator JavaDoc;
15 import java.util.List JavaDoc;
16
17 import org.eclipse.jdt.core.dom.ASTNode;
18 import org.eclipse.jdt.core.dom.ASTVisitor;
19 import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
20 import org.eclipse.jdt.core.dom.AnnotationTypeDeclaration;
21 import org.eclipse.jdt.core.dom.AnnotationTypeMemberDeclaration;
22 import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
23 import org.eclipse.jdt.core.dom.ArrayAccess;
24 import org.eclipse.jdt.core.dom.ArrayCreation;
25 import org.eclipse.jdt.core.dom.ArrayInitializer;
26 import org.eclipse.jdt.core.dom.ArrayType;
27 import org.eclipse.jdt.core.dom.AssertStatement;
28 import org.eclipse.jdt.core.dom.Assignment;
29 import org.eclipse.jdt.core.dom.Block;
30 import org.eclipse.jdt.core.dom.BlockComment;
31 import org.eclipse.jdt.core.dom.BodyDeclaration;
32 import org.eclipse.jdt.core.dom.BooleanLiteral;
33 import org.eclipse.jdt.core.dom.BreakStatement;
34 import org.eclipse.jdt.core.dom.CastExpression;
35 import org.eclipse.jdt.core.dom.CatchClause;
36 import org.eclipse.jdt.core.dom.CharacterLiteral;
37 import org.eclipse.jdt.core.dom.ClassInstanceCreation;
38 import org.eclipse.jdt.core.dom.CompilationUnit;
39 import org.eclipse.jdt.core.dom.ConditionalExpression;
40 import org.eclipse.jdt.core.dom.ConstructorInvocation;
41 import org.eclipse.jdt.core.dom.ContinueStatement;
42 import org.eclipse.jdt.core.dom.DoStatement;
43 import org.eclipse.jdt.core.dom.EmptyStatement;
44 import org.eclipse.jdt.core.dom.EnhancedForStatement;
45 import org.eclipse.jdt.core.dom.EnumConstantDeclaration;
46 import org.eclipse.jdt.core.dom.EnumDeclaration;
47 import org.eclipse.jdt.core.dom.Expression;
48 import org.eclipse.jdt.core.dom.ExpressionStatement;
49 import org.eclipse.jdt.core.dom.FieldAccess;
50 import org.eclipse.jdt.core.dom.FieldDeclaration;
51 import org.eclipse.jdt.core.dom.ForStatement;
52 import org.eclipse.jdt.core.dom.IBinding;
53 import org.eclipse.jdt.core.dom.IVariableBinding;
54 import org.eclipse.jdt.core.dom.IfStatement;
55 import org.eclipse.jdt.core.dom.ImportDeclaration;
56 import org.eclipse.jdt.core.dom.InfixExpression;
57 import org.eclipse.jdt.core.dom.Initializer;
58 import org.eclipse.jdt.core.dom.InstanceofExpression;
59 import org.eclipse.jdt.core.dom.Javadoc;
60 import org.eclipse.jdt.core.dom.LabeledStatement;
61 import org.eclipse.jdt.core.dom.LineComment;
62 import org.eclipse.jdt.core.dom.MarkerAnnotation;
63 import org.eclipse.jdt.core.dom.MemberRef;
64 import org.eclipse.jdt.core.dom.MemberValuePair;
65 import org.eclipse.jdt.core.dom.MethodDeclaration;
66 import org.eclipse.jdt.core.dom.MethodInvocation;
67 import org.eclipse.jdt.core.dom.MethodRef;
68 import org.eclipse.jdt.core.dom.MethodRefParameter;
69 import org.eclipse.jdt.core.dom.Modifier;
70 import org.eclipse.jdt.core.dom.Name;
71 import org.eclipse.jdt.core.dom.NormalAnnotation;
72 import org.eclipse.jdt.core.dom.NullLiteral;
73 import org.eclipse.jdt.core.dom.NumberLiteral;
74 import org.eclipse.jdt.core.dom.PackageDeclaration;
75 import org.eclipse.jdt.core.dom.ParameterizedType;
76 import org.eclipse.jdt.core.dom.ParenthesizedExpression;
77 import org.eclipse.jdt.core.dom.PostfixExpression;
78 import org.eclipse.jdt.core.dom.PrefixExpression;
79 import org.eclipse.jdt.core.dom.PrimitiveType;
80 import org.eclipse.jdt.core.dom.QualifiedName;
81 import org.eclipse.jdt.core.dom.QualifiedType;
82 import org.eclipse.jdt.core.dom.ReturnStatement;
83 import org.eclipse.jdt.core.dom.SimpleName;
84 import org.eclipse.jdt.core.dom.SimpleType;
85 import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
86 import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
87 import org.eclipse.jdt.core.dom.StringLiteral;
88 import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
89 import org.eclipse.jdt.core.dom.SuperFieldAccess;
90 import org.eclipse.jdt.core.dom.SuperMethodInvocation;
91 import org.eclipse.jdt.core.dom.SwitchCase;
92 import org.eclipse.jdt.core.dom.SwitchStatement;
93 import org.eclipse.jdt.core.dom.SynchronizedStatement;
94 import org.eclipse.jdt.core.dom.TagElement;
95 import org.eclipse.jdt.core.dom.TextElement;
96 import org.eclipse.jdt.core.dom.ThisExpression;
97 import org.eclipse.jdt.core.dom.ThrowStatement;
98 import org.eclipse.jdt.core.dom.TryStatement;
99 import org.eclipse.jdt.core.dom.TypeDeclaration;
100 import org.eclipse.jdt.core.dom.TypeDeclarationStatement;
101 import org.eclipse.jdt.core.dom.TypeLiteral;
102 import org.eclipse.jdt.core.dom.TypeParameter;
103 import org.eclipse.jdt.core.dom.VariableDeclarationExpression;
104 import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
105 import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
106 import org.eclipse.jdt.core.dom.WhileStatement;
107 import org.eclipse.jdt.core.dom.WildcardType;
108 import org.eclipse.jdt.core.dom.PrefixExpression.Operator;
109
110 /**
111  * Compute a valid location where to put a breakpoint from an JDOM CompilationUnit.
112  * The result is the first valid location with a line number greater or equals than the given position.
113  */

114 public class ValidBreakpointLocationLocator extends ASTVisitor {
115     
116     public static final int LOCATION_NOT_FOUND= 0;
117     public static final int LOCATION_LINE= 1;
118     public static final int LOCATION_METHOD= 2;
119     public static final int LOCATION_FIELD= 3;
120     
121     private CompilationUnit fCompilationUnit;
122     private int fLineNumber;
123     private boolean fBindingsResolved;
124     private boolean fNeedBindings = false;
125     private boolean fBestMatch;
126
127     private int fLocationType;
128     private boolean fLocationFound;
129     private String JavaDoc fTypeName;
130     private int fLineLocation;
131     private int fMemberOffset;
132     private List JavaDoc fLabels;
133
134     /**
135      * @param compilationUnit the JDOM CompilationUnit of the source code.
136      * @param lineNumber the line number in the source code where to put the breakpoint.
137      * @param bestMatch if <code>true</code> look for the best match, otherwise look only for a valid line
138      */

139     public ValidBreakpointLocationLocator(CompilationUnit compilationUnit, int lineNumber, boolean bindingsResolved, boolean bestMatch) {
140         fCompilationUnit= compilationUnit;
141         fLineNumber= lineNumber;
142         fBindingsResolved= bindingsResolved;
143         fBestMatch= bestMatch;
144         fLocationFound= false;
145     }
146     
147     /**
148      * Returns whether binding information would be helpful in validating a breakpoint
149      * location. If this locator makes a pass of the tree and determines that binding
150      * information would be helpful but was not available, this method returns
151      * <code>true</code>.
152      *
153      * @return whether binding information would be helpful in validating a breakpoint location
154      */

155     public boolean isBindingsRequired() {
156         return fNeedBindings;
157     }
158     
159     /**
160      * Return the type of the valid location found
161      * @return one of LOCATION_NOT_FOUND, LOCATION_LINE, LOCATION_METHOD or LOCATION_FIELD
162      */

163     public int getLocationType() {
164         return fLocationType;
165     }
166     
167     /**
168      * Return of the type where the valid location is.
169      */

170     public String JavaDoc getFullyQualifiedTypeName() {
171         return fTypeName;
172     }
173     
174     /**
175      * Return the line number of the computed valid location, if the location type is LOCATION_LINE.
176      */

177     public int getLineLocation() {
178         if (fLocationType == LOCATION_LINE) {
179             return fLineLocation;
180         }
181         return -1;
182     }
183     
184     /**
185      * Return the offset of the member which is the valid location,
186      * if the location type is LOCATION_METHOD or LOCATION_FIELD.
187      */

188     public int getMemberOffset() {
189         return fMemberOffset;
190     }
191     
192     /**
193      * Compute the name of the type which contains this node.
194      * Result will be the name of the type or the inner type which contains this node, but not of the local or anonymous type.
195      */

196     static protected String JavaDoc computeTypeName(ASTNode node) {
197         String JavaDoc typeName = null;
198         while (!(node instanceof CompilationUnit)) {
199             if (node instanceof AbstractTypeDeclaration) {
200                 String JavaDoc identifier= ((AbstractTypeDeclaration)node).getName().getIdentifier();
201                 if (typeName == null) {
202                     typeName= identifier;
203                 } else {
204                     typeName= identifier + "$" + typeName; //$NON-NLS-1$
205
}
206             } else {
207                 typeName= null;
208             }
209             node= node.getParent();
210         }
211         PackageDeclaration packageDecl= ((CompilationUnit)node).getPackage();
212         String JavaDoc packageIdentifier= ""; //$NON-NLS-1$
213
if (packageDecl != null) {
214             Name packageName= packageDecl.getName();
215             while (packageName.isQualifiedName()) {
216                 QualifiedName qualifiedName= (QualifiedName) packageName;
217                 packageIdentifier= qualifiedName.getName().getIdentifier() + "." + packageIdentifier; //$NON-NLS-1$
218
packageName= qualifiedName.getQualifier();
219             }
220             packageIdentifier= ((SimpleName)packageName).getIdentifier() + "." + packageIdentifier; //$NON-NLS-1$
221
}
222         return packageIdentifier + typeName;
223     }
224
225     /**
226      * Return <code>true</code> if this node children may contain a valid location
227      * for the breakpoint.
228      * @param node the node.
229      * @param isCode true indicated that the first line of the given node always
230      * contains some executable code, even if split in multiple lines.
231      */

232     private boolean visit(ASTNode node, boolean isCode) {
233         // if we already found a correct location
234
// no need to check the element inside.
235
if (fLocationFound) {
236             return false;
237         }
238         int startPosition= node.getStartPosition();
239         int endLine= lineNumber(startPosition + node.getLength() - 1);
240         // if the position is not in this part of the code
241
// no need to check the element inside.
242
if (endLine < fLineNumber) {
243             return false;
244         }
245         // if the first line of this node always represents some executable code and the
246
// breakpoint is requested on this line or on a previous line, this is a valid
247
// location
248
int startLine = lineNumber(startPosition);
249         if (isCode && (fLineNumber <= startLine)) {
250             fLineLocation= startLine;
251             fLocationFound= true;
252             fLocationType= LOCATION_LINE;
253             fTypeName= computeTypeName(node);
254             return false;
255         }
256         return true;
257     }
258     
259     private boolean isReplacedByConstantValue(Expression node) {
260         switch (node.getNodeType()) {
261             // litterals are constant
262
case ASTNode.BOOLEAN_LITERAL:
263             case ASTNode.CHARACTER_LITERAL:
264             case ASTNode.NUMBER_LITERAL:
265             case ASTNode.STRING_LITERAL:
266                 return true;
267             case ASTNode.SIMPLE_NAME:
268             case ASTNode.QUALIFIED_NAME:
269                 return isReplacedByConstantValue((Name)node);
270             case ASTNode.FIELD_ACCESS:
271                 return isReplacedByConstantValue((FieldAccess)node);
272             case ASTNode.SUPER_FIELD_ACCESS:
273                 return isReplacedByConstantValue((SuperFieldAccess)node);
274             case ASTNode.INFIX_EXPRESSION:
275                 return isReplacedByConstantValue((InfixExpression)node);
276             case ASTNode.PREFIX_EXPRESSION:
277                 return isReplacedByConstantValue((PrefixExpression)node);
278             case ASTNode.CAST_EXPRESSION:
279                 return isReplacedByConstantValue(((CastExpression)node).getExpression());
280             default:
281                 return false;
282         }
283     }
284     
285     private boolean isReplacedByConstantValue(InfixExpression node) {
286         // if all operands are constant value, the expression is replaced by a constant value
287
if (!(isReplacedByConstantValue(node.getLeftOperand()) && isReplacedByConstantValue(node.getRightOperand()))) {
288             return false;
289         }
290         if (node.hasExtendedOperands()) {
291             for (Iterator JavaDoc iter = node.extendedOperands().iterator(); iter.hasNext(); ) {
292                 if (!isReplacedByConstantValue((Expression) iter.next())) {
293                     return false;
294                 }
295             }
296         }
297         return true;
298     }
299     
300     private boolean isReplacedByConstantValue(PrefixExpression node) {
301         // for '-', '+', '~' and '!', if the operand is a constant value,
302
// the expression is replaced by a constant value
303
Operator operator = node.getOperator();
304         if (operator != PrefixExpression.Operator.INCREMENT && operator != PrefixExpression.Operator.DECREMENT) {
305             return isReplacedByConstantValue(node.getOperand());
306         }
307         return false;
308     }
309     
310     private boolean isReplacedByConstantValue(Name node) {
311         if (!fBindingsResolved) {
312             fNeedBindings = true;
313             return false;
314         }
315         // if node is a variable with a constant value (static final field)
316
IBinding binding= node.resolveBinding();
317         if (binding != null && binding.getKind() == IBinding.VARIABLE) {
318             return ((IVariableBinding)binding).getConstantValue() != null;
319         }
320         return false;
321     }
322     
323     private boolean isReplacedByConstantValue(FieldAccess node) {
324         if (!fBindingsResolved) {
325             fNeedBindings = true;
326             return false;
327         }
328         // if the node is 'this.<field>', and the field is static final
329
Expression expression= node.getExpression();
330         IVariableBinding binding= node.resolveFieldBinding();
331         if (binding != null && expression.getNodeType() == ASTNode.THIS_EXPRESSION) {
332             return binding.getConstantValue() != null;
333         }
334         return false;
335     }
336     
337     private boolean isReplacedByConstantValue(SuperFieldAccess node) {
338         if (!fBindingsResolved) {
339             fNeedBindings = true;
340             return false;
341         }
342         // if the field is static final
343
IVariableBinding binding= node.resolveFieldBinding();
344         if (binding != null) {
345             return binding.getConstantValue() != null;
346         }
347         return false;
348     }
349
350     /* (non-Javadoc)
351      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.AnnotationTypeDeclaration)
352      */

353     public boolean visit(AnnotationTypeDeclaration node) {
354         return false;
355     }
356
357     /* (non-Javadoc)
358      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.AnnotationTypeMemberDeclaration)
359      */

360     public boolean visit(AnnotationTypeMemberDeclaration node) {
361         return false;
362     }
363
364     /**
365      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.AnonymousClassDeclaration)
366      */

367     public boolean visit(AnonymousClassDeclaration node) {
368         return visit(node, false);
369     }
370
371     /**
372      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ArrayAccess)
373      */

374     public boolean visit(ArrayAccess node) {
375         return visit(node, true);
376     }
377
378     /**
379      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ArrayCreation)
380      */

381     public boolean visit(ArrayCreation node) {
382         return visit(node, node.getInitializer() == null);
383     }
384
385     /**
386      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ArrayInitializer)
387      */

388     public boolean visit(ArrayInitializer node) {
389         return visit(node, true);
390     }
391
392     /**
393      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ArrayType)
394      */

395     public boolean visit(ArrayType node) {
396         return false;
397     }
398
399     /**
400      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.AssertStatement)
401      */

402     public boolean visit(AssertStatement node) {
403         return visit(node, true);
404     }
405
406     /**
407      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.Assignment)
408      */

409     public boolean visit(Assignment node) {
410         if (visit(node, false)) {
411             // if the left hand side represent a local variable, or a static field
412
// and the breakpoint was requested on a line before the line where
413
// starts the assigment, set the location to be the first executable
414
// instruction of the right hand side, as it will be the first part of
415
// this assigment to be executed
416
Expression leftHandSide= node.getLeftHandSide();
417             if (leftHandSide instanceof Name) {
418                 int startLine = lineNumber(node.getStartPosition());
419                 if (fLineNumber < startLine) {
420                     if (fBindingsResolved) {
421                         IVariableBinding binding= (IVariableBinding)((Name)leftHandSide).resolveBinding();
422                         if (binding != null && (!binding.isField() || Modifier.isStatic(binding.getModifiers()))) {
423                             node.getRightHandSide().accept(this);
424                         }
425                     } else {
426                         fNeedBindings = true;
427                     }
428                 }
429             }
430             return true;
431         }
432         return false;
433     }
434
435     /**
436      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.Block)
437      */

438     public boolean visit(Block node) {
439         if (visit(node, false)) {
440             if (node.statements().isEmpty() && node.getParent().getNodeType() == ASTNode.METHOD_DECLARATION) {
441                 // in case of an empty method, set the breakpoint on the last line of the empty block.
442
fLineLocation= lineNumber(node.getStartPosition() + node.getLength() - 1);
443                 fLocationFound= true;
444                 fLocationType= LOCATION_LINE;
445                 fTypeName= computeTypeName(node);
446                 return false;
447             }
448             return true;
449         }
450         return false;
451     }
452
453     /* (non-Javadoc)
454      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.BlockComment)
455      */

456     public boolean visit(BlockComment node) {
457         return false;
458     }
459     
460     /**
461      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.BooleanLiteral)
462      */

463     public boolean visit(BooleanLiteral node) {
464         return visit(node, true);
465     }
466
467     /**
468      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.BreakStatement)
469      */

470     public boolean visit(BreakStatement node) {
471         return visit(node, true);
472     }
473
474     /**
475      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.CastExpression)
476      */

477     public boolean visit(CastExpression node) {
478         return visit(node, true);
479     }
480
481     /**
482      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.CatchClause)
483      */

484     public boolean visit(CatchClause node) {
485         return visit(node, false);
486     }
487
488     /**
489      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.CharacterLiteral)
490      */

491     public boolean visit(CharacterLiteral node) {
492         return visit(node, true);
493     }
494
495     /**
496      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ClassInstanceCreation)
497      */

498     public boolean visit(ClassInstanceCreation node) {
499         return visit(node, true);
500     }
501
502     /**
503      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.CompilationUnit)
504      */

505     public boolean visit(CompilationUnit node) {
506         return visit(node, false);
507     }
508
509     /**
510      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ConditionalExpression)
511      */

512     public boolean visit(ConditionalExpression node) {
513         return visit(node, true);
514     }
515
516     /**
517      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ConstructorInvocation)
518      */

519     public boolean visit(ConstructorInvocation node) {
520         return visit(node, true);
521     }
522
523     /**
524      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ContinueStatement)
525      */

526     public boolean visit(ContinueStatement node) {
527         return visit(node, true);
528     }
529
530     /**
531      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.DoStatement)
532      */

533     public boolean visit(DoStatement node) {
534         return visit(node, false);
535     }
536
537     /**
538      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.EmptyStatement)
539      */

540     public boolean visit(EmptyStatement node) {
541         return false;
542     }
543
544     /* (non-Javadoc)
545      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.EnhancedForStatement)
546      */

547     public boolean visit(EnhancedForStatement node) {
548         if (visit(node, false)) {
549             node.getExpression().accept(this);
550             node.getBody().accept(this);
551         }
552         return false;
553     }
554     
555     /* (non-Javadoc)
556      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.EnumConstantDeclaration)
557      */

558     public boolean visit(EnumConstantDeclaration node) {
559         if (visit(node, false)) {
560             List JavaDoc arguments= node.arguments();
561             for (Iterator JavaDoc iter= arguments.iterator(); iter.hasNext();) {
562                 ((Expression)iter.next()).accept(this);
563             }
564             AnonymousClassDeclaration decl= node.getAnonymousClassDeclaration();
565             if (decl != null) {
566                 decl.accept(this);
567             }
568         }
569         return false;
570     }
571     
572     /* (non-Javadoc)
573      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.EnumDeclaration)
574      */

575     public boolean visit(EnumDeclaration node) {
576         if (visit(node, false)) {
577             List JavaDoc enumConstants= node.enumConstants();
578             for (Iterator JavaDoc iter = enumConstants.iterator(); iter.hasNext();) {
579                 ((EnumConstantDeclaration) iter.next()).accept(this);
580             }
581             List JavaDoc bodyDeclaration= node.bodyDeclarations();
582             for (Iterator JavaDoc iter= bodyDeclaration.iterator(); iter.hasNext();) {
583                 ((BodyDeclaration)iter.next()).accept(this);
584             }
585         }
586         return false;
587     }
588     
589     /**
590      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ExpressionStatement)
591      */

592     public boolean visit(ExpressionStatement node) {
593         return visit(node, false);
594     }
595
596     /**
597      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.FieldAccess)
598      */

599     public boolean visit(FieldAccess node) {
600         return visit(node, false);
601     }
602
603     /**
604      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.FieldDeclaration)
605      */

606     public boolean visit(FieldDeclaration node) {
607         if (visit(node, false)) {
608             if (fBestMatch) {
609                 // check if the line contains a single field declaration.
610
List JavaDoc fragments = node.fragments();
611                 if (fragments.size() == 1) {
612                     int offset= ((VariableDeclarationFragment)fragments.get(0)).getName().getStartPosition();
613                     // check if the breakpoint is to be set on the line which contains the name of the field
614
if (lineNumber(offset) == fLineNumber) {
615                         fMemberOffset= offset;
616                         fLocationType= LOCATION_FIELD;
617                         fLocationFound= true;
618                         return false;
619                     }
620                 }
621             }
622             // visit only the variable declaration fragments, no the variable names.
623
List JavaDoc fragments= node.fragments();
624             for (Iterator JavaDoc iter= fragments.iterator(); iter.hasNext();) {
625                 ((VariableDeclarationFragment)iter.next()).accept(this);
626             }
627         }
628         return false;
629     }
630
631     /**
632      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ForStatement)
633      */

634     public boolean visit(ForStatement node) {
635         // in case on a "for(;;)", the breakpoint can be set on the first token of the node.
636
return visit(node, node.initializers().isEmpty() && node.getExpression() == null && node.updaters().isEmpty());
637     }
638
639     /**
640      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.IfStatement)
641      */

642     public boolean visit(IfStatement node) {
643         return visit(node, false);
644     }
645
646     /**
647      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ImportDeclaration)
648      */

649     public boolean visit(ImportDeclaration node) {
650         return false;
651     }
652
653     /**
654      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.InfixExpression)
655      */

656     public boolean visit(InfixExpression node) {
657         // if the breakpoint is to be set on a constant operand, the breakpoint needs to be
658
// set on the first constant operand after the previous non-constant operand
659
// (or the beginning of the expression, if there is no non-constant operand before).
660
// ex: foo() + // previous non-constant operand
661
// 1 + // breakpoint set here
662
// 2 // breakpoint asked to be set here
663
if (visit(node, false)) {
664             Expression leftOperand= node.getLeftOperand();
665             Expression firstConstant= null;
666             if (visit(leftOperand, false)) {
667                 leftOperand.accept(this);
668                 return false;
669             }
670             if (isReplacedByConstantValue(leftOperand)) {
671                 firstConstant= leftOperand;
672             }
673             Expression rightOperand= node.getRightOperand();
674             if (visit(rightOperand, false)) {
675                 if (firstConstant == null || !isReplacedByConstantValue(rightOperand)) {
676                     rightOperand.accept(this);
677                     return false;
678                 }
679             } else {
680                 if (isReplacedByConstantValue(rightOperand)) {
681                     if (firstConstant == null) {
682                         firstConstant= rightOperand;
683                     }
684                 } else {
685                     firstConstant= null;
686                 }
687                 List JavaDoc extendedOperands= node.extendedOperands();
688                 for (Iterator JavaDoc iter= extendedOperands.iterator(); iter.hasNext();) {
689                     Expression operand= (Expression) iter.next();
690                     if (visit(operand, false)) {
691                         if (firstConstant == null || !isReplacedByConstantValue(operand)) {
692                             operand.accept(this);
693                             return false;
694                         }
695                         break;
696                     }
697                     if (isReplacedByConstantValue(operand)) {
698                         if (firstConstant == null) {
699                             firstConstant= operand;
700                         }
701                     } else {
702                         firstConstant= null;
703                     }
704                     
705                 }
706             }
707             fLineLocation= lineNumber(firstConstant.getStartPosition());
708             fLocationFound= true;
709             fLocationType= LOCATION_LINE;
710             fTypeName= computeTypeName(firstConstant);
711         }
712         return false;
713     }
714
715     /**
716      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.Initializer)
717      */

718     public boolean visit(Initializer node) {
719         return visit(node, false);
720     }
721
722     /**
723      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.InstanceofExpression)
724      */

725     public boolean visit(InstanceofExpression node) {
726         return visit(node, true);
727     }
728
729     /**
730      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.Javadoc)
731      */

732     public boolean visit(Javadoc node) {
733         return false;
734     }
735
736     /**
737      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.LabeledStatement)
738      */

739     public boolean visit(LabeledStatement node) {
740         nestLabel(node.getLabel().getFullyQualifiedName());
741         return visit(node, false);
742     }
743     
744     /* (non-Javadoc)
745      * @see org.eclipse.jdt.core.dom.ASTVisitor#endVisit(org.eclipse.jdt.core.dom.LabeledStatement)
746      */

747     public void endVisit(LabeledStatement node) {
748         popLabel();
749         super.endVisit(node);
750     }
751     
752     private String JavaDoc getLabel() {
753         if (fLabels == null || fLabels.isEmpty()) {
754             return null;
755         }
756         return (String JavaDoc) fLabels.get(fLabels.size() - 1);
757     }
758     
759     private void nestLabel(String JavaDoc label) {
760         if (fLabels == null) {
761             fLabels = new ArrayList JavaDoc();
762         }
763         fLabels.add(label);
764     }
765     
766     private void popLabel() {
767         if (fLabels == null || fLabels.isEmpty()) {
768             return;
769         }
770         fLabels.remove(fLabels.size() - 1);
771     }
772
773     /* (non-Javadoc)
774      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.LineComment)
775      */

776     public boolean visit(LineComment node) {
777         return false;
778     }
779
780     /* (non-Javadoc)
781      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MarkerAnnotation)
782      */

783     public boolean visit(MarkerAnnotation node) {
784         return false;
785     }
786
787     /* (non-Javadoc)
788      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MemberRef)
789      */

790     public boolean visit(MemberRef node) {
791         return false;
792     }
793     
794     /* (non-Javadoc)
795      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MemberValuePair)
796      */

797     public boolean visit(MemberValuePair node) {
798         return false;
799     }
800     
801     /**
802      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MethodDeclaration)
803      */

804     public boolean visit(MethodDeclaration node) {
805         if (visit(node, false)) {
806             if (fBestMatch) {
807                 // check if we are on the line which contains the method name
808
int nameOffset= node.getName().getStartPosition();
809                 if (lineNumber(nameOffset) == fLineNumber) {
810                     fMemberOffset= nameOffset;
811                     fLocationType= LOCATION_METHOD;
812                     fLocationFound= true;
813                     return false;
814                 }
815             }
816             // visit only the body
817
Block body = node.getBody();
818             if (body != null) { // body is null for abstract methods
819
body.accept(this);
820             }
821         }
822         return false;
823     }
824
825     /**
826      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MethodInvocation)
827      */

828     public boolean visit(MethodInvocation node) {
829         return visit(node, true);
830     }
831
832     /* (non-Javadoc)
833      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MethodRef)
834      */

835     public boolean visit(MethodRef node) {
836         return false;
837     }
838     
839     /* (non-Javadoc)
840      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MethodRefParameter)
841      */

842     public boolean visit(MethodRefParameter node) {
843         return false;
844     }
845     
846     /* (non-Javadoc)
847      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.Modifier)
848      */

849     public boolean visit(Modifier node) {
850         return false;
851     }
852     
853     /* (non-Javadoc)
854      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.NormalAnnotation)
855      */

856     public boolean visit(NormalAnnotation node) {
857         return false;
858     }
859     
860     /**
861      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.NullLiteral)
862      */

863     public boolean visit(NullLiteral node) {
864         return visit(node, true);
865     }
866
867     /**
868      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.NumberLiteral)
869      */

870     public boolean visit(NumberLiteral node) {
871         return visit(node, true);
872     }
873
874     /**
875      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.PackageDeclaration)
876      */

877     public boolean visit(PackageDeclaration node) {
878         return false;
879     }
880
881     /* (non-Javadoc)
882      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ParameterizedType)
883      */

884     public boolean visit(ParameterizedType node) {
885         return false;
886     }
887     
888     /**
889      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ParenthesizedExpression)
890      */

891     public boolean visit(ParenthesizedExpression node) {
892         return visit(node, false);
893     }
894
895     /**
896      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.PostfixExpression)
897      */

898     public boolean visit(PostfixExpression node) {
899         return visit(node, true);
900     }
901
902     /**
903      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.PrefixExpression)
904      */

905     public boolean visit(PrefixExpression node) {
906         if (visit(node, false)) {
907             if (isReplacedByConstantValue(node)) {
908                 fLineLocation= lineNumber(node.getStartPosition());
909                 fLocationFound= true;
910                 fLocationType= LOCATION_LINE;
911                 fTypeName= computeTypeName(node);
912                 return false;
913             }
914             return true;
915         }
916         return false;
917     }
918
919     /**
920      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.PrimitiveType)
921      */

922     public boolean visit(PrimitiveType node) {
923         return false;
924     }
925
926     /**
927      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.QualifiedName)
928      */

929     public boolean visit(QualifiedName node) {
930         visit(node, true);
931         return false;
932     }
933
934     /* (non-Javadoc)
935      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.QualifiedType)
936      */

937     public boolean visit(QualifiedType node) {
938         return false;
939     }
940     
941     /**
942      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ReturnStatement)
943      */

944     public boolean visit(ReturnStatement node) {
945         return visit(node, true);
946     }
947
948     /**
949      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.SimpleName)
950      */

951     public boolean visit(SimpleName node) {
952         // the name is only code if its not the current label (if any)
953
return visit(node, !node.getFullyQualifiedName().equals(getLabel()));
954     }
955
956     /**
957      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.SimpleType)
958      */

959     public boolean visit(SimpleType node) {
960         return false;
961     }
962
963     /* (non-Javadoc)
964      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.SingleMemberAnnotation)
965      */

966     public boolean visit(SingleMemberAnnotation node) {
967         return false;
968     }
969     
970     /**
971      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.SingleVariableDeclaration)
972      */

973     public boolean visit(SingleVariableDeclaration node) {
974         return visit(node, false);
975     }
976
977     /**
978      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.StringLiteral)
979      */

980     public boolean visit(StringLiteral node) {
981         return visit(node, true);
982     }
983
984     /**
985      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.SuperConstructorInvocation)
986      */

987     public boolean visit(SuperConstructorInvocation node) {
988         return visit(node, true);
989     }
990
991     /**
992      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.SuperFieldAccess)
993      */

994     public boolean visit(SuperFieldAccess node) {
995         return visit(node, true);
996     }
997
998     /**
999      * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.SuperMethodInvocation)
1000     */

1001    public boolean visit(SuperMethodInvocation node) {
1002        return visit(node, true);
1003    }
1004
1005    /**
1006     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.SwitchCase)
1007     */

1008    public boolean visit(SwitchCase node) {
1009        return false;
1010    }
1011
1012    /**
1013     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.SwitchStatement)
1014     */

1015    public boolean visit(SwitchStatement node) {
1016        return visit(node, false);
1017    }
1018
1019    /**
1020     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.SynchronizedStatement)
1021     */

1022    public boolean visit(SynchronizedStatement node) {
1023        return visit(node, false);
1024    }
1025
1026    /* (non-Javadoc)
1027     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.TagElement)
1028     */

1029    public boolean visit(TagElement node) {
1030        return false;
1031    }
1032    
1033    /* (non-Javadoc)
1034     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.TextElement)
1035     */

1036    public boolean visit(TextElement node) {
1037        return false;
1038    }
1039    
1040    /**
1041     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ThisExpression)
1042     */

1043    public boolean visit(ThisExpression node) {
1044        return visit(node, true);
1045    }
1046
1047    /**
1048     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ThrowStatement)
1049     */

1050    public boolean visit(ThrowStatement node) {
1051        return visit(node, true);
1052    }
1053
1054    /**
1055     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.TryStatement)
1056     */

1057    public boolean visit(TryStatement node) {
1058        return visit(node, false);
1059    }
1060
1061    /**
1062     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.TypeDeclaration)
1063     */

1064    public boolean visit(TypeDeclaration node) {
1065        if (visit(node, false)) {
1066            // visit only the elements of the type declaration
1067
List JavaDoc bodyDeclaration= node.bodyDeclarations();
1068            for (Iterator JavaDoc iter= bodyDeclaration.iterator(); iter.hasNext();) {
1069                ((BodyDeclaration)iter.next()).accept(this);
1070            }
1071        }
1072        return false;
1073    }
1074
1075    /**
1076     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.TypeDeclarationStatement)
1077     */

1078    public boolean visit(TypeDeclarationStatement node) {
1079        return visit(node, false);
1080    }
1081
1082    /* (non-Javadoc)
1083     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.TypeParameter)
1084     */

1085    public boolean visit(TypeParameter node) {
1086        return false;
1087    }
1088    
1089    /**
1090     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.TypeLiteral)
1091     */

1092    public boolean visit(TypeLiteral node) {
1093        return false;
1094    }
1095
1096    /**
1097     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.VariableDeclarationExpression)
1098     */

1099    public boolean visit(VariableDeclarationExpression node) {
1100        return visit(node, false);
1101    }
1102
1103    /**
1104     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.VariableDeclarationFragment)
1105     */

1106    public boolean visit(VariableDeclarationFragment node) {
1107        Expression initializer = node.getInitializer();
1108        if (visit(node, false) && initializer != null) {
1109            int startLine = lineNumber(node.getName().getStartPosition());
1110            
1111            if (fLineNumber == startLine) {
1112                fLineLocation= startLine;
1113                fLocationFound= true;
1114                fLocationType= LOCATION_LINE;
1115                fTypeName= computeTypeName(node);
1116                return false;
1117            }
1118            initializer.accept(this);
1119        }
1120        return false;
1121    }
1122    
1123    private int lineNumber(int offset) {
1124        int lineNumber = fCompilationUnit.getLineNumber(offset);
1125        return lineNumber < 1 ? 1 : lineNumber;
1126    }
1127        
1128
1129    /* (non-Javadoc)
1130     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.WildcardType)
1131     */

1132    public boolean visit(WildcardType node) {
1133        return false;
1134    }
1135    
1136    /**
1137     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.VariableDeclarationStatement)
1138     */

1139    public boolean visit(VariableDeclarationStatement node) {
1140        return visit(node, false);
1141    }
1142
1143    /**
1144     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.WhileStatement)
1145     */

1146    public boolean visit(WhileStatement node) {
1147        return visit(node, false);
1148    }
1149
1150}
1151
Popular Tags