85 lines
3.1 KiB
Dart
85 lines
3.1 KiB
Dart
|
|
// 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.
|
||
|
|
|
||
|
|
/// Contains a builder object useful for creating source maps programatically.
|
||
|
|
library source_maps.builder;
|
||
|
|
|
||
|
|
// TODO(sigmund): add a builder for multi-section mappings.
|
||
|
|
|
||
|
|
import 'dart:convert';
|
||
|
|
|
||
|
|
import 'package:source_span/source_span.dart';
|
||
|
|
|
||
|
|
import 'parser.dart';
|
||
|
|
import 'src/source_map_span.dart';
|
||
|
|
|
||
|
|
/// Builds a source map given a set of mappings.
|
||
|
|
class SourceMapBuilder {
|
||
|
|
final List<Entry> _entries = <Entry>[];
|
||
|
|
|
||
|
|
/// Adds an entry mapping the [targetOffset] to [source].
|
||
|
|
void addFromOffset(SourceLocation source, SourceFile targetFile,
|
||
|
|
int targetOffset, String identifier) {
|
||
|
|
ArgumentError.checkNotNull(targetFile, 'targetFile');
|
||
|
|
_entries.add(Entry(source, targetFile.location(targetOffset), identifier));
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Adds an entry mapping [target] to [source].
|
||
|
|
///
|
||
|
|
/// 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. [isIdentifier]
|
||
|
|
/// takes precedence over [target]'s `isIdentifier` value.
|
||
|
|
void addSpan(SourceSpan source, SourceSpan target, {bool? isIdentifier}) {
|
||
|
|
isIdentifier ??= source is SourceMapSpan ? source.isIdentifier : false;
|
||
|
|
|
||
|
|
var name = isIdentifier ? source.text : null;
|
||
|
|
_entries.add(Entry(source.start, target.start, name));
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Adds an entry mapping [target] to [source].
|
||
|
|
void addLocation(
|
||
|
|
SourceLocation source, SourceLocation target, String? identifier) {
|
||
|
|
_entries.add(Entry(source, target, identifier));
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Encodes all mappings added to this builder as a json map.
|
||
|
|
Map<String, dynamic> build(String fileUrl) {
|
||
|
|
return SingleMapping.fromEntries(_entries, fileUrl).toJson();
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Encodes all mappings added to this builder as a json string.
|
||
|
|
String toJson(String fileUrl) => jsonEncode(build(fileUrl));
|
||
|
|
}
|
||
|
|
|
||
|
|
/// An entry in the source map builder.
|
||
|
|
class Entry implements Comparable<Entry> {
|
||
|
|
/// Span denoting the original location in the input source file
|
||
|
|
final SourceLocation source;
|
||
|
|
|
||
|
|
/// Span indicating the corresponding location in the target file.
|
||
|
|
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].
|
||
|
|
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
|
||
|
|
/// because source map files are encoded by printing each mapping in order as
|
||
|
|
/// they appear in the target file.
|
||
|
|
@override
|
||
|
|
int compareTo(Entry other) {
|
||
|
|
var res = target.compareTo(other.target);
|
||
|
|
if (res != 0) return res;
|
||
|
|
res = source.sourceUrl
|
||
|
|
.toString()
|
||
|
|
.compareTo(other.source.sourceUrl.toString());
|
||
|
|
if (res != 0) return res;
|
||
|
|
return source.compareTo(other.source);
|
||
|
|
}
|
||
|
|
}
|