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

Side by Side Diff: pkg/compiler/lib/src/io/code_output.dart

Issue 830703004: Emit to StreamCodeOutput instead of CodeBuffer. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 11 months 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 dart2js.code_output; 5 library dart2js.code_output;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 8
9 import '../source_file.dart';
10
11 import 'source_map_builder.dart'; 9 import 'source_map_builder.dart';
12 10
13 class CodeOutputMarker { 11 class CodeOutputMarker {
14 final int offsetDelta; 12 final int offsetDelta;
15 final SourceFileLocation sourcePosition; 13 final SourceFileLocation sourcePosition;
16 14
17 CodeOutputMarker(this.offsetDelta, this.sourcePosition); 15 CodeOutputMarker(this.offsetDelta, this.sourcePosition);
18 } 16 }
19 17
18 abstract class CodeOutputListener {
19 void onText(String text);
20 void onDone(int length);
21 }
22
20 abstract class CodeOutput { 23 abstract class CodeOutput {
24 /// Write [text] to this output.
25 ///
26 /// If the output is closed, a [StateError] is thrown.
27 void add(String text);
28
29 /// Adds the content of [buffer] to the output and adds its markers to
30 /// [markers].
31 ///
32 /// If the output is closed, a [StateError] is thrown.
33 void addBuffer(CodeBuffer buffer);
34
35 /// Returns the number of characters currently write to this output.
36 int get length;
37
38 /// Returns `true` if this output has been closed.
39 bool get isClosed;
40
41 /// Closes the output. Further writes will cause a [StateError].
42 void close();
43
44 /// Applies [f] to every marker in this output.
45 void forEachSourceLocation(void f(int targetOffset,
46 SourceFileLocation sourceLocation));
47 }
48
49 abstract class AbstractCodeOutput extends CodeOutput {
21 List<CodeOutputMarker> markers = new List<CodeOutputMarker>(); 50 List<CodeOutputMarker> markers = new List<CodeOutputMarker>();
22
23 int lastBufferOffset = 0; 51 int lastBufferOffset = 0;
24 int mappedRangeCounter = 0; 52 int mappedRangeCounter = 0;
53 bool isClosed = false;
25 54
26 int get length; 55 void _addInternal(String text);
27 56
28 void _writeInternal(String text); 57 @override
29 58 void add(String text) {
30 /// Converts [object] to a string and adds it to the buffer. If [object] is a 59 if (isClosed) {
31 /// [CodeBuffer], adds its markers to [markers]. 60 throw new StateError("Code output is closed. Trying to write '$text'.");
32 void write(var object) {
33 if (object is CodeBuffer) {
34 addBuffer(object);
35 return;
36 } 61 }
37 if (mappedRangeCounter == 0) setSourceLocation(null); 62 if (mappedRangeCounter == 0) setSourceLocation(null);
38 _writeInternal(object); 63 _addInternal(text);
39 } 64 }
40 65
66 @override
41 void addBuffer(CodeBuffer other) { 67 void addBuffer(CodeBuffer other) {
42 if (other.markers.length > 0) { 68 if (other.markers.length > 0) {
43 CodeOutputMarker firstMarker = other.markers[0]; 69 CodeOutputMarker firstMarker = other.markers[0];
44 int offsetDelta = 70 int offsetDelta =
45 length + firstMarker.offsetDelta - lastBufferOffset; 71 length + firstMarker.offsetDelta - lastBufferOffset;
46 markers.add(new CodeOutputMarker(offsetDelta, 72 markers.add(new CodeOutputMarker(offsetDelta,
47 firstMarker.sourcePosition)); 73 firstMarker.sourcePosition));
48 for (int i = 1; i < other.markers.length; ++i) { 74 for (int i = 1; i < other.markers.length; ++i) {
49 markers.add(other.markers[i]); 75 markers.add(other.markers[i]);
50 } 76 }
51 lastBufferOffset = length + other.lastBufferOffset; 77 lastBufferOffset = length + other.lastBufferOffset;
52 } 78 }
53 _writeInternal(other.getText()); 79 if (!other.isClosed) {
80 other.close();
81 }
82 _addInternal(other.getText());
54 } 83 }
55 84
56 void beginMappedRange() { 85 void beginMappedRange() {
57 ++mappedRangeCounter; 86 ++mappedRangeCounter;
58 } 87 }
59 88
60 void endMappedRange() { 89 void endMappedRange() {
61 assert(mappedRangeCounter > 0); 90 assert(mappedRangeCounter > 0);
62 --mappedRangeCounter; 91 --mappedRangeCounter;
63 } 92 }
64 93
65 void setSourceLocation(SourceFileLocation sourcePosition) { 94 void setSourceLocation(SourceFileLocation sourcePosition) {
66 if (sourcePosition == null) { 95 if (sourcePosition == null) {
67 if (markers.length > 0 && markers.last.sourcePosition == null) return; 96 if (markers.length > 0 && markers.last.sourcePosition == null) return;
68 } 97 }
69 int offsetDelta = length - lastBufferOffset; 98 int offsetDelta = length - lastBufferOffset;
70 markers.add(new CodeOutputMarker(offsetDelta, sourcePosition)); 99 markers.add(new CodeOutputMarker(offsetDelta, sourcePosition));
71 lastBufferOffset = length; 100 lastBufferOffset = length;
72 } 101 }
73 102
74 void forEachSourceLocation(void f(int targetOffset, var sourcePosition)) { 103 void forEachSourceLocation(void f(int targetOffset, var sourcePosition)) {
75 int targetOffset = 0; 104 int targetOffset = 0;
76 markers.forEach((marker) { 105 markers.forEach((marker) {
77 targetOffset += marker.offsetDelta; 106 targetOffset += marker.offsetDelta;
78 f(targetOffset, marker.sourcePosition); 107 f(targetOffset, marker.sourcePosition);
79 }); 108 });
80 } 109 }
110
111 void close() {
112 if (isClosed) {
113 throw new StateError("Code output is already closed.");
114 }
115 isClosed = true;
116 }
81 } 117 }
82 118
83 /// [CodeOutput] using a [StringBuffer] as backend. 119 /// [CodeOutput] using a [StringBuffer] as backend.
84 class CodeBuffer extends CodeOutput implements StringBuffer { 120 class CodeBuffer extends AbstractCodeOutput {
85 StringBuffer buffer = new StringBuffer(); 121 StringBuffer buffer = new StringBuffer();
86 122
87 @override 123 @override
88 void _writeInternal(String text) { 124 void _addInternal(String text) {
89 buffer.write(text); 125 buffer.write(text);
90 } 126 }
91 127
92 @override 128 @override
93 int get length => buffer.length; 129 int get length => buffer.length;
94 130
95 @override
96 bool get isEmpty => buffer.isEmpty;
97
98 @override
99 bool get isNotEmpty => buffer.isNotEmpty;
100
101 @override
102 void writeAll(Iterable<Object> objects, [String separator = ""]) {
103 Iterator iterator = objects.iterator;
104 if (!iterator.moveNext()) return;
105 if (separator.isEmpty) {
106 do {
107 write(iterator.current);
108 } while (iterator.moveNext());
109 } else {
110 write(iterator.current);
111 while (iterator.moveNext()) {
112 write(separator);
113 write(iterator.current);
114 }
115 }
116 }
117
118 @override
119 void writeln([var object = ""]) {
120 write(object);
121 write("\n");
122 }
123
124 @override
125 void writeCharCode(int charCode) {
126 buffer.writeCharCode(charCode);
127 }
128
129 @override
130 void clear() {
131 buffer = new StringBuffer();
132 markers.clear();
133 lastBufferOffset = 0;
134 }
135
136 String toString() {
137 throw "Don't use CodeBuffer.toString() since it drops sourcemap data.";
138 }
139
140 String getText() { 131 String getText() {
141 return buffer.toString(); 132 return buffer.toString();
142 } 133 }
134
135 String toString() => getText();
floitsch 2015/01/09 16:35:19 I thought we wanted to avoid this, so that one doe
Johnni Winther 2015/01/13 08:53:05 We do. Reverted.
143 } 136 }
144 137
145 /// [CodeOutput] using a [CompilationOutput] as backend. 138 /// [CodeOutput] using a [CompilationOutput] as backend.
146 class StreamCodeOutput extends CodeOutput { 139 class StreamCodeOutput extends AbstractCodeOutput {
147 int length = 0; 140 int length = 0;
148 final EventSink<String> output; 141 final EventSink<String> output;
142 final List<CodeOutputListener> _listeners;
149 143
150 StreamCodeOutput(this.output); 144 StreamCodeOutput(this.output, [this._listeners]);
151 145
152 @override 146 @override
153 void _writeInternal(String text) { 147 void _addInternal(String text) {
154 output.add(text); 148 output.add(text);
155 length += text.length; 149 length += text.length;
150 if (_listeners != null) {
151 _listeners.forEach((listener) => listener.onText(text));
152 }
156 } 153 }
157 154
158 void close() { 155 void close() {
159 output.close(); 156 output.close();
157 super.close();
158 if (_listeners != null) {
159 _listeners.forEach((listener) => listener.onDone(length));
160 }
160 } 161 }
161 } 162 }
162
163 /// [StreamCodeSink] that collects line information.
164 class LineColumnCodeOutput extends StreamCodeOutput
165 implements LineColumnProvider {
166 int lastLineStart = 0;
167 List<int> lineStarts = <int>[0];
168
169 LineColumnCodeOutput(EventSink<String> output) : super(output);
170
171 @override
172 void _writeInternal(String text) {
173 int offset = lastLineStart;
174 int index = 0;
175 while (index < text.length) {
176 // Unix uses '\n' and Windows uses '\r\n', so this algorithm works for
177 // both platforms.
178 index = text.indexOf('\n', index) + 1;
179 if (index <= 0) break;
180 lastLineStart = offset + index;
181 lineStarts.add(lastLineStart);
182 }
183 super._writeInternal(text);
184 }
185
186 @override
187 int getLine(int offset) {
188 List<int> starts = lineStarts;
189 if (offset < 0|| starts.last <= offset) {
190 throw 'bad position #$offset in buffer with length ${length}.';
191 }
192 int first = 0;
193 int count = starts.length;
194 while (count > 1) {
195 int step = count ~/ 2;
196 int middle = first + step;
197 int lineStart = starts[middle];
198 if (offset < lineStart) {
199 count = step;
200 } else {
201 first = middle;
202 count -= step;
203 }
204 }
205 return first;
206 }
207
208 @override
209 int getColumn(int line, int offset) {
210 return offset - lineStarts[line];
211 }
212
213 @override
214 void close() {
215 lineStarts.add(length);
216 super.close();
217 }
218 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698