// Copyright (c) 2017, 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/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:linter/src/analyzer.dart';

const _desc =
    r"Prefer single quotes where they won't require escape sequences.";

const _details = '''

**DO** use single quotes where they wouldn't require additional escapes.

That means strings with an apostrophe may use double quotes so that the
apostrophe isn't escaped (note: we don't lint the other way around, ie, a single
quoted string with an escaped apostrophe is not flagged).

It's also rare, but possible, to have strings within string interpolations.  In
this case, its much more readable to use a double quote somewhere.  So double
quotes are allowed either within, or containing, an interpolated string literal.
Arguably strings within string interpolations should be its own type of lint.

**BAD:**
```
useStrings(
    "should be single quote",
    r"should be single quote",
    r"""should be single quotes""")
```

**GOOD:**
```
useStrings(
    'should be single quote',
    r'should be single quote",
    r\'''should be single quotes\''',
    "here's ok",
    "nested \${a ? 'strings' : 'can'} be wrapped by a double quote",
    'and nested \${a ? "strings" : "can be double quoted themselves"});
```

''';

class PreferSingleQuotes extends LintRule implements NodeLintRule {
  PreferSingleQuotes()
      : super(
            name: 'prefer_single_quotes',
            description: _desc,
            details: _details,
            group: Group.style);

  @override
  void registerNodeProcessors(NodeLintRegistry registry,
      [LinterContext context]) {
    final visitor = new _Visitor(this);
    registry.addSimpleStringLiteral(this, visitor);
    registry.addStringInterpolation(this, visitor);
  }
}

/// The only way to get immediate children in a unified, typesafe way, is to
/// call visitChildren on that node, and pass in a visitor. This collects at the
/// top level and stops.
class _ImmediateChildrenVisitor extends UnifyingAstVisitor {
  final _children = <AstNode>[];

  @override
  visitNode(AstNode node) {
    _children.add(node);
  }

  static List<AstNode> childrenOf(AstNode node) {
    final visitor = new _ImmediateChildrenVisitor();
    node.visitChildren(visitor);
    return visitor._children;
  }
}

/// Do a top-down analysis to search for string nodes. Note, do not pass in
/// string nodes directly to this visitor, or you will always get true. Pass in
/// its children.
class _IsOrContainsStringVisitor extends UnifyingAstVisitor<bool> {
  /// Different way to express `accept` in a way that's clearer in this visitor.
  bool isOrContainsString(AstNode node) => node.accept(this);

  /// Scan as little of the tree as possible, by bailing out on first match. For
  /// all leaf nodes, they will either have a method defined here and return
  /// true, or they will return false because leaves have no children.
  @override
  bool visitNode(AstNode node) =>
      _ImmediateChildrenVisitor.childrenOf(node).any(isOrContainsString);

  @override
  bool visitSimpleStringLiteral(SimpleStringLiteral string) => true;

  @override
  bool visitStringInterpolation(StringInterpolation string) => true;
}

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

  _Visitor(this.rule);

  /// Strings interpolations can contain other string nodes. Check like this.
  bool containsString(StringInterpolation string) {
    final checkHasString = new _IsOrContainsStringVisitor();
    return string.elements.any((child) => child.accept(checkHasString));
  }

  /// Strings can be within interpolations (ie, nested). Check like this.
  bool isNestedString(AstNode node) =>
      // careful: node.getAncestor will check the node itself.
      node.parent?.thisOrAncestorOfType<StringInterpolation>() != null;

  @override
  void visitSimpleStringLiteral(SimpleStringLiteral string) {
    if (string.isSingleQuoted || string.value.contains("'")) {
      return;
    }

    // Bail out on 'strings ${x ? "containing" : "other"} strings'
    if (!isNestedString(string)) {
      rule.reportLintForToken(string.literal);
    }
  }

  @override
  void visitStringInterpolation(StringInterpolation node) {
    if (node.isSingleQuoted) {
      return;
    }

    // slightly more complicated check there are no single quotes
    if (node.elements
        .any((e) => e is InterpolationString && e.value.contains("'"))) {
      return;
    }

    // Bail out on "strings ${x ? 'containing' : 'other'} strings"
    if (!containsString(node) && !isNestedString(node)) {
      rule.reportLint(node);
    }
  }
}
