golang.org/x/tools/gopls@v0.15.3/internal/cache/parsego/file.go (about)

     1  // Copyright 2023 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 parsego
     6  
     7  import (
     8  	"go/ast"
     9  	"go/parser"
    10  	"go/scanner"
    11  	"go/token"
    12  
    13  	"golang.org/x/tools/gopls/internal/protocol"
    14  	"golang.org/x/tools/gopls/internal/util/safetoken"
    15  )
    16  
    17  // A File contains the results of parsing a Go file.
    18  type File struct {
    19  	URI  protocol.DocumentURI
    20  	Mode parser.Mode
    21  	File *ast.File
    22  	Tok  *token.File
    23  	// Source code used to build the AST. It may be different from the
    24  	// actual content of the file if we have fixed the AST.
    25  	Src []byte
    26  
    27  	// fixedSrc and fixedAST report on "fixing" that occurred during parsing of
    28  	// this file.
    29  	//
    30  	// fixedSrc means Src holds file content that was modified to improve parsing.
    31  	// fixedAST means File was modified after parsing, so AST positions may not
    32  	// reflect the content of Src.
    33  	//
    34  	// TODO(rfindley): there are many places where we haphazardly use the Src or
    35  	// positions without checking these fields. Audit these places and guard
    36  	// accordingly. After doing so, we may find that we don't need to
    37  	// differentiate fixedSrc and fixedAST.
    38  	fixedSrc bool
    39  	fixedAST bool
    40  	Mapper   *protocol.Mapper // may map fixed Src, not file content
    41  	ParseErr scanner.ErrorList
    42  }
    43  
    44  // Fixed reports whether p was "Fixed", meaning that its source or positions
    45  // may not correlate with the original file.
    46  func (p File) Fixed() bool {
    47  	return p.fixedSrc || p.fixedAST
    48  }
    49  
    50  // -- go/token domain convenience helpers --
    51  
    52  // PositionPos returns the token.Pos of protocol position p within the file.
    53  func (pgf *File) PositionPos(p protocol.Position) (token.Pos, error) {
    54  	offset, err := pgf.Mapper.PositionOffset(p)
    55  	if err != nil {
    56  		return token.NoPos, err
    57  	}
    58  	return safetoken.Pos(pgf.Tok, offset)
    59  }
    60  
    61  // PosRange returns a protocol Range for the token.Pos interval in this file.
    62  func (pgf *File) PosRange(start, end token.Pos) (protocol.Range, error) {
    63  	return pgf.Mapper.PosRange(pgf.Tok, start, end)
    64  }
    65  
    66  // PosMappedRange returns a MappedRange for the token.Pos interval in this file.
    67  // A MappedRange can be converted to any other form.
    68  func (pgf *File) PosMappedRange(start, end token.Pos) (protocol.MappedRange, error) {
    69  	return pgf.Mapper.PosMappedRange(pgf.Tok, start, end)
    70  }
    71  
    72  // PosLocation returns a protocol Location for the token.Pos interval in this file.
    73  func (pgf *File) PosLocation(start, end token.Pos) (protocol.Location, error) {
    74  	return pgf.Mapper.PosLocation(pgf.Tok, start, end)
    75  }
    76  
    77  // NodeRange returns a protocol Range for the ast.Node interval in this file.
    78  func (pgf *File) NodeRange(node ast.Node) (protocol.Range, error) {
    79  	return pgf.Mapper.NodeRange(pgf.Tok, node)
    80  }
    81  
    82  // NodeMappedRange returns a MappedRange for the ast.Node interval in this file.
    83  // A MappedRange can be converted to any other form.
    84  func (pgf *File) NodeMappedRange(node ast.Node) (protocol.MappedRange, error) {
    85  	return pgf.Mapper.NodeMappedRange(pgf.Tok, node)
    86  }
    87  
    88  // NodeLocation returns a protocol Location for the ast.Node interval in this file.
    89  func (pgf *File) NodeLocation(node ast.Node) (protocol.Location, error) {
    90  	return pgf.Mapper.PosLocation(pgf.Tok, node.Pos(), node.End())
    91  }
    92  
    93  // RangePos parses a protocol Range back into the go/token domain.
    94  func (pgf *File) RangePos(r protocol.Range) (token.Pos, token.Pos, error) {
    95  	start, end, err := pgf.Mapper.RangeOffsets(r)
    96  	if err != nil {
    97  		return token.NoPos, token.NoPos, err
    98  	}
    99  	return pgf.Tok.Pos(start), pgf.Tok.Pos(end), nil
   100  }