v2 / vlib / v / gen / js / sourcemap / source_map.v
135 lines · 116 sloc · 3.85 KB · e2e5cf8db56f3562c7baa735061690be936bdf3e
Raw
1module sourcemap
2
3import io
4import os
5import x.json2
6
7const source_map_version = 3
8
9type SourceMapJson = map[string]json2.Any
10
11pub struct SourceMap {
12pub mut:
13 version int @[json: version]
14 file string @[json: file]
15 source_root string @[json: source_root]
16 sources Sets @[json: sources]
17 sources_content map[string]string
18 names Sets
19 mappings Mappings
20 sources_content_inline bool
21}
22
23struct StringWriter {
24pub mut:
25 bytes []u8
26}
27
28pub fn new_sourcemap(file string, source_root string, sources_content_inline bool) SourceMap {
29 return SourceMap{
30 version: source_map_version
31 file: file
32 source_root: source_root
33 mappings: new_mappings()
34 sources_content_inline: sources_content_inline
35 }
36}
37
38// Add a single mapping from original source line and column to the generated source's line and column for this source map being created.
39pub fn (mut sm SourceMap) add_mapping(source_name string, source_position SourcePositionType, gen_line u32,
40 gen_column u32, name string) {
41 if source_name == '' {
42 panic('add_mapping, source_name should not be ""')
43 }
44
45 sources_ind := sm.sources.add(source_name)
46
47 names_ind := if name != '' {
48 NameIndexType(IndexNumber(sm.names.add(name)))
49 } else {
50 NameIndexType(Empty{})
51 }
52 sm.mappings.add_mapping(gen_line, gen_column, sources_ind, source_position, names_ind)
53}
54
55// Add multiple mappings from the same source
56pub fn (mut sm SourceMap) add_mapping_list(source_name string, mapping_list []MappingInput) ! {
57 if source_name == '' {
58 panic('add_mapping_list, source_name should not be ""')
59 }
60
61 sources_ind := sm.sources.add(source_name)
62
63 for mapping in mapping_list {
64 names_ind := if mapping.name != '' {
65 NameIndexType(IndexNumber(sm.names.add(mapping.name)))
66 } else {
67 NameIndexType(Empty{})
68 }
69 sm.mappings.add_mapping(mapping.gen_line, mapping.gen_column, sources_ind,
70 mapping.source_position, names_ind)
71 }
72}
73
74// Set the source content for a source file.
75pub fn (mut sm SourceMap) set_source_content(source_name string, source_content string) {
76 sm.sources_content[source_name] = source_content
77}
78
79fn (mut sm SourceMap) export_mappings(mut writer io.Writer) {
80 sm.mappings.export_mappings(mut writer) or { panic('export failed') }
81}
82
83fn (mut sm SourceMap) export_mappings_string() string {
84 mut output := &StringWriter{}
85
86 sm.mappings.export_mappings(mut output) or { panic('export failed') }
87 return output.bytes.bytestr()
88}
89
90// create a JSON representing the sourcemap
91// Sourcemap Specs http://sourcemaps.info/spec.html
92pub fn (mut sm SourceMap) to_json() SourceMapJson {
93 mut source_map_json := map[string]json2.Any{}
94 mappings_json := sm.export_mappings_string()
95 source_map_json['version'] = sm.version
96 if sm.file != '' {
97 source_map_json['file'] = json2.Any(sm.file)
98 }
99 if sm.source_root != '' {
100 source_map_json['sourceRoot'] = json2.Any(sm.source_root)
101 }
102 mut sources_json := []json2.Any{}
103 mut sources_content_json := []json2.Any{}
104 for source_file, _ in sm.sources.value {
105 sources_json << source_file
106 if source_file in sm.sources_content {
107 sources_content_json << sm.sources_content[source_file]
108 } else {
109 if sm.sources_content_inline {
110 if source_file_content := os.read_file(source_file) {
111 sources_content_json << source_file_content
112 } else {
113 sources_content_json << json2.null
114 }
115 } else {
116 sources_content_json << json2.null
117 }
118 }
119 }
120 source_map_json['sources'] = json2.Any(sources_json)
121 source_map_json['sourcesContent'] = json2.Any(sources_content_json)
122
123 mut names_json := []json2.Any{}
124 for name, _ in sm.names.value {
125 names_json << name
126 }
127 source_map_json['names'] = json2.Any(names_json)
128 source_map_json['mappings'] = json2.Any(mappings_json)
129 return source_map_json
130}
131
132fn (mut w StringWriter) write(buf []u8) !int {
133 w.bytes << buf
134 return buf.len
135}
136