mirror of
https://github.com/golang/go
synced 2024-11-18 11:44:45 -07:00
f7b8cc7bd0
Create a real type for protocol.DocumentURIs. Remove span.NewURI in favor of path/URI-specific constructors. Remove span.Parse's ability to parse URI-based spans, which appears to be totally unused. As a consequence, we no longer mangle non-file URIs to start with file://, and crash all over the place when one is opened. Updates golang/go#33699. Change-Id: Ic7347c9768e38002b4ad9c84471329d0af7d2e05 Reviewed-on: https://go-review.googlesource.com/c/tools/+/219482 Run-TryBot: Heschi Kreinick <heschi@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Rebecca Stambler <rstambler@golang.org>
101 lines
2.7 KiB
Go
101 lines
2.7 KiB
Go
// Copyright 2019 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package span
|
|
|
|
import (
|
|
"strconv"
|
|
"strings"
|
|
"unicode/utf8"
|
|
)
|
|
|
|
// Parse returns the location represented by the input.
|
|
// Only file paths are accepted, not URIs.
|
|
// The returned span will be normalized, and thus if printed may produce a
|
|
// different string.
|
|
func Parse(input string) Span {
|
|
// :0:0#0-0:0#0
|
|
valid := input
|
|
var hold, offset int
|
|
hadCol := false
|
|
suf := rstripSuffix(input)
|
|
if suf.sep == "#" {
|
|
offset = suf.num
|
|
suf = rstripSuffix(suf.remains)
|
|
}
|
|
if suf.sep == ":" {
|
|
valid = suf.remains
|
|
hold = suf.num
|
|
hadCol = true
|
|
suf = rstripSuffix(suf.remains)
|
|
}
|
|
switch {
|
|
case suf.sep == ":":
|
|
return New(URIFromPath(suf.remains), NewPoint(suf.num, hold, offset), Point{})
|
|
case suf.sep == "-":
|
|
// we have a span, fall out of the case to continue
|
|
default:
|
|
// separator not valid, rewind to either the : or the start
|
|
return New(URIFromPath(valid), NewPoint(hold, 0, offset), Point{})
|
|
}
|
|
// only the span form can get here
|
|
// at this point we still don't know what the numbers we have mean
|
|
// if have not yet seen a : then we might have either a line or a column depending
|
|
// on whether start has a column or not
|
|
// we build an end point and will fix it later if needed
|
|
end := NewPoint(suf.num, hold, offset)
|
|
hold, offset = 0, 0
|
|
suf = rstripSuffix(suf.remains)
|
|
if suf.sep == "#" {
|
|
offset = suf.num
|
|
suf = rstripSuffix(suf.remains)
|
|
}
|
|
if suf.sep != ":" {
|
|
// turns out we don't have a span after all, rewind
|
|
return New(URIFromPath(valid), end, Point{})
|
|
}
|
|
valid = suf.remains
|
|
hold = suf.num
|
|
suf = rstripSuffix(suf.remains)
|
|
if suf.sep != ":" {
|
|
// line#offset only
|
|
return New(URIFromPath(valid), NewPoint(hold, 0, offset), end)
|
|
}
|
|
// we have a column, so if end only had one number, it is also the column
|
|
if !hadCol {
|
|
end = NewPoint(suf.num, end.v.Line, end.v.Offset)
|
|
}
|
|
return New(URIFromPath(suf.remains), NewPoint(suf.num, hold, offset), end)
|
|
}
|
|
|
|
type suffix struct {
|
|
remains string
|
|
sep string
|
|
num int
|
|
}
|
|
|
|
func rstripSuffix(input string) suffix {
|
|
if len(input) == 0 {
|
|
return suffix{"", "", -1}
|
|
}
|
|
remains := input
|
|
num := -1
|
|
// first see if we have a number at the end
|
|
last := strings.LastIndexFunc(remains, func(r rune) bool { return r < '0' || r > '9' })
|
|
if last >= 0 && last < len(remains)-1 {
|
|
number, err := strconv.ParseInt(remains[last+1:], 10, 64)
|
|
if err == nil {
|
|
num = int(number)
|
|
remains = remains[:last+1]
|
|
}
|
|
}
|
|
// now see if we have a trailing separator
|
|
r, w := utf8.DecodeLastRuneInString(remains)
|
|
if r != ':' && r != '#' && r == '#' {
|
|
return suffix{input, "", -1}
|
|
}
|
|
remains = remains[:len(remains)-w]
|
|
return suffix{remains, string(r), num}
|
|
}
|