///|
/// Position in generated code. Lines and columns are zero-based, matching the
/// Source Map v3 format.
pub struct GeneratedPosition {
line : Int
column : Int
} derive(Eq, Debug, ToJson)
///|
pub fn GeneratedPosition::GeneratedPosition(
line : Int,
column : Int,
) -> GeneratedPosition {
{ line, column }
}
///|
/// Position in an original source file. `name` is optional because most source
/// maps only attach names to identifiers and call sites.
pub struct OriginalPosition {
source : String
line : Int
column : Int
name : String?
} derive(Eq, Debug, ToJson)
///|
pub fn OriginalPosition::OriginalPosition(
source : StringView,
line : Int,
column : Int,
name? : String,
) -> OriginalPosition {
{ source: source.to_owned(), line, column, name }
}
///|
/// A decoded mapping segment. A segment with only generated fields is an
/// unmapped generated span; mapped segments carry a source index and original
/// coordinates, plus an optional name index.
pub struct MappingSegment {
generated_line : Int
generated_column : Int
source_index : Int?
original_line : Int?
original_column : Int?
name_index : Int?
} derive(Eq, Debug, ToJson)
///|
/// Source Map v3 data model. `mappings` is stored decoded so callers can query,
/// validate and transform it without repeatedly parsing VLQ text.
pub struct SourceMap {
version : Int
file : String?
source_root : String?
sources : Array[String]
sources_content : Array[String?]
names : Array[String]
mappings : Array[MappingSegment]
ignore_list : Array[Int]
} derive(Eq, Debug, ToJson)
///|
/// Aggregated counts that are useful in CI output and smoke tests.
pub struct MappingStats {
generated_lines : Int
total_segments : Int
mapped_segments : Int
unmapped_segments : Int
named_segments : Int
source_count : Int
name_count : Int
ignored_source_count : Int
} derive(Eq, Debug, ToJson)
///|
/// Per-source summary for dashboards and build reports.
pub struct SourceSummary {
source : String
index : Int
mapped_segments : Int
named_segments : Int
first_original_line : Int?
last_original_line : Int?
ignored : Bool
} derive(Eq, Debug, ToJson)
///|
/// Validation diagnostic. `severity` is `"error"` or `"warning"`; `path`
/// points at the field or mapping segment that triggered the diagnostic.
pub struct Diagnostic {
severity : String
code : String
path : String
message : String
} derive(Eq, Debug, ToJson)
///|
/// Error type returned by parsing and encoding helpers.
pub(all) enum SourceMapError {
InvalidBase64(char~ : Char, offset~ : Int)
TruncatedVlq(offset~ : Int)
VlqOverflow(offset~ : Int)
InvalidSegment(line~ : Int, segment~ : Int, values~ : Int, reason~ : String)
JsonParse(message~ : String)
JsonDecode(path~ : String, expected~ : String)
MissingField(field~ : String)
InvalidField(field~ : String, message~ : String)
} derive(Eq, Debug, ToJson)
///|
pub fn SourceMapError::message(self : SourceMapError) -> String {
match self {
InvalidBase64(char~, offset~) =>
"invalid base64 VLQ character '\{char}' at offset \{offset}"
TruncatedVlq(offset~) =>
"unterminated VLQ value starting before offset \{offset}"
VlqOverflow(offset~) => "VLQ value overflows Int near offset \{offset}"
InvalidSegment(line~, segment~, values~, reason~) =>
"invalid mapping segment line=\{line} segment=\{segment} values=\{values}: \{reason}"
JsonParse(message~) => "JSON parse error: \{message}"
JsonDecode(path~, expected~) =>
"JSON decode error at \{path}: expected \{expected}"
MissingField(field~) => "missing required field: \{field}"
InvalidField(field~, message~) => "invalid field \{field}: \{message}"
}
}
///|
pub fn MappingSegment::generated_position(
self : MappingSegment,
) -> GeneratedPosition {
{ line: self.generated_line, column: self.generated_column }
}
///|
pub fn MappingSegment::is_mapped(self : MappingSegment) -> Bool {
self.source_index is Some(_) &&
self.original_line is Some(_) &&
self.original_column is Some(_)
}
///|
pub fn MappingSegment::has_name(self : MappingSegment) -> Bool {
self.name_index is Some(_)
}
///|
pub fn MappingSegment::unmapped(
generated_line : Int,
generated_column : Int,
) -> MappingSegment {
{
generated_line,
generated_column,
source_index: None,
original_line: None,
original_column: None,
name_index: None,
}
}
///|
pub fn MappingSegment::mapped(
generated_line : Int,
generated_column : Int,
source_index : Int,
original_line : Int,
original_column : Int,
name_index? : Int,
) -> MappingSegment {
{
generated_line,
generated_column,
source_index: Some(source_index),
original_line: Some(original_line),
original_column: Some(original_column),
name_index,
}
}
///|
pub fn SourceMap::SourceMap(
sources : ArrayView[String],
mappings : ArrayView[MappingSegment],
names? : ArrayView[String] = [],
file? : String,
source_root? : String,
sources_content? : ArrayView[String?] = [],
ignore_list? : ArrayView[Int] = [],
) -> SourceMap {
{
version: 3,
file,
source_root,
sources: sources.to_owned(),
sources_content: sources_content.to_owned(),
names: names.to_owned(),
mappings: mappings.to_owned(),
ignore_list: ignore_list.to_owned(),
}
}
///|
pub fn SourceMap::empty() -> SourceMap {
SourceMap::SourceMap([], [])
}