Coverage report for lib/src/rule/combinator.dart

Line coverage: 20 / 21 (95.2%)

All files > lib/src/rule/combinator.dart

1
// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
2
// for details. All rights reserved. Use of this source code is governed by a
3
// BSD-style license that can be found in the LICENSE file.
4
5
library dart_style.src.rule.combinator;
6
7
import '../chunk.dart';
8
import 'rule.dart';
9
10
/// Handles a list of "combinators".
11
///
12
/// A combinator is a keyword followed by a list of nodes used to modify some
13
/// declaration. It's used for actual hide and show combinators as well as
14
/// "with" and "implements" clauses in class declarations.
15
///
16
/// Combinators can be split in a few different ways:
17
///
18
///     // All on one line:
19
///     import 'animals.dart' show Ant hide Cat;
20
///
21
///     // Wrap before each keyword:
22
///     import 'animals.dart'
23
///         show Ant, Baboon
24
///         hide Cat;
25
///
26
///     // Wrap either or both of the name lists:
27
///     import 'animals.dart'
28
///         show
29
///             Ant,
30
///             Baboon
31
///         hide Cat;
32
///
33
/// These are not allowed:
34
///
35
///     // Wrap list but not keyword:
36
///     import 'animals.dart' show
37
///             Ant,
38
///             Baboon
39
///         hide Cat;
40
///
41
///     // Wrap one keyword but not both:
42
///     import 'animals.dart'
43
///         show Ant, Baboon hide Cat;
44
///
45
/// This ensures that when any wrapping occurs, the keywords are always at
46
/// the beginning of the line.
47
class CombinatorRule extends Rule {
48
  /// The set of chunks before the combinators.
49
  final Set<Chunk> _combinators = new Set();
50
51
  /// A list of sets of chunks prior to each name in a combinator.
52
  ///
53
  /// The outer list is a list of combinators (i.e. "hide", "show", etc.). Each
54
  /// inner set is the set of names for that combinator.
55
  final List<Set<Chunk>> _names = [];
56
571
  int get numValues {
58
    var count = 2; // No wrapping, or wrap just before each combinator.
59
603
    if (_names.length == 2) {
611
      count += 3; // Wrap first set of names, second, or both.
62
    } else {
633
      assert(_names.length == 1);
641
      count++; // Wrap the names.
65
    }
66
67
    return count;
68
  }
69
70
  /// Adds a new combinator to the list of combinators.
71
  ///
72
  /// This must be called before adding any names.
731
  void addCombinator(Chunk chunk) {
742
    _combinators.add(chunk);
753
    _names.add(new Set());
76
  }
77
78
  /// Adds a chunk prior to a name to the current combinator.
791
  void addName(Chunk chunk) {
803
    _names.last.add(chunk);
81
  }
82
831
  bool isSplitAtValue(int value, Chunk chunk) {
84
    switch (value) {
851
      case 1:
86
        // Just split at the combinators.
872
        return _combinators.contains(chunk);
88
891
      case 2:
90
        // Split at the combinators and the first set of names.
911
        return _isCombinatorSplit(0, chunk);
92
931
      case 3:
94
        // If there is two combinators, just split at the combinators and the
95
        // second set of names.
963
        if (_names.length == 2) {
97
          // Two sets of combinators, so just split at the combinators and the
98
          // second set of names.
991
          return _isCombinatorSplit(1, chunk);
100
        }
101
102
        // Split everything.
103
        return true;
104
105
      default:
106
        return true;
107
    }
108
  }
109
110
  /// Returns `true` if [chunk] is for a combinator or a name in the
111
  /// combinator at index [combinator].
1121
  bool _isCombinatorSplit(int combinator, Chunk chunk) {
1135
    return _combinators.contains(chunk) || _names[combinator].contains(chunk);
114
  }
115
1160
  String toString() => "Comb${super.toString()}";
117
}