| OLD | NEW |
| 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 '../../compiler_new.dart'; | 7 import '../../compiler_new.dart'; |
| 8 import 'source_information.dart'; | 8 import 'source_information.dart'; |
| 9 | 9 |
| 10 /// Listener interface for [CodeOutput] activity. | 10 /// Listener interface for [CodeOutput] activity. |
| 11 abstract class CodeOutputListener { | 11 abstract class CodeOutputListener { |
| 12 /// Called when [text] is added to the output. | 12 /// Called when [text] is added to the output. |
| 13 void onText(String text); | 13 void onText(String text); |
| 14 | 14 |
| 15 /// Called when the output is closed with a final length of [length]. | 15 /// Called when the output is closed with a final length of [length]. |
| 16 void onDone(int length); | 16 void onDone(int length); |
| 17 } | 17 } |
| 18 | 18 |
| 19 /// Interface for a mapping of target offsets to source locations. | 19 /// Interface for a mapping of target offsets to source locations. |
| 20 abstract class SourceLocations { | 20 abstract class SourceLocations { |
| 21 /// The name identifying this source mapping. |
| 22 String get name; |
| 23 |
| 21 /// Adds a [sourceLocation] at the specified [targetOffset]. | 24 /// Adds a [sourceLocation] at the specified [targetOffset]. |
| 22 void addSourceLocation(int targetOffset, SourceLocation sourcePosition); | 25 void addSourceLocation(int targetOffset, SourceLocation sourcePosition); |
| 23 | 26 |
| 24 /// Applies [f] to every target offset and associated source location. | 27 /// Applies [f] to every target offset and associated source location. |
| 25 void forEachSourceLocation( | 28 void forEachSourceLocation( |
| 26 void f(int targetOffset, SourceLocation sourceLocation)); | 29 void f(int targetOffset, SourceLocation sourceLocation)); |
| 27 } | 30 } |
| 28 | 31 |
| 29 abstract class CodeOutput implements SourceLocations { | 32 class _SourceLocationsImpl implements SourceLocations { |
| 33 final String name; |
| 34 final AbstractCodeOutput codeOutput; |
| 35 Map<int, List<SourceLocation>> markers = <int, List<SourceLocation>>{}; |
| 36 |
| 37 _SourceLocationsImpl(this.name, this.codeOutput); |
| 38 |
| 39 @override |
| 40 void addSourceLocation(int targetOffset, SourceLocation sourceLocation) { |
| 41 assert(targetOffset <= codeOutput.length); |
| 42 List<SourceLocation> sourceLocations = |
| 43 markers.putIfAbsent(targetOffset, () => <SourceLocation>[]); |
| 44 sourceLocations.add(sourceLocation); |
| 45 } |
| 46 |
| 47 @override |
| 48 void forEachSourceLocation(void f(int targetOffset, var sourceLocation)) { |
| 49 markers.forEach((int targetOffset, List<SourceLocation> sourceLocations) { |
| 50 for (SourceLocation sourceLocation in sourceLocations) { |
| 51 f(targetOffset, sourceLocation); |
| 52 } |
| 53 }); |
| 54 } |
| 55 |
| 56 void _addSourceLocations(_SourceLocationsImpl other) { |
| 57 assert(name == other.name); |
| 58 if (other.markers.length > 0) { |
| 59 other.markers |
| 60 .forEach((int targetOffset, List<SourceLocation> sourceLocations) { |
| 61 markers |
| 62 .putIfAbsent( |
| 63 codeOutput.length + targetOffset, () => <SourceLocation>[]) |
| 64 .addAll(sourceLocations); |
| 65 }); |
| 66 } |
| 67 } |
| 68 } |
| 69 |
| 70 abstract class SourceLocationsProvider { |
| 71 /// Creates a [SourceLocations] mapping identified by [name] and associates |
| 72 /// it with this code output. |
| 73 SourceLocations createSourceLocations(String name); |
| 74 |
| 75 /// Returns the source location mappings associated with this code output. |
| 76 Iterable<SourceLocations> get sourceLocations; |
| 77 } |
| 78 |
| 79 abstract class CodeOutput implements SourceLocationsProvider { |
| 30 /// Write [text] to this output. | 80 /// Write [text] to this output. |
| 31 /// | 81 /// |
| 32 /// If the output is closed, a [StateError] is thrown. | 82 /// If the output is closed, a [StateError] is thrown. |
| 33 void add(String text); | 83 void add(String text); |
| 34 | 84 |
| 35 /// Adds the content of [buffer] to the output and adds its markers to | 85 /// Adds the content of [buffer] to the output and adds its markers to |
| 36 /// [markers]. | 86 /// [markers]. |
| 37 /// | 87 /// |
| 38 /// If the output is closed, a [StateError] is thrown. | 88 /// If the output is closed, a [StateError] is thrown. |
| 39 void addBuffer(CodeBuffer buffer); | 89 void addBuffer(CodeBuffer buffer); |
| 40 | 90 |
| 41 /// Returns the number of characters currently written to this output. | 91 /// Returns the number of characters currently written to this output. |
| 42 int get length; | 92 int get length; |
| 43 | 93 |
| 44 /// Returns `true` if this output has been closed. | 94 /// Returns `true` if this output has been closed. |
| 45 bool get isClosed; | 95 bool get isClosed; |
| 46 | 96 |
| 47 /// Closes the output. Further writes will cause a [StateError]. | 97 /// Closes the output. Further writes will cause a [StateError]. |
| 48 void close(); | 98 void close(); |
| 49 } | 99 } |
| 50 | 100 |
| 51 abstract class AbstractCodeOutput extends CodeOutput { | 101 abstract class AbstractCodeOutput extends CodeOutput { |
| 52 Map<int, List<SourceLocation>> markers = <int, List<SourceLocation>>{}; | 102 Map<String, _SourceLocationsImpl> sourceLocationsMap = |
| 103 <String, _SourceLocationsImpl>{}; |
| 53 bool isClosed = false; | 104 bool isClosed = false; |
| 54 | 105 |
| 55 void _addInternal(String text); | 106 void _addInternal(String text); |
| 56 | 107 |
| 57 @override | 108 @override |
| 58 void add(String text) { | 109 void add(String text) { |
| 59 if (isClosed) { | 110 if (isClosed) { |
| 60 throw new StateError("Code output is closed. Trying to write '$text'."); | 111 throw new StateError("Code output is closed. Trying to write '$text'."); |
| 61 } | 112 } |
| 62 _addInternal(text); | 113 _addInternal(text); |
| 63 } | 114 } |
| 64 | 115 |
| 65 @override | 116 @override |
| 66 void addBuffer(CodeBuffer other) { | 117 void addBuffer(CodeBuffer other) { |
| 67 if (other.markers.length > 0) { | 118 other.sourceLocationsMap.forEach((String name, _SourceLocationsImpl other) { |
| 68 other.markers | 119 createSourceLocations(name)._addSourceLocations(other); |
| 69 .forEach((int targetOffset, List<SourceLocation> sourceLocations) { | 120 }); |
| 70 markers | |
| 71 .putIfAbsent(length + targetOffset, () => <SourceLocation>[]) | |
| 72 .addAll(sourceLocations); | |
| 73 }); | |
| 74 } | |
| 75 if (!other.isClosed) { | 121 if (!other.isClosed) { |
| 76 other.close(); | 122 other.close(); |
| 77 } | 123 } |
| 78 _addInternal(other.getText()); | 124 _addInternal(other.getText()); |
| 79 } | 125 } |
| 80 | 126 |
| 81 void addSourceLocation(int targetOffset, SourceLocation sourceLocation) { | 127 @override |
| 82 assert(targetOffset <= length); | |
| 83 List<SourceLocation> sourceLocations = | |
| 84 markers.putIfAbsent(targetOffset, () => <SourceLocation>[]); | |
| 85 sourceLocations.add(sourceLocation); | |
| 86 } | |
| 87 | |
| 88 void forEachSourceLocation(void f(int targetOffset, var sourceLocation)) { | |
| 89 markers.forEach((int targetOffset, List<SourceLocation> sourceLocations) { | |
| 90 for (SourceLocation sourceLocation in sourceLocations) { | |
| 91 f(targetOffset, sourceLocation); | |
| 92 } | |
| 93 }); | |
| 94 } | |
| 95 | |
| 96 void close() { | 128 void close() { |
| 97 if (isClosed) { | 129 if (isClosed) { |
| 98 throw new StateError("Code output is already closed."); | 130 throw new StateError("Code output is already closed."); |
| 99 } | 131 } |
| 100 isClosed = true; | 132 isClosed = true; |
| 101 } | 133 } |
| 134 |
| 135 @override |
| 136 Iterable<SourceLocations> get sourceLocations => sourceLocationsMap.values; |
| 137 |
| 138 @override |
| 139 _SourceLocationsImpl createSourceLocations(String name) { |
| 140 return sourceLocationsMap.putIfAbsent( |
| 141 name, () => new _SourceLocationsImpl(name, this)); |
| 142 } |
| 102 } | 143 } |
| 103 | 144 |
| 104 abstract class BufferedCodeOutput { | 145 abstract class BufferedCodeOutput { |
| 105 String getText(); | 146 String getText(); |
| 106 } | 147 } |
| 107 | 148 |
| 108 /// [CodeOutput] using a [StringBuffer] as backend. | 149 /// [CodeOutput] using a [StringBuffer] as backend. |
| 109 class CodeBuffer extends AbstractCodeOutput implements BufferedCodeOutput { | 150 class CodeBuffer extends AbstractCodeOutput implements BufferedCodeOutput { |
| 110 StringBuffer buffer = new StringBuffer(); | 151 StringBuffer buffer = new StringBuffer(); |
| 111 | 152 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 144 } | 185 } |
| 145 | 186 |
| 146 void close() { | 187 void close() { |
| 147 output.close(); | 188 output.close(); |
| 148 super.close(); | 189 super.close(); |
| 149 if (_listeners != null) { | 190 if (_listeners != null) { |
| 150 _listeners.forEach((listener) => listener.onDone(length)); | 191 _listeners.forEach((listener) => listener.onDone(length)); |
| 151 } | 192 } |
| 152 } | 193 } |
| 153 } | 194 } |
| OLD | NEW |