github.com/mdaxf/iac@v0.0.0-20240519030858-58a061660378/vendor_skip/gopkg.in/sourcemap.v1/consumer.go (about)

     1  package sourcemap
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"net/url"
     7  	"path"
     8  	"sort"
     9  	"strconv"
    10  )
    11  
    12  type Consumer struct {
    13  	sourceRootURL *url.URL
    14  	smap          *sourceMap
    15  	mappings      []mapping
    16  }
    17  
    18  func Parse(mapURL string, b []byte) (*Consumer, error) {
    19  	smap := new(sourceMap)
    20  	err := json.Unmarshal(b, smap)
    21  	if err != nil {
    22  		return nil, err
    23  	}
    24  
    25  	if smap.Version != 3 {
    26  		return nil, fmt.Errorf(
    27  			"sourcemap: got version=%d, but only 3rd version is supported",
    28  			smap.Version,
    29  		)
    30  	}
    31  
    32  	var sourceRootURL *url.URL
    33  	if smap.SourceRoot != "" {
    34  		u, err := url.Parse(smap.SourceRoot)
    35  		if err != nil {
    36  			return nil, err
    37  		}
    38  		if u.IsAbs() {
    39  			sourceRootURL = u
    40  		}
    41  	} else if mapURL != "" {
    42  		u, err := url.Parse(mapURL)
    43  		if err != nil {
    44  			return nil, err
    45  		}
    46  		if u.IsAbs() {
    47  			u.Path = path.Dir(u.Path)
    48  			sourceRootURL = u
    49  		}
    50  	}
    51  
    52  	mappings, err := parseMappings(smap.Mappings)
    53  	if err != nil {
    54  		return nil, err
    55  	}
    56  	// Free memory.
    57  	smap.Mappings = ""
    58  
    59  	return &Consumer{
    60  		sourceRootURL: sourceRootURL,
    61  		smap:          smap,
    62  		mappings:      mappings,
    63  	}, nil
    64  }
    65  
    66  func (c *Consumer) File() string {
    67  	return c.smap.File
    68  }
    69  
    70  func (c *Consumer) Source(genLine, genCol int) (source, name string, line, col int, ok bool) {
    71  	i := sort.Search(len(c.mappings), func(i int) bool {
    72  		m := &c.mappings[i]
    73  		if m.genLine == genLine {
    74  			return m.genCol >= genCol
    75  		}
    76  		return m.genLine >= genLine
    77  	})
    78  
    79  	// Mapping not found.
    80  	if i == len(c.mappings) {
    81  		return
    82  	}
    83  
    84  	match := &c.mappings[i]
    85  
    86  	// Fuzzy match.
    87  	if match.genLine > genLine || match.genCol > genCol {
    88  		if i == 0 {
    89  			return
    90  		}
    91  		match = &c.mappings[i-1]
    92  	}
    93  
    94  	if match.sourcesInd >= 0 {
    95  		source = c.absSource(c.smap.Sources[match.sourcesInd])
    96  	}
    97  	if match.namesInd >= 0 {
    98  		v := c.smap.Names[match.namesInd]
    99  		switch v := v.(type) {
   100  		case string:
   101  			name = v
   102  		case float64:
   103  			name = strconv.FormatFloat(v, 'f', -1, 64)
   104  		default:
   105  			name = fmt.Sprint(v)
   106  		}
   107  	}
   108  	line = match.sourceLine
   109  	col = match.sourceCol
   110  	ok = true
   111  	return
   112  }
   113  
   114  func (c *Consumer) absSource(source string) string {
   115  	if path.IsAbs(source) {
   116  		return source
   117  	}
   118  
   119  	if u, err := url.Parse(source); err == nil && u.IsAbs() {
   120  		return source
   121  	}
   122  
   123  	if c.sourceRootURL != nil {
   124  		u := *c.sourceRootURL
   125  		u.Path = path.Join(c.sourceRootURL.Path, source)
   126  		return u.String()
   127  	}
   128  
   129  	if c.smap.SourceRoot != "" {
   130  		return path.Join(c.smap.SourceRoot, source)
   131  	}
   132  
   133  	return source
   134  }