// Copyright (c) 2015, 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 related_types;

import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/compiler.dart';
import 'package:compiler/src/common_elements.dart';
import 'package:compiler/src/elements/resolution_types.dart';
import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
import 'package:compiler/src/diagnostics/messages.dart';
import 'package:compiler/src/elements/elements.dart';
import 'package:compiler/src/elements/names.dart';
import 'package:compiler/src/filenames.dart';
import 'package:compiler/src/resolution/semantic_visitor.dart';
import 'package:compiler/src/tree/tree.dart';
import 'package:compiler/src/universe/call_structure.dart';
import 'package:compiler/src/universe/selector.dart';
import 'package:compiler/src/world.dart';
import 'memory_compiler.dart';

main(List<String> arguments) async {
  if (arguments.isNotEmpty) {
    Uri entryPoint = Uri.base.resolve(nativeToUriPath(arguments.last));
    CompilationResult result = await runCompiler(
        entryPoint: entryPoint,
        options: [Flags.analyzeOnly, '--categories=Client,Server']);
    if (result.isSuccess) {
      checkRelatedTypes(result.compiler);
    }
  } else {
    print('Usage dart related_types.dart <entry-point>');
  }
}

/// Check all loaded libraries in [compiler] for unrelated types.
void checkRelatedTypes(Compiler compiler) {
  compiler.closeResolution(
      compiler.frontendStrategy.elementEnvironment.mainFunction);
  for (LibraryElement library in compiler.libraryLoader.libraries) {
    checkLibraryElement(compiler, library);
  }
}

/// Check [library] for unrelated types.
void checkLibraryElement(Compiler compiler, LibraryElement library) {
  library.forEachLocalMember((Element element) {
    if (element.isClass) {
      ClassElement cls = element;
      cls.forEachLocalMember((_member) {
        MemberElement member = _member;
        checkMemberElement(compiler, member);
      });
    } else if (!element.isTypedef) {
      checkMemberElement(compiler, element);
    }
  });
}

/// Check [member] for unrelated types.
void checkMemberElement(Compiler compiler, MemberElement member) {
  if (!compiler.resolution.hasBeenResolved(member)) return;

  ResolvedAst resolvedAst = member.resolvedAst;
  if (resolvedAst.kind == ResolvedAstKind.PARSED) {
    RelatedTypesChecker relatedTypesChecker =
        new RelatedTypesChecker(compiler, resolvedAst);
    compiler.reporter.withCurrentElement(member.implementation, () {
      relatedTypesChecker.apply(resolvedAst.node);
    });
  }
}

class RelatedTypesChecker
    extends TraversalVisitor<ResolutionDartType, dynamic> {
  final Compiler compiler;
  final ResolvedAst resolvedAst;

  RelatedTypesChecker(this.compiler, ResolvedAst resolvedAst)
      : this.resolvedAst = resolvedAst,
        super(resolvedAst.elements);

  ClosedWorld get world =>
      compiler.resolutionWorldBuilder.closedWorldForTesting;

  CommonElements get commonElements => compiler.resolution.commonElements;

  DiagnosticReporter get reporter => compiler.reporter;

  ResolutionInterfaceType get thisType =>
      resolvedAst.element.enclosingClass.thisType;

  /// Returns `true` if there exists no common subtype of [left] and [right].
  bool hasEmptyIntersection(ResolutionDartType left, ResolutionDartType right) {
    if (left == right) return false;
    if (left == null || right == null) return false;
    ClassElement leftClass = const ClassFinder().findClass(left);
    ClassElement rightClass = const ClassFinder().findClass(right);
    if (leftClass != null && rightClass != null) {
      return !world.haveAnyCommonSubtypes(leftClass, rightClass);
    }
    return false;
  }

  /// Checks that there exists a common subtype of [left] and [right] or report
  /// a hint otherwise.
  void checkRelated(
      Node node, ResolutionDartType left, ResolutionDartType right) {
    if (hasEmptyIntersection(left, right)) {
      reporter.reportHintMessage(
          node, MessageKind.NO_COMMON_SUBTYPES, {'left': left, 'right': right});
    }
  }

  /// Check weakly typed collection methods, like `Map.containsKey`,
  /// `Map.containsValue` and `Iterable.contains`.
  void checkDynamicInvoke(Node node, ResolutionDartType receiverType,
      List<ResolutionDartType> argumentTypes, Selector selector) {
    if (selector.name == 'containsKey' &&
        selector.callStructure == CallStructure.ONE_ARG) {
      ResolutionInterfaceType mapType = findMapType(receiverType);
      if (mapType != null) {
        ResolutionDartType keyType = findMapKeyType(mapType);
        checkRelated(node, keyType, argumentTypes.first);
      }
    } else if (selector.name == 'containsValue' &&
        selector.callStructure == CallStructure.ONE_ARG) {
      ResolutionInterfaceType mapType = findMapType(receiverType);
      if (mapType != null) {
        ResolutionDartType valueType = findMapValueType(mapType);
        checkRelated(node, valueType, argumentTypes.first);
      }
    } else if (selector.name == 'contains' &&
        selector.callStructure == CallStructure.ONE_ARG) {
      ResolutionInterfaceType iterableType = findIterableType(receiverType);
      if (iterableType != null) {
        ResolutionDartType elementType = findIterableElementType(iterableType);
        checkRelated(node, elementType, argumentTypes.first);
      }
    } else if (selector.name == 'remove' &&
        selector.callStructure == CallStructure.ONE_ARG) {
      ResolutionInterfaceType mapType = findMapType(receiverType);
      if (mapType != null) {
        ResolutionDartType keyType = findMapKeyType(mapType);
        checkRelated(node, keyType, argumentTypes.first);
      }
      ResolutionInterfaceType listType = findListType(receiverType);
      if (listType != null) {
        ResolutionDartType valueType = findListElementType(listType);
        checkRelated(node, valueType, argumentTypes.first);
      }
    }
  }

  /// Return the interface type implemented by [type] or `null` if no interface
  /// type is implied by [type].
  ResolutionInterfaceType findInterfaceType(ResolutionDartType type) {
    return Types.computeInterfaceType(compiler.resolution, type);
  }

  /// Returns the supertype of [receiver] that implements [cls], if any.
  ResolutionInterfaceType findClassType(
      ResolutionDartType receiver, ClassElement cls) {
    ResolutionInterfaceType interfaceType = findInterfaceType(receiver);
    if (interfaceType == null) return null;
    ResolutionInterfaceType mapType = interfaceType.asInstanceOf(cls);
    if (mapType == null) return null;
    return mapType;
  }

  /// Returns the supertype of [receiver] that implements `Iterable`, if any.
  ResolutionInterfaceType findIterableType(ResolutionDartType receiver) {
    return findClassType(receiver, commonElements.iterableClass);
  }

  /// Returns the element type of the supertype of [receiver] that implements
  /// `Iterable`, if any.
  ResolutionDartType findIterableElementType(
      ResolutionInterfaceType iterableType) {
    if (iterableType == null) return null;
    return iterableType.typeArguments[0];
  }

  /// Returns the supertype of [receiver] that implements `Map`, if any.
  ResolutionInterfaceType findMapType(ResolutionDartType receiver) {
    return findClassType(receiver, commonElements.mapClass);
  }

  /// Returns the key type of the supertype of [receiver] that implements
  /// `Map`, if any.
  ResolutionDartType findMapKeyType(ResolutionInterfaceType mapType) {
    if (mapType == null) return null;
    return mapType.typeArguments[0];
  }

  /// Returns the value type of the supertype of [receiver] that implements
  /// `Map`, if any.
  ResolutionDartType findMapValueType(ResolutionInterfaceType mapType) {
    if (mapType == null) return null;
    return mapType.typeArguments[1];
  }

  /// Returns the supertype of [receiver] that implements `List`, if any.
  ResolutionInterfaceType findListType(ResolutionDartType receiver) {
    return findClassType(receiver, commonElements.listClass);
  }

  /// Returns the element type of the supertype of [receiver] that implements
  /// `List`, if any.
  ResolutionDartType findListElementType(ResolutionInterfaceType listType) {
    if (listType == null) return null;
    return listType.typeArguments[0];
  }

  /// Returns the implied return type of [type] or `dynamic` if no return type
  /// is implied.
  ResolutionDartType findReturnType(ResolutionDartType type) {
    if (type is ResolutionFunctionType) {
      return type.returnType;
    }
    return const ResolutionDynamicType();
  }

  /// Visits [arguments] and returns the list of their corresponding types.
  List<ResolutionDartType> findArgumentTypes(NodeList arguments) {
    List<ResolutionDartType> argumentTypes = <ResolutionDartType>[];
    for (Node argument in arguments) {
      argumentTypes.add(apply(argument));
    }
    return argumentTypes;
  }

  /// Finds the [MemberSignature] of the [name] property on [type], if any.
  MemberSignature lookupInterfaceMember(ResolutionDartType type, Name name) {
    ResolutionInterfaceType interfaceType = findInterfaceType(type);
    if (interfaceType == null) return null;
    return interfaceType.lookupInterfaceMember(name);
  }

  /// Returns the type of an access of the [name] property on [type], or
  /// `dynamic` if no property was found.
  ResolutionDartType lookupInterfaceMemberAccessType(
      ResolutionDartType type, Name name) {
    MemberSignature member = lookupInterfaceMember(type, name);
    if (member == null) return const ResolutionDynamicType();
    return member.type;
  }

  /// Returns the function type of the [name] property on [type], or
  /// `dynamic` if no property was found.
  ResolutionFunctionType lookupInterfaceMemberInvocationType(
      ResolutionDartType type, Name name) {
    MemberSignature member = lookupInterfaceMember(type, name);
    if (member == null) return null;
    return member.functionType;
  }

  ResolutionDartType apply(Node node, [_]) {
    ResolutionDartType type = node.accept(this);
    if (type == null) {
      type = const ResolutionDynamicType();
    }
    return type;
  }

  @override
  ResolutionInterfaceType visitEquals(Send node, Node left, Node right, _) {
    ResolutionDartType leftType = apply(left);
    ResolutionDartType rightType = apply(right);
    checkRelated(node, leftType, rightType);
    return commonElements.boolType;
  }

  @override
  ResolutionInterfaceType visitNotEquals(Send node, Node left, Node right, _) {
    ResolutionDartType leftType = apply(left);
    ResolutionDartType rightType = apply(right);
    checkRelated(node, leftType, rightType);
    return commonElements.boolType;
  }

  @override
  ResolutionDartType visitIndex(Send node, Node receiver, Node index, _) {
    ResolutionDartType receiverType = apply(receiver);
    ResolutionDartType indexType = apply(index);
    ResolutionInterfaceType mapType = findMapType(receiverType);
    ResolutionDartType keyType = findMapKeyType(mapType);
    ResolutionDartType valueType = findMapValueType(mapType);
    checkRelated(index, keyType, indexType);
    return valueType;
  }

  @override
  ResolutionInterfaceType visitLiteralInt(LiteralInt node) {
    return commonElements.intType;
  }

  @override
  ResolutionInterfaceType visitLiteralString(LiteralString node) {
    return commonElements.stringType;
  }

  @override
  ResolutionInterfaceType visitLiteralBool(LiteralBool node) {
    return commonElements.boolType;
  }

  @override
  ResolutionDartType visitLiteralMap(LiteralMap node) {
    return elements.getType(node);
  }

  @override
  ResolutionDartType visitLiteralList(LiteralList node) {
    return elements.getType(node);
  }

  @override
  ResolutionDartType visitLiteralNull(LiteralNull node) {
    return elements.getType(node);
  }

  @override
  ResolutionDartType visitLocalVariableGet(
      Send node, LocalVariableElement variable, _) {
    return variable.type;
  }

  @override
  ResolutionDartType visitLocalFunctionGet(
      Send node, LocalFunctionElement function, _) {
    return function.type;
  }

  @override
  ResolutionDartType visitParameterGet(
      Send node, ParameterElement parameter, _) {
    return parameter.type;
  }

  @override
  ResolutionDartType visitThisPropertyGet(Send node, Name name, _) {
    return lookupInterfaceMemberAccessType(thisType, name);
  }

  @override
  ResolutionDartType visitDynamicPropertyGet(
      Send node, Node receiver, Name name, _) {
    ResolutionDartType receiverType = apply(receiver);
    return lookupInterfaceMemberAccessType(receiverType, name);
  }

  @override
  ResolutionDartType visitIfNotNullDynamicPropertyGet(
      Send node, Node receiver, Name name, _) {
    ResolutionDartType receiverType = apply(receiver);
    return lookupInterfaceMemberAccessType(receiverType, name);
  }

  @override
  ResolutionDartType visitStaticFieldGet(Send node, FieldElement field, _) {
    return field.type;
  }

  @override
  ResolutionDartType visitTopLevelFieldGet(Send node, FieldElement field, _) {
    return field.type;
  }

  @override
  ResolutionDartType visitDynamicPropertyInvoke(
      Send node, Node receiver, NodeList arguments, Selector selector, _) {
    ResolutionDartType receiverType = apply(receiver);
    List<ResolutionDartType> argumentTypes = findArgumentTypes(arguments);
    ResolutionFunctionType methodType =
        lookupInterfaceMemberInvocationType(receiverType, selector.memberName);
    checkDynamicInvoke(node, receiverType, argumentTypes, selector);
    return findReturnType(methodType);
  }

  @override
  ResolutionDartType visitThisPropertyInvoke(
      Send node, NodeList arguments, Selector selector, _) {
    ResolutionDartType receiverType = thisType;
    List<ResolutionDartType> argumentTypes = findArgumentTypes(arguments);
    ResolutionFunctionType methodType =
        lookupInterfaceMemberInvocationType(receiverType, selector.memberName);
    checkDynamicInvoke(node, receiverType, argumentTypes, selector);
    return findReturnType(methodType);
  }

  @override
  ResolutionDartType visitIfNotNullDynamicPropertyInvoke(
      Send node, Node receiver, NodeList arguments, Selector selector, _) {
    ResolutionDartType receiverType = apply(receiver);
    List<ResolutionDartType> argumentTypes = findArgumentTypes(arguments);
    ResolutionFunctionType methodType =
        lookupInterfaceMemberInvocationType(receiverType, selector.memberName);
    checkDynamicInvoke(node, receiverType, argumentTypes, selector);
    return findReturnType(methodType);
  }

  @override
  ResolutionDartType visitTopLevelFunctionInvoke(
      Send node,
      MethodElement function,
      NodeList arguments,
      CallStructure callStructure,
      _) {
    apply(arguments);
    return findReturnType(function.type);
  }

  @override
  ResolutionDartType visitStaticFunctionInvoke(
      Send node,
      MethodElement function,
      NodeList arguments,
      CallStructure callStructure,
      _) {
    apply(arguments);
    return findReturnType(function.type);
  }
}

/// Computes the [ClassElement] implied by a type.
// TODO(johnniwinther): Handle type variables, function types and typedefs.
class ClassFinder extends BaseResolutionDartTypeVisitor<ClassElement, dynamic> {
  const ClassFinder();

  ClassElement findClass(ResolutionDartType type) => type.accept(this, null);

  @override
  ClassElement visitType(ResolutionDartType type, _) => null;

  @override
  ClassElement visitInterfaceType(ResolutionInterfaceType type, _) {
    return type.element;
  }
}
