| /* |
| * Copyright (c) 2012, 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; |
| |
| import com.google.dart.engine.ast.AstNode; |
| import com.google.dart.engine.ast.CompilationUnit; |
| import com.google.dart.engine.ast.Identifier; |
| import com.google.dart.engine.context.AnalysisContext; |
| import com.google.dart.engine.context.AnalysisException; |
| import com.google.dart.engine.element.Element; |
| import com.google.dart.engine.element.ElementAnnotation; |
| import com.google.dart.engine.element.ElementKind; |
| import com.google.dart.engine.element.ElementLocation; |
| import com.google.dart.engine.element.ElementVisitor; |
| import com.google.dart.engine.element.LibraryElement; |
| import com.google.dart.engine.element.MultiplyDefinedElement; |
| import com.google.dart.engine.internal.type.DynamicTypeImpl; |
| import com.google.dart.engine.source.Source; |
| import com.google.dart.engine.type.Type; |
| |
| import java.util.HashSet; |
| |
| /** |
| * Instances of the class {@code MultiplyDefinedElementImpl} represent a collection of elements that |
| * have the same name within the same scope. |
| * |
| * @coverage dart.engine.element |
| */ |
| public class MultiplyDefinedElementImpl implements MultiplyDefinedElement { |
| /** |
| * Return an element that represents the given conflicting elements. |
| * |
| * @param context the analysis context in which the multiply defined elements are defined |
| * @param firstElement the first element that conflicts |
| * @param secondElement the second element that conflicts |
| */ |
| public static Element fromElements(AnalysisContext context, Element firstElement, |
| Element secondElement) { |
| Element[] conflictingElements = computeConflictingElements(firstElement, secondElement); |
| int length = conflictingElements.length; |
| if (length == 0) { |
| return null; |
| } else if (length == 1) { |
| return conflictingElements[0]; |
| } |
| return new MultiplyDefinedElementImpl(context, conflictingElements); |
| } |
| |
| /** |
| * Add the given element to the list of elements. If the element is a multiply-defined element, |
| * add all of the conflicting elements that it represents. |
| * |
| * @param elements the list to which the element(s) are to be added |
| * @param element the element(s) to be added |
| */ |
| private static void add(HashSet<Element> elements, Element element) { |
| if (element instanceof MultiplyDefinedElementImpl) { |
| for (Element conflictingElement : ((MultiplyDefinedElementImpl) element).conflictingElements) { |
| elements.add(conflictingElement); |
| } |
| } else { |
| elements.add(element); |
| } |
| } |
| |
| /** |
| * Use the given elements to construct an array of conflicting elements. If either of the given |
| * elements are multiply-defined elements then the conflicting elements they represent will be |
| * included in the array. Otherwise, the element itself will be included. |
| * |
| * @param firstElement the first element to be included |
| * @param secondElement the second element to be included |
| * @return an array containing all of the conflicting elements |
| */ |
| private static Element[] computeConflictingElements(Element firstElement, Element secondElement) { |
| HashSet<Element> elements = new HashSet<Element>(); |
| add(elements, firstElement); |
| add(elements, secondElement); |
| return elements.toArray(new Element[elements.size()]); |
| } |
| |
| /** |
| * The analysis context in which the multiply defined elements are defined. |
| */ |
| private AnalysisContext context; |
| |
| /** |
| * The name of the conflicting elements. |
| */ |
| private String name; |
| |
| /** |
| * A list containing all of the elements that conflict. |
| */ |
| private Element[] conflictingElements; |
| |
| /** |
| * Initialize a newly created element to represent a list of conflicting elements. |
| * |
| * @param context the analysis context in which the multiply defined elements are defined |
| * @param conflictingElements the elements that conflict |
| */ |
| public MultiplyDefinedElementImpl(AnalysisContext context, Element[] conflictingElements) { |
| this.context = context; |
| name = conflictingElements[0].getName(); |
| this.conflictingElements = conflictingElements; |
| } |
| |
| @Override |
| public <R> R accept(ElementVisitor<R> visitor) { |
| return visitor.visitMultiplyDefinedElement(this); |
| } |
| |
| @Override |
| public String computeDocumentationComment() throws AnalysisException { |
| return null; |
| } |
| |
| @Override |
| public <E extends Element> E getAncestor(Class<E> elementClass) { |
| return null; |
| } |
| |
| @Override |
| public Element[] getConflictingElements() { |
| return conflictingElements; |
| } |
| |
| @Override |
| public AnalysisContext getContext() { |
| return context; |
| } |
| |
| @Override |
| public String getDisplayName() { |
| return name; |
| } |
| |
| @Override |
| public Element getEnclosingElement() { |
| return null; |
| } |
| |
| @Override |
| public String getExtendedDisplayName(String shortName) { |
| if (shortName != null) { |
| return shortName; |
| } |
| return getDisplayName(); |
| } |
| |
| @Override |
| public ElementKind getKind() { |
| return ElementKind.ERROR; |
| } |
| |
| @Override |
| public LibraryElement getLibrary() { |
| return null; |
| } |
| |
| @Override |
| public ElementLocation getLocation() { |
| return null; |
| } |
| |
| @Override |
| public ElementAnnotation[] getMetadata() { |
| return ElementAnnotationImpl.EMPTY_ARRAY; |
| } |
| |
| @Override |
| public String getName() { |
| return name; |
| } |
| |
| @Override |
| public int getNameOffset() { |
| return -1; |
| } |
| |
| @Override |
| public AstNode getNode() throws AnalysisException { |
| return null; |
| } |
| |
| @Override |
| public Source getSource() { |
| return null; |
| } |
| |
| @Override |
| public Type getType() { |
| return DynamicTypeImpl.getInstance(); |
| } |
| |
| @Override |
| public CompilationUnit getUnit() throws AnalysisException { |
| return null; |
| } |
| |
| @Override |
| public boolean isAccessibleIn(LibraryElement library) { |
| for (Element element : conflictingElements) { |
| if (element.isAccessibleIn(library)) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| @Override |
| public boolean isDeprecated() { |
| return false; |
| } |
| |
| @Override |
| public boolean isOverride() { |
| return false; |
| } |
| |
| @Override |
| public boolean isPrivate() { |
| String name = getDisplayName(); |
| if (name == null) { |
| return false; |
| } |
| return Identifier.isPrivateName(name); |
| } |
| |
| @Override |
| public boolean isPublic() { |
| return !isPrivate(); |
| } |
| |
| @Override |
| public boolean isSynthetic() { |
| return true; |
| } |
| |
| @Override |
| public String toString() { |
| StringBuilder builder = new StringBuilder(); |
| builder.append("["); |
| int count = conflictingElements.length; |
| for (int i = 0; i < count; i++) { |
| if (i > 0) { |
| builder.append(", "); |
| } |
| ((ElementImpl) conflictingElements[i]).appendTo(builder); |
| } |
| builder.append("]"); |
| return builder.toString(); |
| } |
| |
| @Override |
| public void visitChildren(ElementVisitor<?> visitor) { |
| // There are no children to visit |
| } |
| } |