Chromium Code Reviews| Index: pkg/compiler/lib/src/io/code_output.dart |
| diff --git a/pkg/compiler/lib/src/io/code_output.dart b/pkg/compiler/lib/src/io/code_output.dart |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..9fb2302639a4c85370cc42566b760d4650befc0c |
| --- /dev/null |
| +++ b/pkg/compiler/lib/src/io/code_output.dart |
| @@ -0,0 +1,206 @@ |
| +// Copyright (c) 2012, 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. |
| + |
| +library dart2js.code_output; |
| + |
| +import 'dart:async'; |
| + |
| +import '../source_file.dart'; |
| + |
| +import 'source_map_builder.dart'; |
| + |
| +abstract class CodeOutput { |
| + List<CodeOutputMarker> markers = new List<CodeOutputMarker>(); |
| + |
| + int lastBufferOffset = 0; |
| + int mappedRangeCounter = 0; |
| + |
| + int get length; |
| + |
| + void writeInternal(String text); |
|
floitsch
2014/12/29 18:36:35
private?
Johnni Winther
2014/12/30 11:05:18
Done.
|
| + |
| + /// Converts [object] to a string and adds it to the buffer. If [object] is a |
| + /// [CodeBuffer], adds its markers to [markers]. |
| + void write(var object) { |
| + if (object is CodeBuffer) { |
| + return addBuffer(object); |
|
floitsch
2014/12/29 18:36:35
Don't return from a void function. (even if the ta
Johnni Winther
2014/12/30 11:05:18
Done.
|
| + } |
| + if (mappedRangeCounter == 0) setSourceLocation(null); |
| + writeInternal(object); |
| + } |
| + |
| + void addBuffer(CodeBuffer other) { |
| + if (other.markers.length > 0) { |
| + CodeOutputMarker firstMarker = other.markers[0]; |
| + int offsetDelta = |
| + length + firstMarker.offsetDelta - lastBufferOffset; |
| + markers.add(new CodeOutputMarker(offsetDelta, |
| + firstMarker.sourcePosition)); |
| + for (int i = 1; i < other.markers.length; ++i) { |
| + markers.add(other.markers[i]); |
| + } |
| + lastBufferOffset = length + other.lastBufferOffset; |
| + } |
| + writeInternal(other.getText()); |
| + } |
| + |
| + void beginMappedRange() { |
| + ++mappedRangeCounter; |
| + } |
| + |
| + void endMappedRange() { |
| + assert(mappedRangeCounter > 0); |
| + --mappedRangeCounter; |
| + } |
| + |
| + void setSourceLocation(SourceFileLocation sourcePosition) { |
| + if (sourcePosition == null) { |
| + if (markers.length > 0 && markers.last.sourcePosition == null) return; |
| + } |
| + int offsetDelta = length - lastBufferOffset; |
| + markers.add(new CodeOutputMarker(offsetDelta, sourcePosition)); |
| + lastBufferOffset = length; |
| + } |
| + |
| + void forEachSourceLocation(void f(int targetOffset, var sourcePosition)) { |
| + int targetOffset = 0; |
| + markers.forEach((marker) { |
| + targetOffset += marker.offsetDelta; |
| + f(targetOffset, marker.sourcePosition); |
| + }); |
| + } |
| +} |
| + |
| +/// [CodeOutput] using a [StringBuffer] as backend. |
| +class CodeBuffer extends CodeOutput implements StringBuffer { |
| + StringBuffer buffer = new StringBuffer(); |
| + |
| + void writeInternal(String text) { |
| + buffer.write(text); |
| + } |
| + |
| + int get length => buffer.length; |
| + |
| + bool get isEmpty => buffer.isEmpty; |
| + |
| + bool get isNotEmpty => buffer.isNotEmpty; |
| + |
| + void writeAll(Iterable<Object> objects, [String separator = ""]) { |
| + Iterator iterator = objects.iterator; |
| + if (!iterator.moveNext()) return; |
| + if (separator.isEmpty) { |
| + do { |
| + write(iterator.current); |
| + } while (iterator.moveNext()); |
| + } else { |
| + write(iterator.current); |
| + while (iterator.moveNext()) { |
| + write(separator); |
| + write(iterator.current); |
| + } |
| + } |
| + } |
| + |
| + void writeln([var object = ""]) { |
| + write(object); |
| + write("\n"); |
| + } |
| + |
| + void writeCharCode(int charCode) { |
| + buffer.writeCharCode(charCode); |
| + } |
| + |
| + void clear() { |
| + buffer = new StringBuffer(); |
| + markers.clear(); |
| + lastBufferOffset = 0; |
| + } |
| + |
| + String toString() { |
| + throw "Don't use CodeBuffer.toString() since it drops sourcemap data."; |
| + } |
| + |
| + String getText() { |
| + return buffer.toString(); |
| + } |
| +} |
| + |
| +/// [CodeOutput] using a [CompilationOutput] as backend. |
| +class StreamCodeOutput extends CodeOutput { |
| + int length = 0; |
| + final EventSink<String> output; |
| + |
| + StreamCodeOutput(this.output); |
| + |
| + void writeInternal(String text) { |
| + output.add(text); |
| + length += text.length; |
| + } |
| + |
| + void close() { |
| + output.close(); |
| + } |
| +} |
| + |
| +/// [StreamCodeSink] that collects line information. |
| +class LineColumnCodeOutput extends StreamCodeOutput |
| + implements LineColumnProvider { |
| + int lastLineStart = 0; |
| + List<int> lineStarts = <int>[0]; |
| + |
| + LineColumnCodeOutput(EventSink<String> output) : super(output); |
| + |
| + @override |
| + void writeInternal(String text) { |
| + int offset = lastLineStart; |
| + int index = 0; |
| + while (index < text.length) { |
| + // Unix uses '\n' and Windows uses '\r\n', so this algorithm works for |
| + // both platforms. |
| + index = text.indexOf('\n', index) + 1; |
| + if (index <= 0) break; |
| + lastLineStart = offset + index; |
| + lineStarts.add(lastLineStart); |
| + } |
| + super.writeInternal(text); |
| + } |
| + |
| + int getLine(int offset) { |
| + List<int> starts = lineStarts; |
| + if (offset < 0|| starts.last <= offset) { |
| + throw 'bad position #$offset in buffer with length ${length}.'; |
| + } |
| + int first = 0; |
| + int count = starts.length; |
| + while (count > 1) { |
| + int step = count ~/ 2; |
| + int middle = first + step; |
| + int lineStart = starts[middle]; |
| + if (offset < lineStart) { |
| + count = step; |
| + } else { |
| + first = middle; |
| + count -= step; |
| + } |
| + } |
| + return first; |
| + } |
| + |
| + int getColumn(int line, int offset) { |
| + return offset - lineStarts[line]; |
| + } |
| + |
| + @override |
| + void close() { |
| + lineStarts.add(length); |
| + super.close(); |
| + } |
| +} |
| + |
| +class CodeOutputMarker { |
|
floitsch
2014/12/29 18:36:35
Move up?
Johnni Winther
2014/12/30 11:05:18
Done.
|
| + final int offsetDelta; |
| + final SourceFileLocation sourcePosition; |
| + |
| + CodeOutputMarker(this.offsetDelta, this.sourcePosition); |
| +} |