blob: ed1f305b90906891a0fdf073ff03377082bc233f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2008 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.wst.jsdt.internal.ui.javaeditor;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.TextSelection;
import org.eclipse.wst.jsdt.core.IJavaScriptElement;
import org.eclipse.wst.jsdt.core.IJavaScriptUnit;
import org.eclipse.wst.jsdt.core.JavaScriptModelException;
import org.eclipse.wst.jsdt.core.dom.ASTNode;
import org.eclipse.wst.jsdt.core.dom.AbstractTypeDeclaration;
import org.eclipse.wst.jsdt.core.dom.BodyDeclaration;
import org.eclipse.wst.jsdt.core.dom.JavaScriptUnit;
import org.eclipse.wst.jsdt.core.dom.SingleVariableDeclaration;
import org.eclipse.wst.jsdt.core.dom.VariableDeclarationFragment;
import org.eclipse.wst.jsdt.internal.corext.dom.Selection;
import org.eclipse.wst.jsdt.internal.corext.dom.SelectionAnalyzer;
import org.eclipse.wst.jsdt.internal.ui.JavaScriptPlugin;
import org.eclipse.wst.jsdt.internal.ui.actions.SelectionConverter;
/**
* A special text selection that gives access to the resolved and
* enclosing element.
*/
public class JavaTextSelection extends TextSelection {
private IJavaScriptElement fElement;
private IJavaScriptElement[] fResolvedElements;
private boolean fEnclosingElementRequested;
private IJavaScriptElement fEnclosingElement;
private boolean fPartialASTRequested;
private JavaScriptUnit fPartialAST;
private boolean fNodesRequested;
private ASTNode[] fSelectedNodes;
private ASTNode fCoveringNode;
private boolean fInMethodBodyRequested;
private boolean fInMethodBody;
private boolean fInClassInitializerRequested;
private boolean fInClassInitializer;
private boolean fInVariableInitializerRequested;
private boolean fInVariableInitializer;
/**
* Creates a new text selection at the given offset and length.
*/
public JavaTextSelection(IJavaScriptElement element, IDocument document, int offset, int length) {
super(document, offset, length);
fElement= element;
}
/**
* Resolves the <code>IJavaScriptElement</code>s at the current offset. Returns
* an empty array if the string under the offset doesn't resolve to a
* <code>IJavaScriptElement</code>.
*
* @return the resolved java elements at the current offset
* @throws JavaScriptModelException passed from the underlying code resolve API
*/
public IJavaScriptElement[] resolveElementAtOffset() throws JavaScriptModelException {
if (fResolvedElements != null)
return fResolvedElements;
// long start= System.currentTimeMillis();
fResolvedElements= SelectionConverter.codeResolve(fElement, this);
// System.out.println("Time resolving element: " + (System.currentTimeMillis() - start));
return fResolvedElements;
}
public IJavaScriptElement resolveEnclosingElement() throws JavaScriptModelException {
if (fEnclosingElementRequested)
return fEnclosingElement;
fEnclosingElementRequested= true;
fEnclosingElement= SelectionConverter.resolveEnclosingElement(fElement, this);
return fEnclosingElement;
}
public JavaScriptUnit resolvePartialAstAtOffset() {
if (fPartialASTRequested)
return fPartialAST;
fPartialASTRequested= true;
if (! (fElement instanceof IJavaScriptUnit))
return null;
// long start= System.currentTimeMillis();
fPartialAST= JavaScriptPlugin.getDefault().getASTProvider().getAST(fElement, ASTProvider.WAIT_YES, null);
// System.out.println("Time requesting partial AST: " + (System.currentTimeMillis() - start));
return fPartialAST;
}
public ASTNode[] resolveSelectedNodes() {
if (fNodesRequested)
return fSelectedNodes;
fNodesRequested= true;
JavaScriptUnit root= resolvePartialAstAtOffset();
if (root == null)
return null;
Selection ds= Selection.createFromStartLength(getOffset(), getLength());
SelectionAnalyzer analyzer= new SelectionAnalyzer(ds, false);
root.accept(analyzer);
fSelectedNodes= analyzer.getSelectedNodes();
fCoveringNode= analyzer.getLastCoveringNode();
return fSelectedNodes;
}
public ASTNode resolveCoveringNode() {
if (fNodesRequested)
return fCoveringNode;
resolveSelectedNodes();
return fCoveringNode;
}
public boolean resolveInMethodBody() {
if (fInMethodBodyRequested)
return fInMethodBody;
fInMethodBodyRequested= true;
resolveSelectedNodes();
ASTNode node= getStartNode();
if (node == null) {
fInMethodBody= true;
} else {
while (node != null) {
int nodeType= node.getNodeType();
if (nodeType == ASTNode.BLOCK && node.getParent() instanceof BodyDeclaration) {
fInMethodBody= node.getParent().getNodeType() == ASTNode.FUNCTION_DECLARATION;
break;
} else if (nodeType == ASTNode.ANONYMOUS_CLASS_DECLARATION) {
fInMethodBody= false;
break;
}
node= node.getParent();
}
}
return fInMethodBody;
}
public boolean resolveInClassInitializer() {
if (fInClassInitializerRequested)
return fInClassInitializer;
fInClassInitializerRequested= true;
resolveSelectedNodes();
ASTNode node= getStartNode();
if (node == null) {
fInClassInitializer= true;
} else {
while (node != null) {
int nodeType= node.getNodeType();
if (node instanceof AbstractTypeDeclaration) {
fInClassInitializer= false;
break;
} else if (nodeType == ASTNode.ANONYMOUS_CLASS_DECLARATION) {
fInClassInitializer= false;
break;
} else if (nodeType == ASTNode.INITIALIZER) {
fInClassInitializer= true;
break;
}
node= node.getParent();
}
}
return fInClassInitializer;
}
public boolean resolveInVariableInitializer() {
if (fInVariableInitializerRequested)
return fInVariableInitializer;
fInVariableInitializerRequested= true;
resolveSelectedNodes();
ASTNode node= getStartNode();
ASTNode last= null;
while (node != null) {
int nodeType= node.getNodeType();
if (node instanceof AbstractTypeDeclaration) {
fInVariableInitializer= false;
break;
} else if (nodeType == ASTNode.ANONYMOUS_CLASS_DECLARATION) {
fInVariableInitializer= false;
break;
} else if (nodeType == ASTNode.VARIABLE_DECLARATION_FRAGMENT &&
((VariableDeclarationFragment)node).getInitializer() == last) {
fInVariableInitializer= true;
break;
} else if (nodeType == ASTNode.SINGLE_VARIABLE_DECLARATION &&
((SingleVariableDeclaration)node).getInitializer() == last) {
fInVariableInitializer= true;
break;
}
last= node;
node= node.getParent();
}
return fInVariableInitializer;
}
private ASTNode getStartNode() {
if (fSelectedNodes != null && fSelectedNodes.length > 0)
return fSelectedNodes[0];
else
return fCoveringNode;
}
}