forked from MathieuTurcotte/sourcemap
-
Notifications
You must be signed in to change notification settings - Fork 0
/
sourcemap.go
107 lines (87 loc) · 2.84 KB
/
sourcemap.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
// Copyright (c) 2013 Mathieu Turcotte
// Licensed under the MIT license.
// This packages implement functions to read the source map format described
// in the "Source Map Revision 3 Proposal" available at http://goo.gl/bcVlcK
package sourcemap
import (
"fmt"
"sort"
)
// Represents the mapping to a line/column/name in the original file.
type OriginalMapping struct {
File string // The filename of the original file.
Line int // 1-based line number.
Column int // 1-based column number.
Name string // The symbol name, if any.
}
// Represents a section of the generated source that can be mapped back to the
// original source.
type Entry struct {
GeneratedColumn int // 0-based column of this entry in the generated source.
SourceFileId int // Index of the source file in the "sources" list.
SourceLine int // 0-based line number of this entry in the source file.
SourceColumn int // 0-based column number of this entry in the source file.
NameId int // Index of the symbol name in the "names" list.
}
// Represents a line in the generated source. A line is composed of entries
// containing information about the original source file.
type Line []Entry
// A struct representing the decoded source map.
type SourceMap struct {
Version int
File string
SourceRoot string
Sources []string
SourcesContent []string
Names []string
Mappings []Line
}
// Given a line and a column number in the generated code, find a mapping in
// the original source. The line and column parameters are 1-based. If no
// mapping can be found for a given line, a mapping on the previous line is
// returned.
func (s *SourceMap) GetSourceMapping(linum, column int) (mapping OriginalMapping, err error) {
linum--
column--
if linum < 0 || linum > len(s.Mappings) {
err = fmt.Errorf("invalid line number: %v", linum+1)
return
}
if column < 0 {
err = fmt.Errorf("invalid column number: %v", column+1)
return
}
line := s.Mappings[linum]
if len(line) == 0 || line[0].GeneratedColumn > column {
return s.getPreviousLineMapping(linum)
}
index := sort.Search(len(line), func(i int) bool {
return line[i].GeneratedColumn <= column
})
entry := line[index]
s.populateMapping(&mapping, entry)
return
}
func (s *SourceMap) getPreviousLineMapping(linum int) (mapping OriginalMapping, err error) {
for {
linum--
if linum < 0 {
err = fmt.Errorf("cannot find previous line mapping")
return
}
line := s.Mappings[linum]
if len(line) > 0 {
entry := line[len(line)-1]
s.populateMapping(&mapping, entry)
return
}
}
}
func (s *SourceMap) populateMapping(mapping *OriginalMapping, entry Entry) {
mapping.File = s.Sources[entry.SourceFileId]
mapping.Line = entry.SourceLine + 1
mapping.Column = entry.SourceColumn + 1
if entry.NameId >= 0 {
mapping.Name = s.Names[entry.NameId]
}
}