Skip to content

Commit 36bd3db

Browse files
committed
gopls/internal/lsp/protocol: move MappedRange
It was formerly in the source package; now it lives adjacent to ColumnMapper, to which it is closely related. Also, encapsulate its start/end offsets and establish the invariant that they are always valid by defining a constructor method, ColumnMapper.OffsetMappedRange. A TODO comment sketches a possible next step: make its conversion methods infallible. Change-Id: I1e148ccdb37a762c0c387a77240a41237612e2cc Reviewed-on: https://go-review.googlesource.com/c/tools/+/460915 TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Robert Findley <[email protected]> Run-TryBot: Alan Donovan <[email protected]> gopls-CI: kokoro <[email protected]>
1 parent 16b3bf8 commit 36bd3db

File tree

6 files changed

+73
-43
lines changed

6 files changed

+73
-43
lines changed

gopls/internal/lsp/protocol/span.go

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,13 @@
66

77
// Here's a handy guide for your tour of the location zoo:
88
//
9-
// Imports: source --> lsppos --> protocol --> span --> token
10-
//
11-
// source.MappedRange = (protocol.ColumnMapper, {start,end}Offset int)
9+
// Imports: lsppos --> protocol --> span --> token
1210
//
1311
// lsppos.TokenMapper = (token.File, lsppos.Mapper)
1412
// lsppos.Mapper = (line offset table, content)
1513
//
1614
// protocol.ColumnMapper = (URI, Content). Does all offset <=> column conversions.
15+
// protocol.MappedRange = (protocol.ColumnMapper, {start,end} int)
1716
// protocol.Location = (URI, protocol.Range)
1817
// protocol.Range = (start, end Position)
1918
// protocol.Position = (line, char uint32) 0-based UTF-16
@@ -37,6 +36,10 @@
3736
// - Replace all uses of lsppos.TokenMapper by the underlying ParsedGoFile,
3837
// which carries a token.File and a ColumnMapper.
3938
// - Then delete lsppos package.
39+
// - ColumnMapper.OffsetPoint and .Position aren't used outside this package.
40+
// OffsetSpan is barely used, and its user would better off with a MappedRange
41+
// or protocol.Range. The span package data tyes are mostly used in tests
42+
// and in argument parsing (without access to file content).
4043

4144
package protocol
4245

@@ -287,6 +290,54 @@ func (m *ColumnMapper) Point(p Position) (span.Point, error) {
287290
return span.FromUTF16Column(lineStart, int(p.Character)+1, m.Content)
288291
}
289292

293+
// OffsetMappedRange returns a MappedRange for the given byte offsets.
294+
// A MappedRange can be converted to any other form.
295+
func (m *ColumnMapper) OffsetMappedRange(start, end int) (MappedRange, error) {
296+
if !(0 <= start && start <= end && end <= len(m.Content)) {
297+
return MappedRange{}, fmt.Errorf("invalid offsets (%d, %d) (file %s has size %d)", start, end, m.URI, len(m.Content))
298+
}
299+
return MappedRange{m, start, end}, nil
300+
}
301+
302+
// A MappedRange represents a valid byte-offset range of a file.
303+
// Through its ColumnMapper it can be converted into other forms such
304+
// as protocol.Range or span.Span.
305+
//
306+
// Construct one by calling ColumnMapper.OffsetMappedRange with start/end offsets.
307+
// From the go/token domain, call safetoken.Offsets first,
308+
// or use a helper such as ParsedGoFile.MappedPosRange.
309+
type MappedRange struct {
310+
Mapper *ColumnMapper
311+
start, end int // valid byte offsets
312+
}
313+
314+
// Offsets returns the (start, end) byte offsets of this range.
315+
func (mr MappedRange) Offsets() (start, end int) { return mr.start, mr.end }
316+
317+
// -- convenience functions --
318+
319+
// URI returns the URI of the range's file.
320+
func (mr MappedRange) URI() span.URI {
321+
return mr.Mapper.URI
322+
}
323+
324+
// TODO(adonovan): once the fluff is removed from all the
325+
// location-conversion methods, it will be obvious that a properly
326+
// constructed MappedRange is always valid and its Range and Span (and
327+
// other) methods simply cannot fail.
328+
// At that point we might want to provide variants of methods such as
329+
// Range and Span below that don't return an error.
330+
331+
// Range returns the range in protocol form.
332+
func (mr MappedRange) Range() (Range, error) {
333+
return mr.Mapper.OffsetRange(mr.start, mr.end)
334+
}
335+
336+
// Span returns the range in span form.
337+
func (mr MappedRange) Span() (span.Span, error) {
338+
return mr.Mapper.OffsetSpan(mr.start, mr.end)
339+
}
340+
290341
func IsPoint(r Range) bool {
291342
return r.Start.Line == r.End.Line && r.Start.Character == r.End.Character
292343
}

gopls/internal/lsp/source/folding_range.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import (
1717

1818
// FoldingRangeInfo holds range and kind info of folding for an ast.Node
1919
type FoldingRangeInfo struct {
20-
MappedRange MappedRange
20+
MappedRange protocol.MappedRange
2121
Kind protocol.FoldingRangeKind
2222
}
2323

gopls/internal/lsp/source/identifier.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ import (
2626
type IdentifierInfo struct {
2727
Name string
2828
Snapshot Snapshot // only needed for .View(); TODO(adonovan): reduce.
29-
MappedRange MappedRange
29+
MappedRange protocol.MappedRange
3030

3131
Type struct {
32-
MappedRange MappedRange
32+
MappedRange protocol.MappedRange
3333
Object types.Object
3434
}
3535

@@ -54,7 +54,7 @@ func (i *IdentifierInfo) IsImport() bool {
5454
}
5555

5656
type Declaration struct {
57-
MappedRange []MappedRange
57+
MappedRange []protocol.MappedRange
5858

5959
// The typechecked node
6060
node ast.Node
@@ -140,7 +140,7 @@ func findIdentifier(ctx context.Context, snapshot Snapshot, pkg Package, pgf *Pa
140140
Declaration: Declaration{
141141
node: decl.File.Name,
142142
nodeFile: decl,
143-
MappedRange: []MappedRange{declRng},
143+
MappedRange: []protocol.MappedRange{declRng},
144144
},
145145
}, nil
146146
}

gopls/internal/lsp/source/references.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import (
2424
// ReferenceInfo holds information about reference to an identifier in Go source.
2525
type ReferenceInfo struct {
2626
Name string
27-
MappedRange MappedRange
27+
MappedRange protocol.MappedRange
2828
ident *ast.Ident
2929
obj types.Object
3030
pkg Package

gopls/internal/lsp/source/util.go

Lines changed: 10 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -23,33 +23,12 @@ import (
2323
"golang.org/x/tools/internal/typeparams"
2424
)
2525

26-
// A MappedRange represents a byte-offset interval within a file.
27-
// Through the ColumnMapper it can be converted into other forms such
28-
// as protocol.Range or span.Span.
26+
// IsGenerated gets and reads the file denoted by uri and reports
27+
// whether it contains a "go:generated" directive as described at
28+
// https://golang.org/s/generatedcode.
2929
//
30-
// Call ParsedGoFile.MappedPosRange to construct from the go/token domain.
31-
type MappedRange struct {
32-
Mapper *protocol.ColumnMapper
33-
Start, End int // byte offsets
34-
}
35-
36-
// -- convenience functions --
37-
38-
// Range returns the range in protocol form.
39-
func (mr MappedRange) Range() (protocol.Range, error) {
40-
return mr.Mapper.OffsetRange(mr.Start, mr.End)
41-
}
42-
43-
// Span returns the range in span form.
44-
func (mr MappedRange) Span() (span.Span, error) {
45-
return mr.Mapper.OffsetSpan(mr.Start, mr.End)
46-
}
47-
48-
// URI returns the URI of the range's file.
49-
func (mr MappedRange) URI() span.URI {
50-
return mr.Mapper.URI
51-
}
52-
30+
// TODO(adonovan): opt: this function does too much.
31+
// Move snapshot.GetFile into the caller (most of which have already done it).
5332
func IsGenerated(ctx context.Context, snapshot Snapshot, uri span.URI) bool {
5433
fh, err := snapshot.GetFile(ctx, uri)
5534
if err != nil {
@@ -72,7 +51,7 @@ func IsGenerated(ctx context.Context, snapshot Snapshot, uri span.URI) bool {
7251
return false
7352
}
7453

75-
func objToMappedRange(pkg Package, obj types.Object) (MappedRange, error) {
54+
func objToMappedRange(pkg Package, obj types.Object) (protocol.MappedRange, error) {
7655
nameLen := len(obj.Name())
7756
if pkgName, ok := obj.(*types.PkgName); ok {
7857
// An imported Go package has a package-local, unqualified name.
@@ -98,18 +77,18 @@ func objToMappedRange(pkg Package, obj types.Object) (MappedRange, error) {
9877
// TODO(adonovan): many of the callers need only the ParsedGoFile so
9978
// that they can call pgf.PosRange(pos, end) to get a Range; they
10079
// don't actually need a MappedRange.
101-
func posToMappedRange(pkg Package, pos, end token.Pos) (MappedRange, error) {
80+
func posToMappedRange(pkg Package, pos, end token.Pos) (protocol.MappedRange, error) {
10281
if !pos.IsValid() {
103-
return MappedRange{}, fmt.Errorf("invalid start position")
82+
return protocol.MappedRange{}, fmt.Errorf("invalid start position")
10483
}
10584
if !end.IsValid() {
106-
return MappedRange{}, fmt.Errorf("invalid end position")
85+
return protocol.MappedRange{}, fmt.Errorf("invalid end position")
10786
}
10887

10988
logicalFilename := pkg.FileSet().File(pos).Name() // ignore line directives
11089
pgf, _, err := findFileInDeps(pkg, span.URIFromPath(logicalFilename))
11190
if err != nil {
112-
return MappedRange{}, err
91+
return protocol.MappedRange{}, err
11392
}
11493
return pgf.PosMappedRange(pos, end)
11594
}

gopls/internal/lsp/source/view.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -401,12 +401,12 @@ func (pgf *ParsedGoFile) PosRange(start, end token.Pos) (protocol.Range, error)
401401

402402
// PosMappedRange returns a MappedRange for the token.Pos interval in this file.
403403
// A MappedRange can be converted to any other form.
404-
func (pgf *ParsedGoFile) PosMappedRange(startPos, endPos token.Pos) (MappedRange, error) {
404+
func (pgf *ParsedGoFile) PosMappedRange(startPos, endPos token.Pos) (protocol.MappedRange, error) {
405405
start, end, err := safetoken.Offsets(pgf.Tok, startPos, endPos)
406406
if err != nil {
407-
return MappedRange{}, nil
407+
return protocol.MappedRange{}, nil
408408
}
409-
return MappedRange{pgf.Mapper, start, end}, nil
409+
return pgf.Mapper.OffsetMappedRange(start, end)
410410
}
411411

412412
// RangeToSpanRange parses a protocol Range back into the go/token domain.

0 commit comments

Comments
 (0)