View | Details | Raw Unified | Return to bug 53024 | Differences between
and this patch

Collapse All | Expand All

(-)dom/org/eclipse/jdt/core/dom/ASTNode.java (-4 / +7 lines)
Lines 103-109 Link Here
103
 * </p>
103
 * </p>
104
 * <p>
104
 * <p>
105
 * ASTs also support the visitor pattern; see the class <code>ASTVisitor</code>
105
 * ASTs also support the visitor pattern; see the class <code>ASTVisitor</code>
106
 * for details.
106
 * for details. The <code>NodeFinder</code> class can be used to find a specific
107
 * node inside a tree.
107
 * </p>
108
 * </p>
108
 * <p>
109
 * <p>
109
 * Compilation units created by <code>ASTParser</code> from a
110
 * Compilation units created by <code>ASTParser</code> from a
Lines 117-122 Link Here
117
 *
118
 *
118
 * @see ASTParser
119
 * @see ASTParser
119
 * @see ASTVisitor
120
 * @see ASTVisitor
121
 * @see NodeFinder
120
 * @since 2.0
122
 * @since 2.0
121
 * @noextend This class is not intended to be subclassed by clients.
123
 * @noextend This class is not intended to be subclassed by clients.
122
 */
124
 */
Lines 2473-2481 Link Here
2473
			throw new IllegalArgumentException();
2475
			throw new IllegalArgumentException();
2474
		}
2476
		}
2475
		// begin with the generic pre-visit
2477
		// begin with the generic pre-visit
2476
		visitor.preVisit(this);
2478
		if (visitor.preVisit2(this)) {
2477
		// dynamic dispatch to internal method for type-specific visit/endVisit
2479
			// dynamic dispatch to internal method for type-specific visit/endVisit
2478
		accept0(visitor);
2480
			accept0(visitor);
2481
		}
2479
		// end with the generic post-visit
2482
		// end with the generic post-visit
2480
		visitor.postVisit(this);
2483
		visitor.postVisit(this);
2481
	}
2484
	}
(-)dom/org/eclipse/jdt/core/dom/ASTVisitor.java (-2 / +23 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2007 IBM Corporation and others.
2
 * Copyright (c) 2000, 2008 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 136-154 Link Here
136
	}
136
	}
137
137
138
	/**
138
	/**
139
	 * Visits the given AST node prior to the type-specific visit.
139
	 * Visits the given AST node prior to the type-specific visit
140
	 * (before <code>visit</code>).
140
	 * (before <code>visit</code>).
141
	 * <p>
141
	 * <p>
142
	 * The default implementation does nothing. Subclasses may reimplement.
142
	 * The default implementation does nothing. Subclasses may reimplement.
143
	 * </p>
143
	 * </p>
144
	 *
144
	 *
145
	 * @param node the node to visit
145
	 * @param node the node to visit
146
	 *
147
	 * @see #preVisit2(ASTNode)
146
	 */
148
	 */
147
	public void preVisit(ASTNode node) {
149
	public void preVisit(ASTNode node) {
148
		// default implementation: do nothing
150
		// default implementation: do nothing
149
	}
151
	}
150
152
151
	/**
153
	/**
154
	 * Visits the given AST node prior to the type-specific visit (before <code>visit</code>).
155
	 * This API is still under discussion, see https://bugs.eclipse.org/53024 .
156
	 * <p>
157
	 * The default implementation calls {@link #preVisit(ASTNode)} and then
158
	 * returns true. Subclasses may reimplement.
159
	 * </p>
160
	 *
161
	 * @param node the node to visit
162
	 * @return <code>true</code> if <code>visit(node)</code> should be called,
163
	 * and <code>false</code> otherwise.
164
	 * @see #preVisit(ASTNode)
165
	 * @since 3.5
166
	 */
167
	public boolean preVisit2(ASTNode node) {
168
		preVisit(node);
169
		return true;
170
	}
171
172
	/**
152
	 * Visits the given AST node following the type-specific visit
173
	 * Visits the given AST node following the type-specific visit
153
	 * (after <code>endVisit</code>).
174
	 * (after <code>endVisit</code>).
154
	 * <p>
175
	 * <p>
(-)dom/org/eclipse/jdt/core/dom/NodeFinder.java (+207 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2008 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.core.dom;
12
13
import org.eclipse.jdt.core.IBuffer;
14
import org.eclipse.jdt.core.ISourceRange;
15
import org.eclipse.jdt.core.ITypeRoot;
16
import org.eclipse.jdt.core.JavaModelException;
17
import org.eclipse.jdt.core.ToolFactory;
18
import org.eclipse.jdt.core.compiler.IScanner;
19
import org.eclipse.jdt.core.compiler.ITerminalSymbols;
20
import org.eclipse.jdt.core.compiler.InvalidInputException;
21
22
/**
23
 * For a given range, finds the covered node and the covering node.
24
 * This API is still under discussion, see https://bugs.eclipse.org/53024 .
25
 *
26
 * @since 3.5
27
 */
28
public final class NodeFinder {
29
	/**
30
	 * This class defines the actual visitor that finds the node.
31
	 */
32
	private static class NodeFinderVisitor extends ASTVisitor {
33
		private int fStart;
34
		private int fEnd;
35
		private ASTNode fCoveringNode;
36
		private ASTNode fCoveredNode;
37
38
		NodeFinderVisitor(int offset, int length) {
39
			super(true); // include Javadoc tags
40
			this.fStart= offset;
41
			this.fEnd= offset + length;
42
		}
43
44
		public boolean preVisit2(ASTNode node) {
45
			int nodeStart= node.getStartPosition();
46
			int nodeEnd= nodeStart + node.getLength();
47
			if (nodeEnd < this.fStart || this.fEnd < nodeStart) {
48
				return false;
49
			}
50
			if (nodeStart <= this.fStart && this.fEnd <= nodeEnd) {
51
				this.fCoveringNode= node;
52
			}
53
			if (this.fStart <= nodeStart && nodeEnd <= this.fEnd) {
54
				if (this.fCoveringNode == node) { // nodeStart == fStart && nodeEnd == fEnd
55
					this.fCoveredNode= node;
56
					return true; // look further for node with same length as parent
57
				} else if (this.fCoveredNode == null) { // no better found
58
					this.fCoveredNode= node;
59
				}
60
				return false;
61
			}
62
			return true;
63
		}
64
		/**
65
		 * Returns the covered node. If more than one nodes are covered by the selection, the
66
		 * returned node is first covered node found in a top-down traversal of the AST
67
		 * @return ASTNode
68
		 */
69
		public ASTNode getCoveredNode() {
70
			return this.fCoveredNode;
71
		}
72
73
		/**
74
		 * Returns the covering node. If more than one nodes are covering the selection, the
75
		 * returned node is last covering node found in a top-down traversal of the AST
76
		 * @return ASTNode
77
		 */
78
		public ASTNode getCoveringNode() {
79
			return this.fCoveringNode;
80
		}
81
	}
82
	/**
83
	 * Maps a selection to a given ASTNode, where the selection is defined using a start and a length.
84
	 * The result node is determined as follows:
85
	 * <ul>
86
	 *   <li>first the visitor tries to find a node with the exact <code>start</code> and <code>length</code></li>
87
	 *   <li>if no such node exists than the node that encloses the range defined by
88
	 *       <code>start</code> and <code>length</code> is returned.</li>
89
	 *   <li>if the length is zero than also nodes are considered where the node's
90
	 *       start or end position matches <code>start</code>.</li>
91
	 *   <li>otherwise <code>null</code> is returned.</li>
92
	 * </ul>
93
	 *
94
	 * @param root the root node from which the search starts
95
	 * @param start the given start
96
	 * @param length the given length
97
	 *
98
	 * @return the found node
99
	 */
100
	public static ASTNode perform(ASTNode root, int start, int length) {
101
		NodeFinder finder = new NodeFinder(root, start, length);
102
		ASTNode result= finder.getCoveredNode();
103
		if (result == null || result.getStartPosition() != start || result.getLength() != length) {
104
			return finder.getCoveringNode();
105
		}
106
		return result;
107
	}
108
109
	/**
110
	 * Maps a selection to a given ASTNode, where the selection is defined using a source range.
111
	 * It calls <code>perform(root, range.getOffset(), range.getLength())</code>.
112
	 * 
113
	 * @return the result node
114
	 * @see #perform(ASTNode, int, int)
115
	 */
116
	public static ASTNode perform(ASTNode root, ISourceRange range) {
117
		return perform(root, range.getOffset(), range.getLength());
118
	}
119
120
	/**
121
	 * Maps a selection to a given ASTNode, where the selection is given by a start and a length.
122
	 * The result node is determined as follows:
123
	 * <ul>
124
	 *   <li>first the visitor tries to find a node that is covered by <code>start</code> and
125
	 *       <code>length</code> where either <code>start</code> and <code>length</code> exactly
126
	 *       matches the node or where the text covered before and after the node only consists
127
	 *       of white spaces or comments.</li>
128
	 *   <li>if no such node exists than the node that encloses the range defined by
129
	 *       <code>start</code> and <code>length</code> is returned.</li>
130
	 *   <li>if the length is zero than also nodes are considered where the node's
131
	 *       start or end position matches <code>start</code>.</li>
132
	 *   <li>otherwise <code>null</code> is returned.</li>
133
	 * </ul>
134
	 *
135
	 * @param root the root node from which the search starts
136
	 * @param start the given start
137
	 * @param length the given length
138
	 * @param source the source of the compilation unit
139
	 *
140
	 * @return the result node
141
	 * @throws JavaModelException if an error occurs in the Java model
142
	 */
143
	public static ASTNode perform(ASTNode root, int start, int length, ITypeRoot source) throws JavaModelException {
144
		NodeFinder finder = new NodeFinder(root, start, length);
145
		ASTNode result= finder.getCoveredNode();
146
		if (result == null)
147
			return null;
148
		int nodeStart= result.getStartPosition();
149
		if (start <= nodeStart && ((nodeStart + result.getLength()) <= (start + length))) {
150
			IBuffer buffer= source.getBuffer();
151
			if (buffer != null) {
152
				IScanner scanner= ToolFactory.createScanner(false, false, false, false);
153
				scanner.setSource(buffer.getText(start, length).toCharArray());
154
				try {
155
					int token= scanner.getNextToken();
156
					if (token != ITerminalSymbols.TokenNameEOF) {
157
						int tStart= scanner.getCurrentTokenStartPosition();
158
						if (tStart == result.getStartPosition() - start) {
159
							scanner.resetTo(tStart + result.getLength(), length - 1);
160
							token= scanner.getNextToken();
161
							if (token == ITerminalSymbols.TokenNameEOF)
162
								return result;
163
						}
164
					}
165
				} catch (InvalidInputException e) {
166
					// ignore
167
				}
168
			}
169
		}
170
		return finder.getCoveringNode();
171
	}
172
	private ASTNode fCoveringNode;
173
	private ASTNode fCoveredNode;
174
175
	/**
176
	 * Instantiate a new node finder using the given root node, the given start and the given length.
177
	 *
178
	 * @param root the given root node
179
	 * @param start the given start
180
	 * @param length the given length
181
	 */
182
	public NodeFinder(ASTNode root, int start, int length) {
183
		NodeFinderVisitor nodeFinderVisitor = new NodeFinderVisitor(start, length);
184
		root.accept(nodeFinderVisitor);
185
		this.fCoveredNode = nodeFinderVisitor.getCoveredNode();
186
		this.fCoveringNode = nodeFinderVisitor.getCoveringNode();
187
	}
188
	/**
189
	 * Returns the covered node. If more than one nodes are covered by the selection, the
190
	 * returned node is first covered node found in a top-down traversal of the AST.
191
	 *
192
	 * @return the covered node
193
	 */
194
	public ASTNode getCoveredNode() {
195
		return this.fCoveredNode;
196
	}
197
198
	/**
199
	 * Returns the covering node. If more than one nodes are covering the selection, the
200
	 * returned node is last covering node found in a top-down traversal of the AST.
201
	 *
202
	 * @return the covering node
203
	 */
204
	public ASTNode getCoveringNode() {
205
		return this.fCoveringNode;
206
	}
207
}

Return to bug 53024