// Copyright (c) 2018, 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 'package:analyzer/analysis_rule/rule_context.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/dart/element/type_system.dart';
import 'package:analyzer/error/error.dart';

import '../analyzer.dart';
import '../extensions.dart';

const _desc = r'Unnecessary parentheses can be removed.';

class UnnecessaryParenthesis extends LintRule {
  UnnecessaryParenthesis()
    : super(name: LintNames.unnecessary_parenthesis, description: _desc);

  @override
  DiagnosticCode get diagnosticCode => LinterLintCode.unnecessary_parenthesis;

  @override
  void registerNodeProcessors(NodeLintRegistry registry, RuleContext context) {
    var visitor = _Visitor(this, context.typeSystem);
    registry.addParenthesizedExpression(this, visitor);
  }
}

class _ContainsFunctionExpressionVisitor extends UnifyingAstVisitor<void> {
  bool hasFunctionExpression = false;

  @override
  void visitFunctionExpression(FunctionExpression node) {
    hasFunctionExpression = true;
  }

  @override
  void visitNode(AstNode node) {
    if (!hasFunctionExpression) {
      node.visitChildren(this);
    }
  }
}

class _Visitor extends SimpleAstVisitor<void> {
  final LintRule rule;
  final TypeSystem typeSystem;

  _Visitor(this.rule, this.typeSystem);

  @override
  void visitParenthesizedExpression(ParenthesizedExpression node) {
    var parent = node.parent;
    // `case const (a + b):` is OK.
    if (parent is ConstantPattern) return;

    // `[...(p as List)]` is OK.
    if (parent is SpreadElement) return;

    var expression = node.expression;

    // Don't over-report on records missing trailing commas.
    // `(int,) r = (3);` is OK.
    if (parent is VariableDeclaration &&
        parent.declaredElement?.type is RecordType) {
      if (expression is! RecordLiteral) return;
    }

    // `g((3)); => g((int,) i) { }` is OK.
    if (parent is ArgumentList) {
      var element = node.correspondingParameter;
      if (element?.type is RecordType && node.expression is! RecordLiteral) {
        return;
      }
    }

    // `g(i: (3)); => g({required (int,) i}) { }` is OK.
    if (parent is NamedExpression &&
        parent.correspondingParameter?.type is RecordType) {
      if (expression is! RecordLiteral) return;
    }

    // Directly wrapped into parentheses already - always report.
    if (parent is ParenthesizedExpression ||
        parent is InterpolationExpression ||
        (parent is ArgumentList && parent.arguments.length == 1) ||
        (parent is IfStatement && node == parent.expression) ||
        (parent is IfElement && node == parent.expression) ||
        (parent is WhileStatement && node == parent.condition) ||
        (parent is DoStatement && node == parent.condition) ||
        (parent is SwitchStatement && node == parent.expression) ||
        (parent is SwitchExpression && node == parent.expression)) {
      rule.reportAtNode(node);
      return;
    }

    // `(foo ? bar : baz)` is OK.
    if (expression is ConditionalExpression) return;

    // `(List<int>).toString()` is OK.
    if (expression is TypeLiteral) return;

    if (expression.isOneToken ||
        expression.containsNullAwareInvocationInChain) {
      if (parent is PropertyAccess) {
        var name = parent.propertyName.name;
        if (name == 'hashCode' || name == 'runtimeType') {
          // `(String).hashCode` is OK.
          return;
        }

        // Parentheses are required to stop null-aware shorting, which then
        // allows an extension getter, which extends a nullable type, to be
        // called on a `null` value.
        var target = parent.propertyName.element?.enclosingElement;
        if (target is ExtensionElement &&
            typeSystem.isNullable(target.extendedType)) {
          return;
        }
      } else if (parent is MethodInvocation) {
        var name = parent.methodName.name;
        if (name == 'noSuchMethod' || name == 'toString') {
          // `(String).noSuchMethod()` is OK.
          return;
        }

        // Parentheses are required to stop null-aware shorting, which then
        // allows an extension method, which extends a nullable type, to be
        // called on a `null` value.
        var target = parent.methodName.element?.enclosingElement;
        if (target is ExtensionElement &&
            typeSystem.isNullable(target.extendedType)) {
          return;
        }
      } else if (parent is PostfixExpression &&
          parent.operator.type == TokenType.BANG) {
        return;
      } else if (expression is IndexExpression && expression.isNullAware) {
        if (parent is ConditionalExpression &&
            identical(parent.thenExpression, node)) {
          // In `a ? (b?[c]) : d`, the parentheses are necessary to prevent the
          // second `?` from being interpreted as the start of a nested
          // conditional expression (see
          // https://github.com/dart-lang/linter/issues/4812).
          return;
        } else if (parent is MapLiteralEntry && identical(parent.key, node)) {
          // In `{(a?[b]): c}`, the parentheses are necessary to prevent the
          // second `?` from being interpreted as the start of a nested
          // conditional expression (see
          // https://github.com/dart-lang/linter/issues/4812).
          return;
        }
      }
      rule.reportAtNode(node);
      return;
    }

    if (expression is ConstructorReference) {
      if (parent is! FunctionExpressionInvocation ||
          parent.typeArguments == null) {
        rule.reportAtNode(node);
        return;
      }
    }

    // `a..b = (c..d)` is OK.
    if (expression is CascadeExpression ||
        node.thisOrAncestorMatching(
              (n) => n is Statement || n is CascadeExpression,
            )
            is CascadeExpression) {
      return;
    }

    // Constructor field initializers are rather unguarded by delimiting
    // tokens, which can get confused with a function expression. See test
    // cases for issues #1395 and #1473.
    //
    // We cannot just look at the immediate `parent`. Take this example of a
    // constructor:
    //
    // ```dart
    // C(bool Function()? e) : e = e ??= (() => true);
    // ```
    //
    // The parentheses in question are not an immediate child of a constructor
    // field initializer; they are the right side of `e ??= ...`, which is an
    // immediate child of a constructor field initializer. There can be any
    // number of expressions like this in between. The important principle is
    // that `=>` must not be "bare", such that it can be interpreted as the
    // delimiter for the constructor body.
    if (node.isBareInConstructorFieldInitializer &&
        node.containsFunctionExpression) {
      return;
    }

    // `foo = (a == b)` is OK, `return (count != 0)` is OK.
    if (expression is BinaryExpression &&
        (expression.operator.type == TokenType.EQ_EQ ||
            expression.operator.type == TokenType.BANG_EQ)) {
      if (parent is AssignmentExpression ||
          parent is VariableDeclaration ||
          parent is ReturnStatement ||
          parent is YieldStatement ||
          parent is ConstructorFieldInitializer) {
        return;
      }
    }

    // `switch` at the beginning of a statement will be parsed as a switch
    // statement, the parenthesis are required to parse as a switch expression
    // instead.
    if (parent is ExpressionStatement && expression is SwitchExpression) {
      return;
    }

    if (expression.directlyContainsWhitespace) {
      // An expression with internal whitespace can be made more readable when
      // wrapped in parentheses in many cases. But when the parentheses are
      // inside one of the following nodes, the readability is not affected.
      // See https://github.com/dart-lang/linter/issues/2944.
      if (parent is! AssignmentExpression &&
          parent is! ConstructorFieldInitializer &&
          parent is! ExpressionFunctionBody &&
          parent is! RecordLiteral &&
          parent is! ReturnStatement &&
          parent is! VariableDeclaration &&
          parent is! YieldStatement &&
          !node.isArgument) {
        return;
      }
    }

    if (parent is Expression) {
      if (parent is BinaryExpression) return;
      if (parent is ConditionalExpression) return;
      if (parent is CascadeExpression) return;
      if (parent is FunctionExpressionInvocation &&
          expression is! PrefixedIdentifier) {
        return;
      }
      if (parent is AsExpression) return;
      if (parent is IsExpression) return;

      if (parent
          case MethodInvocation(:var target) || PropertyAccess(:var target)) {
        // Another case of the above exception, something like
        // `!(const [7]).contains(5);`, where the _parent's_ parent is the
        // PrefixExpression.
        if (parent.parent is PrefixExpression &&
            target == node &&
            expression.directlyContainsWhitespace) {
          return;
        }

        // `(p++).toString()` is OK. `(++p).toString()` is OK.
        if (expression is PostfixExpression && target == node) return;
        if (expression is PrefixExpression && target == node) return;
      }

      // Something like `({1, 2, 3}).forEach(print);`.
      // The parens cannot be removed because then the curly brackets are not
      // interpreted as a set-or-map literal.
      if (node.wouldBeParsedAsStatementBlock) return;
    }
    rule.reportAtNode(node);
  }
}

extension on ParenthesizedExpression {
  bool get containsFunctionExpression {
    var visitor = _ContainsFunctionExpressionVisitor();
    accept(visitor);
    return visitor.hasFunctionExpression;
  }

  bool get isBareInConstructorFieldInitializer {
    var ancestor = parent;
    while (ancestor != null) {
      if (ancestor is ConstructorFieldInitializer) return true;
      if (ancestor is FunctionBody || ancestor is MethodInvocation) {
        // The delimiters (e.g. parentheses) in such an ancestor mean that
        // `this` is not a "bare" expression within the constructor field
        // initializer.
        return false;
      }
      ancestor = ancestor.parent;
    }
    return false;
  }

  /// Returns whether a parser would attempt to parse `this` as a statement
  /// block if the parentheses were removed.
  ///
  /// The two components that make this true are:
  /// * the parenthesized expression is a [SetOrMapLiteral] (starting with `{`),
  /// * the open parenthesis of this expression is the first token of an
  ///   [ExpressionStatement].
  bool get wouldBeParsedAsStatementBlock {
    if (expression is! SetOrMapLiteral) {
      return false;
    }
    var exprStatementAncestor = thisOrAncestorOfType<ExpressionStatement>();
    if (exprStatementAncestor == null) {
      return false;
    }
    return exprStatementAncestor.beginToken == leftParenthesis;
  }
}

extension on Expression? {
  /// Returns whether this directly contains whitespace.
  bool get directlyContainsWhitespace {
    var self = this;
    return self is AsExpression ||
        self is AssignmentExpression ||
        self is AwaitExpression ||
        self is BinaryExpression ||
        self is FunctionExpression ||
        self is IsExpression ||
        self is SwitchExpression ||
        // As in, `!(new Foo())`.
        (self is InstanceCreationExpression && self.keyword != null) ||
        // No TypedLiteral (ListLiteral, MapLiteral, SetLiteral) accepts `-`
        // or `!` as a prefix operator, but this method can be called
        // recursively, so this catches things like
        // `!(const [].contains(42))`.
        (self is TypedLiteral && self.constKeyword != null) ||
        // As in, `!(const List(3).contains(7))`, and chains like
        // `-(new List(3).skip(1).take(3).skip(1).length)`.
        (self is MethodInvocation && self.target.directlyContainsWhitespace) ||
        // As in, `-(new List(3).length)`, and chains like
        // `-(new List(3).length.bitLength.bitLength)`.
        (self is PropertyAccess && self.target.directlyContainsWhitespace);
  }
}

extension on Expression {
  /// Whether this expression is directly inside an argument list or the
  /// expression of a named argument.
  bool get isArgument =>
      parent is ArgumentList ||
      (parent is NamedExpression && parent?.parent is ArgumentList);

  /// Whether this expression is a sigle token.
  ///
  /// This excludes type literals because they often need to be parenthesized.
  bool get isOneToken =>
      this is SimpleIdentifier ||
      this is StringLiteral ||
      this is IntegerLiteral ||
      this is DoubleLiteral ||
      this is NullLiteral ||
      this is BooleanLiteral;
}
