Remove support for the old Span classes from source_maps. This releases source_maps 0.10.0, code_transformers 0.2.0+2, observe 0.11.0+3, and polymer 0.12.0+4. BUG=19930 R=sigmund@google.com Review URL: https://codereview.chromium.org//421723004 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/source_maps@38803 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/pkgs/source_maps/lib/builder.dart b/pkgs/source_maps/lib/builder.dart index 494a6b6..091e220 100644 --- a/pkgs/source_maps/lib/builder.dart +++ b/pkgs/source_maps/lib/builder.dart
@@ -9,9 +9,10 @@ import 'dart:convert'; +import 'package:source_span/source_span.dart'; + import 'parser.dart'; -import 'span.dart'; -import 'src/span_wrapper.dart'; +import 'src/source_map_span.dart'; /// Builds a source map given a set of mappings. class SourceMapBuilder { @@ -19,39 +20,33 @@ final List<Entry> _entries = <Entry>[]; /// Adds an entry mapping the [targetOffset] to [source]. - /// - /// [source] can be either a [Location] or a [SourceLocation]. Using a - /// [Location] is deprecated and will be unsupported in version 0.10.0. - void addFromOffset(source, targetFile, int targetOffset, String identifier) { + void addFromOffset(SourceLocation source, SourceFile targetFile, + int targetOffset, String identifier) { if (targetFile == null) { throw new ArgumentError('targetFile cannot be null'); } - _entries.add(new Entry(source, - new FileLocation(targetFile, targetOffset), identifier)); + _entries.add( + new Entry(source, targetFile.location(targetOffset), identifier)); } /// Adds an entry mapping [target] to [source]. /// - /// [source] and [target] can be either a [Span] or a [SourceSpan]. Using a - /// [Span] is deprecated and will be unsupported in version 0.10.0. - /// - /// If [isIdentifier] is true, this entry is considered to represent an - /// identifier whose value will be stored in the source map. - void addSpan(source, target, {bool isIdentifier}) { - source = SpanWrapper.wrap(source); - target = SpanWrapper.wrap(target); - if (isIdentifier == null) isIdentifier = source.isIdentifier; + /// If [isIdentifier] is true or if [target] is a [SourceMapSpan] with + /// `isIdentifier` set to true, this entry is considered to represent an + /// identifier whose value will be stored in the source map. [isIdenfier] + /// takes precedence over [target]'s `isIdentifier` value. + void addSpan(SourceSpan source, SourceSpan target, {bool isIdentifier}) { + if (isIdentifier == null) { + isIdentifier = source is SourceMapSpan ? source.isIdentifier : false; + } var name = isIdentifier ? source.text : null; _entries.add(new Entry(source.start, target.start, name)); } /// Adds an entry mapping [target] to [source]. - /// - /// [source] and [target] can be either a [Location] or a [SourceLocation]. - /// Using a [Location] is deprecated and will be unsupported in version - /// 0.10.0. - void addLocation(source, target, String identifier) { + void addLocation(SourceLocation source, SourceLocation target, + String identifier) { _entries.add(new Entry(source, target, identifier)); } @@ -67,22 +62,16 @@ /// An entry in the source map builder. class Entry implements Comparable { /// Span denoting the original location in the input source file - final Location source; + final SourceLocation source; /// Span indicating the corresponding location in the target file. - final Location target; + final SourceLocation target; /// An identifier name, when this location is the start of an identifier. final String identifierName; /// Creates a new [Entry] mapping [target] to [source]. - /// - /// [source] and [target] can be either a [Location] or a [SourceLocation]. - /// Using a [Location] is deprecated and will be unsupported in version - /// 0.10.0. - Entry(source, target, this.identifierName) - : source = LocationWrapper.wrap(source), - target = LocationWrapper.wrap(target); + Entry(this.source, this.target, this.identifierName); /// Implements [Comparable] to ensure that entries are ordered by their /// location in the target file. We sort primarily by the target offset @@ -91,7 +80,8 @@ int compareTo(Entry other) { int res = target.compareTo(other.target); if (res != 0) return res; - res = source.sourceUrl.compareTo(other.source.sourceUrl); + res = source.sourceUrl.toString().compareTo( + other.source.sourceUrl.toString()); if (res != 0) return res; return source.compareTo(other.source); }
diff --git a/pkgs/source_maps/lib/parser.dart b/pkgs/source_maps/lib/parser.dart index c18a1d6..d67a65e 100644 --- a/pkgs/source_maps/lib/parser.dart +++ b/pkgs/source_maps/lib/parser.dart
@@ -8,9 +8,10 @@ import 'dart:collection'; import 'dart:convert'; +import 'package:source_span/source_span.dart'; + import 'builder.dart' as builder; -import 'span.dart'; -import 'src/span_wrapper.dart'; +import 'src/source_map_span.dart'; import 'src/utils.dart'; import 'src/vlq.dart'; @@ -49,19 +50,11 @@ /// A mapping parsed out of a source map. abstract class Mapping { /// Returns the span associated with [line] and [column]. - /// - /// The values of [files] can be either `source_map` [SourceFile]s or - /// `source_span` `SourceFile`s. Using `source_map` [SourceFile]s is - /// deprecated and will be unsupported in version 0.10.0. - Span spanFor(int line, int column, {Map<String, dynamic> files}); + SourceMapSpan spanFor(int line, int column, {Map<String, SourceFile> files}); /// Returns the span associated with [location]. - /// - /// The values of [files] may be either `source_map` [SourceFile]s or - /// `source_span` `SourceFile`s. Using `source_map` [SourceFile]s is - /// deprecated and will be unsupported in version 0.10.0. - Span spanForLocation(location, {Map<String, dynamic> files}) { - location = LocationWrapper.wrap(location); + SourceMapSpan spanForLocation(SourceLocation location, + {Map<String, SourceFile> files}) { return spanFor(location.line, location.column, files: files); } } @@ -124,7 +117,7 @@ return _lineStart.length - 1; } - Span spanFor(int line, int column, {Map<String, dynamic> files}) { + SourceMapSpan spanFor(int line, int column, {Map<String, SourceFile> files}) { int index = _indexFor(line, column); return _maps[index].spanFor( line - _lineStart[index], column - _columnStart[index], files: files); @@ -191,8 +184,9 @@ if (sourceEntry.source == null) { targetEntries.add(new TargetEntry(sourceEntry.target.column)); } else { + var sourceUrl = sourceEntry.source.sourceUrl; var urlId = urls.putIfAbsent( - sourceEntry.source.sourceUrl, () => urls.length); + sourceUrl == null ? '' : sourceUrl.toString(), () => urls.length); var srcNameId = sourceEntry.identifierName == null ? null : names.putIfAbsent(sourceEntry.identifierName, () => names.length); targetEntries.add(new TargetEntry( @@ -363,7 +357,7 @@ return (index <= 0) ? null : entries[index - 1]; } - Span spanFor(int line, int column, {Map<String, dynamic> files}) { + SourceMapSpan spanFor(int line, int column, {Map<String, SourceFile> files}) { var entry = _findColumn(line, column, _findLine(line)); if (entry == null || entry.sourceUrlId == null) return null; var url = urls[entry.sourceUrlId]; @@ -371,21 +365,24 @@ url = '${sourceRoot}${url}'; } if (files != null && files[url] != null) { - var file = SourceFileWrapper.wrap(files[url]); + var file = files[url]; var start = file.getOffset(entry.sourceLine, entry.sourceColumn); if (entry.sourceNameId != null) { var text = names[entry.sourceNameId]; - return new FileSpan(files[url], start, start + text.length, true); + return new SourceMapFileSpan( + files[url].span(start, start + text.length), + isIdentifier: true); } else { - return new FileSpan(files[url], start); + return new SourceMapFileSpan(files[url].location(start).pointSpan()); } } else { + var start = new SourceLocation(0, + sourceUrl: url, line: entry.sourceLine, column: entry.sourceColumn); // Offset and other context is not available. if (entry.sourceNameId != null) { - return new FixedSpan(url, 0, entry.sourceLine, entry.sourceColumn, - text: names[entry.sourceNameId], isIdentifier: true); + return new SourceMapSpan.identifier(start, names[entry.sourceNameId]); } else { - return new FixedSpan(url, 0, entry.sourceLine, entry.sourceColumn); + return new SourceMapSpan(start, start, ''); } } }
diff --git a/pkgs/source_maps/lib/printer.dart b/pkgs/source_maps/lib/printer.dart index aa18bd7..906e260 100644 --- a/pkgs/source_maps/lib/printer.dart +++ b/pkgs/source_maps/lib/printer.dart
@@ -5,11 +5,10 @@ /// Contains a code printer that generates code by recording the source maps. library source_maps.printer; -import 'package:source_span/source_span.dart' as source_span; +import 'package:source_span/source_span.dart'; import 'builder.dart'; -import 'span.dart'; -import 'src/span_wrapper.dart'; +import 'src/source_map_span.dart'; const int _LF = 10; const int _CR = 13; @@ -24,7 +23,7 @@ String get map => _maps.toJson(filename); /// Current source location mapping. - Location _loc; + SourceLocation _loc; /// Current line in the buffer; int _line = 0; @@ -49,11 +48,12 @@ _line++; _column = 0; if (projectMarks && _loc != null) { - if (_loc is FixedLocation) { - mark(new FixedLocation(0, _loc.sourceUrl, _loc.line + 1, 0)); - } else if (_loc is FileLocation) { + if (_loc is FileLocation) { var file = (_loc as FileLocation).file; - mark(new FileLocation(file, file.getOffset(_loc.line + 1, 0))); + mark(file.location(file.getOffset(_loc.line + 1))); + } else { + mark(new SourceLocation(0, + sourceUrl: _loc.sourceUrl, line: _loc.line + 1, column: 0)); } } } else { @@ -72,21 +72,23 @@ } /// Marks that the current point in the target file corresponds to the [mark] - /// in the source file, which can be either a [Location] or a [Span]. When the - /// mark is an identifier's Span, this also records the name of the identifier - /// in the source map information. + /// in the source file, which can be either a [SourceLocation] or a + /// [SourceSpan]. When the mark is a [SourceMapSpan] with `isIdentifier` set, + /// this also records the name of the identifier in the source map + /// information. void mark(mark) { var loc; var identifier = null; - if (mark is Location || mark is source_span.SourceLocation) { - loc = LocationWrapper.wrap(mark); - } else if (mark is Span || mark is source_span.SourceSpan) { - mark = SpanWrapper.wrap(mark); + if (mark is SourceLocation) { + loc = mark; + } else if (mark is SourceSpan) { loc = mark.start; - if (mark.isIdentifier) identifier = mark.text; + if (mark is SourceMapSpan && mark.isIdentifier) identifier = mark.text; } - _maps.addLocation(loc, - new FixedLocation(_buff.length, null, _line, _column), identifier); + _maps.addLocation( + loc, + new SourceLocation(_buff.length, line: _line, column: _column), + identifier); _loc = loc; } } @@ -101,7 +103,8 @@ class NestedPrinter implements NestedItem { /// Items recoded by this printer, which can be [String] literals, - /// [NestedItem]s, and source map information like [Location] and [Span]. + /// [NestedItem]s, and source map information like [SourceLocation] and + /// [SourceSpan]. List _items = []; /// Internal buffer to merge consecutive strings added to this printer. @@ -128,19 +131,16 @@ /// location of [object] in the original input. Only one, [location] or /// [span], should be provided at a time. /// - /// [location] can be either a [Location] or a [SourceLocation]. [span] can be - /// either a [Span] or a [SourceSpan]. Using a [Location] or a [Span] is - /// deprecated and will be unsupported in version 0.10.0. - /// /// Indicate [isOriginal] when [object] is copied directly from the user code. /// Setting [isOriginal] will make this printer propagate source map locations /// on every line-break. - void add(object, {location, span, bool isOriginal: false}) { + void add(object, {SourceLocation location, SourceSpan span, + bool isOriginal: false}) { if (object is! String || location != null || span != null || isOriginal) { _flush(); assert(location == null || span == null); - if (location != null) _items.add(LocationWrapper.wrap(location)); - if (span != null) _items.add(SpanWrapper.wrap(span)); + if (location != null) _items.add(location); + if (span != null) _items.add(span); if (isOriginal) _items.add(_ORIGINAL); } @@ -164,16 +164,12 @@ /// The [location] and [span] parameters indicate the corresponding source map /// location of [object] in the original input. Only one, [location] or /// [span], should be provided at a time. - /// - /// [location] can be either a [Location] or a [SourceLocation]. [span] can be - /// either a [Span] or a [SourceSpan]. Using a [Location] or a [Span] is - /// deprecated and will be unsupported in version 0.10.0. - void addLine(String line, {location, span}) { + void addLine(String line, {SourceLocation location, SourceSpan span}) { if (location != null || span != null) { _flush(); assert(location == null || span == null); - if (location != null) _items.add(LocationWrapper.wrap(location)); - if (span != null) _items.add(SpanWrapper.wrap(span)); + if (location != null) _items.add(location); + if (span != null) _items.add(span); } if (line == null) return; if (line != '') { @@ -235,7 +231,7 @@ } else if (item is String) { printer.add(item, projectMarks: propagate); propagate = false; - } else if (item is Location || item is Span) { + } else if (item is SourceLocation || item is SourceSpan) { printer.mark(item); } else if (item == _ORIGINAL) { // we insert booleans when we are about to quote text that was copied
diff --git a/pkgs/source_maps/lib/refactor.dart b/pkgs/source_maps/lib/refactor.dart index 47ce2ed..a33b86b 100644 --- a/pkgs/source_maps/lib/refactor.dart +++ b/pkgs/source_maps/lib/refactor.dart
@@ -8,9 +8,9 @@ /// [guessIndent] helps to guess the appropriate indentiation for the new code. library source_maps.refactor; -import 'span.dart'; +import 'package:source_span/source_span.dart'; + import 'printer.dart'; -import 'src/span_wrapper.dart'; /// Editable text transaction. /// @@ -22,12 +22,7 @@ final _edits = <_TextEdit>[]; /// Creates a new transaction. - /// - /// [file] can be either a `source_map` [SourceFile] or a `source_span` - /// `SourceFile`. Using a `source_map` [SourceFile] is deprecated and will be - /// unsupported in version 0.10.0. - TextEditTransaction(this.original, file) - : file = SourceFileWrapper.wrap(file); + TextEditTransaction(this.original, this.file); bool get hasEdits => _edits.length > 0; @@ -38,8 +33,8 @@ _edits.add(new _TextEdit(begin, end, replacement)); } - /// Create a source map [Location] for [offset]. - Location _loc(int offset) => + /// Create a source map [SourceLocation] for [offset]. + SourceLocation _loc(int offset) => file != null ? file.location(offset) : null; /// Applies all pending [edit]s and returns a [NestedPrinter] containing the @@ -62,7 +57,7 @@ for (var edit in _edits) { if (consumed > edit.begin) { var sb = new StringBuffer(); - sb..write(file.location(edit.begin).formatString) + sb..write(file.location(edit.begin).toolString) ..write(': overlapping edits. Insert at offset ') ..write(edit.begin) ..write(' but have consumed ')
diff --git a/pkgs/source_maps/lib/source_maps.dart b/pkgs/source_maps/lib/source_maps.dart index 2d4a4cc..9531903 100644 --- a/pkgs/source_maps/lib/source_maps.dart +++ b/pkgs/source_maps/lib/source_maps.dart
@@ -11,7 +11,8 @@ /// ..add(inputSpan3, outputSpan3) /// .toJson(outputFile); /// -/// Use the [Span] and [SourceFile] classes to specify span locations. +/// Use the source_span package's [SourceSpan] and [SourceFile] classes to +/// specify span locations. /// /// Parse a source map using [parse], and call `spanFor` on the returned mapping /// object. For example: @@ -40,4 +41,4 @@ export "parser.dart"; export "printer.dart"; export "refactor.dart"; -export "span.dart"; +export 'src/source_map_span.dart';
diff --git a/pkgs/source_maps/lib/span.dart b/pkgs/source_maps/lib/span.dart deleted file mode 100644 index a21e893..0000000 --- a/pkgs/source_maps/lib/span.dart +++ /dev/null
@@ -1,404 +0,0 @@ -// Copyright (c) 2013, 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. - -/// Dart classes representing the souce spans and source files. -library source_maps.span; - -import 'dart:math' show min, max; - -import 'package:path/path.dart' as p; - -import 'src/utils.dart'; - -/// A simple class that describe a segment of source text. -@Deprecated("Use the source_span package instead.") -abstract class Span implements Comparable { - /// The start location of this span. - final Location start; - - /// The end location of this span, exclusive. - final Location end; - - /// Url of the source (typically a file) containing this span. - String get sourceUrl => start.sourceUrl; - - /// The length of this span, in characters. - int get length => end.offset - start.offset; - - /// The source text for this span, if available. - String get text; - - /// Whether [text] corresponds to an identifier symbol. - final bool isIdentifier; - - Span(this.start, this.end, bool isIdentifier) - : isIdentifier = isIdentifier != null ? isIdentifier : false { - _checkRange(); - } - - /// Creates a new span that is the union of two existing spans [start] and - /// [end]. Note that the resulting span might contain some positions that were - /// not in either of the original spans if [start] and [end] are disjoint. - Span.union(Span start, Span end) - : start = start.start, end = end.end, isIdentifier = false { - _checkRange(); - } - - void _checkRange() { - if (start.offset < 0) throw new ArgumentError('start $start must be >= 0'); - if (end.offset < start.offset) { - throw new ArgumentError('end $end must be >= start $start'); - } - } - - /// Compares two spans. If the spans are not in the same source, this method - /// generates an error. - int compareTo(Span other) { - int d = start.compareTo(other.start); - return d == 0 ? end.compareTo(other.end) : d; - } - - /// Gets the location in standard printed form `filename:line:column`, where - /// line and column are adjusted by 1 to match the convention in editors. - String get formatLocation => start.formatString; - - String getLocationMessage(String message, - {bool useColors: false, String color}) { - var source = start.sourceUrl == null ? '' : - ' of ${p.prettyUri(start.sourceUrl)}'; - return 'line ${start.line + 1}, column ${start.column + 1}$source: ' + - message; - } - - bool operator ==(Span other) => - sourceUrl == other.sourceUrl && start == other.start && end == other.end; - - int get hashCode => sourceUrl.hashCode + start.offset + (31 * length); - - String toString() => '<$runtimeType: $start $end $formatLocation $text>'; -} - -/// A location in the source text -@Deprecated("Use the source_span package instead.") -abstract class Location implements Comparable { - /// Url of the source containing this span. - String get sourceUrl; - - /// The offset of this location, 0-based. - final int offset; - - /// The 0-based line in the source of this location. - int get line; - - /// The 0-based column in the source of this location. - int get column; - - Location(this.offset); - - /// Compares two locations. If the locations are not in the same source, this - /// method generates an error. - int compareTo(Location other) { - if (sourceUrl != other.sourceUrl) { - throw new ArgumentError('can only compare locations of the same source'); - } - return offset - other.offset; - } - - bool operator ==(Location other) => - sourceUrl == other.sourceUrl && offset == other.offset; - - int get hashCode => sourceUrl.hashCode + offset; - - String toString() => '(Location $offset)'; - String get formatString => '$sourceUrl:${line + 1}:${column + 1}'; -} - -/// Implementation of [Location] with fixed values given at allocation time. -@Deprecated("Use the source_span package instead.") -class FixedLocation extends Location { - final String sourceUrl; - final int line; - final int column; - - FixedLocation(int offset, this.sourceUrl, this.line, this.column) - : super(offset); -} - -/// Implementation of [Span] where all the values are given at allocation time. -@Deprecated("Use the source_span package instead.") -class FixedSpan extends Span { - /// The source text for this span, if available. - final String text; - - /// Creates a span which starts and end in the same line. - FixedSpan(String sourceUrl, int start, int line, int column, - {String text: '', bool isIdentifier: false}) - : text = text, super(new FixedLocation(start, sourceUrl, line, column), - new FixedLocation(start + text.length, sourceUrl, line, - column + text.length), - isIdentifier); -} - -/// [Location] with values computed from an underling [SourceFile]. -@Deprecated("Use the source_span package instead.") -class FileLocation extends Location { - /// The source file containing this location. - final SourceFile file; - - String get sourceUrl => file.url; - int get line => file.getLine(offset); - int get column => file.getColumn(line, offset); - - FileLocation(this.file, int offset): super(offset); -} - -/// [Span] where values are computed from an underling [SourceFile]. -@Deprecated("Use the source_span package instead.") -class FileSpan extends Span { - /// The source file containing this span. - final SourceFile file; - - /// The source text for this span, if available. - String get text => file.getText(start.offset, end.offset); - - factory FileSpan(SourceFile file, int start, - [int end, bool isIdentifier = false]) { - var startLoc = new FileLocation(file, start); - var endLoc = end == null ? startLoc : new FileLocation(file, end); - return new FileSpan.locations(startLoc, endLoc, isIdentifier); - } - - FileSpan.locations(FileLocation start, FileLocation end, - bool isIdentifier) - : file = start.file, super(start, end, isIdentifier); - - /// Creates a new span that is the union of two existing spans [start] and - /// [end]. Note that the resulting span might contain some positions that were - /// not in either of the original spans if [start] and [end] are disjoint. - FileSpan.union(FileSpan start, FileSpan end) - : file = start.file, super.union(start, end) { - if (start.file != end.file) { - throw new ArgumentError('start and end must be from the same file'); - } - } - - String getLocationMessage(String message, - {bool useColors: false, String color}) { - return file.getLocationMessage(message, start.offset, end.offset, - useColors: useColors, color: color); - } -} - -// Constants to determine end-of-lines. -const int _LF = 10; -const int _CR = 13; - -// Color constants used for generating messages. -const String _RED_COLOR = '\u001b[31m'; -const String _NO_COLOR = '\u001b[0m'; - -/// Stores information about a source file, to permit computation of the line -/// and column. Also contains a nice default error message highlighting the code -/// location. -@Deprecated("Use the source_span package instead.") -class SourceFile { - /// Url where the source file is located. - final String url; - final List<int> _lineStarts; - final List<int> _decodedChars; - - SourceFile(this.url, this._lineStarts, this._decodedChars); - - SourceFile.text(this.url, String text) - : _lineStarts = <int>[0], - _decodedChars = text.runes.toList() { - for (int i = 0; i < _decodedChars.length; i++) { - var c = _decodedChars[i]; - if (c == _CR) { - // Return not followed by newline is treated as a newline - int j = i + 1; - if (j >= _decodedChars.length || _decodedChars[j] != _LF) { - c = _LF; - } - } - if (c == _LF) _lineStarts.add(i + 1); - } - } - - /// Returns a span in this [SourceFile] with the given offsets. - Span span(int start, [int end, bool isIdentifier = false]) => - new FileSpan(this, start, end, isIdentifier); - - /// Returns a location in this [SourceFile] with the given offset. - Location location(int offset) => new FileLocation(this, offset); - - /// Gets the 0-based line corresponding to an offset. - int getLine(int offset) => binarySearch(_lineStarts, (o) => o > offset) - 1; - - /// Gets the 0-based column corresponding to an offset. - int getColumn(int line, int offset) { - if (line < 0 || line >= _lineStarts.length) return 0; - return offset - _lineStarts[line]; - } - - /// Get the offset for a given line and column - int getOffset(int line, int column) { - if (line < 0) return getOffset(0, 0); - if (line < _lineStarts.length) { - return _lineStarts[line] + column; - } else { - return _decodedChars.length; - } - } - - /// Gets the text at the given offsets. - String getText(int start, [int end]) => - new String.fromCharCodes(_decodedChars.sublist(max(start, 0), end)); - - /// Create a pretty string representation from a span. - String getLocationMessage(String message, int start, int end, - {bool useColors: false, String color}) { - // TODO(jmesserly): it would be more useful to pass in an object that - // controls how the errors are printed. This method is a bit too smart. - var line = getLine(start); - var column = getColumn(line, start); - - var source = url == null ? '' : ' of ${p.prettyUri(url)}'; - var msg = 'line ${line + 1}, column ${column + 1}$source: $message'; - - if (_decodedChars == null) { - // We don't have any text to include, so exit. - return msg; - } - - var buf = new StringBuffer(msg); - buf.write('\n'); - - // +1 for 0-indexing, +1 again to avoid the last line - var textLine = getText(getOffset(line, 0), getOffset(line + 1, 0)); - - column = min(column, textLine.length - 1); - int toColumn = min(column + end - start, textLine.length); - if (useColors) { - if (color == null) { - color = _RED_COLOR; - } - buf.write(textLine.substring(0, column)); - buf.write(color); - buf.write(textLine.substring(column, toColumn)); - buf.write(_NO_COLOR); - buf.write(textLine.substring(toColumn)); - } else { - buf.write(textLine); - if (textLine != '' && !textLine.endsWith('\n')) buf.write('\n'); - } - - int i = 0; - for (; i < column; i++) { - buf.write(' '); - } - - if (useColors) buf.write(color); - for (; i < toColumn; i++) { - buf.write('^'); - } - if (useColors) buf.write(_NO_COLOR); - return buf.toString(); - } -} - -/// A convenience type to treat a code segment as if it were a separate -/// [SourceFile]. A [SourceFileSegment] shifts all locations by an offset, which -/// allows you to set source-map locations based on the locations relative to -/// the start of the segment, but that get translated to absolute locations in -/// the original source file. -@Deprecated("Use the source_span package instead.") -class SourceFileSegment extends SourceFile { - final int _baseOffset; - final int _baseLine; - final int _baseColumn; - final int _maxOffset; - - SourceFileSegment(String url, String textSegment, Location startOffset) - : _baseOffset = startOffset.offset, - _baseLine = startOffset.line, - _baseColumn = startOffset.column, - _maxOffset = startOffset.offset + textSegment.length, - super.text(url, textSegment); - - /// Craete a span, where [start] is relative to this segment's base offset. - /// The returned span stores the real offset on the file, so that error - /// messages are reported at the real location. - Span span(int start, [int end, bool isIdentifier = false]) => - super.span(start + _baseOffset, - end == null ? null : end + _baseOffset, isIdentifier); - - /// Create a location, where [offset] relative to this segment's base offset. - /// The returned span stores the real offset on the file, so that error - /// messages are reported at the real location. - Location location(int offset) => super.location(offset + _baseOffset); - - /// Return the line on the underlying file associated with the [offset] of the - /// underlying file. This method operates on the real offsets from the - /// original file, so that error messages can be reported accurately. When the - /// requested offset is past the length of the segment, this returns the line - /// number after the end of the segment (total lines + 1). - int getLine(int offset) { - var res = super.getLine(max(offset - _baseOffset, 0)) + _baseLine; - return (offset > _maxOffset) ? res + 1 : res; - } - - /// Return the column on the underlying file associated with [line] and - /// [offset], where [line] is absolute from the beginning of the underlying - /// file. This method operates on the real offsets from the original file, so - /// that error messages can be reported accurately. - int getColumn(int line, int offset) { - var col = super.getColumn(line - _baseLine, max(offset - _baseOffset, 0)); - return line == _baseLine ? col + _baseColumn : col; - } - - /// Return the offset associated with a line and column. This method operates - /// on the real offsets from the original file, so that error messages can be - /// reported accurately. - int getOffset(int line, int column) => - super.getOffset(line - _baseLine, - line == _baseLine ? column - _baseColumn : column) + _baseOffset; - - /// Retrieve the text associated with the specified range. This method - /// operates on the real offsets from the original file, so that error - /// messages can be reported accurately. - String getText(int start, [int end]) => - super.getText(start - _baseOffset, end == null ? null : end - _baseOffset); -} - -/// A class for exceptions that have source span information attached. -@Deprecated("Use the source_span package instead.") -class SpanException implements Exception { - /// A message describing the exception. - final String message; - - /// The span associated with this exception. - /// - /// This may be `null` if the source location can't be determined. - final Span span; - - SpanException(this.message, this.span); - - String toString({bool useColors: false, String color}) { - if (span == null) return message; - return "Error on " + span.getLocationMessage(message, - useColors: useColors, color: color); - } -} - -/// A [SpanException] that's also a [FormatException]. -@Deprecated("Use the source_span package instead.") -class SpanFormatException extends SpanException implements FormatException { - final source; - - SpanFormatException(String message, Span span, [this.source]) - : super(message, span); - - int get offset => span == null ? null : span.start.offset; -}
diff --git a/pkgs/source_maps/lib/src/source_map_span.dart b/pkgs/source_maps/lib/src/source_map_span.dart new file mode 100644 index 0000000..20eb17a --- /dev/null +++ b/pkgs/source_maps/lib/src/source_map_span.dart
@@ -0,0 +1,59 @@ +// Copyright (c) 2014, 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 source_maps.source_map_span; + +import 'package:source_span/source_span.dart'; + +/// A [SourceSpan] for spans coming from or being written to source maps. +/// +/// These spans have an extra piece of metadata: whether or not they represent +/// an identifier (see [isIdentifier]). +class SourceMapSpan extends SourceSpanBase { + /// Whether this span represents an identifier. + /// + /// If this is `true`, [text] is the value of the identifier. + final bool isIdentifier; + + SourceMapSpan(SourceLocation start, SourceLocation end, String text, + {this.isIdentifier: false}) + : super(start, end, text); + + /// Creates a [SourceMapSpan] for an identifier with value [text] starting at + /// [start]. + /// + /// The [end] location is determined by adding [text] to [start]. + SourceMapSpan.identifier(SourceLocation start, String text) + : this( + start, + new SourceLocation(start.offset + text.length, + sourceUrl: start.sourceUrl, + line: start.line, + column: start.column + text.length), + text, + isIdentifier: true); +} + +/// A wrapper aruond a [FileSpan] that implements [SourceMapSpan]. +class SourceMapFileSpan implements SourceMapSpan, FileSpan { + final FileSpan _inner; + final bool isIdentifier; + + SourceFile get file => _inner.file; + FileLocation get start => _inner.start; + FileLocation get end => _inner.end; + String get text => _inner.text; + Uri get sourceUrl => _inner.sourceUrl; + int get length => _inner.length; + + SourceMapFileSpan(this._inner, {this.isIdentifier: false}); + + int compareTo(SourceSpan other) => _inner.compareTo(other); + SourceSpan union(SourceSpan other) => _inner.union(other); + FileSpan expand(FileSpan other) => _inner.expand(other); + String message(String message, {color}) => + _inner.message(message, color: color); + String toString() => _inner.toString() + .replaceAll("FileSpan", "SourceMapFileSpan"); +}
diff --git a/pkgs/source_maps/lib/src/span_wrapper.dart b/pkgs/source_maps/lib/src/span_wrapper.dart deleted file mode 100644 index e0c107b..0000000 --- a/pkgs/source_maps/lib/src/span_wrapper.dart +++ /dev/null
@@ -1,85 +0,0 @@ -// Copyright (c) 2014, 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 source_maps.span_wrapper; - -import 'package:source_span/source_span.dart' as source_span; - -import '../span.dart'; - -/// A wrapper that exposes a [source_span.SourceSpan] as a [Span]. -class SpanWrapper extends Span { - final source_span.SourceSpan _inner; - - String get text => _inner.text; - - SpanWrapper(source_span.SourceSpan inner, bool isIdentifier) - : _inner = inner, - super( - new LocationWrapper(inner.start), - new LocationWrapper(inner.end), - isIdentifier); - - static Span wrap(span, [bool isIdentifier = false]) { - if (span is Span) return span; - return new SpanWrapper(span, isIdentifier); - } -} - -/// A wrapper that exposes a [source_span.SourceLocation] as a [Location]. -class LocationWrapper extends Location { - final source_span.SourceLocation _inner; - - String get sourceUrl => _inner.sourceUrl.toString(); - int get line => _inner.line; - int get column => _inner.column; - - LocationWrapper(source_span.SourceLocation inner) - : _inner = inner, - super(inner.offset); - - static Location wrap(location) { - if (location is Location) return location; - return new LocationWrapper(location); - } -} - -/// A wrapper that exposes a [source_span.SourceFile] as a [SourceFile]. -class SourceFileWrapper implements SourceFile { - final source_span.SourceFile _inner; - - // These are necessary to avoid analyzer warnings; - final _lineStarts = null; - final _decodedChars = null; - - String get url => _inner.url.toString(); - - SourceFileWrapper(this._inner); - - static SourceFile wrap(sourceFile) { - if (sourceFile is SourceFile) return sourceFile; - return new SourceFileWrapper(sourceFile); - } - - Span span(int start, [int end, bool isIdentifier = false]) { - if (end == null) end = start; - return new SpanWrapper(_inner.span(start, end), isIdentifier); - } - - Location location(int offset) => new LocationWrapper(_inner.location(offset)); - - int getLine(int offset) => _inner.getLine(offset); - - int getColumn(int line, int offset) => _inner.getColumn(offset, line: line); - - int getOffset(int line, int column) => _inner.getOffset(line, column); - - String getText(int start, [int end]) => _inner.getText(start, end); - - String getLocationMessage(String message, int start, int end, - {bool useColors: false, String color}) { - return span(start, end).getLocationMessage(message, - useColors: useColors, color: color); - } -}
diff --git a/pkgs/source_maps/test/builder_test.dart b/pkgs/source_maps/test/builder_test.dart index 8842c62..ca0ca8d 100644 --- a/pkgs/source_maps/test/builder_test.dart +++ b/pkgs/source_maps/test/builder_test.dart
@@ -16,7 +16,7 @@ ..addSpan(inputFunction, outputFunction) ..addSpan(inputVar2, outputVar2) ..addSpan(inputExpr, outputExpr)) - .build(output.url); + .build(output.url.toString()); expect(map, equals(EXPECTED_MAP)); }); @@ -26,7 +26,7 @@ ..addLocation(inputFunction.start, outputFunction.start, 'longName') ..addLocation(inputVar2.start, outputVar2.start, 'longVar2') ..addLocation(inputExpr.start, outputExpr.start, null)) - .toJson(output.url); + .toJson(output.url.toString()); expect(str, JSON.encode(EXPECTED_MAP)); }); }
diff --git a/pkgs/source_maps/test/common.dart b/pkgs/source_maps/test/common.dart index 0c1f28a..73a8d40 100644 --- a/pkgs/source_maps/test/common.dart +++ b/pkgs/source_maps/test/common.dart
@@ -6,6 +6,7 @@ library test.common; import 'package:source_maps/source_maps.dart'; +import 'package:source_span/source_span.dart'; import 'package:unittest/unittest.dart'; /// Content of the source file @@ -18,40 +19,40 @@ return longVar1 + longVar2; } '''; -var input = new SourceFile.text('input.dart', INPUT); +var input = new SourceFile(INPUT, url: 'input.dart'); /// A span in the input file -Span ispan(int start, int end, [bool isIdentifier = false]) => - new FileSpan(input, start, end, isIdentifier); +SourceMapSpan ispan(int start, int end, [bool isIdentifier = false]) => + new SourceMapFileSpan(input.span(start, end), isIdentifier: isIdentifier); -Span inputVar1 = ispan(30, 38, true); -Span inputFunction = ispan(74, 82, true); -Span inputVar2 = ispan(87, 95, true); +SourceMapSpan inputVar1 = ispan(30, 38, true); +SourceMapSpan inputFunction = ispan(74, 82, true); +SourceMapSpan inputVar2 = ispan(87, 95, true); -Span inputVar1NoSymbol = ispan(30, 38); -Span inputFunctionNoSymbol = ispan(74, 82); -Span inputVar2NoSymbol = ispan(87, 95); +SourceMapSpan inputVar1NoSymbol = ispan(30, 38); +SourceMapSpan inputFunctionNoSymbol = ispan(74, 82); +SourceMapSpan inputVar2NoSymbol = ispan(87, 95); -Span inputExpr = ispan(108, 127); +SourceMapSpan inputExpr = ispan(108, 127); /// Content of the target file const String OUTPUT = ''' var x = 3; f(y) => x + y; '''; -var output = new SourceFile.text('output.dart', OUTPUT); +var output = new SourceFile(OUTPUT, url: 'output.dart'); /// A span in the output file -Span ospan(int start, int end, [bool isIdentifier = false]) => - new FileSpan(output, start, end, isIdentifier); +SourceMapSpan ospan(int start, int end, [bool isIdentifier = false]) => + new SourceMapFileSpan(output.span(start, end), isIdentifier: isIdentifier); -Span outputVar1 = ospan(4, 5, true); -Span outputFunction = ospan(11, 12, true); -Span outputVar2 = ospan(13, 14, true); -Span outputVar1NoSymbol = ospan(4, 5); -Span outputFunctionNoSymbol = ospan(11, 12); -Span outputVar2NoSymbol = ospan(13, 14); -Span outputExpr = ospan(19, 24); +SourceMapSpan outputVar1 = ospan(4, 5, true); +SourceMapSpan outputFunction = ospan(11, 12, true); +SourceMapSpan outputVar2 = ospan(13, 14, true); +SourceMapSpan outputVar1NoSymbol = ospan(4, 5); +SourceMapSpan outputFunctionNoSymbol = ospan(11, 12); +SourceMapSpan outputVar2NoSymbol = ospan(13, 14); +SourceMapSpan outputExpr = ospan(19, 24); /// Expected output mapping when recording the following four mappings: /// inputVar1 <= outputVar1 @@ -70,7 +71,8 @@ 'file': 'output.dart' }; -check(Span outputSpan, Mapping mapping, Span inputSpan, bool realOffsets) { +check(SourceSpan outputSpan, Mapping mapping, SourceMapSpan inputSpan, + bool realOffsets) { var line = outputSpan.start.line; var column = outputSpan.start.column; var files = realOffsets ? {'input.dart': input} : null;
diff --git a/pkgs/source_maps/test/end2end_test.dart b/pkgs/source_maps/test/end2end_test.dart index 99fe40d..7dbc6bd 100644 --- a/pkgs/source_maps/test/end2end_test.dart +++ b/pkgs/source_maps/test/end2end_test.dart
@@ -6,6 +6,7 @@ import 'package:unittest/unittest.dart'; import 'package:source_maps/source_maps.dart'; +import 'package:source_span/source_span.dart'; import 'common.dart'; main() { @@ -33,7 +34,7 @@ ..addSpan(inputFunction, outputFunction) ..addSpan(inputVar2, outputVar2) ..addSpan(inputExpr, outputExpr)) - .build(output.url); + .build(output.url.toString()); var mapping = parseJson(map); check(outputVar1, mapping, inputVar1, false); check(outputVar2, mapping, inputVar2, false); @@ -47,7 +48,7 @@ ..addSpan(inputFunctionNoSymbol, outputFunctionNoSymbol) ..addSpan(inputVar2NoSymbol, outputVar2NoSymbol) ..addSpan(inputExpr, outputExpr)) - .build(output.url); + .build(output.url.toString()); var mapping = parseJson(map); check(outputVar1NoSymbol, mapping, inputVar1NoSymbol, false); check(outputVar2NoSymbol, mapping, inputVar2NoSymbol, false); @@ -65,7 +66,7 @@ ..addSpan(inputVar2, outputVar2) ..addSpan(inputExpr, outputExpr) ..addSpan(inputExpr, outputExpr)) - .build(output.url); + .build(output.url.toString()); var mapping = parseJson(map); check(outputVar1, mapping, inputVar1, false); check(outputVar2, mapping, inputVar2, false); @@ -82,7 +83,7 @@ ..addSpan(inputVar2NoSymbol, outputVar2NoSymbol) ..addSpan(inputVar2NoSymbol, outputVar2NoSymbol) ..addSpan(inputExpr, outputExpr)) - .build(output.url); + .build(output.url.toString()); var mapping = parseJson(map); check(outputVar1NoSymbol, mapping, inputVar1NoSymbol, false); check(outputVar2NoSymbol, mapping, inputVar2NoSymbol, false); @@ -96,7 +97,7 @@ ..addSpan(inputFunction, outputFunction) ..addSpan(inputVar2, outputVar2) ..addSpan(inputExpr, outputExpr)) - .toJson(output.url); + .toJson(output.url.toString()); var mapping = parse(json); check(outputVar1, mapping, inputVar1, true); check(outputVar2, mapping, inputVar2, true); @@ -106,7 +107,7 @@ test('printer projecting marks + parse', () { var out = INPUT.replaceAll('long', '_s'); - var file = new SourceFile.text('output2.dart', out); + var file = new SourceFile(out, url: 'output2.dart'); var printer = new Printer('output2.dart'); printer.mark(ispan(0, 0)); @@ -132,10 +133,11 @@ expect(printer.text, out); var mapping = parse(printer.map); - checkHelper(Span inputSpan, int adjustment) { + checkHelper(SourceMapSpan inputSpan, int adjustment) { var start = inputSpan.start.offset - adjustment; var end = (inputSpan.end.offset - adjustment) - 2; - var span = new FileSpan(file, start, end, inputSpan.isIdentifier); + var span = new SourceMapFileSpan(file.span(start, end), + isIdentifier: inputSpan.isIdentifier); check(span, mapping, inputSpan, true); } @@ -145,17 +147,16 @@ checkHelper(inputExpr, 6); // We projected correctly lines that have no mappings - check(new FileSpan(file, 66, 66, false), mapping, ispan(45, 45), true); - check(new FileSpan(file, 63, 64, false), mapping, ispan(45, 45), true); - check(new FileSpan(file, 68, 68, false), mapping, ispan(70, 70), true); - check(new FileSpan(file, 71, 71, false), mapping, ispan(70, 70), true); + check(file.span(66, 66), mapping, ispan(45, 45), true); + check(file.span(63, 64), mapping, ispan(45, 45), true); + check(file.span(68, 68), mapping, ispan(70, 70), true); + check(file.span(71, 71), mapping, ispan(70, 70), true); // Start of the last line var oOffset = out.length - 2; var iOffset = INPUT.length - 2; - check(new FileSpan(file, oOffset, oOffset, false), mapping, - ispan(iOffset, iOffset), true); - check(new FileSpan(file, oOffset + 1, oOffset + 1, false), mapping, + check(file.span(oOffset, oOffset), mapping, ispan(iOffset, iOffset), true); + check(file.span(oOffset + 1, oOffset + 1), mapping, ispan(iOffset, iOffset), true); }); }
diff --git a/pkgs/source_maps/test/parser_test.dart b/pkgs/source_maps/test/parser_test.dart index 62cd08f..8528683 100644 --- a/pkgs/source_maps/test/parser_test.dart +++ b/pkgs/source_maps/test/parser_test.dart
@@ -104,7 +104,7 @@ var inputMap = new Map.from(MAP_WITH_SOURCE_LOCATION); inputMap['sourceRoot'] = '/pkg/'; var mapping = parseJson(inputMap); - expect(mapping.spanFor(0, 0).sourceUrl, "/pkg/input.dart"); + expect(mapping.spanFor(0, 0).sourceUrl, Uri.parse("/pkg/input.dart")); var newSourceRoot = '/new/';
diff --git a/pkgs/source_maps/test/printer_test.dart b/pkgs/source_maps/test/printer_test.dart index fe27f76..e55ca9f 100644 --- a/pkgs/source_maps/test/printer_test.dart +++ b/pkgs/source_maps/test/printer_test.dart
@@ -6,8 +6,8 @@ import 'dart:convert'; import 'package:unittest/unittest.dart'; -import 'package:source_maps/printer.dart'; -import 'package:source_maps/span.dart'; +import 'package:source_maps/source_maps.dart'; +import 'package:source_span/source_span.dart'; import 'common.dart'; main() { @@ -53,13 +53,12 @@ // 8 new lines in the source map: expect(printer.map.split(';').length, 8); - asFixed(Span s) => new FixedSpan(s.sourceUrl, - s.start.offset, s.start.line, s.start.column, - text: s.text, isIdentifier: s.isIdentifier); + asFixed(SourceMapSpan s) => new SourceMapSpan(s.start, s.end, s.text, + isIdentifier: s.isIdentifier); // The result is the same if we use fixed positions var printer2 = new Printer('output2.dart'); - printer2..mark(new FixedSpan('input.dart', 0, 0, 0)) + printer2..mark(new SourceLocation(0, sourceUrl: 'input.dart').pointSpan()) ..add(segments[0], projectMarks: true) ..mark(asFixed(inputVar1)) ..add('_s')
diff --git a/pkgs/source_maps/test/refactor_test.dart b/pkgs/source_maps/test/refactor_test.dart index 5d0abf1..08b8965 100644 --- a/pkgs/source_maps/test/refactor_test.dart +++ b/pkgs/source_maps/test/refactor_test.dart
@@ -6,13 +6,13 @@ import 'package:unittest/unittest.dart'; import 'package:source_maps/refactor.dart'; -import 'package:source_maps/span.dart'; import 'package:source_maps/parser.dart' show parse, Mapping; +import 'package:source_span/source_span.dart'; main() { group('conflict detection', () { var original = "0123456789abcdefghij"; - var file = new SourceFile.text('', original); + var file = new SourceFile(original); test('no conflict, in order', () { var txn = new TextEditTransaction(original, file); @@ -48,7 +48,7 @@ test('generated source maps', () { var original = "0123456789\n0*23456789\n01*3456789\nabcdefghij\nabcd*fghij\n"; - var file = new SourceFile.text('', original); + var file = new SourceFile(original); var txn = new TextEditTransaction(original, file); txn.edit(27, 29, '__\n '); txn.edit(34, 35, '___'); @@ -60,42 +60,90 @@ // Line 1 and 2 are unmodified: mapping any column returns the beginning // of the corresponding line: - expect(_span(1, 1, map, file), "line 1, column 1 of .: \n0123456789"); - expect(_span(1, 5, map, file), "line 1, column 1 of .: \n0123456789"); - expect(_span(2, 1, map, file), "line 2, column 1 of .: \n0*23456789"); - expect(_span(2, 8, map, file), "line 2, column 1 of .: \n0*23456789"); + expect(_span(1, 1, map, file), + "line 1, column 1: \n" + "0123456789\n" + "^"); + expect(_span(1, 5, map, file), + "line 1, column 1: \n" + "0123456789\n" + "^"); + expect(_span(2, 1, map, file), + "line 2, column 1: \n" + "0*23456789\n" + "^"); + expect(_span(2, 8, map, file), + "line 2, column 1: \n" + "0*23456789\n" + "^"); // Line 3 is modified part way: mappings before the edits have the right // mapping, after the edits the mapping is null. - expect(_span(3, 1, map, file), "line 3, column 1 of .: \n01*3456789"); - expect(_span(3, 5, map, file), "line 3, column 1 of .: \n01*3456789"); + expect(_span(3, 1, map, file), + "line 3, column 1: \n" + "01*3456789\n" + "^"); + expect(_span(3, 5, map, file), + "line 3, column 1: \n" + "01*3456789\n" + "^"); // Start of edits map to beginning of the edit secion: - expect(_span(3, 6, map, file), "line 3, column 6 of .: \n01*3456789"); - expect(_span(3, 7, map, file), "line 3, column 6 of .: \n01*3456789"); + expect(_span(3, 6, map, file), + "line 3, column 6: \n" + "01*3456789\n" + " ^"); + expect(_span(3, 7, map, file), + "line 3, column 6: \n" + "01*3456789\n" + " ^"); // Lines added have no mapping (they should inherit the last mapping), // but the end of the edit region continues were we left off: expect(_span(4, 1, map, file), isNull); - expect(_span(4, 5, map, file), "line 3, column 8 of .: \n01*3456789"); + expect(_span(4, 5, map, file), + "line 3, column 8: \n" + "01*3456789\n" + " ^"); // Subsequent lines are still mapped correctly: // a (in a___cd...) - expect(_span(5, 1, map, file), "line 4, column 1 of .: \nabcdefghij"); + expect(_span(5, 1, map, file), + "line 4, column 1: \n" + "abcdefghij\n" + "^"); // _ (in a___cd...) - expect(_span(5, 2, map, file), "line 4, column 2 of .: \nabcdefghij"); + expect(_span(5, 2, map, file), + "line 4, column 2: \n" + "abcdefghij\n" + " ^"); // _ (in a___cd...) - expect(_span(5, 3, map, file), "line 4, column 2 of .: \nabcdefghij"); + expect(_span(5, 3, map, file), + "line 4, column 2: \n" + "abcdefghij\n" + " ^"); // _ (in a___cd...) - expect(_span(5, 4, map, file), "line 4, column 2 of .: \nabcdefghij"); + expect(_span(5, 4, map, file), + "line 4, column 2: \n" + "abcdefghij\n" + " ^"); // c (in a___cd...) - expect(_span(5, 5, map, file), "line 4, column 3 of .: \nabcdefghij"); - expect(_span(6, 1, map, file), "line 5, column 1 of .: \nabcd*fghij"); - expect(_span(6, 8, map, file), "line 5, column 1 of .: \nabcd*fghij"); + expect(_span(5, 5, map, file), + "line 4, column 3: \n" + "abcdefghij\n" + " ^"); + expect(_span(6, 1, map, file), + "line 5, column 1: \n" + "abcd*fghij\n" + "^"); + expect(_span(6, 8, map, file), + "line 5, column 1: \n" + "abcd*fghij\n" + "^"); }); } String _span(int line, int column, Mapping map, SourceFile file) { var span = map.spanFor(line - 1, column - 1, files: {'': file}); - return span == null ? null : span.getLocationMessage('').trim(); + return span == null ? null : span.message('').trim(); }
diff --git a/pkgs/source_maps/test/run.dart b/pkgs/source_maps/test/run.dart index 21d2037..ec3c3ab 100755 --- a/pkgs/source_maps/test/run.dart +++ b/pkgs/source_maps/test/run.dart
@@ -14,7 +14,6 @@ import 'parser_test.dart' as parser_test; import 'printer_test.dart' as printer_test; import 'refactor_test.dart' as refactor_test; -import 'span_test.dart' as span_test; import 'utils_test.dart' as utils_test; import 'vlq_test.dart' as vlq_test; @@ -33,7 +32,6 @@ addGroup('parser_test.dart', parser_test.main); addGroup('printer_test.dart', printer_test.main); addGroup('refactor_test.dart', refactor_test.main); - addGroup('span_test.dart', span_test.main); addGroup('utils_test.dart', utils_test.main); addGroup('vlq_test.dart', vlq_test.main); }
diff --git a/pkgs/source_maps/test/span_test.dart b/pkgs/source_maps/test/span_test.dart deleted file mode 100644 index 190b7a6..0000000 --- a/pkgs/source_maps/test/span_test.dart +++ /dev/null
@@ -1,341 +0,0 @@ -// Copyright (c) 2013, 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 test.span_test; - -import 'package:unittest/unittest.dart'; -import 'package:source_maps/span.dart'; - -const String TEST_FILE = ''' -+23456789_ - + _123456789_123456789_123456789_123456789_123456789_123456789_123456789_ - + _123456789_1 -123+56789_123456789_1234567 -1234+6789_1234 -12345+789_123456789_12345 -123456+89_123456789_123456789_123456789_123456789_123456789_123456789_123456789 -1234567+9_123456789_123456789_123456789_123456789_123456789_123456789_123 -12345678+_123456789_123456789_123456789_123456789_1 -123456789+123456789_123456789_12345678 -123456789_+23456789_123456789_123456789_123 -123456789_1+3456789_123456789 -'''; - -List<int> newLines = TEST_FILE.split('\n').map((s) => s.length).toList(); - -main() { - var file = new SourceFile.text('file', TEST_FILE); - span(int start, int end) => file.span(start, end); - loc(int offset) => file.location(offset); - - test('validate test input', () { - expect(newLines, - const [10, 80, 31, 27, 14, 25, 79, 73, 51, 38, 43, 29, 0]); - }); - - test('get line and column', () { - line(int n) => file.getLine(n); - col(int n) => file.getColumn(file.getLine(n), n); - - expect(line(8), 0); - expect(line(10), 0); - expect(line(11), 1); - expect(line(12), 1); - expect(line(91), 1); - expect(line(92), 2); - expect(line(93), 2); - expect(col(11), 0); - expect(col(12), 1); - expect(col(91), 80); - expect(col(92), 0); - expect(col(93), 1); - - int j = 0; - int lineOffset = 0; - for (int i = 0; i < TEST_FILE.length; i++) { - if (i > lineOffset + newLines[j]) { - lineOffset += newLines[j] + 1; - j++; - } - expect(line(i), j, reason: 'position: $i'); - expect(col(i), i - lineOffset, reason: 'position: $i'); - } - }); - - test('get text', () { - // fifth line (including 4 new lines), columns 2 .. 11 - var line = 10 + 80 + 31 + 27 + 4; - expect(file.getText(line + 2, line + 11), '34+6789_1'); - }); - - group('location message', () { - test('first line', () { - expect(file.getLocationMessage('the message', 1, 3), - 'line 1, column 2 of file: the message\n' - '+23456789_\n' - ' ^^'); - }); - - test('in the middle of the file', () { - // fifth line (including 4 new lines), columns 2 .. 11 - var line = 10 + 80 + 31 + 27 + 4; - expect(file.getLocationMessage('the message', line + 2, line + 11), - 'line 5, column 3 of file: the message\n' - '1234+6789_1234\n' - ' ^^^^^^^^^'); - }); - - test('no file url', () { - var line = 10 + 80 + 31 + 27 + 4; - expect(new SourceFile.text(null, TEST_FILE).getLocationMessage( - 'the message', line + 2, line + 11), - 'line 5, column 3: the message\n' - '1234+6789_1234\n' - ' ^^^^^^^^^'); - }); - - test('penultimate line', () { - // We search '\n' backwards twice because last line is \n terminated: - int index = TEST_FILE.lastIndexOf('\n'); - var start = TEST_FILE.lastIndexOf('\n', index - 1) - 3; - expect(file.getLocationMessage('the message', start, start + 2), - 'line 11, column 41 of file: the message\n' - '123456789_+23456789_123456789_123456789_123\n' - ' ^^'); - }); - - test('last line', () { - var start = TEST_FILE.lastIndexOf('\n') - 2; - expect(file.getLocationMessage('the message', start, start + 1), - 'line 12, column 28 of file: the message\n' - '123456789_1+3456789_123456789\n' - ' ^'); - }); - - group('no trailing empty-line at the end -', () { - var text = TEST_FILE.substring(0, TEST_FILE.length - 1); - var file2 = new SourceFile.text('file', text); - - test('penultimate line', () { - var start = text.lastIndexOf('\n') - 3; - expect(file2.getLocationMessage('the message', start, start + 2), - 'line 11, column 41 of file: the message\n' - '123456789_+23456789_123456789_123456789_123\n' - ' ^^'); - }); - - test('last line', () { - var start = text.length - 2; - expect(file2.getLocationMessage('the message', start, start + 1), - 'line 12, column 28 of file: the message\n' - '123456789_1+3456789_123456789\n' - ' ^'); - }); - }); - - test('single line', () { - var text = "this is a single line"; - int start = text.indexOf(' ') + 1; - var file2 = new SourceFile.text('file', text); - expect(file2.getLocationMessage('the message', start, start + 2), - 'line 1, column ${start + 1} of file: the message\n' - 'this is a single line\n' - ' ^^'); - }); - }); - - test('location getters', () { - expect(loc(8).line, 0); - expect(loc(8).column, 8); - expect(loc(9).line, 0); - expect(loc(9).column, 9); - expect(loc(8).formatString, 'file:1:9'); - expect(loc(12).line, 1); - expect(loc(12).column, 1); - expect(loc(95).line, 2); - expect(loc(95).column, 3); - }); - - test('location compare', () { - var list = [9, 8, 11, 14, 6, 6, 1, 1].map((n) => loc(n)).toList(); - list.sort(); - var lastOffset = 0; - for (var location in list) { - expect(location.offset, greaterThanOrEqualTo(lastOffset)); - lastOffset = location.offset; - } - }); - - test('span getters', () { - expect(span(8, 9).start.line, 0); - expect(span(8, 9).start.column, 8); - expect(span(8, 9).end.line, 0); - expect(span(8, 9).end.column, 9); - expect(span(8, 9).text, '9'); - expect(span(8, 9).isIdentifier, false); - expect(span(8, 9).formatLocation, 'file:1:9'); - - var line = 10 + 80 + 31 + 27 + 4; - expect(span(line + 2, line + 11).getLocationMessage('the message'), - 'line 5, column 3 of file: the message\n' - '1234+6789_1234\n' - ' ^^^^^^^^^'); - - expect(span(12, 95).start.line, 1); - expect(span(12, 95).start.column, 1); - expect(span(12, 95).end.line, 2); - expect(span(12, 95).end.column, 3); - expect(span(12, 95).text, - '+ _123456789_123456789_123456789_123456789_123456789_1234567' - '89_123456789_\n +'); - expect(span(12, 95).formatLocation, 'file:2:2'); - }); - - test('span union', () { - var union = new FileSpan.union(span(8, 9), span(12, 95)); - expect(union.start.offset, 8); - expect(union.start.line, 0); - expect(union.start.column, 8); - expect(union.end.offset, 95); - expect(union.end.line, 2); - expect(union.end.column, 3); - expect(union.text, - '9_\n' - ' + _123456789_123456789_123456789_123456789_123456789_' - '123456789_123456789_\n +'); - expect(union.formatLocation, 'file:1:9'); - }); - - test('span compare', () { - var list = [span(9, 10), span(8, 9), span(11, 12), span(14, 19), - span(6, 12), span(6, 8), span(1, 9), span(1, 2)]; - list.sort(); - var lastStart = 0; - var lastEnd = 0; - for (var span in list) { - expect(span.start.offset, greaterThanOrEqualTo(lastStart)); - if (span.start.offset == lastStart) { - expect(span.end.offset, greaterThanOrEqualTo(lastEnd)); - } - lastStart = span.start.offset; - lastEnd = span.end.offset; - } - }); - - test('range check for large offsets', () { - var start = TEST_FILE.length; - expect(file.getLocationMessage('the message', start, start + 9), - 'line 13, column 1 of file: the message\n'); - }); - - group('file segment', () { - var baseOffset = 123; - var segmentText = TEST_FILE.substring(baseOffset, TEST_FILE.length - 100); - var segment = new SourceFileSegment('file', segmentText, loc(baseOffset)); - sline(int n) => segment.getLine(n); - scol(int n) => segment.getColumn(segment.getLine(n), n); - line(int n) => file.getLine(n); - col(int n) => file.getColumn(file.getLine(n), n); - - test('get line and column', () { - int j = 0; - int lineOffset = 0; - for (int i = baseOffset; i < segmentText.length; i++) { - if (i > lineOffset + newLines[j]) { - lineOffset += newLines[j] + 1; - j++; - } - expect(segment.location(i - baseOffset).offset, i); - expect(segment.location(i - baseOffset).line, line(i)); - expect(segment.location(i - baseOffset).column, col(i)); - expect(segment.span(i - baseOffset).start.offset, i); - expect(segment.span(i - baseOffset).start.line, line(i)); - expect(segment.span(i - baseOffset).start.column, col(i)); - - expect(sline(i), line(i)); - expect(scol(i), col(i)); - } - }); - - test('get text', () { - var start = 10 + 80 + 31 + 27 + 4 + 2; - expect(segment.getText(start, start + 9), file.getText(start, start + 9)); - }); - - group('location message', () { - test('first line', () { - var start = baseOffset + 7; - expect(segment.getLocationMessage('the message', start, start + 2), - file.getLocationMessage('the message', start, start + 2)); - }); - - test('in a middle line', () { - // Example from another test above: - var start = 10 + 80 + 31 + 27 + 4 + 2; - expect(segment.getLocationMessage('the message', start, start + 9), - file.getLocationMessage('the message', start, start + 9)); - }); - - test('last segment line', () { - var start = segmentText.length - 4; - expect(segment.getLocationMessage('the message', start, start + 2), - file.getLocationMessage('the message', start, start + 2)); - }); - - test('past segment, same as last segment line', () { - var start = segmentText.length; - expect(segment.getLocationMessage('the message', start, start + 2), - file.getLocationMessage('the message', start, start + 2)); - - start = segmentText.length + 20; - expect(segment.getLocationMessage('the message', start, start + 2), - file.getLocationMessage('the message', start, start + 2)); - }); - - test('past segment, past its line', () { - var start = TEST_FILE.length - 2; - expect(file.getLocationMessage('the message', start, start + 1), - 'line 12, column 29 of file: the message\n' - '123456789_1+3456789_123456789\n' - ' ^'); - - // The answer below is different because the segment parsing only knows - // about the 10 lines it has (and nothing about the possible extra lines - // afterwards) - expect(segment.getLocationMessage('the message', start, start + 1), - 'line 11, column 1 of file: the message\n'); - }); - }); - }); - - test('span isIdentifier defaults to false', () { - var start = new TestLocation(0); - var end = new TestLocation(1); - expect(new TestSpan(start, end).isIdentifier, false); - expect(file.span(8, 9, null).isIdentifier, false); - expect(new FixedSpan('', 8, 1, 8, isIdentifier: null).isIdentifier, false); - }); - - test('span/location implement == and hashCode', () { - expect(identical(span(10, 14), span(10, 14)), isFalse); - expect(span(10, 14), equals(span(10, 14))); - expect(span(10, 14).hashCode, span(10, 14).hashCode); - - expect(identical(loc(13), loc(13)), isFalse); - expect(loc(13), equals(loc(13))); - expect(loc(13).hashCode, loc(13).hashCode); - }); -} - -class TestSpan extends Span { - TestSpan(Location start, Location end) : super(start, end, null); - get text => null; -} - -class TestLocation extends Location { - String get sourceUrl => ''; - TestLocation(int offset) : super(offset); - get line => 0; - get column => 0; -}