blob: 5846dbe8520b071875b156edea787ba3c4c22597 [file] [log] [blame]
/*
* Copyright (c) 2013, the Dart project authors.
*
* Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.eclipse.org/legal/epl-v10.html
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.dart.engine.internal.element.handle;
import com.google.dart.engine.ast.AstNode;
import com.google.dart.engine.ast.CompilationUnit;
import com.google.dart.engine.context.AnalysisContext;
import com.google.dart.engine.context.AnalysisException;
import com.google.dart.engine.element.ClassElement;
import com.google.dart.engine.element.CompilationUnitElement;
import com.google.dart.engine.element.ConstructorElement;
import com.google.dart.engine.element.Element;
import com.google.dart.engine.element.ElementAnnotation;
import com.google.dart.engine.element.ElementLocation;
import com.google.dart.engine.element.ElementVisitor;
import com.google.dart.engine.element.ExportElement;
import com.google.dart.engine.element.FieldElement;
import com.google.dart.engine.element.FunctionElement;
import com.google.dart.engine.element.FunctionTypeAliasElement;
import com.google.dart.engine.element.ImportElement;
import com.google.dart.engine.element.LabelElement;
import com.google.dart.engine.element.LibraryElement;
import com.google.dart.engine.element.LocalVariableElement;
import com.google.dart.engine.element.MethodElement;
import com.google.dart.engine.element.ParameterElement;
import com.google.dart.engine.element.PrefixElement;
import com.google.dart.engine.element.PropertyAccessorElement;
import com.google.dart.engine.element.TopLevelVariableElement;
import com.google.dart.engine.element.TypeParameterElement;
import com.google.dart.engine.source.Source;
import java.lang.ref.WeakReference;
/**
* The abstract class {@code ElementHandle} implements the behavior common to objects that implement
* a handle to an {@link Element}.
*
* @coverage dart.engine.element
*/
public abstract class ElementHandle implements Element {
/**
* Return a handle on the given element. If the element is already a handle, then it will be
* returned directly, otherwise a handle of the appropriate class will be constructed.
*
* @param element the element for which a handle is to be constructed
* @return a handle on the given element
*/
@SuppressWarnings("unchecked")
public static <E extends Element> E forElement(E element) {
if (element instanceof ElementHandle) {
return element;
}
switch (element.getKind()) {
case CLASS:
return (E) new ClassElementHandle((ClassElement) element);
case COMPILATION_UNIT:
return (E) new CompilationUnitElementHandle((CompilationUnitElement) element);
case CONSTRUCTOR:
return (E) new ConstructorElementHandle((ConstructorElement) element);
case EXPORT:
return (E) new ExportElementHandle((ExportElement) element);
case FIELD:
return (E) new FieldElementHandle((FieldElement) element);
case FUNCTION:
return (E) new FunctionElementHandle((FunctionElement) element);
case GETTER:
return (E) new PropertyAccessorElementHandle((PropertyAccessorElement) element);
//case HTML:
case IMPORT:
return (E) new ImportElementHandle((ImportElement) element);
case LABEL:
return (E) new LabelElementHandle((LabelElement) element);
case LIBRARY:
return (E) new LibraryElementHandle((LibraryElement) element);
case LOCAL_VARIABLE:
return (E) new LocalVariableElementHandle((LocalVariableElement) element);
case METHOD:
return (E) new MethodElementHandle((MethodElement) element);
case PARAMETER:
return (E) new ParameterElementHandle((ParameterElement) element);
case PREFIX:
return (E) new PrefixElementHandle((PrefixElement) element);
case SETTER:
return (E) new PropertyAccessorElementHandle((PropertyAccessorElement) element);
case TOP_LEVEL_VARIABLE:
return (E) new TopLevelVariableElementHandle((TopLevelVariableElement) element);
case FUNCTION_TYPE_ALIAS:
return (E) new FunctionTypeAliasElementHandle((FunctionTypeAliasElement) element);
case TYPE_PARAMETER:
return (E) new TypeParameterElementHandle((TypeParameterElement) element);
default:
throw new UnsupportedOperationException();
}
}
/**
* Return an array of the same size as the given array where each element of the returned array is
* a handle for the corresponding element of the given array.
*
* @param elements the elements for which handles are to be created
* @return an array of handles to the given elements
*/
public static <E extends Element> E[] forElements(E[] elements) {
int length = elements.length;
E[] handles = elements.clone();
for (int i = 0; i < length; i++) {
handles[i] = forElement(elements[i]);
}
return handles;
}
/**
* The context in which the element is defined.
*/
private AnalysisContext context;
/**
* The location of this element, used to reconstitute the element if it has been garbage
* collected.
*/
private ElementLocation location;
/**
* A reference to the element being referenced by this handle, or {@code null} if the element has
* been garbage collected.
*/
private WeakReference<Element> elementReference;
/**
* Initialize a newly created element handle to represent the given element.
*
* @param element the element being represented
*/
public ElementHandle(Element element) {
context = element.getContext();
location = element.getLocation();
elementReference = new WeakReference<Element>(element);
}
@Override
public <R> R accept(ElementVisitor<R> visitor) {
return getActualElement().accept(visitor);
}
@Override
public String computeDocumentationComment() throws AnalysisException {
return getActualElement().computeDocumentationComment();
}
@Override
public boolean equals(Object object) {
return object instanceof Element && ((Element) object).getLocation().equals(location);
}
@Override
public <E extends Element> E getAncestor(Class<E> elementClass) {
return getActualElement().getAncestor(elementClass);
}
@Override
public AnalysisContext getContext() {
return context;
}
@Override
public String getDisplayName() {
return getActualElement().getDisplayName();
}
@Override
public Element getEnclosingElement() {
return getActualElement().getEnclosingElement();
}
@Override
public String getExtendedDisplayName(String shortName) {
return getActualElement().getExtendedDisplayName(shortName);
}
@Override
public LibraryElement getLibrary() {
return getAncestor(LibraryElement.class);
}
@Override
public ElementLocation getLocation() {
return location;
}
@Override
public ElementAnnotation[] getMetadata() {
return getActualElement().getMetadata();
}
@Override
public String getName() {
return getActualElement().getName();
}
@Override
public int getNameOffset() {
return getActualElement().getNameOffset();
}
@Override
public AstNode getNode() throws AnalysisException {
return getActualElement().getNode();
}
@Override
public Source getSource() {
return getActualElement().getSource();
}
@Override
public CompilationUnit getUnit() throws AnalysisException {
return getActualElement().getUnit();
}
@Override
public int hashCode() {
return location.hashCode();
}
@Override
public boolean isAccessibleIn(LibraryElement library) {
return getActualElement().isAccessibleIn(library);
}
@Override
public boolean isDeprecated() {
return getActualElement().isDeprecated();
}
@Override
public boolean isOverride() {
return getActualElement().isOverride();
}
@Override
public boolean isPrivate() {
return getActualElement().isPrivate();
}
@Override
public boolean isPublic() {
return getActualElement().isPublic();
}
@Override
public boolean isSynthetic() {
return getActualElement().isSynthetic();
}
@Override
public void visitChildren(ElementVisitor<?> visitor) {
getActualElement().visitChildren(visitor);
}
/**
* Return the element being represented by this handle, reconstituting the element if the
* reference has been set to {@code null}.
*
* @return the element being represented by this handle
*/
protected Element getActualElement() {
Element element = elementReference.get();
if (element == null) {
element = context.getElement(location);
elementReference = new WeakReference<Element>(element);
}
return element;
}
}