.gitignore added
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.1.1-0.20210319172145-bda8f5cee399 / internal / span / parse.go
1 // Copyright 2019 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package span
6
7 import (
8         "path/filepath"
9         "strconv"
10         "strings"
11         "unicode/utf8"
12 )
13
14 // Parse returns the location represented by the input.
15 // Only file paths are accepted, not URIs.
16 // The returned span will be normalized, and thus if printed may produce a
17 // different string.
18 func Parse(input string) Span {
19         return ParseInDir(input, ".")
20 }
21
22 // ParseInDir is like Parse, but interprets paths relative to wd.
23 func ParseInDir(input, wd string) Span {
24         uri := func(path string) URI {
25                 if !filepath.IsAbs(path) {
26                         path = filepath.Join(wd, path)
27                 }
28                 return URIFromPath(path)
29         }
30         // :0:0#0-0:0#0
31         valid := input
32         var hold, offset int
33         hadCol := false
34         suf := rstripSuffix(input)
35         if suf.sep == "#" {
36                 offset = suf.num
37                 suf = rstripSuffix(suf.remains)
38         }
39         if suf.sep == ":" {
40                 valid = suf.remains
41                 hold = suf.num
42                 hadCol = true
43                 suf = rstripSuffix(suf.remains)
44         }
45         switch {
46         case suf.sep == ":":
47                 return New(uri(suf.remains), NewPoint(suf.num, hold, offset), Point{})
48         case suf.sep == "-":
49                 // we have a span, fall out of the case to continue
50         default:
51                 // separator not valid, rewind to either the : or the start
52                 return New(uri(valid), NewPoint(hold, 0, offset), Point{})
53         }
54         // only the span form can get here
55         // at this point we still don't know what the numbers we have mean
56         // if have not yet seen a : then we might have either a line or a column depending
57         // on whether start has a column or not
58         // we build an end point and will fix it later if needed
59         end := NewPoint(suf.num, hold, offset)
60         hold, offset = 0, 0
61         suf = rstripSuffix(suf.remains)
62         if suf.sep == "#" {
63                 offset = suf.num
64                 suf = rstripSuffix(suf.remains)
65         }
66         if suf.sep != ":" {
67                 // turns out we don't have a span after all, rewind
68                 return New(uri(valid), end, Point{})
69         }
70         valid = suf.remains
71         hold = suf.num
72         suf = rstripSuffix(suf.remains)
73         if suf.sep != ":" {
74                 // line#offset only
75                 return New(uri(valid), NewPoint(hold, 0, offset), end)
76         }
77         // we have a column, so if end only had one number, it is also the column
78         if !hadCol {
79                 end = NewPoint(suf.num, end.v.Line, end.v.Offset)
80         }
81         return New(uri(suf.remains), NewPoint(suf.num, hold, offset), end)
82 }
83
84 type suffix struct {
85         remains string
86         sep     string
87         num     int
88 }
89
90 func rstripSuffix(input string) suffix {
91         if len(input) == 0 {
92                 return suffix{"", "", -1}
93         }
94         remains := input
95         num := -1
96         // first see if we have a number at the end
97         last := strings.LastIndexFunc(remains, func(r rune) bool { return r < '0' || r > '9' })
98         if last >= 0 && last < len(remains)-1 {
99                 number, err := strconv.ParseInt(remains[last+1:], 10, 64)
100                 if err == nil {
101                         num = int(number)
102                         remains = remains[:last+1]
103                 }
104         }
105         // now see if we have a trailing separator
106         r, w := utf8.DecodeLastRuneInString(remains)
107         if r != ':' && r != '#' && r == '#' {
108                 return suffix{input, "", -1}
109         }
110         remains = remains[:len(remains)-w]
111         return suffix{remains, string(r), num}
112 }