Changed: DB Params
This commit is contained in:
192
templ/lsp/uri/uri.go
Normal file
192
templ/lsp/uri/uri.go
Normal file
@@ -0,0 +1,192 @@
|
||||
// Copyright 2019 The Go Language Server 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 uri
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
const (
|
||||
// FileScheme schema of filesystem path.
|
||||
FileScheme = "file"
|
||||
|
||||
// HTTPScheme schema of http.
|
||||
HTTPScheme = "http"
|
||||
|
||||
// HTTPSScheme schema of https.
|
||||
HTTPSScheme = "https"
|
||||
)
|
||||
|
||||
const (
|
||||
hierPart = "://"
|
||||
)
|
||||
|
||||
// URI Uniform Resource Identifier (URI) https://tools.ietf.org/html/rfc3986.
|
||||
//
|
||||
// This class is a simple parser which creates the basic component parts
|
||||
// (http://tools.ietf.org/html/rfc3986#section-3) with minimal validation
|
||||
// and encoding.
|
||||
//
|
||||
// foo://example.com:8042/over/there?name=ferret#nose
|
||||
// \_/ \______________/\_________/ \_________/ \__/
|
||||
// | | | | |
|
||||
// scheme authority path query fragment
|
||||
// | _____________________|__
|
||||
// / \ / \
|
||||
// urn:example:animal:ferret:nose
|
||||
type URI string
|
||||
|
||||
// Filename returns the file path for the given URI.
|
||||
// It is an error to call this on a URI that is not a valid filename.
|
||||
func (u URI) Filename() string {
|
||||
filename, err := filename(u)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return filepath.FromSlash(filename)
|
||||
}
|
||||
|
||||
func filename(uri URI) (string, error) {
|
||||
u, err := url.ParseRequestURI(string(uri))
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to parse request URI: %w", err)
|
||||
}
|
||||
|
||||
if u.Scheme != FileScheme {
|
||||
return "", fmt.Errorf("only file URIs are supported, got %v", u.Scheme)
|
||||
}
|
||||
|
||||
if isWindowsDriveURI(u.Path) {
|
||||
u.Path = u.Path[1:]
|
||||
}
|
||||
|
||||
return u.Path, nil
|
||||
}
|
||||
|
||||
// New parses and creates a new URI from s.
|
||||
func New(s string) URI {
|
||||
if u, err := url.PathUnescape(s); err == nil {
|
||||
s = u
|
||||
}
|
||||
|
||||
if strings.HasPrefix(s, FileScheme+hierPart) {
|
||||
return URI(s)
|
||||
}
|
||||
|
||||
return File(s)
|
||||
}
|
||||
|
||||
// File parses and creates a new filesystem URI from path.
|
||||
func File(path string) URI {
|
||||
const goRootPragma = "$GOROOT"
|
||||
if len(path) >= len(goRootPragma) && strings.EqualFold(goRootPragma, path[:len(goRootPragma)]) {
|
||||
path = runtime.GOROOT() + path[len(goRootPragma):]
|
||||
}
|
||||
|
||||
if !isWindowsDrivePath(path) {
|
||||
if abs, err := filepath.Abs(path); err == nil {
|
||||
path = abs
|
||||
}
|
||||
}
|
||||
|
||||
if isWindowsDrivePath(path) {
|
||||
path = "/" + path
|
||||
}
|
||||
|
||||
path = filepath.ToSlash(path)
|
||||
u := url.URL{
|
||||
Scheme: FileScheme,
|
||||
Path: path,
|
||||
}
|
||||
|
||||
return URI(u.String())
|
||||
}
|
||||
|
||||
// Parse parses and creates a new URI from s.
|
||||
func Parse(s string) (u URI, err error) {
|
||||
us, err := url.Parse(s)
|
||||
if err != nil {
|
||||
return u, fmt.Errorf("url.Parse: %w", err)
|
||||
}
|
||||
|
||||
switch us.Scheme {
|
||||
case FileScheme:
|
||||
ut := url.URL{
|
||||
Scheme: FileScheme,
|
||||
Path: us.Path,
|
||||
RawPath: filepath.FromSlash(us.Path),
|
||||
}
|
||||
u = URI(ut.String())
|
||||
|
||||
case HTTPScheme, HTTPSScheme:
|
||||
ut := url.URL{
|
||||
Scheme: us.Scheme,
|
||||
Host: us.Host,
|
||||
Path: us.Path,
|
||||
RawQuery: us.Query().Encode(),
|
||||
Fragment: us.Fragment,
|
||||
}
|
||||
u = URI(ut.String())
|
||||
|
||||
default:
|
||||
return u, errors.New("unknown scheme")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// From returns the new URI from args.
|
||||
func From(scheme, authority, path, query, fragment string) URI {
|
||||
switch scheme {
|
||||
case FileScheme:
|
||||
u := url.URL{
|
||||
Scheme: FileScheme,
|
||||
Path: path,
|
||||
RawPath: filepath.FromSlash(path),
|
||||
}
|
||||
return URI(u.String())
|
||||
|
||||
case HTTPScheme, HTTPSScheme:
|
||||
u := url.URL{
|
||||
Scheme: scheme,
|
||||
Host: authority,
|
||||
Path: path,
|
||||
RawQuery: url.QueryEscape(query),
|
||||
Fragment: fragment,
|
||||
}
|
||||
return URI(u.String())
|
||||
|
||||
default:
|
||||
panic(fmt.Sprintf("unknown scheme: %s", scheme))
|
||||
}
|
||||
}
|
||||
|
||||
// isWindowsDrivePath returns true if the file path is of the form used by Windows.
|
||||
//
|
||||
// We check if the path begins with a drive letter, followed by a ":".
|
||||
func isWindowsDrivePath(path string) bool {
|
||||
if len(path) < 4 {
|
||||
return false
|
||||
}
|
||||
return unicode.IsLetter(rune(path[0])) && path[1] == ':'
|
||||
}
|
||||
|
||||
// isWindowsDriveURI returns true if the file URI is of the format used by
|
||||
// Windows URIs. The url.Parse package does not specially handle Windows paths
|
||||
// (see https://golang.org/issue/6027). We check if the URI path has
|
||||
// a drive prefix (e.g. "/C:"). If so, we trim the leading "/".
|
||||
func isWindowsDriveURI(uri string) bool {
|
||||
if len(uri) < 4 {
|
||||
return false
|
||||
}
|
||||
return uri[0] == '/' && unicode.IsLetter(rune(uri[1])) && uri[2] == ':'
|
||||
}
|
142
templ/lsp/uri/uri_test.go
Normal file
142
templ/lsp/uri/uri_test.go
Normal file
@@ -0,0 +1,142 @@
|
||||
// Copyright 2019 The Go Language Server 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 uri
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
)
|
||||
|
||||
func TestFile(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
path string
|
||||
want URI
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "ValidFileScheme",
|
||||
path: "/users/me/c#-projects/",
|
||||
want: URI(FileScheme + hierPart + "/users/me/c%23-projects"),
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Invalid",
|
||||
path: "users-me-c#-projects",
|
||||
want: URI(""),
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if diff := cmp.Diff(File(tt.path), tt.want); (diff != "") != tt.wantErr {
|
||||
t.Errorf("%s: (-got, +want)\n%s", tt.name, diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestParse(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
s string
|
||||
want URI
|
||||
}{
|
||||
{
|
||||
name: "ValidFileScheme",
|
||||
s: "file://code.visualstudio.com/docs/extensions/overview.md",
|
||||
want: URI(FileScheme + hierPart + "/docs/extensions/overview.md"),
|
||||
},
|
||||
{
|
||||
name: "ValidHTTPScheme",
|
||||
s: "http://code.visualstudio.com/docs/extensions/overview#frag",
|
||||
want: URI(HTTPScheme + hierPart + "code.visualstudio.com/docs/extensions/overview#frag"),
|
||||
},
|
||||
{
|
||||
name: "ValidHTTPSScheme",
|
||||
s: "https://code.visualstudio.com/docs/extensions/overview#frag",
|
||||
want: URI(HTTPSScheme + hierPart + "code.visualstudio.com/docs/extensions/overview#frag"),
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
got, err := Parse(tt.s)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
if diff := cmp.Diff(got, tt.want); diff != "" {
|
||||
t.Errorf("%s: (-got, +want)\n%s", tt.name, diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFrom(t *testing.T) {
|
||||
type args struct {
|
||||
scheme string
|
||||
authority string
|
||||
path string
|
||||
query string
|
||||
fragment string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want URI
|
||||
}{
|
||||
{
|
||||
name: "ValidFileScheme",
|
||||
args: args{
|
||||
scheme: "file",
|
||||
authority: "example.com",
|
||||
path: "/over/there",
|
||||
query: "name=ferret",
|
||||
fragment: "nose",
|
||||
},
|
||||
want: URI(FileScheme + hierPart + "/over/there"),
|
||||
},
|
||||
{
|
||||
name: "ValidHTTPScheme",
|
||||
args: args{
|
||||
scheme: "http",
|
||||
authority: "example.com:8042",
|
||||
path: "/over/there",
|
||||
query: "name=ferret",
|
||||
fragment: "nose",
|
||||
},
|
||||
want: URI(HTTPScheme + hierPart + "example.com:8042/over/there?name%3Dferret#nose"),
|
||||
},
|
||||
{
|
||||
name: "ValidHTTPSScheme",
|
||||
args: args{
|
||||
scheme: "https",
|
||||
authority: "example.com:8042",
|
||||
path: "/over/there",
|
||||
query: "name=ferret",
|
||||
fragment: "nose",
|
||||
},
|
||||
want: URI(HTTPSScheme + hierPart + "example.com:8042/over/there?name%3Dferret#nose"),
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if diff := cmp.Diff(From(tt.args.scheme, tt.args.authority, tt.args.path, tt.args.query, tt.args.fragment), tt.want); diff != "" {
|
||||
t.Errorf("%s: (-got, +want)\n%s", tt.name, diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user