001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.internal.ui.javaeditor;
011:
012: import org.eclipse.jface.text.IDocument;
013: import org.eclipse.jface.text.TextSelection;
014:
015: import org.eclipse.jdt.core.ICompilationUnit;
016: import org.eclipse.jdt.core.IJavaElement;
017: import org.eclipse.jdt.core.ITypeRoot;
018: import org.eclipse.jdt.core.JavaModelException;
019:
020: import org.eclipse.jdt.core.dom.ASTNode;
021: import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
022: import org.eclipse.jdt.core.dom.AnnotationTypeMemberDeclaration;
023: import org.eclipse.jdt.core.dom.BodyDeclaration;
024: import org.eclipse.jdt.core.dom.CompilationUnit;
025: import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
026: import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
027:
028: import org.eclipse.jdt.internal.corext.dom.Selection;
029: import org.eclipse.jdt.internal.corext.dom.SelectionAnalyzer;
030:
031: import org.eclipse.jdt.ui.SharedASTProvider;
032:
033: import org.eclipse.jdt.internal.ui.actions.SelectionConverter;
034:
035: /**
036: * A special text selection that gives access to the resolved and
037: * enclosing element.
038: */
039: public class JavaTextSelection extends TextSelection {
040:
041: private ITypeRoot fElement;
042: private IJavaElement[] fResolvedElements;
043:
044: private boolean fEnclosingElementRequested;
045: private IJavaElement fEnclosingElement;
046:
047: private boolean fPartialASTRequested;
048: private CompilationUnit fPartialAST;
049:
050: private boolean fNodesRequested;
051: private ASTNode[] fSelectedNodes;
052: private ASTNode fCoveringNode;
053:
054: private boolean fInMethodBodyRequested;
055: private boolean fInMethodBody;
056:
057: private boolean fInClassInitializerRequested;
058: private boolean fInClassInitializer;
059:
060: private boolean fInVariableInitializerRequested;
061: private boolean fInVariableInitializer;
062:
063: /**
064: * Creates a new text selection at the given offset and length.
065: * @param element the root element
066: * @param document the document
067: * @param offset offset of the selection
068: * @param length length of the selection
069: */
070: public JavaTextSelection(ITypeRoot element, IDocument document,
071: int offset, int length) {
072: super (document, offset, length);
073: fElement = element;
074: }
075:
076: /**
077: * Resolves the <code>IJavaElement</code>s at the current offset. Returns
078: * an empty array if the string under the offset doesn't resolve to a
079: * <code>IJavaElement</code>.
080: *
081: * @return the resolved java elements at the current offset
082: * @throws JavaModelException passed from the underlying code resolve API
083: */
084: public IJavaElement[] resolveElementAtOffset()
085: throws JavaModelException {
086: if (fResolvedElements != null)
087: return fResolvedElements;
088: // long start= System.currentTimeMillis();
089: fResolvedElements = SelectionConverter.codeResolve(fElement,
090: this );
091: // System.out.println("Time resolving element: " + (System.currentTimeMillis() - start));
092: return fResolvedElements;
093: }
094:
095: public IJavaElement resolveEnclosingElement()
096: throws JavaModelException {
097: if (fEnclosingElementRequested)
098: return fEnclosingElement;
099: fEnclosingElementRequested = true;
100: fEnclosingElement = SelectionConverter.resolveEnclosingElement(
101: fElement, this );
102: return fEnclosingElement;
103: }
104:
105: public CompilationUnit resolvePartialAstAtOffset() {
106: if (fPartialASTRequested)
107: return fPartialAST;
108: fPartialASTRequested = true;
109: if (!(fElement instanceof ICompilationUnit))
110: return null;
111: // long start= System.currentTimeMillis();
112: fPartialAST = SharedASTProvider.getAST(fElement,
113: SharedASTProvider.WAIT_YES, null);
114: // System.out.println("Time requesting partial AST: " + (System.currentTimeMillis() - start));
115: return fPartialAST;
116: }
117:
118: public ASTNode[] resolveSelectedNodes() {
119: if (fNodesRequested)
120: return fSelectedNodes;
121: fNodesRequested = true;
122: CompilationUnit root = resolvePartialAstAtOffset();
123: if (root == null)
124: return null;
125: Selection ds = Selection.createFromStartLength(getOffset(),
126: getLength());
127: SelectionAnalyzer analyzer = new SelectionAnalyzer(ds, false);
128: root.accept(analyzer);
129: fSelectedNodes = analyzer.getSelectedNodes();
130: fCoveringNode = analyzer.getLastCoveringNode();
131: return fSelectedNodes;
132: }
133:
134: public ASTNode resolveCoveringNode() {
135: if (fNodesRequested)
136: return fCoveringNode;
137: resolveSelectedNodes();
138: return fCoveringNode;
139: }
140:
141: public boolean resolveInMethodBody() {
142: if (fInMethodBodyRequested)
143: return fInMethodBody;
144: fInMethodBodyRequested = true;
145: resolveSelectedNodes();
146: ASTNode node = getStartNode();
147: if (node == null) {
148: fInMethodBody = true;
149: } else {
150: while (node != null) {
151: int nodeType = node.getNodeType();
152: if (nodeType == ASTNode.BLOCK
153: && node.getParent() instanceof BodyDeclaration) {
154: fInMethodBody = node.getParent().getNodeType() == ASTNode.METHOD_DECLARATION;
155: break;
156: } else if (nodeType == ASTNode.ANONYMOUS_CLASS_DECLARATION) {
157: fInMethodBody = false;
158: break;
159: }
160: node = node.getParent();
161: }
162: }
163: return fInMethodBody;
164: }
165:
166: public boolean resolveInClassInitializer() {
167: if (fInClassInitializerRequested)
168: return fInClassInitializer;
169: fInClassInitializerRequested = true;
170: resolveSelectedNodes();
171: ASTNode node = getStartNode();
172: if (node == null) {
173: fInClassInitializer = true;
174: } else {
175: while (node != null) {
176: int nodeType = node.getNodeType();
177: if (node instanceof AbstractTypeDeclaration) {
178: fInClassInitializer = false;
179: break;
180: } else if (nodeType == ASTNode.ANONYMOUS_CLASS_DECLARATION) {
181: fInClassInitializer = false;
182: break;
183: } else if (nodeType == ASTNode.INITIALIZER) {
184: fInClassInitializer = true;
185: break;
186: }
187: node = node.getParent();
188: }
189: }
190: return fInClassInitializer;
191: }
192:
193: public boolean resolveInVariableInitializer() {
194: if (fInVariableInitializerRequested)
195: return fInVariableInitializer;
196: fInVariableInitializerRequested = true;
197: resolveSelectedNodes();
198: ASTNode node = getStartNode();
199: ASTNode last = null;
200: while (node != null) {
201: int nodeType = node.getNodeType();
202: if (node instanceof AbstractTypeDeclaration) {
203: fInVariableInitializer = false;
204: break;
205: } else if (nodeType == ASTNode.ANONYMOUS_CLASS_DECLARATION) {
206: fInVariableInitializer = false;
207: break;
208: } else if (nodeType == ASTNode.VARIABLE_DECLARATION_FRAGMENT
209: && ((VariableDeclarationFragment) node)
210: .getInitializer() == last) {
211: fInVariableInitializer = true;
212: break;
213: } else if (nodeType == ASTNode.SINGLE_VARIABLE_DECLARATION
214: && ((SingleVariableDeclaration) node)
215: .getInitializer() == last) {
216: fInVariableInitializer = true;
217: break;
218: } else if (nodeType == ASTNode.ANNOTATION_TYPE_MEMBER_DECLARATION
219: && ((AnnotationTypeMemberDeclaration) node)
220: .getDefault() == last) {
221: fInVariableInitializer = true;
222: break;
223: }
224: last = node;
225: node = node.getParent();
226: }
227: return fInVariableInitializer;
228: }
229:
230: private ASTNode getStartNode() {
231: if (fSelectedNodes != null && fSelectedNodes.length > 0)
232: return fSelectedNodes[0];
233: else
234: return fCoveringNode;
235: }
236: }
|