aboutsummaryrefslogblamecommitdiffstats
path: root/vendor/gopkg.in/sourcemap.v1/consumer.go
blob: 3bed06a2a57a890d659e05413ba7d5fb43cc83e0 (plain) (tree)
1
2
3
4
5
6
7
8
9
                 


                       
             



                 















                                                        



                                                                                       
























































                                                                                              



                                                             






                                                                      

                                                 




                                                                  
                                            




























                                                                 
package sourcemap

import (
    "encoding/json"
    "fmt"
    "net/url"
    "path"
    "sort"
    "strconv"
)

type Consumer struct {
    sourceRootURL *url.URL
    smap          *sourceMap
    mappings      []mapping
}

func Parse(mapURL string, b []byte) (*Consumer, error) {
    smap := new(sourceMap)
    err := json.Unmarshal(b, smap)
    if err != nil {
        return nil, err
    }

    if smap.Version != 3 {
        return nil, fmt.Errorf(
            "sourcemap: got version=%d, but only 3rd version is supported",
            smap.Version,
        )
    }

    var sourceRootURL *url.URL
    if smap.SourceRoot != "" {
        u, err := url.Parse(smap.SourceRoot)
        if err != nil {
            return nil, err
        }
        if u.IsAbs() {
            sourceRootURL = u
        }
    } else if mapURL != "" {
        u, err := url.Parse(mapURL)
        if err != nil {
            return nil, err
        }
        if u.IsAbs() {
            u.Path = path.Dir(u.Path)
            sourceRootURL = u
        }
    }

    mappings, err := parseMappings(smap.Mappings)
    if err != nil {
        return nil, err
    }
    // Free memory.
    smap.Mappings = ""

    return &Consumer{
        sourceRootURL: sourceRootURL,
        smap:          smap,
        mappings:      mappings,
    }, nil
}

func (c *Consumer) File() string {
    return c.smap.File
}

func (c *Consumer) Source(genLine, genCol int) (source, name string, line, col int, ok bool) {
    i := sort.Search(len(c.mappings), func(i int) bool {
        m := &c.mappings[i]
        if m.genLine == genLine {
            return m.genCol >= genCol
        }
        return m.genLine >= genLine
    })

    // Mapping not found.
    if i == len(c.mappings) {
        return
    }

    match := &c.mappings[i]

    // Fuzzy match.
    if match.genLine > genLine || match.genCol > genCol {
        if i == 0 {
            return
        }
        match = &c.mappings[i-1]
    }

    if match.sourcesInd >= 0 {
        source = c.absSource(c.smap.Sources[match.sourcesInd])
    }
    if match.namesInd >= 0 {
        v := c.smap.Names[match.namesInd]
        switch v := v.(type) {
        case string:
            name = v
        case float64:
            name = strconv.FormatFloat(v, 'f', -1, 64)
        default:
            name = fmt.Sprint(v)
        }
    }
    line = match.sourceLine
    col = match.sourceCol
    ok = true
    return
}

func (c *Consumer) absSource(source string) string {
    if path.IsAbs(source) {
        return source
    }

    if u, err := url.Parse(source); err == nil && u.IsAbs() {
        return source
    }

    if c.sourceRootURL != nil {
        u := *c.sourceRootURL
        u.Path = path.Join(c.sourceRootURL.Path, source)
        return u.String()
    }

    if c.smap.SourceRoot != "" {
        return path.Join(c.smap.SourceRoot, source)
    }

    return source
}