// 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.

library resolution.compute_members;

import '../elements/elements.dart'
    show Element,
         Name,
         PublicName,
         Member,
         MemberSignature,
         LibraryElement,
         ClassElement,
         MixinApplicationElement;
import '../elements/modelx.dart'
    show BaseClassElementX;
import '../dart_types.dart';
import '../dart2jslib.dart'
    show Compiler,
         MessageKind,
         invariant;
import '../util/util.dart';

part 'member_impl.dart';

class MembersCreator {
  final ClassElement cls;
  final Compiler compiler;

  Map<Name, Member> classMembers = new Map<Name, Member>();
  Map<Name, MemberSignature> interfaceMembers =
      new Map<Name, MemberSignature>();

  Map<dynamic/* Member | Element */, Set<MessageKind>> reportedMessages =
      new Map<dynamic, Set<MessageKind>>();

  MembersCreator(Compiler this.compiler, ClassElement this.cls);

  void reportMessage(var marker, MessageKind kind, report()) {
    Set<MessageKind> messages =
        reportedMessages.putIfAbsent(marker,
            () => new Set<MessageKind>());
    if (messages.add(kind)) {
      report();
    }
  }

  void computeMembers() {
    Map<Name, Set<Member>> inheritedInterfaceMembers =
        _computeSuperMembers();
    Map<Name, Member> declaredMembers = _computeClassMembers();
    _computeInterfaceMembers(inheritedInterfaceMembers, declaredMembers);

    if (!cls.modifiers.isAbstract() &&
        !declaredMembers.containsKey(const PublicName('noSuchMethod'))) {
      // Check for unimplemented members on concrete classes that neither have
      // a `@proxy` annotation nor declare a `noSuchMethod` method.
      checkInterfaceImplementation();
    }
  }

  Map<Name, Set<Member>> _computeSuperMembers() {
    Map<Name, Set<Member>> inheritedInterfaceMembers =
        new Map<Name, Set<Member>>();

    void inheritInterfaceMembers(InterfaceType supertype) {
      supertype.element.forEachInterfaceMember((MemberSignature member) {
        Set<Member> members =
            inheritedInterfaceMembers.putIfAbsent(
                member.name, () => new Set<Member>());
        for (DeclaredMember declaredMember in member.declarations) {
          members.add(declaredMember.inheritFrom(supertype));
        }
      });
    }

    // Inherit class and interface members from superclass.
    InterfaceType superclass = cls.supertype;
    if (superclass != null) {
      computeClassMembers(compiler, superclass.element);
      superclass.element.forEachClassMember((DeclaredMember member) {
        if (!member.isStatic) {
          DeclaredMember inherited = member.inheritFrom(superclass);
          classMembers[member.name] = inherited;
        }
      });
      inheritInterfaceMembers(superclass);
    }

    // Inherit interface members from superinterfaces.
    for (Link<DartType> link = cls.interfaces;
         !link.isEmpty;
         link = link.tail) {
      InterfaceType superinterface = link.head;
      computeClassMembers(compiler, superinterface.element);
      inheritInterfaceMembers(superinterface);
    }

    return inheritedInterfaceMembers;
  }

  Map<Name, Member> _computeClassMembers() {
    Map<Name, Member> declaredMembers = new Map<Name, Member>();

    void overrideMember(DeclaredMember declared) {
      DeclaredMember inherited = classMembers[declared.name];
      classMembers[declared.name] = declared;
      checkValidOverride(declared, inherited);
    }

    if (cls.isMixinApplication) {
      MixinApplicationElement mixinApplication = cls;
      if (mixinApplication.mixin != null) {
        // Only mix in class members when the mixin type is not malformed.
        computeClassMembers(compiler, mixinApplication.mixin);

        mixinApplication.mixin.forEachClassMember((DeclaredMember member) {
          if (!member.isStatic) {
            // Abstract and static members are not mixed in.
            DeclaredMember mixedInMember =
                member.inheritFrom(mixinApplication.mixinType);
            overrideMember(mixedInMember);
          }
        });
      }
    } else {
      LibraryElement library = cls.getLibrary();
      InterfaceType thisType = cls.thisType;

      cls.forEachLocalMember((Element element) {
        if (element.isConstructor()) return;

        Name name = new Name(element.name, library);
        if (element.isField()) {
          DartType type = element.computeType(compiler);
          declaredMembers[name] = new DeclaredMember(
              name, element, thisType, type,
              new FunctionType(compiler.functionClass, type));
          if (!element.modifiers.isConst() &&
              !element.modifiers.isFinal()) {
            name = name.setter;
            declaredMembers[name] = new DeclaredMember(
                name, element, thisType, type,
                new FunctionType(compiler.functionClass,
                                 compiler.types.voidType,
                                 const Link<DartType>().prepend(type)));
          }
        } else if (element.isGetter()) {
          FunctionType functionType = element.computeType(compiler);
          DartType type = functionType.returnType;
          declaredMembers[name] =
              new DeclaredMember(name, element, thisType, type, functionType);
        } else if (element.isSetter()) {
          FunctionType functionType = element.computeType(compiler);
          DartType type;
          if (!functionType.parameterTypes.isEmpty) {
            type = functionType.parameterTypes.head;
          } else {
            type = compiler.types.dynamicType;
          }
          name = name.setter;
          declaredMembers[name] = new DeclaredMember(
              name, element, thisType, type, functionType);
        } else {
          assert(invariant(element, element.isFunction()));
          FunctionType type = element.computeType(compiler);
          declaredMembers[name] = new DeclaredMember(
              name, element, thisType, type, type);
        }
      });
    }

    declaredMembers.values.forEach((Member member) {
      if (!member.element.isAbstract) {
        overrideMember(member);
      }
    });

    return declaredMembers;
  }

  void _computeInterfaceMembers(
        Map<Name, Set<Member>> inheritedInterfaceMembers,
        Map<Name, Member> declaredMembers) {
    InterfaceType thisType = cls.thisType;
    // Compute the interface members by overriding the inherited members with
    // a declared member or by computing a single, possibly synthesized,
    // inherited member.
    inheritedInterfaceMembers.forEach(
        (Name name, Set<Member> inheritedMembers) {
      Member declared = declaredMembers[name];
      if (declared != null) {
        // Check that [declaredMember] is a valid override
        for (Member inherited in inheritedMembers) {
          checkValidOverride(declared, inherited);
        }
        if (!declared.isStatic) {
          interfaceMembers[name] = declared;
        }
      } else {
        bool someAreGetters = false;
        bool allAreGetters = true;
        Map<DartType, Set<Member>> subtypesOfAllInherited =
            new Map<DartType, Set<Member>>();
        outer: for (Member inherited in inheritedMembers) {
          if (inherited.isGetter) {
            someAreGetters = true;
            if (!allAreGetters) break outer;
          } else {
            allAreGetters = false;
            if (someAreGetters) break outer;
          }
          for (MemberSignature other in inheritedMembers) {
            if (!compiler.types.isSubtype(inherited.functionType,
                                          other.functionType)) {
              continue outer;
            }
          }
          subtypesOfAllInherited.putIfAbsent(inherited.functionType,
              () => new Set<Member>()).add(inherited);
        }
        if (someAreGetters && !allAreGetters) {
          compiler.reportWarningCode(cls,
                                     MessageKind.INHERIT_GETTER_AND_METHOD,
                                     {'class': thisType, 'name': name.text });
          for (Member inherited in inheritedMembers) {
            MessageKind kind;
            if (inherited.isMethod) {
              kind = MessageKind.INHERITED_METHOD;
            } else {
              assert(invariant(cls, inherited.isGetter,
                  message: 'Conflicting member is neither a method nor a '
                           'getter.'));
              if (inherited.isDeclaredByField) {
                kind = MessageKind.INHERITED_IMPLICIT_GETTER;
              } else {
                kind = MessageKind.INHERITED_EXPLICIT_GETTER;
              }
            }
            compiler.reportInfo(inherited.element, kind,
                {'class': inherited.declarer, 'name': name.text });
          }
          interfaceMembers[name] = new ErroneousMember(inheritedMembers);
        } else if (subtypesOfAllInherited.length == 1) {
          // All signatures have the same type.
          Set<Member> members = subtypesOfAllInherited.values.first;
          MemberSignature inherited = members.first;
          if (members.length != 1) {
            // Multiple signatures with the same type => return a
            // synthesized signature.
            inherited = new SyntheticMember(
                members, inherited.type, inherited.functionType);
          }
          interfaceMembers[name] = inherited;
        } else {
          _inheritedSynthesizedMember(name, inheritedMembers);
        }
      }
    });

    // Add the non-overriding instance methods to the interface members.
    declaredMembers.forEach((Name name, Member member) {
      if (!member.isStatic) {
        interfaceMembers.putIfAbsent(name, () => member);
      }
    });
  }

  /// Create and inherit a synthesized member for [inheritedMembers].
  void _inheritedSynthesizedMember(Name name,
                                   Set<Member> inheritedMembers) {
    // Multiple signatures with different types => create the synthesized
    // version.
    int minRequiredParameters;
    int maxPositionalParameters;
    Set<String> names = new Set<String>();
    for (MemberSignature member in inheritedMembers) {
      int requiredParameters = 0;
      int optionalParameters = 0;
      if (member.isSetter) {
        requiredParameters = 1;
      }
      if (member.type.kind == TypeKind.FUNCTION) {
        FunctionType type = member.type;
        type.namedParameters.forEach(
            (String name) => names.add(name));
        requiredParameters = type.parameterTypes.slowLength();
        optionalParameters = type.optionalParameterTypes.slowLength();
      }
      int positionalParameters = requiredParameters + optionalParameters;
      if (minRequiredParameters == null ||
          minRequiredParameters > requiredParameters) {
        minRequiredParameters = requiredParameters;
      }
      if (maxPositionalParameters == null ||
          maxPositionalParameters < positionalParameters) {
        maxPositionalParameters = positionalParameters;
      }
    }
    int optionalParameters =
        maxPositionalParameters - minRequiredParameters;
    // TODO(johnniwinther): Support function types with both optional
    // and named parameters?
    if (optionalParameters == 0 || names.isEmpty) {
      Link<DartType> requiredParameterTypes = const Link<DartType>();
      while (--minRequiredParameters >= 0) {
        requiredParameterTypes =
            requiredParameterTypes.prepend(compiler.types.dynamicType);
      }
      Link<DartType> optionalParameterTypes = const Link<DartType>();
      while (--optionalParameters >= 0) {
        optionalParameterTypes =
            optionalParameterTypes.prepend(compiler.types.dynamicType);
      }
      Link<String> namedParameters = const Link<String>();
      Link<DartType> namedParameterTypes = const Link<DartType>();
      List<String> namesReversed =
          names.toList()..sort((a, b) => -a.compareTo(b));
      for (String name in namesReversed) {
        namedParameters = namedParameters.prepend(name);
        namedParameterTypes =
            namedParameterTypes.prepend(compiler.types.dynamicType);
      }
      FunctionType memberType = new FunctionType(
          compiler.functionClass,
          compiler.types.dynamicType,
          requiredParameterTypes,
          optionalParameterTypes,
          namedParameters, namedParameterTypes);
      DartType type = memberType;
      if (inheritedMembers.first.isGetter ||
          inheritedMembers.first.isSetter) {
        type = compiler.types.dynamicType;
      }
      interfaceMembers[name] = new SyntheticMember(
          inheritedMembers, type, memberType);
    }
  }

  /// Checks that a class member exists for every interface member.
  void checkInterfaceImplementation() {
    LibraryElement library = cls.getLibrary();

    interfaceMembers.forEach((Name name, MemberSignature interfaceMember) {
      if (!name.isAccessibleFrom(library)) return;
      Member classMember = classMembers[name];
      if (classMember != null) return;
      if (interfaceMember is DeclaredMember &&
          interfaceMember.declarer.element == cls) {
        // Abstract method declared in [cls].
        MessageKind kind = MessageKind.ABSTRACT_METHOD;
        if (interfaceMember.isSetter) {
          kind = MessageKind.ABSTRACT_SETTER;
        } else if (interfaceMember.isGetter) {
          kind = MessageKind.ABSTRACT_GETTER;
        }
        reportMessage(
            interfaceMember.element, MessageKind.ABSTRACT_METHOD, () {
          compiler.reportWarningCode(
              interfaceMember.element, kind,
              {'class': cls.name, 'name': name.text});
        });
      } else {
         reportWarning(MessageKind singleKind,
                       MessageKind multipleKind,
                       MessageKind explicitlyDeclaredKind,
                       [MessageKind implicitlyDeclaredKind]) {
          Member inherited = interfaceMember.declarations.first;
          reportMessage(
              interfaceMember, MessageKind.UNIMPLEMENTED_METHOD, () {
            compiler.reportWarningCode(cls,
                interfaceMember.declarations.length == 1
                    ? singleKind : multipleKind,
                {'class': cls.name,
                 'name': name.text,
                 'method': interfaceMember,
                 'declarer': inherited.declarer});
            for (Member inherited in interfaceMember.declarations) {
              compiler.reportInfo(inherited.element,
                  inherited.isDeclaredByField ?
                      implicitlyDeclaredKind : explicitlyDeclaredKind,
                  {'class': inherited.declarer.name,
                   'name': name.text});
            }
          });
        }
        if (interfaceMember.isSetter) {
          reportWarning(MessageKind.UNIMPLEMENTED_SETTER_ONE,
                        MessageKind.UNIMPLEMENTED_SETTER,
                        MessageKind.UNIMPLEMENTED_EXPLICIT_SETTER,
                        MessageKind.UNIMPLEMENTED_IMPLICIT_SETTER);
        } else if (interfaceMember.isGetter) {
          reportWarning(MessageKind.UNIMPLEMENTED_GETTER_ONE,
                        MessageKind.UNIMPLEMENTED_GETTER,
                        MessageKind.UNIMPLEMENTED_EXPLICIT_GETTER,
                        MessageKind.UNIMPLEMENTED_IMPLICIT_GETTER);
        } else if (interfaceMember.isMethod) {
          reportWarning(MessageKind.UNIMPLEMENTED_METHOD_ONE,
                        MessageKind.UNIMPLEMENTED_METHOD,
                        MessageKind.UNIMPLEMENTED_METHOD_CONT);
        }
      }
      // TODO(johnniwinther): If [cls] is not abstract, check that for all
      // interface members, there is a class member whose type is a subtype of
      // the interface member.
    });
  }

  void checkValidOverride(Member declared, MemberSignature superMember) {
    if (superMember == null) {
      // No override.
      if (!declared.isStatic) {
        ClassElement superclass = cls.superclass;
        while (superclass != null) {
          Member superMember =
              superclass.lookupClassMember(declared.name);
          if (superMember != null && superMember.isStatic) {
            reportMessage(superMember, MessageKind.INSTANCE_STATIC_SAME_NAME,
                () {
              compiler.reportWarningCode(
                  declared.element,
                  MessageKind.INSTANCE_STATIC_SAME_NAME,
                  {'memberName': declared.name,
                    'className': superclass.name});
              compiler.reportInfo(superMember.element,
                  MessageKind.INSTANCE_STATIC_SAME_NAME_CONT);
            });
            break;
          }
          superclass = superclass.superclass;
        }
      }
    } else {
      assert(declared.name == superMember.name);
      if (declared.isStatic) {
        for (Member inherited in superMember.declarations) {
          reportMessage(
              inherited.element, MessageKind.NO_STATIC_OVERRIDE, () {
            reportErrorWithContext(
                declared.element, MessageKind.NO_STATIC_OVERRIDE,
                inherited.element, MessageKind.NO_STATIC_OVERRIDE_CONT);
          });
        }
      }

      DartType declaredType = declared.functionType;
      for (Member inherited in superMember.declarations) {

        void reportError(MessageKind errorKind, MessageKind infoKind) {
          reportMessage(
              inherited.element, MessageKind.INVALID_OVERRIDE_METHOD, () {
            compiler.reportError(declared.element, errorKind,
                {'name': declared.name.text,
                 'class': cls.thisType,
                 'inheritedClass': inherited.declarer});
            compiler.reportInfo(inherited.element, infoKind,
                {'name': declared.name.text,
                 'class': inherited.declarer});
          });
        }

        if (declared.isDeclaredByField && inherited.isMethod) {
          reportError(MessageKind.CANNOT_OVERRIDE_METHOD_WITH_FIELD,
              MessageKind.CANNOT_OVERRIDE_METHOD_WITH_FIELD_CONT);
        } else if (declared.isMethod && inherited.isDeclaredByField) {
          reportError(MessageKind.CANNOT_OVERRIDE_FIELD_WITH_METHOD,
              MessageKind.CANNOT_OVERRIDE_FIELD_WITH_METHOD_CONT);
        } else if (declared.isGetter && inherited.isMethod) {
          reportError(MessageKind.CANNOT_OVERRIDE_METHOD_WITH_GETTER,
                      MessageKind.CANNOT_OVERRIDE_METHOD_WITH_GETTER_CONT);
        } else if (declared.isMethod && inherited.isGetter) {
          reportError(MessageKind.CANNOT_OVERRIDE_GETTER_WITH_METHOD,
                      MessageKind.CANNOT_OVERRIDE_GETTER_WITH_METHOD_CONT);
        } else {
          DartType inheritedType = inherited.functionType;
          if (!compiler.types.isSubtype(declaredType, inheritedType)) {
            void reportWarning(var marker,
                               MessageKind warningKind,
                               MessageKind infoKind) {
              reportMessage(marker, MessageKind.INVALID_OVERRIDE_METHOD, () {
                compiler.reportWarningCode(declared.element, warningKind,
                    {'declaredType': declared.type,
                     'name': declared.name.text,
                     'class': cls.thisType,
                     'inheritedType': inherited.type,
                     'inheritedClass': inherited.declarer});
                compiler.reportInfo(inherited.element, infoKind,
                    {'name': declared.name.text,
                     'class': inherited.declarer});
              });
            }
            if (declared.isDeclaredByField) {
              if (inherited.isDeclaredByField) {
                reportWarning(inherited.element,
                              MessageKind.INVALID_OVERRIDE_FIELD,
                              MessageKind.INVALID_OVERRIDDEN_FIELD);
              } else if (inherited.isGetter) {
                reportWarning(inherited,
                              MessageKind.INVALID_OVERRIDE_GETTER_WITH_FIELD,
                              MessageKind.INVALID_OVERRIDDEN_GETTER);
              } else if (inherited.isSetter) {
                reportWarning(inherited,
                              MessageKind.INVALID_OVERRIDE_SETTER_WITH_FIELD,
                              MessageKind.INVALID_OVERRIDDEN_SETTER);
              }
            } else if (declared.isGetter) {
              if (inherited.isDeclaredByField) {
                reportWarning(inherited,
                              MessageKind.INVALID_OVERRIDE_FIELD_WITH_GETTER,
                              MessageKind.INVALID_OVERRIDDEN_FIELD);
              } else {
                reportWarning(inherited,
                              MessageKind.INVALID_OVERRIDE_GETTER,
                              MessageKind.INVALID_OVERRIDDEN_GETTER);
              }
            } else if (declared.isSetter) {
              if (inherited.isDeclaredByField) {
                reportWarning(inherited,
                              MessageKind.INVALID_OVERRIDE_FIELD_WITH_SETTER,
                              MessageKind.INVALID_OVERRIDDEN_FIELD);
              } else {
                reportWarning(inherited,
                              MessageKind.INVALID_OVERRIDE_SETTER,
                              MessageKind.INVALID_OVERRIDDEN_SETTER);
              }
            } else {
              reportWarning(inherited,
                            MessageKind.INVALID_OVERRIDE_METHOD,
                            MessageKind.INVALID_OVERRIDDEN_METHOD);
            }
          }
        }
      }
    }
  }

  void reportErrorWithContext(Element errorneousElement,
                         MessageKind errorMessage,
                         Element contextElement,
                         MessageKind contextMessage) {
    compiler.reportError(
        errorneousElement,
        errorMessage,
        {'memberName': contextElement.name,
         'className': contextElement.getEnclosingClass().name});
    compiler.reportInfo(contextElement, contextMessage);
  }

  static void computeClassMembers(Compiler compiler, BaseClassElementX cls) {
    if (cls.classMembers != null) return;
    MembersCreator creator = new MembersCreator(compiler, cls);
    creator.computeMembers();
    cls.classMembers = creator.classMembers;
    cls.interfaceMembers = creator.interfaceMembers;
  }
}
