Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(65)

Side by Side Diff: packages/dart_style/lib/src/nesting_builder.dart

Issue 1521693002: Roll Observatory deps (charted -> ^0.3.0) (Closed) Base URL: https://chromium.googlesource.com/external/github.com/dart-lang/observatory_pub_packages.git@master
Patch Set: Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 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 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library dart_style.src.nesting_builder; 5 library dart_style.src.nesting_builder;
6 6
7 import 'nesting_level.dart'; 7 import 'nesting_level.dart';
8 import 'whitespace.dart'; 8 import 'whitespace.dart';
9 9
10 /// Keeps track of expression nesting while the source code is being visited 10 /// Keeps track of block indentation and expression nesting while the source
11 /// and the chunks are being built. 11 /// code is being visited and the chunks are being built.
12 ///
13 /// This class requires (and verifies) that indentation and nesting are
14 /// stratified from each other. Expression nesting is always inside block
15 /// indentation, which means it is an error to try to change the block
16 /// indentation while any expression nesting is in effect.
12 class NestingBuilder { 17 class NestingBuilder {
13 /// The expression nesting levels and block indentation levels. 18 /// The block indentation levels.
14 /// 19 ///
15 /// This is tracked as a stack of [_IndentLevel]s. Each element in the stack 20 /// This is tracked as a stack of numbers, each of which is the total number
16 /// represents a level of block indentation. It's stored as a stack because 21 /// of spaces of block indentation. We only store the stack of previous
17 /// expressions may contain blocks which in turn contain other expressions. 22 /// levels as a convenience to the caller: it spares you from having to pass
18 /// The nesting level of the inner expressions are unrelated to the 23 /// the unindent amount to [unindent()].
19 /// surrounding ones. For example: 24 final List<int> _stack = [0];
25
26 /// When not `null`, the expression nesting after the next token is written.
20 /// 27 ///
21 /// outer(invocation(() { 28 /// When the nesting is increased, we don't want it to take effect until
22 /// inner(lambda());
23 /// }));
24 ///
25 /// When writing `inner(lambda())`, we need to track its nesting level. At
26 /// the same time, when the lambda is done, we need to return to the nesting
27 /// level of `outer(invocation(...`.
28 // TODO(rnystrom): I think this is no longer true now that blocks are handled
29 // as separate nested chunks. Once cascades use expression nesting, we may
30 // be able to just store a single nesting depth in NestingBuilder.
31 ///
32 /// Has an implicit entry for top-most expression nesting outside of any
33 /// block for things like wrapped directives.
34 final List<_IndentLevel> _stack = [new _IndentLevel(0)];
35
36 /// When not `null`, the nesting level of the current innermost block after
37 /// the next token is written.
38 ///
39 /// When the nesting level is increased, we don't want it to take effect until
40 /// after at least one token has been written. That ensures that comments 29 /// after at least one token has been written. That ensures that comments
41 /// appearing before the first token are correctly indented. For example, a 30 /// appearing before the first token are correctly indented. For example, a
42 /// binary operator expression increases the nesting before the first operand 31 /// binary operator expression increases the nesting before the first operand
43 /// to ensure any splits within the left operand are handled correctly. If we 32 /// to ensure any splits within the left operand are handled correctly. If we
44 /// changed the nesting level immediately, then code like: 33 /// changed the nesting level immediately, then code like:
45 /// 34 ///
46 /// { 35 /// {
47 /// // comment 36 /// // comment
48 /// foo + bar; 37 /// foo + bar;
49 /// } 38 /// }
50 /// 39 ///
51 /// would incorrectly get indented because the line comment adds a split which 40 /// would incorrectly get indented because the line comment adds a split which
52 /// would take the nesting level of the binary operator into account even 41 /// would take the nesting level of the binary operator into account even
53 /// though we haven't written any of its tokens yet. 42 /// though we haven't written any of its tokens yet.
43 ///
44 /// Likewise, when nesting is decreased, we may want to defer that until
45 /// we've written the next token to handle uncommon cases like:
46 ///
47 /// do // comment
48 /// {
49 /// ...
50 /// }
51 ///
52 /// Here, if we discard the expression nesting before we reach the "{", then
53 /// it won't get indented as it should.
54 NestingLevel _pendingNesting; 54 NestingLevel _pendingNesting;
55 55
56 /// The current number of characters of block indentation. 56 /// The current number of characters of block indentation.
57 int get indentation => _stack.last.indent; 57 int get indentation => _stack.last;
58 58
59 /// The nesting depth of the current inner-most block. 59 /// The current nesting, ignoring any pending nesting.
60 NestingLevel get nesting => _stack.last.nesting; 60 NestingLevel get nesting => _nesting;
61 NestingLevel _nesting = new NestingLevel();
61 62
62 /// The nesting depth of the current inner-most block, including any pending 63 /// The current nesting, including any pending nesting.
63 /// nesting.
64 NestingLevel get currentNesting => 64 NestingLevel get currentNesting =>
65 _pendingNesting != null ? _pendingNesting : _stack.last.nesting; 65 _pendingNesting != null ? _pendingNesting : _nesting;
66 66
67 /// The top "nesting level" that represents no expression nesting for the 67 /// The top "nesting level" that represents no expression nesting for the
68 /// current block. 68 /// current block.
69 NestingLevel get blockNesting { 69 NestingLevel get blockNesting {
70 // Walk the nesting levels until we bottom out. 70 // Walk the nesting levels until we bottom out.
71 var result = nesting; 71 var result = _nesting;
72 while (result.parent != null) { 72 while (result.parent != null) {
73 result = result.parent; 73 result = result.parent;
74 } 74 }
75 return result; 75 return result;
76 } 76 }
77 77
78 /// Creates a new indentation level [spaces] deeper than the current one. 78 /// Creates a new indentation level [spaces] deeper than the current one.
79 /// 79 ///
80 /// If omitted, [spaces] defaults to [Indent.block]. 80 /// If omitted, [spaces] defaults to [Indent.block].
81 void indent([int spaces]) { 81 void indent([int spaces]) {
82 if (spaces == null) spaces = Indent.block; 82 if (spaces == null) spaces = Indent.block;
83 83
84 // Indentation should only change outside of nesting.
84 assert(_pendingNesting == null); 85 assert(_pendingNesting == null);
86 assert(_nesting.indent == 0);
85 87
86 _stack.add(new _IndentLevel(_stack.last.indent + spaces)); 88 _stack.add(_stack.last + spaces);
87 } 89 }
88 90
89 /// Discards the most recent indentation level. 91 /// Discards the most recent indentation level.
90 void unindent() { 92 void unindent() {
93 // Indentation should only change outside of nesting.
91 assert(_pendingNesting == null); 94 assert(_pendingNesting == null);
95 assert(_nesting.indent == 0);
96
97 // If this fails, an unindent() call did not have a preceding indent() call.
98 assert(_stack.isNotEmpty);
99
92 _stack.removeLast(); 100 _stack.removeLast();
93 } 101 }
94 102
95 /// Begins a new expression nesting level [indent] deeper than the current 103 /// Begins a new expression nesting level [indent] deeper than the current
96 /// one if it splits. 104 /// one if it splits.
97 /// 105 ///
106 /// Expressions that are more nested will get increased indentation when split
107 /// if the previous line has a lower level of nesting.
108 ///
98 /// If [indent] is omitted, defaults to [Indent.expression]. 109 /// If [indent] is omitted, defaults to [Indent.expression].
99 void nest([int indent]) { 110 void nest([int indent]) {
100 if (indent == null) indent = Indent.expression; 111 if (indent == null) indent = Indent.expression;
101 112
102 if (_pendingNesting != null) { 113 if (_pendingNesting != null) {
103 _pendingNesting = _pendingNesting.nest(indent); 114 _pendingNesting = _pendingNesting.nest(indent);
104 } else { 115 } else {
105 _pendingNesting = nesting.nest(indent); 116 _pendingNesting = _nesting.nest(indent);
106 } 117 }
107 } 118 }
108 119
109 /// Discards the most recent level of expression nesting. 120 /// Discards the most recent level of expression nesting.
110 ///
111 /// Expressions that are more nested will get increased indentation when split
112 /// if the previous line has a lower level of nesting.
113 void unnest() { 121 void unnest() {
114 // By the time the nesting is done, it should have emitted some text and 122 if (_pendingNesting != null) {
115 // not be pending anymore. 123 _pendingNesting = _pendingNesting.parent;
116 assert(_pendingNesting == null); 124 } else {
125 _pendingNesting = _nesting.parent;
126 }
117 127
118 _setNesting(nesting.parent); 128 // If this fails, an unnest() call did not have a preceding nest() call.
129 assert(_pendingNesting != null);
119 } 130 }
120 131
121 /// Applies any pending nesting now that we are ready for it to take effect. 132 /// Applies any pending nesting now that we are ready for it to take effect.
122 void commitNesting() { 133 void commitNesting() {
123 if (_pendingNesting == null) return; 134 if (_pendingNesting == null) return;
124 135
125 _setNesting(_pendingNesting); 136 _nesting = _pendingNesting;
126 _pendingNesting = null; 137 _pendingNesting = null;
127 } 138 }
128
129 /// Sets the nesting level of the innermost block to [level].
130 void _setNesting(NestingLevel level) {
131 _stack.last.nesting = level;
132 }
133 } 139 }
134
135 /// A level of block nesting.
136 ///
137 /// This represents indentation changes that typically occur at statement or
138 /// block boundaries.
139 class _IndentLevel {
140 /// The number of spaces of indentation at this level.
141 final int indent;
142
143 /// The current expression nesting in this indentation level.
144 NestingLevel nesting = new NestingLevel();
145
146 _IndentLevel(this.indent);
147 }
OLDNEW
« no previous file with comments | « packages/dart_style/lib/src/line_writer.dart ('k') | packages/dart_style/lib/src/rule/argument.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698