Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/eclipse/jdt/internal/corext/dom/NodeFinder.java


1   /*******************************************************************************
2    * Copyright (c) 2000, 2004 IBM Corporation and others.
3    * All rights reserved. This program and the accompanying materials 
4    * are made available under the terms of the Common Public License v1.0
5    * which accompanies this distribution, and is available at
6    * http://www.eclipse.org/legal/cpl-v10.html
7    * 
8    * Contributors:
9    *     IBM Corporation - initial API and implementation
10   *******************************************************************************/
11  package org.eclipse.jdt.internal.corext.dom;
12  
13  import org.eclipse.jdt.core.ICompilationUnit;
14  import org.eclipse.jdt.core.ISourceRange;
15  import org.eclipse.jdt.core.JavaModelException;
16  import org.eclipse.jdt.core.ToolFactory;
17  import org.eclipse.jdt.core.compiler.IScanner;
18  import org.eclipse.jdt.core.compiler.ITerminalSymbols;
19  import org.eclipse.jdt.core.compiler.InvalidInputException;
20  import org.eclipse.jdt.core.dom.ASTNode;
21  /**
22   * For a give range finds the node covered and the node covering.
23   * 
24   * @since    2.1
25   */
26  public class NodeFinder extends GenericVisitor {
27  
28    /**
29     * A visitor that maps a selection to a given ASTNode. The result node is
30     * determined as follows:
31     * <ul>
32     *   <li>first the visitor tries to find a node with the exact start and length</li>
33     *    <li>if no such node exists than the node that encloses the range defined by
34     *       start and end is returned.</li>
35     *   <li>if the length is zero than also nodes are considered where the node's
36     *       start or end position matches <code>start</code>.</li>
37     *   <li>otherwise <code>null</code> is returned.</li>
38     * </ul>
39     * 
40     * @since    2.1
41     */
42    public static ASTNode perform(ASTNode root, int start, int length) {
43      NodeFinder finder= new NodeFinder(start, length);
44      root.accept(finder);
45      ASTNode result= finder.getCoveredNode();
46      if (result == null || result.getStartPosition() != start || result.getLength() != length) {
47        return finder.getCoveringNode();
48      }
49      return result;
50    }
51    
52    public static ASTNode perform(ASTNode root, ISourceRange range) {
53      return perform(root, range.getOffset(), range.getLength());
54    }
55    
56    /**
57     * A visitor that maps a selection to a given ASTNode. The result node is
58     * determined as follows:
59     * <ul>
60     *   <li>first the visitor tries to find a node that is covered by <code>start</code> and
61     *       <code>length</code> where either <code>start</code> and <code>length</code> exactly
62     *       matches the node or where the text covered before and after the node only consists
63     *       of white spaces or comments.</li>
64     *    <li>if no such node exists than the node that encloses the range defined by
65     *       start and end is returned.</li>
66     *   <li>if the length is zero than also nodes are considered where the node's
67     *       start or end position matches <code>start</code>.</li>
68     *   <li>otherwise <code>null</code> is returned.</li>
69     * </ul>
70     * 
71     * @since    3.0
72     */
73    public static ASTNode perform(ASTNode root, int start, int length, ICompilationUnit source) throws JavaModelException {
74      NodeFinder finder= new NodeFinder(start, length);
75      root.accept(finder);
76      ASTNode result= finder.getCoveredNode();
77      if (result == null)
78        return null;
79      Selection selection= Selection.createFromStartLength(start, length);
80      if (selection.covers(result)) {
81        IScanner scanner= ToolFactory.createScanner(false, false, false, false);
82        scanner.setSource(source.getBuffer().getText(start, length).toCharArray());
83        try {
84          int token= scanner.getNextToken();
85          if (token != ITerminalSymbols.TokenNameEOF) {
86            int tStart= scanner.getCurrentTokenStartPosition();
87            if (tStart == result.getStartPosition() - start) {
88              scanner.resetTo(tStart + result.getLength(), length - 1);
89              token= scanner.getNextToken();
90              if (token == ITerminalSymbols.TokenNameEOF)
91                return result;
92            }
93          }
94        } catch (InvalidInputException e) {
95        }
96      }
97      return finder.getCoveringNode();
98    }
99  
100   private int fStart;
101   private int fEnd;
102   
103   private ASTNode fCoveringNode;
104   private ASTNode fCoveredNode;
105   
106   public NodeFinder(int offset, int length) {
107     super(true); // include Javadoc tags
108     fStart= offset;
109     fEnd= offset + length;
110   }
111 
112   protected boolean visitNode(ASTNode node) {
113     int nodeStart= node.getStartPosition();
114     int nodeEnd= nodeStart + node.getLength();
115     if (nodeEnd < fStart || fEnd < nodeStart) {
116       return false;
117     }
118     if (nodeStart <= fStart && fEnd <= nodeEnd) {
119       fCoveringNode= node;
120     }
121     if (fStart <= nodeStart && nodeEnd <= fEnd) {
122       if (fCoveringNode == node) { // nodeStart == fStart && nodeEnd == fEnd
123         fCoveredNode= node;
124         return true; // look further for node with same length as parent
125       } else if (fCoveredNode == null) { // no better found
126         fCoveredNode= node;
127       }
128       return false;
129     }
130     return true;
131   }
132 
133   /**
134    * Returns the covered node. If more than one nodes are covered by the selection, the
135    * returned node is first covered node found in a top-down traversal of the AST
136    * @return ASTNode
137    */
138   public ASTNode getCoveredNode() {
139     return fCoveredNode;
140   }
141 
142   /**
143    * Returns the covering node. If more than one nodes are covering the selection, the
144    * returned node is last covering node found in a top-down traversal of the AST
145    * @return ASTNode
146    */
147   public ASTNode getCoveringNode() {
148     return fCoveringNode;
149   }
150   
151 }