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

import 'dart:async';

import 'package:analysis_server/src/protocol_server.dart'
    show CompletionSuggestionKind;
import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
import 'package:analysis_server/src/utilities/strings.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/dart/element/type_provider.dart';
import 'package:analyzer_plugin/src/utilities/completion/completion_target.dart';
import 'package:analyzer_plugin/src/utilities/completion/optype.dart';
import 'package:analyzer_plugin/src/utilities/visitors/local_declaration_visitor.dart'
    show LocalDeclarationVisitor;
import 'package:meta/meta.dart';

/// A contributor that produces suggestions based on the declarations in the
/// local file and containing library.  This contributor also produces
/// suggestions based on the instance members from the supertypes of a given
/// type. More concretely, this class produces suggestions for places where an
/// inherited instance member might be invoked via an implicit target of `this`.
class LocalReferenceContributor extends DartCompletionContributor {
  /// The builder used to build some suggestions.
  MemberSuggestionBuilder memberBuilder;

  /// The kind of suggestion to make.
  CompletionSuggestionKind classMemberSuggestionKind;

  /// The [_VisibilityTracker] tracks the set of elements already added in the
  /// completion list, this object helps prevents suggesting elements that have
  /// been shadowed by local declarations.
  _VisibilityTracker visibilityTracker = _VisibilityTracker();

  @override
  Future<void> computeSuggestions(
      DartCompletionRequest request, SuggestionBuilder builder) async {
    var opType = request.opType;
    var node = request.target.containingNode;

    // Suggest local fields for constructor initializers.
    var suggestLocalFields = node is ConstructorDeclaration &&
        node.initializers.contains(request.target.entity);

    var localVisitor;

    // Collect suggestions from the specific child [AstNode] that contains the
    // completion offset and all of its parents recursively.
    if (!opType.isPrefixed) {
      if (opType.includeReturnValueSuggestions ||
          opType.includeTypeNameSuggestions ||
          opType.includeVoidReturnSuggestions ||
          opType.includeConstructorSuggestions ||
          suggestLocalFields) {
        // Do not suggest local variables within the current expression.
        while (node is Expression) {
          node = node.parent;
        }

        // Do not suggest loop variable of a ForEachStatement when completing
        // the expression of the ForEachStatement.
        if (node is ForStatement && node.forLoopParts is ForEachParts) {
          node = node.parent;
        } else if (node is ForEachParts) {
          node = node.parent.parent;
        }

        localVisitor = _LocalVisitor(request, builder, visibilityTracker,
            suggestLocalFields: suggestLocalFields);
        try {
          builder.laterReplacesEarlier = false;
          localVisitor.visit(node);
        } finally {
          builder.laterReplacesEarlier = true;
        }
      }
    }

    // From this point forward the logic is for the inherited references.
    if (request.includeIdentifiers) {
      var member = _enclosingMember(request.target);
      if (member != null) {
        var classOrMixin = member.parent;
        if (classOrMixin is ClassOrMixinDeclaration &&
            classOrMixin.declaredElement != null) {
          memberBuilder = MemberSuggestionBuilder(request, builder);
          _computeSuggestionsForClass(classOrMixin.declaredElement, request);
        }
      }
    }
  }

  void _addSuggestionsForType(InterfaceType type, DartCompletionRequest request,
      double inheritanceDistance,
      {bool isFunctionalArgument = false}) {
    var opType = request.opType;
    if (!isFunctionalArgument) {
      for (var accessor in type.accessors) {
        if (visibilityTracker._isVisible(accessor.declaration)) {
          if (accessor.isGetter) {
            if (opType.includeReturnValueSuggestions) {
              memberBuilder.addSuggestionForAccessor(
                  accessor: accessor, inheritanceDistance: inheritanceDistance);
            }
          } else {
            if (opType.includeVoidReturnSuggestions) {
              memberBuilder.addSuggestionForAccessor(
                  accessor: accessor, inheritanceDistance: inheritanceDistance);
            }
          }
        }
      }
    }
    for (var method in type.methods) {
      if (visibilityTracker._isVisible(method.declaration)) {
        if (method.returnType == null) {
          memberBuilder.addSuggestionForMethod(
              method: method,
              inheritanceDistance: inheritanceDistance,
              kind: classMemberSuggestionKind);
        } else if (!method.returnType.isVoid) {
          if (opType.includeReturnValueSuggestions) {
            memberBuilder.addSuggestionForMethod(
                method: method,
                inheritanceDistance: inheritanceDistance,
                kind: classMemberSuggestionKind);
          }
        } else {
          if (opType.includeVoidReturnSuggestions) {
            memberBuilder.addSuggestionForMethod(
                method: method,
                inheritanceDistance: inheritanceDistance,
                kind: classMemberSuggestionKind);
          }
        }
      }
    }
  }

  void _computeSuggestionsForClass(
      ClassElement classElement, DartCompletionRequest request) {
    var isFunctionalArgument = request.target.isFunctionalArgument();
    classMemberSuggestionKind = isFunctionalArgument
        ? CompletionSuggestionKind.IDENTIFIER
        : CompletionSuggestionKind.INVOCATION;
    for (var type in classElement.allSupertypes) {
      double inheritanceDistance;
      if (request.useNewRelevance) {
        inheritanceDistance = request.featureComputer
            .inheritanceDistanceFeature(classElement, type.element);
      }
      _addSuggestionsForType(type, request, inheritanceDistance,
          isFunctionalArgument: isFunctionalArgument);
    }
  }

  /// Return the class member containing the target or `null` if the target is
  /// in a static method or static field or not in a class member.
  ClassMember _enclosingMember(CompletionTarget target) {
    var node = target.containingNode;
    while (node != null) {
      if (node is MethodDeclaration) {
        if (!node.isStatic) {
          return node;
        }
      } else if (node is FieldDeclaration) {
        if (!node.isStatic) {
          return node;
        }
      } else if (node is ConstructorDeclaration) {
        return node;
      }
      node = node.parent;
    }
    return null;
  }
}

/// A visitor for collecting suggestions from the most specific child [AstNode]
/// that contains the completion offset to the [CompilationUnit].
class _LocalVisitor extends LocalDeclarationVisitor {
  /// The request for which suggestions are being computed.
  final DartCompletionRequest request;

  /// The builder used to build the suggestions.
  final SuggestionBuilder builder;

  /// The op type associated with the request.
  final OpType opType;

  /// A flag indicating whether the suggestions should use the new relevance
  /// scores.
  final bool useNewRelevance;

  /// A flag indicating whether the target of the request is a function-valued
  /// argument in an argument list.
  final bool targetIsFunctionalArgument;

  /// A flag indicating whether local fields should be suggested.
  final bool suggestLocalFields;

  /// A flag indicating whether suggestions are being made inside an `extends`
  /// clause.
  bool inExtendsClause = false;

  /// Only used when [useNewRelevance] is `false`.
  int privateMemberRelevance = DART_RELEVANCE_DEFAULT;

  _VisibilityTracker visibilityTracker;

  _LocalVisitor(this.request, this.builder, this.visibilityTracker,
      {@required this.suggestLocalFields})
      : assert(visibilityTracker != null),
        opType = request.opType,
        useNewRelevance = request.useNewRelevance,
        targetIsFunctionalArgument = request.target.isFunctionalArgument(),
        super(request.offset) {
    // Suggestions for inherited members are provided by
    // InheritedReferenceContributor.
    if (!useNewRelevance) {
      // If the user typed an identifier starting with '_' then do not suppress
      // the relevance of private members.
      var data = request.result != null
          ? request.result.content
          : request.sourceContents;
      var offset = request.offset;
      if (data != null && 0 < offset && offset <= data.length) {
        bool isIdentifierChar(int index) {
          var code = data.codeUnitAt(index);
          return isLetterOrDigit(code) || code == CHAR_UNDERSCORE;
        }

        if (isIdentifierChar(offset - 1)) {
          while (offset > 0 && isIdentifierChar(offset - 1)) {
            --offset;
          }
          if (data.codeUnitAt(offset) == CHAR_UNDERSCORE) {
            privateMemberRelevance = null;
          }
        }
      }
    }
  }

  TypeProvider get typeProvider => request.libraryElement.typeProvider;

  CompletionSuggestionKind get _defaultKind => targetIsFunctionalArgument
      ? CompletionSuggestionKind.IDENTIFIER
      : opType.suggestKind;

  @override
  void declaredClass(ClassDeclaration declaration) {
    var classElt = declaration.declaredElement;
    if (visibilityTracker._isVisible(classElt)) {
      if (opType.includeTypeNameSuggestions) {
        builder.suggestClass(classElt, kind: _defaultKind);
      }

      // Generate the suggestions for the constructors. We are required to loop
      // through elements here instead of using declaredConstructor() due to
      // implicit constructors (i.e. there is no AstNode for an implicit
      // constructor)
      if (!opType.isPrefixed && opType.includeConstructorSuggestions) {
        for (var constructor in classElt.constructors) {
          if (!classElt.isAbstract || constructor.isFactory) {
            builder.suggestConstructor(constructor);
          }
        }
      }
    }
  }

  @override
  void declaredClassTypeAlias(ClassTypeAlias declaration) {
    if (opType.includeTypeNameSuggestions) {
      builder.suggestClass(declaration.declaredElement, kind: _defaultKind);
    }
  }

  @override
  void declaredConstructor(ConstructorDeclaration declaration) {
    // ignored: constructor completions are handled in declaredClass() above
  }

  @override
  void declaredEnum(EnumDeclaration declaration) {
    if (visibilityTracker._isVisible(declaration.declaredElement) &&
        opType.includeTypeNameSuggestions) {
      builder.suggestClass(declaration.declaredElement, kind: _defaultKind);
      for (var enumConstant in declaration.constants) {
        if (!enumConstant.isSynthetic) {
          builder.suggestEnumConstant(enumConstant.declaredElement);
        }
      }
    }
  }

  @override
  void declaredExtension(ExtensionDeclaration declaration) {
    if (visibilityTracker._isVisible(declaration.declaredElement) &&
        opType.includeReturnValueSuggestions &&
        declaration.name != null) {
      builder.suggestExtension(declaration.declaredElement, kind: _defaultKind);
    }
  }

  @override
  void declaredField(FieldDeclaration fieldDecl, VariableDeclaration varDecl) {
    var field = varDecl.declaredElement;
    if ((visibilityTracker._isVisible(field) &&
            opType.includeReturnValueSuggestions &&
            (!opType.inStaticMethodBody || fieldDecl.isStatic)) ||
        suggestLocalFields) {
      var inheritanceDistance = -1.0;
      var enclosingClass = request.target.containingNode
          .thisOrAncestorOfType<ClassDeclaration>();
      if (enclosingClass != null) {
        inheritanceDistance = request.featureComputer
            .inheritanceDistanceFeature(
                enclosingClass.declaredElement, field.enclosingElement);
      }
      builder.suggestField(field, inheritanceDistance: inheritanceDistance);
    }
  }

  @override
  void declaredFunction(FunctionDeclaration declaration) {
    if (visibilityTracker._isVisible(declaration.declaredElement) &&
        (opType.includeReturnValueSuggestions ||
            opType.includeVoidReturnSuggestions)) {
      if (declaration.isSetter) {
        if (!opType.includeVoidReturnSuggestions) {
          return;
        }
      } else if (!declaration.isGetter) {
        if (!opType.includeVoidReturnSuggestions &&
            _isVoid(declaration.returnType)) {
          return;
        }
      }
      var declaredElement = declaration.declaredElement;
      if (declaredElement is FunctionElement) {
        builder.suggestTopLevelFunction(declaredElement, kind: _defaultKind);
      } else if (declaredElement is PropertyAccessorElement) {
        builder.suggestTopLevelPropertyAccessor(declaredElement,
            kind: _defaultKind);
      }
    }
  }

  @override
  void declaredFunctionTypeAlias(FunctionTypeAlias declaration) {
    if (opType.includeTypeNameSuggestions) {
      builder.suggestFunctionTypeAlias(declaration.declaredElement,
          kind: _defaultKind);
    }
  }

  @override
  void declaredGenericTypeAlias(GenericTypeAlias declaration) {
    if (opType.includeTypeNameSuggestions) {
      builder.suggestFunctionTypeAlias(declaration.declaredElement,
          kind: _defaultKind);
    }
  }

  @override
  void declaredLabel(Label label, bool isCaseLabel) {
    // ignored: handled by the label_contributor.dart
  }

  @override
  void declaredLocalVar(SimpleIdentifier id, TypeAnnotation typeName) {
    if (visibilityTracker._isVisible(id.staticElement) &&
        opType.includeReturnValueSuggestions) {
      builder.suggestLocalVariable(id.staticElement as LocalVariableElement);
    }
  }

  @override
  void declaredMethod(MethodDeclaration declaration) {
    var element = declaration.declaredElement;
    if (visibilityTracker._isVisible(element) &&
        (opType.includeReturnValueSuggestions ||
            opType.includeVoidReturnSuggestions) &&
        (!opType.inStaticMethodBody || declaration.isStatic)) {
      var inheritanceDistance = -1.0;
      var enclosingClass = request.target.containingNode
          .thisOrAncestorOfType<ClassDeclaration>();
      if (enclosingClass != null) {
        inheritanceDistance = request.featureComputer
            .inheritanceDistanceFeature(
                enclosingClass.declaredElement, element.enclosingElement);
      }
      if (element is MethodElement) {
        builder.suggestMethod(element,
            inheritanceDistance: inheritanceDistance, kind: _defaultKind);
      } else if (element is PropertyAccessorElement) {
        builder.suggestAccessor(element,
            inheritanceDistance: inheritanceDistance);
      }
    }
  }

  @override
  void declaredMixin(MixinDeclaration declaration) {
    if (!inExtendsClause &&
        visibilityTracker._isVisible(declaration.declaredElement) &&
        opType.includeTypeNameSuggestions) {
      builder.suggestClass(declaration.declaredElement, kind: _defaultKind);
    }
  }

  @override
  void declaredParam(SimpleIdentifier id, TypeAnnotation typeName) {
    var element = id.staticElement;
    if (visibilityTracker._isVisible(element) &&
        opType.includeReturnValueSuggestions) {
      if (_isUnused(id.name)) {
        return;
      }
      if (element is ParameterElement) {
        builder.suggestParameter(element);
      } else if (element is LocalVariableElement) {
        builder.suggestCatchParameter(element);
      }
    }
  }

  @override
  void declaredTopLevelVar(
      VariableDeclarationList varList, VariableDeclaration varDecl) {
    var variableElement = varDecl.declaredElement;
    if (visibilityTracker._isVisible(variableElement) &&
        opType.includeReturnValueSuggestions) {
      builder.suggestTopLevelPropertyAccessor(
          (variableElement as TopLevelVariableElement).getter);
    }
  }

  @override
  void declaredTypeParameter(TypeParameter node) {
    if (visibilityTracker._isVisible(node.declaredElement) &&
        opType.includeTypeNameSuggestions) {
      builder.suggestTypeParameter(node.declaredElement);
    }
  }

  @override
  void visitExtendsClause(ExtendsClause node) {
    inExtendsClause = true;
    return super.visitExtendsClause(node);
  }

  /// Return `true` if the [identifier] is composed of one or more underscore
  /// characters and nothing else.
  bool _isUnused(String identifier) => RegExp(r'^_+$').hasMatch(identifier);

  bool _isVoid(TypeAnnotation returnType) {
    if (returnType is TypeName) {
      var id = returnType.name;
      if (id != null && id.name == 'void') {
        return true;
      }
    }
    return false;
  }
}

/// This class tracks the set of elements already added in the completion list,
/// this object helps prevents suggesting elements that have been shadowed by
/// local declarations.
class _VisibilityTracker {
  /// The set of known previously declared names in this contributor.
  final Set<String> declaredNames = {};

  /// Before completions are added by this contributor, we verify with this
  /// method if the element has already been added, this prevents suggesting
  /// [Element]s that are shadowed.
  bool _isVisible(Element element) =>
      element != null && declaredNames.add(element.name);
}
