// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

package com.google.dart.compiler.resolver;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Objects;
import com.google.dart.compiler.DartCompilerContext;
import com.google.dart.compiler.ErrorCode;
import com.google.dart.compiler.ast.ASTVisitor;
import com.google.dart.compiler.ast.DartBlock;
import com.google.dart.compiler.ast.DartClass;
import com.google.dart.compiler.ast.DartExpression;
import com.google.dart.compiler.ast.DartField;
import com.google.dart.compiler.ast.DartFieldDefinition;
import com.google.dart.compiler.ast.DartFunction;
import com.google.dart.compiler.ast.DartFunctionTypeAlias;
import com.google.dart.compiler.ast.DartIdentifier;
import com.google.dart.compiler.ast.DartMethodDefinition;
import com.google.dart.compiler.ast.DartNativeBlock;
import com.google.dart.compiler.ast.DartNode;
import com.google.dart.compiler.ast.DartParameter;
import com.google.dart.compiler.ast.DartParameterizedTypeNode;
import com.google.dart.compiler.ast.DartPropertyAccess;
import com.google.dart.compiler.ast.DartThisExpression;
import com.google.dart.compiler.ast.DartUnit;
import com.google.dart.compiler.ast.Modifiers;
import com.google.dart.compiler.common.HasSourceInfo;
import com.google.dart.compiler.common.SourceInfo;
import com.google.dart.compiler.type.Type;
import com.google.dart.compiler.type.Types;
import com.google.dart.compiler.util.apache.StringUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * Builds the method, field and constructor elements of classes and the library in a DartUnit.
 */
public class MemberBuilder {
  private ResolutionContext topLevelContext;
  private LibraryElement libraryElement;

  public void exec(DartUnit unit, DartCompilerContext context, CoreTypeProvider typeProvider) {
    Scope scope = unit.getLibrary().getElement().getScope();
    exec(unit, context, scope, typeProvider);
  }

  @VisibleForTesting
  public void exec(DartUnit unit, DartCompilerContext compilerContext, Scope scope,
                   CoreTypeProvider typeProvider) {
    libraryElement = unit.getLibrary().getElement();
    topLevelContext = new ResolutionContext(scope, compilerContext, typeProvider);
    unit.accept(new MemberElementBuilder(typeProvider));
  }

  /**
   * Creates elements for the fields, methods and constructors of a class. The
   * elements are added to the ClassElement.
   *
   * TODO(ngeoffray): Errors reported:
   *  - Duplicate member names in the same class.
   *  - Unresolved types.
   */
  private class MemberElementBuilder extends ResolveVisitor {
    EnclosingElement currentHolder;
    private EnclosingElement enclosingElement;
    private ResolutionContext context;
    private boolean isStatic;
    private boolean isFactory;

    MemberElementBuilder(CoreTypeProvider typeProvider) {
      super(typeProvider);
      context = topLevelContext;
      currentHolder = libraryElement;
    }

    @Override
    ResolutionContext getContext() {
      return context;
    }

    @Override
    protected EnclosingElement getEnclosingElement() {
      return enclosingElement;
    }

    @Override
    public Element visitClass(DartClass node) {
      assert !ElementKind.of(currentHolder).equals(ElementKind.CLASS) : "nested class?";
      beginClassContext(node);
      ClassElement classElement = node.getElement();
      EnclosingElement previousEnclosingElement = enclosingElement;
      enclosingElement = classElement;
      // visit fields, to make their Elements ready for constructor parameters
      for (DartNode member : node.getMembers()) {
        if (member instanceof DartFieldDefinition) {
          member.accept(this);
        }
      }
      // visit all other members
      for (DartNode member : node.getMembers()) {
        if (!(member instanceof DartFieldDefinition)) {
          member.accept(this);
        }
      }
      // check constructor names
      for (ConstructorElement constructor : classElement.getConstructors()) {
        String name = constructor.getName();
        SourceInfo nameLocation = constructor.getNameLocation();
        // should be name of immediately enclosing class
        if (constructor.getModifiers().isFactory()) {
          String rawName = constructor.getRawName();
          String consClassName = StringUtils.substringBefore(rawName, ".");
          String consUserName = StringUtils.substringAfter(rawName, ".");
          if (!StringUtils.equals(consClassName, classElement.getName())) {
            // report error for for M part of M.id or pure M
            SourceInfo consClassLocation = new SourceInfo(nameLocation.getSource(),
                nameLocation.getOffset(), consClassName.length());
            resolutionError(consClassLocation,
                ResolverErrorCode.CONSTRUCTOR_NAME_NOT_ENCLOSING_CLASS);
            // in addition also report warning for whole constructor name
            if (!StringUtils.isEmpty(consUserName)) {
              resolutionError(nameLocation,
                  ResolverErrorCode.CONSTRUCTOR_NAME_NOT_ENCLOSING_CLASS_ID);
            }
          }
        }
        // should not conflict with member names
        {
          Element member = classElement.lookupLocalElement(name);
          if (member != null) {
            resolutionError(nameLocation,
                ResolverErrorCode.CONSTRUCTOR_WITH_NAME_OF_MEMBER);
          }
        }
      }
      // done with this class
      enclosingElement = previousEnclosingElement;
      endClassContext();
      return null;
    }

    private void checkParameterInitializer(DartMethodDefinition method, DartParameter parameter) {
      if (Elements.isNonFactoryConstructor(method.getElement())) {
        if (method.getModifiers().isRedirectedConstructor()) {
          resolutionError(parameter.getName(),
              ResolverErrorCode.PARAMETER_INIT_WITH_REDIR_CONSTRUCTOR);
        }

        FieldElement element =
          Elements.lookupLocalField((ClassElement) currentHolder, parameter.getParameterName());
        if (element == null) {
          resolutionError(parameter, ResolverErrorCode.PARAMETER_NOT_MATCH_FIELD,
                          parameter.getName());
        } else if (element.isStatic()) {
          resolutionError(parameter,
                          ResolverErrorCode.PARAMETER_INIT_STATIC_FIELD,
                          parameter.getName());
        }

        // Field parameters are not visible as parameters, so we do not declare them
        // in the context. Instead we record the resolved field element.
        Elements.setParameterInitializerElement(parameter.getElement(), element);

        // The editor expects the referenced elements to be non-null
        DartPropertyAccess prop = (DartPropertyAccess)parameter.getName();
        prop.setElement(element);
        prop.getName().setElement(element);

        // If no type specified, use type of field.
        if (parameter.getTypeNode() == null && element != null) {
          Elements.setType(parameter.getElement(), element.getType());
        }
      } else {
        resolutionError(parameter.getName(),
            ResolverErrorCode.PARAMETER_INIT_OUTSIDE_CONSTRUCTOR);
      }
    }

    @Override
    public Element visitFunctionTypeAlias(DartFunctionTypeAlias node) {
      isStatic = false;
      isFactory = false;
      assert !ElementKind.of(currentHolder).equals(ElementKind.CLASS) : "nested class?";
      FunctionAliasElement element = node.getElement();
      currentHolder = element;
      context = context.extend((ClassElement) currentHolder); // Put type variables in scope.
      visit(node.getTypeParameters());
      List<VariableElement> parameters = new ArrayList<VariableElement>();
      for (DartParameter parameter : node.getParameters()) {
        parameters.add((VariableElement) parameter.accept(this));
      }
      Type returnType = resolveType(node.getReturnTypeNode(), false, false, true,
          TypeErrorCode.NO_SUCH_TYPE, TypeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS);
      ClassElement functionElement = getTypeProvider().getFunctionType().getElement();
      element.setFunctionType(Types.makeFunctionType(getContext(), functionElement,
                                                     parameters, returnType));
      currentHolder = libraryElement;
      context = topLevelContext;
      return null;
    }

    @Override
    public Element visitMethodDefinition(final DartMethodDefinition method) {
      isFactory = method.getModifiers().isFactory();
      isStatic = method.getModifiers().isStatic() || isFactory;
      MethodNodeElement element = method.getElement();
      if (element == null) {
        switch (getMethodKind(method)) {
          case NONE:
          case CONSTRUCTOR:
            element = buildConstructor(method);
            checkConstructor(element, method);
            addConstructor((ClassElement) currentHolder, (ConstructorNodeElement) element);
            break;

          case METHOD:
            element = Elements.methodFromMethodNode(method, currentHolder);
            addMethod(currentHolder, element);
            break;
        }
      } else {
        // This is a top-level element, and an element was already created in
        // TopLevelElementBuilder.
        Elements.addMethod(currentHolder, element);
        assertTopLevel(method);
      }
      if (element != null) {
        checkTopLevelMainFunction(method);
        checkModifiers(element, method);
        recordElement(method, element);
        recordElement(method.getName(), element);
        ResolutionContext previous = context;
        context = context.extend(element.getName());
        EnclosingElement previousEnclosingElement = enclosingElement;
        enclosingElement = element;
        resolveFunction(method.getFunction(), element);
        enclosingElement = previousEnclosingElement;
        context = previous;
      }
      return null;
    }

    @Override
    protected void resolveFunctionWithParameters(DartFunction node, MethodElement element) {
      super.resolveFunctionWithParameters(node, element);
      // Bind "formal initializers" to fields.
      if (node.getParent() instanceof DartMethodDefinition) {
        DartMethodDefinition method = (DartMethodDefinition) node.getParent();
        for (DartParameter parameter : node.getParameters()) {
          if (parameter.getQualifier() instanceof DartThisExpression) {
            checkParameterInitializer(method, parameter);
          }
        }
      }
    }

    @Override
    public Element visitFieldDefinition(DartFieldDefinition node) {
      isStatic = false;
      isFactory = false;
      for (DartField fieldNode : node.getFields()) {
        if (fieldNode.getModifiers().isStatic()) {
          isStatic = true;
        }
      }
      Type type = resolveType(node.getTypeNode(), isStatic, false, true, TypeErrorCode.NO_SUCH_TYPE,
          TypeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS);
      for (DartField fieldNode : node.getFields()) {
        if (fieldNode.getModifiers().isAbstractField()) {
          buildAbstractField(fieldNode);
        } else {
          buildField(fieldNode, type);
        }
      }
      return null;
    }

    private void beginClassContext(final DartClass node) {
      assert !ElementKind.of(currentHolder).equals(ElementKind.CLASS) : "nested class?";
      currentHolder = node.getElement();
      context = context.extend((ClassElement) currentHolder);
    }

    private void endClassContext() {
      currentHolder = libraryElement;
      context = topLevelContext;
    }

    private Element resolveConstructorName(final DartMethodDefinition method) {
      return method.getName().accept(new ASTVisitor<Element>() {
        @Override
        public Element visitPropertyAccess(DartPropertyAccess node) {
          Element element = context.resolveName(node);
          if (ElementKind.of(element) == ElementKind.CLASS) {
            return resolveType(node);
          } else {
            element = node.getQualifier().accept(this);
            recordElement(node.getQualifier(), element);
          }
          if (ElementKind.of(element) == ElementKind.CLASS) {
            return Elements.constructorFromMethodNode(
                method, node.getPropertyName(), (ClassElement) currentHolder, (ClassElement) element);
          } else {
            // Nothing else is valid. Already warned in getMethodKind().
            return getTypeProvider().getDynamicType().getElement();
          }
        }
        @Override
        public Element visitIdentifier(DartIdentifier node) {
          return resolveType(node);
        }
        private Element resolveType(DartNode node) {
          return context.resolveType(
              node,
              node,
              null,
              true,
              false,
              false,
              ResolverErrorCode.NO_SUCH_TYPE_CONSTRUCTOR,
              ResolverErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS).getElement();
        }
        @Override
        public Element visitParameterizedTypeNode(DartParameterizedTypeNode node) {
          Element element = node.getExpression().accept(this);
          if (ElementKind.of(element).equals(ElementKind.CONSTRUCTOR)) {
            recordElement(node.getExpression(), currentHolder);
          } else {
            recordElement(node.getExpression(), element);
          }
          return element;
        }
        @Override
        public Element visitNode(DartNode node) {
          throw new RuntimeException("Unexpected node " + node);
        }
      });
    }

    private MethodNodeElement buildConstructor(final DartMethodDefinition method) {
      // Resolve the constructor's name and class name.
      Element e = resolveConstructorName(method);

      switch (ElementKind.of(e)) {
        default:
          // Report an error and create a fake constructor element below.
          resolutionError(method.getName(), ResolverErrorCode.INVALID_TYPE_NAME_IN_CONSTRUCTOR);
          break;

        case DYNAMIC:
        case CLASS:
          break;

        case CONSTRUCTOR:
          return (ConstructorNodeElement) e;
      }

      // If the constructor name resolves to a class or there was an error,
      // create the unnamed constructor.
      return Elements.constructorFromMethodNode(method, "", (ClassElement) currentHolder,
                                                (ClassElement) e);
    }

    private FieldElement buildField(DartField fieldNode, Type type) {
      assert !fieldNode.getModifiers().isAbstractField();
      Modifiers modifiers = fieldNode.getModifiers();
      // top-level fields are implicitly static.
      if (context == topLevelContext) {
        modifiers = modifiers.makeStatic();
      }
      if (fieldNode.getValue() != null) {
        modifiers = modifiers.makeInitialized();
      }
      FieldNodeElement fieldElement = fieldNode.getElement();
      if (fieldElement == null) {
        fieldElement = Elements.fieldFromNode(fieldNode, currentHolder, fieldNode.getObsoleteMetadata(),
            modifiers);
        addField(currentHolder, fieldElement);
      } else {
        // This is a top-level element, and an element was already created in
        // TopLevelElementBuilder.
        Elements.addField(currentHolder, fieldElement);
        assertTopLevel(fieldNode);
      }
      fieldElement.setType(type);
      recordElement(fieldNode.getName(), fieldElement);
      return recordElement(fieldNode, fieldElement);
    }

    private void assertTopLevel(DartNode node) throws AssertionError {
      if (!currentHolder.getKind().equals(ElementKind.LIBRARY)) {
        throw topLevelContext.internalError(node, "expected top-level node");
      }
    }

    /**
     * Creates FieldElement for AST getters and setters.
     *
     * class A {
     *   int get foo() { ... }
     *   set foo(x) { ... }
     * }
     *
     * The AST will have the shape (simplified):
     * DartClass
     *   members
     *     DartFieldDefinition
     *       DartField
     *       + name: foo
     *       + modifiers: abstractfield
     *       + accessor: int get foo() { ... }
     *     DartFieldDefinition
     *       DartField
     *       + name: foo
     *       + modifiers: abstractfield
     *       + accessor: set foo(x) { ... }
     *
     * MemberBuilder will reduce to one class element as below (simplified):
     * ClassElement
     *   members:
     *     FieldElement
     *     + name: foo
     *     + getter:
     *       MethodElement
     *       + name: foo
     *       + function: int get foo() { ... }
     *     + setter:
     *       MethodElement
     *       + name: foo
     *       + function: set foo(x) { ... }
     *
     */
    private FieldElement buildAbstractField(DartField fieldNode) {
      assert fieldNode.getModifiers().isAbstractField();
      boolean topLevelDefinition = fieldNode.getParent().getParent() instanceof DartUnit;
      DartMethodDefinition accessorNode = fieldNode.getAccessor();
      MethodNodeElement accessorElement = Elements.methodFromMethodNode(accessorNode, currentHolder);
      EnclosingElement previousEnclosingElement = enclosingElement;
      enclosingElement = accessorElement;
      recordElement(accessorNode, accessorElement);
      resolveFunction(accessorNode.getFunction(), accessorElement);
      enclosingElement = previousEnclosingElement;

      String name = fieldNode.getName().getName();
      Element element = null;
      if (currentHolder != null) {
          element = currentHolder.lookupLocalElement(name);
          if (element == null) {
            element = currentHolder.lookupLocalElement("setter " + name);
          }
      } else {
        // Top level nodes are not handled gracefully
        Scope scope = topLevelContext.getScope();
        LibraryElement library = context.getScope().getLibrary();
        element = scope.findElement(library, name);
        if (element == null) {
          element = scope.findElement(library, "setter " + name);
        }
      }

      FieldElementImplementation fieldElement = null;
      if (element == null || element.getKind().equals(ElementKind.FIELD)
          && element.getModifiers().isAbstractField()) {
        fieldElement = (FieldElementImplementation) element;
      }

      if (accessorNode.getModifiers().isGetter() && fieldElement != null && fieldElement.getSetter() != null) {
        MethodNodeElement oldSetter = fieldElement.getSetter();
        fieldElement = Elements.fieldFromNode(fieldNode, currentHolder, fieldNode.getObsoleteMetadata(),
            fieldNode.getModifiers());
        fieldElement.setSetter(oldSetter);
        addField(currentHolder, fieldElement);
      }

      if (fieldElement == null) {
        fieldElement = Elements.fieldFromNode(fieldNode, currentHolder, fieldNode.getObsoleteMetadata(),
            fieldNode.getModifiers());
        addField(currentHolder, fieldElement);
      }

      if (accessorNode.getModifiers().isGetter()) {
        if (fieldElement.getGetter() != null) {
          if (!topLevelDefinition) {
            reportDuplicateDeclaration(ResolverErrorCode.DUPLICATE_MEMBER, fieldElement.getGetter());
            reportDuplicateDeclaration(ResolverErrorCode.DUPLICATE_MEMBER, accessorElement);
          }
        } else {
          fieldElement.setGetter(accessorElement);
          fieldElement.setType(accessorElement.getReturnType());
        }
      } else if (accessorNode.getModifiers().isSetter()) {
        if (fieldElement.getSetter() != null) {
          if (!topLevelDefinition) {
            reportDuplicateDeclaration(ResolverErrorCode.DUPLICATE_MEMBER, fieldElement.getSetter());
            reportDuplicateDeclaration(ResolverErrorCode.DUPLICATE_MEMBER, accessorElement);
          }
        } else {
          fieldElement.setSetter(accessorElement);
          List<VariableElement> parameters = accessorElement.getParameters();
          Type type;
          if (parameters.size() == 0) {
            // Error flagged in parser
            type = getTypeProvider().getDynamicType();
          } else {
            type = parameters.get(0).getType();
          }
          fieldElement.setType(type);
        }
      }
      recordElement(fieldNode.getName(), accessorElement);
      return recordElement(fieldNode, fieldElement);
    }

    private void addField(EnclosingElement holder, FieldNodeElement element) {
      if (holder != null) {
        checkUniqueName(holder, element);
        checkMemberNameNotSameAsEnclosingClassName(holder, element);
        Elements.addField(holder, element);
      }
    }

    private void addMethod(EnclosingElement holder, MethodNodeElement element) {
      checkUniqueName(holder, element);
      checkMemberNameNotSameAsEnclosingClassName(holder, element);
      Elements.addMethod(holder, element);
    }

    private void addConstructor(ClassElement cls, ConstructorNodeElement element) {
      checkUniqueName(cls, element);
      Elements.addConstructor(cls, element);
    }

    private ElementKind getMethodKind(DartMethodDefinition method) {
      if (!ElementKind.of(currentHolder).equals(ElementKind.CLASS)) {
        return ElementKind.METHOD;
      }

      if (method.getModifiers().isFactory()) {
        return ElementKind.CONSTRUCTOR;
      }

      DartExpression name = method.getName();
      if (name instanceof DartIdentifier) {
        if (((DartIdentifier) name).getName().equals(currentHolder.getName())) {
          return ElementKind.CONSTRUCTOR;
        } else {
          return ElementKind.METHOD;
        }
      } else {
        DartPropertyAccess property = (DartPropertyAccess) name;
        if (property.getQualifier() instanceof DartIdentifier) {
          DartIdentifier qualifier = (DartIdentifier) property.getQualifier();
          if (qualifier.getName().equals(currentHolder.getName())) {
            return ElementKind.CONSTRUCTOR;
          }
          resolutionError(method.getName(),
                          ResolverErrorCode.CANNOT_DECLARE_NON_FACTORY_CONSTRUCTOR);
        } else if (property.getQualifier() instanceof DartParameterizedTypeNode) {
          DartParameterizedTypeNode paramNode = (DartParameterizedTypeNode)property.getQualifier();
          if (paramNode.getExpression() instanceof DartIdentifier) {
            return ElementKind.CONSTRUCTOR;
          }
          resolutionError(method.getName(),
                          ResolverErrorCode.TOO_MANY_QUALIFIERS_FOR_METHOD);
        } else {
          // Multiple qualifiers (Foo.bar.baz)
          resolutionError(method.getName(),
                          ResolverErrorCode.TOO_MANY_QUALIFIERS_FOR_METHOD);
        }
      }

      return ElementKind.NONE;
    }

    /**
     * Checks that top-level "main()" has no parameters.
     */
    private void checkTopLevelMainFunction(DartMethodDefinition method) {
      if (!method.getFunction().getParameters().isEmpty()
          && currentHolder instanceof LibraryElement
          && Objects.equal(method.getName().toString(), "main")) {
        resolutionError(method.getName(), ResolverErrorCode.MAIN_FUNCTION_PARAMETERS);
      }
    }

    private void checkModifiers(MethodElement element, DartMethodDefinition method) {
      Modifiers modifiers = method.getModifiers();
      boolean isNonFactoryConstructor = Elements.isNonFactoryConstructor(element);
      // TODO(ngeoffray): The errors should report the position of the modifier.
      if (isNonFactoryConstructor) {
        if (modifiers.isStatic()) {
          resolutionError(method.getName(), ResolverErrorCode.CONSTRUCTOR_CANNOT_BE_STATIC);
        }
        if (modifiers.isAbstract()) {
          resolutionError(method.getName(), ResolverErrorCode.CONSTRUCTOR_CANNOT_BE_ABSTRACT);
        }
        if (modifiers.isConstant()) {
          // Allow const ... native ... ; type of constructors.  Used in core libraries.
          DartBlock dartBlock = method.getFunction().getBody();
          if (dartBlock != null && !(dartBlock instanceof DartNativeBlock)) {
            resolutionError(method.getName(),
                            ResolverErrorCode.CONST_CONSTRUCTOR_CANNOT_HAVE_BODY);
          }
        }
      }

      if (modifiers.isFactory()) {
        if (modifiers.isConstant()) {
          // Allow const factory ... native ... ; type of constructors, used in core libraries.
          // Allow const factory redirecting.
          DartBlock dartBlock = method.getFunction().getBody();
          if (!(dartBlock instanceof DartNativeBlock || method.getRedirectedTypeName() != null)) {
            resolutionError(method.getName(), ResolverErrorCode.FACTORY_CANNOT_BE_CONST);
          }
        }
      }
      // TODO(ngeoffray): Add more checks on the modifiers. For
      // example const and missing body.
    }

    private void checkConstructor(MethodElement element, DartMethodDefinition method) {
      if (Elements.isNonFactoryConstructor(element) && method.getFunction() != null
          && method.getFunction().getReturnTypeNode() != null) {
        resolutionError(method.getFunction().getReturnTypeNode(),
            ResolverErrorCode.CONSTRUCTOR_CANNOT_HAVE_RETURN_TYPE);
      }
    }

    private void checkMemberNameNotSameAsEnclosingClassName(EnclosingElement holder, Element e) {
      if (ElementKind.of(holder) == ElementKind.CLASS) {
        if (Objects.equal(holder.getName(), e.getName())) {
          resolutionError(e.getNameLocation(), ResolverErrorCode.MEMBER_WITH_NAME_OF_CLASS);
        }
      }
    }
      
    private void checkUniqueName(EnclosingElement holder, Element e) {
      if (ElementKind.of(holder) == ElementKind.LIBRARY) {
        return;
      }
      Element other = lookupElementByName(holder, e.getName(), e.getModifiers());
      assert e != other : "forgot to call checkUniqueName() before adding to the class?";
      
      if (other == null && e instanceof FieldElement) {
        FieldElement eField = (FieldElement) e;
        if (!eField.getModifiers().isAbstractField()) {
          other = lookupElementByName(holder, "setter " + e.getName(), e.getModifiers());
        }
        if (eField.getModifiers().isAbstractField()
            && StringUtils.startsWith(e.getName(), "setter ")) {
          Element other2 = lookupElementByName(holder,
              StringUtils.removeStart(e.getName(), "setter "), e.getModifiers());
          if (other2 instanceof FieldElement) {
            FieldElement otherField = (FieldElement) other2;
            if (!otherField.getModifiers().isAbstractField()) {
              other = otherField;
            }
          }
        }
      }
      
      if (other != null) {
        ElementKind eKind = ElementKind.of(e);
        ElementKind oKind = ElementKind.of(other);

        // Constructors have a separate namespace.
        boolean oIsConstructor = oKind.equals(ElementKind.CONSTRUCTOR);
        boolean eIsConstructor = eKind.equals(ElementKind.CONSTRUCTOR);
        if (oIsConstructor != eIsConstructor) {
          return;
        }

        // Both can be constructors, as long as they're for different classes.
        if (oIsConstructor && eIsConstructor) {
          if (((ConstructorElement) e).getConstructorType() !=
              ((ConstructorElement) other).getConstructorType()) {
            return;
          }
        }

        boolean eIsOperator = e.getModifiers().isOperator();
        boolean oIsOperator = other.getModifiers().isOperator();
        if (oIsOperator != eIsOperator) {
          return;
        }

        // Operators and methods can share the same name.
        boolean oIsMethod = oKind.equals(ElementKind.METHOD);
        boolean eIsMethod = eKind.equals(ElementKind.METHOD);
        if ((oIsOperator && eIsMethod) || (oIsMethod && eIsOperator)) {
          return;
        }

        // Report initial declaration and current declaration.
        reportDuplicateDeclaration(ResolverErrorCode.DUPLICATE_MEMBER, other);
        reportDuplicateDeclaration(ResolverErrorCode.DUPLICATE_MEMBER, e);
      }
    }

    private Element lookupElementByName(EnclosingElement holder, String name, Modifiers modifiers) {
      Element element = holder.lookupLocalElement(name);
      if (element == null && ElementKind.of(holder).equals(ElementKind.CLASS)) {
        ClassElement cls = (ClassElement) holder;
        String ctorName = name.equals(holder.getName()) ? "" : name;
        for (Element e : cls.getConstructors()) {
          if (e.getName().equals(ctorName)) {
            return e;
          }
        }
      }
      return element;
    }

    void resolutionError(HasSourceInfo node, ErrorCode errorCode, Object... arguments) {
      resolutionError(node.getSourceInfo(), errorCode, arguments);
    }

    void resolutionError(SourceInfo sourceInfo, ErrorCode errorCode, Object... arguments) {
      topLevelContext.onError(sourceInfo, errorCode, arguments);
    }

    /**
     * Reports duplicate declaration for given named element.
     */
    private void reportDuplicateDeclaration(ErrorCode errorCode, Element element) {
      String name =
          element instanceof MethodElement
              ? Elements.getRawMethodName((MethodElement) element)
              : element.getName();
      resolutionError(element.getNameLocation(), errorCode, name);
    }
  }
}
