github.com/jd-ly/tools@v0.5.7/internal/lsp/cache/parse.go (about)

     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 cache
     6  
     7  import (
     8  	"bytes"
     9  	"context"
    10  	"fmt"
    11  	"go/ast"
    12  	"go/parser"
    13  	"go/scanner"
    14  	"go/token"
    15  	"reflect"
    16  	"strconv"
    17  
    18  	"github.com/jd-ly/tools/internal/event"
    19  	"github.com/jd-ly/tools/internal/lsp/debug/tag"
    20  	"github.com/jd-ly/tools/internal/lsp/protocol"
    21  	"github.com/jd-ly/tools/internal/lsp/source"
    22  	"github.com/jd-ly/tools/internal/memoize"
    23  	"github.com/jd-ly/tools/internal/span"
    24  	errors "golang.org/x/xerrors"
    25  )
    26  
    27  // parseKey uniquely identifies a parsed Go file.
    28  type parseKey struct {
    29  	file source.FileIdentity
    30  	mode source.ParseMode
    31  }
    32  
    33  // astCacheKey is similar to parseKey, but is a distinct type because
    34  // it is used to key a different value within the same map.
    35  type astCacheKey parseKey
    36  
    37  type parseGoHandle struct {
    38  	handle         *memoize.Handle
    39  	file           source.FileHandle
    40  	mode           source.ParseMode
    41  	astCacheHandle *memoize.Handle
    42  }
    43  
    44  type parseGoData struct {
    45  	parsed *source.ParsedGoFile
    46  
    47  	// If true, we adjusted the AST to make it type check better, and
    48  	// it may not match the source code.
    49  	fixed bool
    50  	err   error // any other errors
    51  }
    52  
    53  func (s *snapshot) parseGoHandle(ctx context.Context, fh source.FileHandle, mode source.ParseMode) *parseGoHandle {
    54  	key := parseKey{
    55  		file: fh.FileIdentity(),
    56  		mode: mode,
    57  	}
    58  	if pgh := s.getGoFile(key); pgh != nil {
    59  		return pgh
    60  	}
    61  	parseHandle := s.generation.Bind(key, func(ctx context.Context, arg memoize.Arg) interface{} {
    62  		snapshot := arg.(*snapshot)
    63  		return parseGo(ctx, snapshot.view.session.cache.fset, fh, mode)
    64  	}, nil)
    65  
    66  	astHandle := s.generation.Bind(astCacheKey(key), func(ctx context.Context, arg memoize.Arg) interface{} {
    67  		snapshot := arg.(*snapshot)
    68  		return buildASTCache(ctx, snapshot, parseHandle)
    69  	}, nil)
    70  
    71  	pgh := &parseGoHandle{
    72  		handle:         parseHandle,
    73  		file:           fh,
    74  		mode:           mode,
    75  		astCacheHandle: astHandle,
    76  	}
    77  	return s.addGoFile(key, pgh)
    78  }
    79  
    80  func (pgh *parseGoHandle) String() string {
    81  	return pgh.File().URI().Filename()
    82  }
    83  
    84  func (pgh *parseGoHandle) File() source.FileHandle {
    85  	return pgh.file
    86  }
    87  
    88  func (pgh *parseGoHandle) Mode() source.ParseMode {
    89  	return pgh.mode
    90  }
    91  
    92  func (s *snapshot) ParseGo(ctx context.Context, fh source.FileHandle, mode source.ParseMode) (*source.ParsedGoFile, error) {
    93  	pgh := s.parseGoHandle(ctx, fh, mode)
    94  	pgf, _, err := s.parseGo(ctx, pgh)
    95  	return pgf, err
    96  }
    97  
    98  func (s *snapshot) parseGo(ctx context.Context, pgh *parseGoHandle) (*source.ParsedGoFile, bool, error) {
    99  	d, err := pgh.handle.Get(ctx, s.generation, s)
   100  	if err != nil {
   101  		return nil, false, err
   102  	}
   103  	data := d.(*parseGoData)
   104  	return data.parsed, data.fixed, data.err
   105  }
   106  
   107  func (s *snapshot) PosToDecl(ctx context.Context, pgf *source.ParsedGoFile) (map[token.Pos]ast.Decl, error) {
   108  	fh, err := s.GetFile(ctx, pgf.URI)
   109  	if err != nil {
   110  		return nil, err
   111  	}
   112  
   113  	pgh := s.parseGoHandle(ctx, fh, pgf.Mode)
   114  	d, err := pgh.astCacheHandle.Get(ctx, s.generation, s)
   115  	if err != nil {
   116  		return nil, err
   117  	}
   118  
   119  	data := d.(*astCacheData)
   120  	return data.posToDecl, data.err
   121  }
   122  
   123  func (s *snapshot) PosToField(ctx context.Context, pgf *source.ParsedGoFile) (map[token.Pos]*ast.Field, error) {
   124  	fh, err := s.GetFile(ctx, pgf.URI)
   125  	if err != nil {
   126  		return nil, err
   127  	}
   128  
   129  	pgh := s.parseGoHandle(ctx, fh, pgf.Mode)
   130  	d, err := pgh.astCacheHandle.Get(ctx, s.generation, s)
   131  	if err != nil || d == nil {
   132  		return nil, err
   133  	}
   134  
   135  	data := d.(*astCacheData)
   136  	return data.posToField, data.err
   137  }
   138  
   139  type astCacheData struct {
   140  	err error
   141  
   142  	posToDecl  map[token.Pos]ast.Decl
   143  	posToField map[token.Pos]*ast.Field
   144  }
   145  
   146  // buildASTCache builds caches to aid in quickly going from the typed
   147  // world to the syntactic world.
   148  func buildASTCache(ctx context.Context, snapshot *snapshot, parseHandle *memoize.Handle) *astCacheData {
   149  	var (
   150  		// path contains all ancestors, including n.
   151  		path []ast.Node
   152  		// decls contains all ancestors that are decls.
   153  		decls []ast.Decl
   154  	)
   155  
   156  	v, err := parseHandle.Get(ctx, snapshot.generation, snapshot)
   157  	if err != nil {
   158  		return &astCacheData{err: err}
   159  	}
   160  	file := v.(*parseGoData).parsed.File
   161  	if err != nil {
   162  		return &astCacheData{err: fmt.Errorf("nil file")}
   163  	}
   164  
   165  	data := &astCacheData{
   166  		posToDecl:  make(map[token.Pos]ast.Decl),
   167  		posToField: make(map[token.Pos]*ast.Field),
   168  	}
   169  
   170  	ast.Inspect(file, func(n ast.Node) bool {
   171  		if n == nil {
   172  			lastP := path[len(path)-1]
   173  			path = path[:len(path)-1]
   174  			if len(decls) > 0 && decls[len(decls)-1] == lastP {
   175  				decls = decls[:len(decls)-1]
   176  			}
   177  			return false
   178  		}
   179  
   180  		path = append(path, n)
   181  
   182  		switch n := n.(type) {
   183  		case *ast.Field:
   184  			addField := func(f ast.Node) {
   185  				if f.Pos().IsValid() {
   186  					data.posToField[f.Pos()] = n
   187  					if len(decls) > 0 {
   188  						data.posToDecl[f.Pos()] = decls[len(decls)-1]
   189  					}
   190  				}
   191  			}
   192  
   193  			// Add mapping for *ast.Field itself. This handles embedded
   194  			// fields which have no associated *ast.Ident name.
   195  			addField(n)
   196  
   197  			// Add mapping for each field name since you can have
   198  			// multiple names for the same type expression.
   199  			for _, name := range n.Names {
   200  				addField(name)
   201  			}
   202  
   203  			// Also map "X" in "...X" to the containing *ast.Field. This
   204  			// makes it easy to format variadic signature params
   205  			// properly.
   206  			if elips, ok := n.Type.(*ast.Ellipsis); ok && elips.Elt != nil {
   207  				addField(elips.Elt)
   208  			}
   209  		case *ast.FuncDecl:
   210  			decls = append(decls, n)
   211  
   212  			if n.Name != nil && n.Name.Pos().IsValid() {
   213  				data.posToDecl[n.Name.Pos()] = n
   214  			}
   215  		case *ast.GenDecl:
   216  			decls = append(decls, n)
   217  
   218  			for _, spec := range n.Specs {
   219  				switch spec := spec.(type) {
   220  				case *ast.TypeSpec:
   221  					if spec.Name != nil && spec.Name.Pos().IsValid() {
   222  						data.posToDecl[spec.Name.Pos()] = n
   223  					}
   224  				case *ast.ValueSpec:
   225  					for _, id := range spec.Names {
   226  						if id != nil && id.Pos().IsValid() {
   227  							data.posToDecl[id.Pos()] = n
   228  						}
   229  					}
   230  				}
   231  			}
   232  		}
   233  
   234  		return true
   235  	})
   236  
   237  	return data
   238  }
   239  
   240  func parseGo(ctx context.Context, fset *token.FileSet, fh source.FileHandle, mode source.ParseMode) *parseGoData {
   241  	ctx, done := event.Start(ctx, "cache.parseGo", tag.File.Of(fh.URI().Filename()))
   242  	defer done()
   243  
   244  	if fh.Kind() != source.Go {
   245  		return &parseGoData{err: errors.Errorf("cannot parse non-Go file %s", fh.URI())}
   246  	}
   247  	buf, err := fh.Read()
   248  	if err != nil {
   249  		return &parseGoData{err: err}
   250  	}
   251  
   252  	parserMode := parser.AllErrors | parser.ParseComments
   253  	if mode == source.ParseHeader {
   254  		parserMode = parser.ImportsOnly | parser.ParseComments
   255  	}
   256  	file, parseError := parser.ParseFile(fset, fh.URI().Filename(), buf, parserMode)
   257  	var tok *token.File
   258  	var fixed bool
   259  	if file != nil {
   260  		tok = fset.File(file.Pos())
   261  		if tok == nil {
   262  			tok = fset.AddFile(fh.URI().Filename(), -1, len(buf))
   263  			tok.SetLinesForContent(buf)
   264  			return &parseGoData{
   265  				parsed: &source.ParsedGoFile{
   266  					URI:  fh.URI(),
   267  					Mode: mode,
   268  					Src:  buf,
   269  					File: file,
   270  					Tok:  tok,
   271  					Mapper: &protocol.ColumnMapper{
   272  						URI:       fh.URI(),
   273  						Content:   buf,
   274  						Converter: span.NewTokenConverter(fset, tok),
   275  					},
   276  					ParseErr: parseError,
   277  				},
   278  			}
   279  		}
   280  
   281  		// Fix any badly parsed parts of the AST.
   282  		fixed = fixAST(ctx, file, tok, buf)
   283  
   284  		// Fix certain syntax errors that render the file unparseable.
   285  		newSrc := fixSrc(file, tok, buf)
   286  		if newSrc != nil {
   287  			newFile, _ := parser.ParseFile(fset, fh.URI().Filename(), newSrc, parserMode)
   288  			if newFile != nil {
   289  				// Maintain the original parseError so we don't try formatting the doctored file.
   290  				file = newFile
   291  				buf = newSrc
   292  				tok = fset.File(file.Pos())
   293  
   294  				fixed = fixAST(ctx, file, tok, buf)
   295  			}
   296  		}
   297  
   298  		if mode == source.ParseExported {
   299  			trimAST(file)
   300  		}
   301  	}
   302  	// A missing file is always an error; use the parse error or make one up if there isn't one.
   303  	if file == nil {
   304  		if parseError == nil {
   305  			parseError = errors.Errorf("parsing %s failed with no parse error reported", fh.URI())
   306  		}
   307  		err = parseError
   308  	}
   309  	m := &protocol.ColumnMapper{
   310  		URI:       fh.URI(),
   311  		Converter: span.NewTokenConverter(fset, tok),
   312  		Content:   buf,
   313  	}
   314  
   315  	return &parseGoData{
   316  		parsed: &source.ParsedGoFile{
   317  			URI:      fh.URI(),
   318  			Mode:     mode,
   319  			Src:      buf,
   320  			File:     file,
   321  			Tok:      tok,
   322  			Mapper:   m,
   323  			ParseErr: parseError,
   324  		},
   325  		fixed: fixed,
   326  		err:   err,
   327  	}
   328  }
   329  
   330  // trimAST clears any part of the AST not relevant to type checking
   331  // expressions at pos.
   332  func trimAST(file *ast.File) {
   333  	ast.Inspect(file, func(n ast.Node) bool {
   334  		if n == nil {
   335  			return false
   336  		}
   337  		switch n := n.(type) {
   338  		case *ast.FuncDecl:
   339  			n.Body = nil
   340  		case *ast.BlockStmt:
   341  			n.List = nil
   342  		case *ast.CaseClause:
   343  			n.Body = nil
   344  		case *ast.CommClause:
   345  			n.Body = nil
   346  		case *ast.CompositeLit:
   347  			// types.Info.Types for long slice/array literals are particularly
   348  			// expensive. Try to clear them out.
   349  			at, ok := n.Type.(*ast.ArrayType)
   350  			if !ok {
   351  				break
   352  			}
   353  			// Removing the elements from an ellipsis array changes its type.
   354  			// Try to set the length explicitly so we can continue.
   355  			if _, ok := at.Len.(*ast.Ellipsis); ok {
   356  				length, ok := arrayLength(n)
   357  				if !ok {
   358  					break
   359  				}
   360  				at.Len = &ast.BasicLit{
   361  					Kind:     token.INT,
   362  					Value:    fmt.Sprint(length),
   363  					ValuePos: at.Len.Pos(),
   364  				}
   365  			}
   366  			n.Elts = nil
   367  		}
   368  		return true
   369  	})
   370  }
   371  
   372  // arrayLength returns the length of some simple forms of ellipsis array literal.
   373  // Notably, it handles the tables in golang.org/x/text.
   374  func arrayLength(array *ast.CompositeLit) (int, bool) {
   375  	litVal := func(expr ast.Expr) (int, bool) {
   376  		lit, ok := expr.(*ast.BasicLit)
   377  		if !ok {
   378  			return 0, false
   379  		}
   380  		val, err := strconv.ParseInt(lit.Value, 10, 64)
   381  		if err != nil {
   382  			return 0, false
   383  		}
   384  		return int(val), true
   385  	}
   386  	largestKey := -1
   387  	for _, elt := range array.Elts {
   388  		kve, ok := elt.(*ast.KeyValueExpr)
   389  		if !ok {
   390  			continue
   391  		}
   392  		switch key := kve.Key.(type) {
   393  		case *ast.BasicLit:
   394  			if val, ok := litVal(key); ok && largestKey < val {
   395  				largestKey = val
   396  			}
   397  		case *ast.BinaryExpr:
   398  			// golang.org/x/text uses subtraction (and only subtraction) in its indices.
   399  			if key.Op != token.SUB {
   400  				break
   401  			}
   402  			x, ok := litVal(key.X)
   403  			if !ok {
   404  				break
   405  			}
   406  			y, ok := litVal(key.Y)
   407  			if !ok {
   408  				break
   409  			}
   410  			if val := x - y; largestKey < val {
   411  				largestKey = val
   412  			}
   413  		}
   414  	}
   415  	if largestKey != -1 {
   416  		return largestKey + 1, true
   417  	}
   418  	return len(array.Elts), true
   419  }
   420  
   421  // fixAST inspects the AST and potentially modifies any *ast.BadStmts so that it can be
   422  // type-checked more effectively.
   423  func fixAST(ctx context.Context, n ast.Node, tok *token.File, src []byte) (fixed bool) {
   424  	var err error
   425  	walkASTWithParent(n, func(n, parent ast.Node) bool {
   426  		switch n := n.(type) {
   427  		case *ast.BadStmt:
   428  			if fixed = fixDeferOrGoStmt(n, parent, tok, src); fixed {
   429  				// Recursively fix in our fixed node.
   430  				_ = fixAST(ctx, parent, tok, src)
   431  			} else {
   432  				err = errors.Errorf("unable to parse defer or go from *ast.BadStmt: %v", err)
   433  			}
   434  			return false
   435  		case *ast.BadExpr:
   436  			if fixed = fixArrayType(n, parent, tok, src); fixed {
   437  				// Recursively fix in our fixed node.
   438  				_ = fixAST(ctx, parent, tok, src)
   439  				return false
   440  			}
   441  
   442  			// Fix cases where parser interprets if/for/switch "init"
   443  			// statement as "cond" expression, e.g.:
   444  			//
   445  			//   // "i := foo" is init statement, not condition.
   446  			//   for i := foo
   447  			//
   448  			fixInitStmt(n, parent, tok, src)
   449  
   450  			return false
   451  		case *ast.SelectorExpr:
   452  			// Fix cases where a keyword prefix results in a phantom "_" selector, e.g.:
   453  			//
   454  			//   foo.var<> // want to complete to "foo.variance"
   455  			//
   456  			fixPhantomSelector(n, tok, src)
   457  			return true
   458  
   459  		case *ast.BlockStmt:
   460  			switch parent.(type) {
   461  			case *ast.SwitchStmt, *ast.TypeSwitchStmt, *ast.SelectStmt:
   462  				// Adjust closing curly brace of empty switch/select
   463  				// statements so we can complete inside them.
   464  				fixEmptySwitch(n, tok, src)
   465  			}
   466  
   467  			return true
   468  		default:
   469  			return true
   470  		}
   471  	})
   472  	return fixed
   473  }
   474  
   475  // walkASTWithParent walks the AST rooted at n. The semantics are
   476  // similar to ast.Inspect except it does not call f(nil).
   477  func walkASTWithParent(n ast.Node, f func(n ast.Node, parent ast.Node) bool) {
   478  	var ancestors []ast.Node
   479  	ast.Inspect(n, func(n ast.Node) (recurse bool) {
   480  		defer func() {
   481  			if recurse {
   482  				ancestors = append(ancestors, n)
   483  			}
   484  		}()
   485  
   486  		if n == nil {
   487  			ancestors = ancestors[:len(ancestors)-1]
   488  			return false
   489  		}
   490  
   491  		var parent ast.Node
   492  		if len(ancestors) > 0 {
   493  			parent = ancestors[len(ancestors)-1]
   494  		}
   495  
   496  		return f(n, parent)
   497  	})
   498  }
   499  
   500  // fixSrc attempts to modify the file's source code to fix certain
   501  // syntax errors that leave the rest of the file unparsed.
   502  func fixSrc(f *ast.File, tok *token.File, src []byte) (newSrc []byte) {
   503  	walkASTWithParent(f, func(n, parent ast.Node) bool {
   504  		if newSrc != nil {
   505  			return false
   506  		}
   507  
   508  		switch n := n.(type) {
   509  		case *ast.BlockStmt:
   510  			newSrc = fixMissingCurlies(f, n, parent, tok, src)
   511  		case *ast.SelectorExpr:
   512  			newSrc = fixDanglingSelector(n, tok, src)
   513  		}
   514  
   515  		return newSrc == nil
   516  	})
   517  
   518  	return newSrc
   519  }
   520  
   521  // fixMissingCurlies adds in curly braces for block statements that
   522  // are missing curly braces. For example:
   523  //
   524  //   if foo
   525  //
   526  // becomes
   527  //
   528  //   if foo {}
   529  func fixMissingCurlies(f *ast.File, b *ast.BlockStmt, parent ast.Node, tok *token.File, src []byte) []byte {
   530  	// If the "{" is already in the source code, there isn't anything to
   531  	// fix since we aren't missing curlies.
   532  	if b.Lbrace.IsValid() {
   533  		braceOffset := tok.Offset(b.Lbrace)
   534  		if braceOffset < len(src) && src[braceOffset] == '{' {
   535  			return nil
   536  		}
   537  	}
   538  
   539  	parentLine := tok.Line(parent.Pos())
   540  
   541  	if parentLine >= tok.LineCount() {
   542  		// If we are the last line in the file, no need to fix anything.
   543  		return nil
   544  	}
   545  
   546  	// Insert curlies at the end of parent's starting line. The parent
   547  	// is the statement that contains the block, e.g. *ast.IfStmt. The
   548  	// block's Pos()/End() can't be relied upon because they are based
   549  	// on the (missing) curly braces. We assume the statement is a
   550  	// single line for now and try sticking the curly braces at the end.
   551  	insertPos := tok.LineStart(parentLine+1) - 1
   552  
   553  	// Scootch position backwards until it's not in a comment. For example:
   554  	//
   555  	// if foo<> // some amazing comment |
   556  	// someOtherCode()
   557  	//
   558  	// insertPos will be located at "|", so we back it out of the comment.
   559  	didSomething := true
   560  	for didSomething {
   561  		didSomething = false
   562  		for _, c := range f.Comments {
   563  			if c.Pos() < insertPos && insertPos <= c.End() {
   564  				insertPos = c.Pos()
   565  				didSomething = true
   566  			}
   567  		}
   568  	}
   569  
   570  	// Bail out if line doesn't end in an ident or ".". This is to avoid
   571  	// cases like below where we end up making things worse by adding
   572  	// curlies:
   573  	//
   574  	//   if foo &&
   575  	//     bar<>
   576  	switch precedingToken(insertPos, tok, src) {
   577  	case token.IDENT, token.PERIOD:
   578  		// ok
   579  	default:
   580  		return nil
   581  	}
   582  
   583  	var buf bytes.Buffer
   584  	buf.Grow(len(src) + 3)
   585  	buf.Write(src[:tok.Offset(insertPos)])
   586  
   587  	// Detect if we need to insert a semicolon to fix "for" loop situations like:
   588  	//
   589  	//   for i := foo(); foo<>
   590  	//
   591  	// Just adding curlies is not sufficient to make things parse well.
   592  	if fs, ok := parent.(*ast.ForStmt); ok {
   593  		if _, ok := fs.Cond.(*ast.BadExpr); !ok {
   594  			if xs, ok := fs.Post.(*ast.ExprStmt); ok {
   595  				if _, ok := xs.X.(*ast.BadExpr); ok {
   596  					buf.WriteByte(';')
   597  				}
   598  			}
   599  		}
   600  	}
   601  
   602  	// Insert "{}" at insertPos.
   603  	buf.WriteByte('{')
   604  	buf.WriteByte('}')
   605  	buf.Write(src[tok.Offset(insertPos):])
   606  	return buf.Bytes()
   607  }
   608  
   609  // fixEmptySwitch moves empty switch/select statements' closing curly
   610  // brace down one line. This allows us to properly detect incomplete
   611  // "case" and "default" keywords as inside the switch statement. For
   612  // example:
   613  //
   614  //   switch {
   615  //   def<>
   616  //   }
   617  //
   618  // gets parsed like:
   619  //
   620  //   switch {
   621  //   }
   622  //
   623  // Later we manually pull out the "def" token, but we need to detect
   624  // that our "<>" position is inside the switch block. To do that we
   625  // move the curly brace so it looks like:
   626  //
   627  //   switch {
   628  //
   629  //   }
   630  //
   631  func fixEmptySwitch(body *ast.BlockStmt, tok *token.File, src []byte) {
   632  	// We only care about empty switch statements.
   633  	if len(body.List) > 0 || !body.Rbrace.IsValid() {
   634  		return
   635  	}
   636  
   637  	// If the right brace is actually in the source code at the
   638  	// specified position, don't mess with it.
   639  	braceOffset := tok.Offset(body.Rbrace)
   640  	if braceOffset < len(src) && src[braceOffset] == '}' {
   641  		return
   642  	}
   643  
   644  	braceLine := tok.Line(body.Rbrace)
   645  	if braceLine >= tok.LineCount() {
   646  		// If we are the last line in the file, no need to fix anything.
   647  		return
   648  	}
   649  
   650  	// Move the right brace down one line.
   651  	body.Rbrace = tok.LineStart(braceLine + 1)
   652  }
   653  
   654  // fixDanglingSelector inserts real "_" selector expressions in place
   655  // of phantom "_" selectors. For example:
   656  //
   657  // func _() {
   658  //   x.<>
   659  // }
   660  // var x struct { i int }
   661  //
   662  // To fix completion at "<>", we insert a real "_" after the "." so the
   663  // following declaration of "x" can be parsed and type checked
   664  // normally.
   665  func fixDanglingSelector(s *ast.SelectorExpr, tok *token.File, src []byte) []byte {
   666  	if !isPhantomUnderscore(s.Sel, tok, src) {
   667  		return nil
   668  	}
   669  
   670  	if !s.X.End().IsValid() {
   671  		return nil
   672  	}
   673  
   674  	// Insert directly after the selector's ".".
   675  	insertOffset := tok.Offset(s.X.End()) + 1
   676  	if src[insertOffset-1] != '.' {
   677  		return nil
   678  	}
   679  
   680  	var buf bytes.Buffer
   681  	buf.Grow(len(src) + 1)
   682  	buf.Write(src[:insertOffset])
   683  	buf.WriteByte('_')
   684  	buf.Write(src[insertOffset:])
   685  	return buf.Bytes()
   686  }
   687  
   688  // fixPhantomSelector tries to fix selector expressions with phantom
   689  // "_" selectors. In particular, we check if the selector is a
   690  // keyword, and if so we swap in an *ast.Ident with the keyword text. For example:
   691  //
   692  // foo.var
   693  //
   694  // yields a "_" selector instead of "var" since "var" is a keyword.
   695  func fixPhantomSelector(sel *ast.SelectorExpr, tok *token.File, src []byte) {
   696  	if !isPhantomUnderscore(sel.Sel, tok, src) {
   697  		return
   698  	}
   699  
   700  	// Only consider selectors directly abutting the selector ".". This
   701  	// avoids false positives in cases like:
   702  	//
   703  	//   foo. // don't think "var" is our selector
   704  	//   var bar = 123
   705  	//
   706  	if sel.Sel.Pos() != sel.X.End()+1 {
   707  		return
   708  	}
   709  
   710  	maybeKeyword := readKeyword(sel.Sel.Pos(), tok, src)
   711  	if maybeKeyword == "" {
   712  		return
   713  	}
   714  
   715  	replaceNode(sel, sel.Sel, &ast.Ident{
   716  		Name:    maybeKeyword,
   717  		NamePos: sel.Sel.Pos(),
   718  	})
   719  }
   720  
   721  // isPhantomUnderscore reports whether the given ident is a phantom
   722  // underscore. The parser sometimes inserts phantom underscores when
   723  // it encounters otherwise unparseable situations.
   724  func isPhantomUnderscore(id *ast.Ident, tok *token.File, src []byte) bool {
   725  	if id == nil || id.Name != "_" {
   726  		return false
   727  	}
   728  
   729  	// Phantom underscore means the underscore is not actually in the
   730  	// program text.
   731  	offset := tok.Offset(id.Pos())
   732  	return len(src) <= offset || src[offset] != '_'
   733  }
   734  
   735  // fixInitStmt fixes cases where the parser misinterprets an
   736  // if/for/switch "init" statement as the "cond" conditional. In cases
   737  // like "if i := 0" the user hasn't typed the semicolon yet so the
   738  // parser is looking for the conditional expression. However, "i := 0"
   739  // are not valid expressions, so we get a BadExpr.
   740  func fixInitStmt(bad *ast.BadExpr, parent ast.Node, tok *token.File, src []byte) {
   741  	if !bad.Pos().IsValid() || !bad.End().IsValid() {
   742  		return
   743  	}
   744  
   745  	// Try to extract a statement from the BadExpr.
   746  	stmtBytes := src[tok.Offset(bad.Pos()) : tok.Offset(bad.End()-1)+1]
   747  	stmt, err := parseStmt(bad.Pos(), stmtBytes)
   748  	if err != nil {
   749  		return
   750  	}
   751  
   752  	// If the parent statement doesn't already have an "init" statement,
   753  	// move the extracted statement into the "init" field and insert a
   754  	// dummy expression into the required "cond" field.
   755  	switch p := parent.(type) {
   756  	case *ast.IfStmt:
   757  		if p.Init != nil {
   758  			return
   759  		}
   760  		p.Init = stmt
   761  		p.Cond = &ast.Ident{
   762  			Name:    "_",
   763  			NamePos: stmt.End(),
   764  		}
   765  	case *ast.ForStmt:
   766  		if p.Init != nil {
   767  			return
   768  		}
   769  		p.Init = stmt
   770  		p.Cond = &ast.Ident{
   771  			Name:    "_",
   772  			NamePos: stmt.End(),
   773  		}
   774  	case *ast.SwitchStmt:
   775  		if p.Init != nil {
   776  			return
   777  		}
   778  		p.Init = stmt
   779  		p.Tag = nil
   780  	}
   781  }
   782  
   783  // readKeyword reads the keyword starting at pos, if any.
   784  func readKeyword(pos token.Pos, tok *token.File, src []byte) string {
   785  	var kwBytes []byte
   786  	for i := tok.Offset(pos); i < len(src); i++ {
   787  		// Use a simplified identifier check since keywords are always lowercase ASCII.
   788  		if src[i] < 'a' || src[i] > 'z' {
   789  			break
   790  		}
   791  		kwBytes = append(kwBytes, src[i])
   792  
   793  		// Stop search at arbitrarily chosen too-long-for-a-keyword length.
   794  		if len(kwBytes) > 15 {
   795  			return ""
   796  		}
   797  	}
   798  
   799  	if kw := string(kwBytes); token.Lookup(kw).IsKeyword() {
   800  		return kw
   801  	}
   802  
   803  	return ""
   804  }
   805  
   806  // fixArrayType tries to parse an *ast.BadExpr into an *ast.ArrayType.
   807  // go/parser often turns lone array types like "[]int" into BadExprs
   808  // if it isn't expecting a type.
   809  func fixArrayType(bad *ast.BadExpr, parent ast.Node, tok *token.File, src []byte) bool {
   810  	// Our expected input is a bad expression that looks like "[]someExpr".
   811  
   812  	from := bad.Pos()
   813  	to := bad.End()
   814  
   815  	if !from.IsValid() || !to.IsValid() {
   816  		return false
   817  	}
   818  
   819  	exprBytes := make([]byte, 0, int(to-from)+3)
   820  	// Avoid doing tok.Offset(to) since that panics if badExpr ends at EOF.
   821  	exprBytes = append(exprBytes, src[tok.Offset(from):tok.Offset(to-1)+1]...)
   822  	exprBytes = bytes.TrimSpace(exprBytes)
   823  
   824  	// If our expression ends in "]" (e.g. "[]"), add a phantom selector
   825  	// so we can complete directly after the "[]".
   826  	if len(exprBytes) > 0 && exprBytes[len(exprBytes)-1] == ']' {
   827  		exprBytes = append(exprBytes, '_')
   828  	}
   829  
   830  	// Add "{}" to turn our ArrayType into a CompositeLit. This is to
   831  	// handle the case of "[...]int" where we must make it a composite
   832  	// literal to be parseable.
   833  	exprBytes = append(exprBytes, '{', '}')
   834  
   835  	expr, err := parseExpr(from, exprBytes)
   836  	if err != nil {
   837  		return false
   838  	}
   839  
   840  	cl, _ := expr.(*ast.CompositeLit)
   841  	if cl == nil {
   842  		return false
   843  	}
   844  
   845  	at, _ := cl.Type.(*ast.ArrayType)
   846  	if at == nil {
   847  		return false
   848  	}
   849  
   850  	return replaceNode(parent, bad, at)
   851  }
   852  
   853  // precedingToken scans src to find the token preceding pos.
   854  func precedingToken(pos token.Pos, tok *token.File, src []byte) token.Token {
   855  	s := &scanner.Scanner{}
   856  	s.Init(tok, src, nil, 0)
   857  
   858  	var lastTok token.Token
   859  	for {
   860  		p, t, _ := s.Scan()
   861  		if t == token.EOF || p >= pos {
   862  			break
   863  		}
   864  
   865  		lastTok = t
   866  	}
   867  	return lastTok
   868  }
   869  
   870  // fixDeferOrGoStmt tries to parse an *ast.BadStmt into a defer or a go statement.
   871  //
   872  // go/parser packages a statement of the form "defer x." as an *ast.BadStmt because
   873  // it does not include a call expression. This means that go/types skips type-checking
   874  // this statement entirely, and we can't use the type information when completing.
   875  // Here, we try to generate a fake *ast.DeferStmt or *ast.GoStmt to put into the AST,
   876  // instead of the *ast.BadStmt.
   877  func fixDeferOrGoStmt(bad *ast.BadStmt, parent ast.Node, tok *token.File, src []byte) bool {
   878  	// Check if we have a bad statement containing either a "go" or "defer".
   879  	s := &scanner.Scanner{}
   880  	s.Init(tok, src, nil, 0)
   881  
   882  	var (
   883  		pos token.Pos
   884  		tkn token.Token
   885  	)
   886  	for {
   887  		if tkn == token.EOF {
   888  			return false
   889  		}
   890  		if pos >= bad.From {
   891  			break
   892  		}
   893  		pos, tkn, _ = s.Scan()
   894  	}
   895  
   896  	var stmt ast.Stmt
   897  	switch tkn {
   898  	case token.DEFER:
   899  		stmt = &ast.DeferStmt{
   900  			Defer: pos,
   901  		}
   902  	case token.GO:
   903  		stmt = &ast.GoStmt{
   904  			Go: pos,
   905  		}
   906  	default:
   907  		return false
   908  	}
   909  
   910  	var (
   911  		from, to, last   token.Pos
   912  		lastToken        token.Token
   913  		braceDepth       int
   914  		phantomSelectors []token.Pos
   915  	)
   916  FindTo:
   917  	for {
   918  		to, tkn, _ = s.Scan()
   919  
   920  		if from == token.NoPos {
   921  			from = to
   922  		}
   923  
   924  		switch tkn {
   925  		case token.EOF:
   926  			break FindTo
   927  		case token.SEMICOLON:
   928  			// If we aren't in nested braces, end of statement means
   929  			// end of expression.
   930  			if braceDepth == 0 {
   931  				break FindTo
   932  			}
   933  		case token.LBRACE:
   934  			braceDepth++
   935  		}
   936  
   937  		// This handles the common dangling selector case. For example in
   938  		//
   939  		// defer fmt.
   940  		// y := 1
   941  		//
   942  		// we notice the dangling period and end our expression.
   943  		//
   944  		// If the previous token was a "." and we are looking at a "}",
   945  		// the period is likely a dangling selector and needs a phantom
   946  		// "_". Likewise if the current token is on a different line than
   947  		// the period, the period is likely a dangling selector.
   948  		if lastToken == token.PERIOD && (tkn == token.RBRACE || tok.Line(to) > tok.Line(last)) {
   949  			// Insert phantom "_" selector after the dangling ".".
   950  			phantomSelectors = append(phantomSelectors, last+1)
   951  			// If we aren't in a block then end the expression after the ".".
   952  			if braceDepth == 0 {
   953  				to = last + 1
   954  				break
   955  			}
   956  		}
   957  
   958  		lastToken = tkn
   959  		last = to
   960  
   961  		switch tkn {
   962  		case token.RBRACE:
   963  			braceDepth--
   964  			if braceDepth <= 0 {
   965  				if braceDepth == 0 {
   966  					// +1 to include the "}" itself.
   967  					to += 1
   968  				}
   969  				break FindTo
   970  			}
   971  		}
   972  	}
   973  
   974  	if !from.IsValid() || tok.Offset(from) >= len(src) {
   975  		return false
   976  	}
   977  
   978  	if !to.IsValid() || tok.Offset(to) >= len(src) {
   979  		return false
   980  	}
   981  
   982  	// Insert any phantom selectors needed to prevent dangling "." from messing
   983  	// up the AST.
   984  	exprBytes := make([]byte, 0, int(to-from)+len(phantomSelectors))
   985  	for i, b := range src[tok.Offset(from):tok.Offset(to)] {
   986  		if len(phantomSelectors) > 0 && from+token.Pos(i) == phantomSelectors[0] {
   987  			exprBytes = append(exprBytes, '_')
   988  			phantomSelectors = phantomSelectors[1:]
   989  		}
   990  		exprBytes = append(exprBytes, b)
   991  	}
   992  
   993  	if len(phantomSelectors) > 0 {
   994  		exprBytes = append(exprBytes, '_')
   995  	}
   996  
   997  	expr, err := parseExpr(from, exprBytes)
   998  	if err != nil {
   999  		return false
  1000  	}
  1001  
  1002  	// Package the expression into a fake *ast.CallExpr and re-insert
  1003  	// into the function.
  1004  	call := &ast.CallExpr{
  1005  		Fun:    expr,
  1006  		Lparen: to,
  1007  		Rparen: to,
  1008  	}
  1009  
  1010  	switch stmt := stmt.(type) {
  1011  	case *ast.DeferStmt:
  1012  		stmt.Call = call
  1013  	case *ast.GoStmt:
  1014  		stmt.Call = call
  1015  	}
  1016  
  1017  	return replaceNode(parent, bad, stmt)
  1018  }
  1019  
  1020  // parseStmt parses the statement in src and updates its position to
  1021  // start at pos.
  1022  func parseStmt(pos token.Pos, src []byte) (ast.Stmt, error) {
  1023  	// Wrap our expression to make it a valid Go file we can pass to ParseFile.
  1024  	fileSrc := bytes.Join([][]byte{
  1025  		[]byte("package fake;func _(){"),
  1026  		src,
  1027  		[]byte("}"),
  1028  	}, nil)
  1029  
  1030  	// Use ParseFile instead of ParseExpr because ParseFile has
  1031  	// best-effort behavior, whereas ParseExpr fails hard on any error.
  1032  	fakeFile, err := parser.ParseFile(token.NewFileSet(), "", fileSrc, 0)
  1033  	if fakeFile == nil {
  1034  		return nil, errors.Errorf("error reading fake file source: %v", err)
  1035  	}
  1036  
  1037  	// Extract our expression node from inside the fake file.
  1038  	if len(fakeFile.Decls) == 0 {
  1039  		return nil, errors.Errorf("error parsing fake file: %v", err)
  1040  	}
  1041  
  1042  	fakeDecl, _ := fakeFile.Decls[0].(*ast.FuncDecl)
  1043  	if fakeDecl == nil || len(fakeDecl.Body.List) == 0 {
  1044  		return nil, errors.Errorf("no statement in %s: %v", src, err)
  1045  	}
  1046  
  1047  	stmt := fakeDecl.Body.List[0]
  1048  
  1049  	// parser.ParseFile returns undefined positions.
  1050  	// Adjust them for the current file.
  1051  	offsetPositions(stmt, pos-1-(stmt.Pos()-1))
  1052  
  1053  	return stmt, nil
  1054  }
  1055  
  1056  // parseExpr parses the expression in src and updates its position to
  1057  // start at pos.
  1058  func parseExpr(pos token.Pos, src []byte) (ast.Expr, error) {
  1059  	stmt, err := parseStmt(pos, src)
  1060  	if err != nil {
  1061  		return nil, err
  1062  	}
  1063  
  1064  	exprStmt, ok := stmt.(*ast.ExprStmt)
  1065  	if !ok {
  1066  		return nil, errors.Errorf("no expr in %s: %v", src, err)
  1067  	}
  1068  
  1069  	return exprStmt.X, nil
  1070  }
  1071  
  1072  var tokenPosType = reflect.TypeOf(token.NoPos)
  1073  
  1074  // offsetPositions applies an offset to the positions in an ast.Node.
  1075  func offsetPositions(n ast.Node, offset token.Pos) {
  1076  	ast.Inspect(n, func(n ast.Node) bool {
  1077  		if n == nil {
  1078  			return false
  1079  		}
  1080  
  1081  		v := reflect.ValueOf(n).Elem()
  1082  
  1083  		switch v.Kind() {
  1084  		case reflect.Struct:
  1085  			for i := 0; i < v.NumField(); i++ {
  1086  				f := v.Field(i)
  1087  				if f.Type() != tokenPosType {
  1088  					continue
  1089  				}
  1090  
  1091  				if !f.CanSet() {
  1092  					continue
  1093  				}
  1094  
  1095  				f.SetInt(f.Int() + int64(offset))
  1096  			}
  1097  		}
  1098  
  1099  		return true
  1100  	})
  1101  }
  1102  
  1103  // replaceNode updates parent's child oldChild to be newChild. It
  1104  // returns whether it replaced successfully.
  1105  func replaceNode(parent, oldChild, newChild ast.Node) bool {
  1106  	if parent == nil || oldChild == nil || newChild == nil {
  1107  		return false
  1108  	}
  1109  
  1110  	parentVal := reflect.ValueOf(parent).Elem()
  1111  	if parentVal.Kind() != reflect.Struct {
  1112  		return false
  1113  	}
  1114  
  1115  	newChildVal := reflect.ValueOf(newChild)
  1116  
  1117  	tryReplace := func(v reflect.Value) bool {
  1118  		if !v.CanSet() || !v.CanInterface() {
  1119  			return false
  1120  		}
  1121  
  1122  		// If the existing value is oldChild, we found our child. Make
  1123  		// sure our newChild is assignable and then make the swap.
  1124  		if v.Interface() == oldChild && newChildVal.Type().AssignableTo(v.Type()) {
  1125  			v.Set(newChildVal)
  1126  			return true
  1127  		}
  1128  
  1129  		return false
  1130  	}
  1131  
  1132  	// Loop over parent's struct fields.
  1133  	for i := 0; i < parentVal.NumField(); i++ {
  1134  		f := parentVal.Field(i)
  1135  
  1136  		switch f.Kind() {
  1137  		// Check interface and pointer fields.
  1138  		case reflect.Interface, reflect.Ptr:
  1139  			if tryReplace(f) {
  1140  				return true
  1141  			}
  1142  
  1143  		// Search through any slice fields.
  1144  		case reflect.Slice:
  1145  			for i := 0; i < f.Len(); i++ {
  1146  				if tryReplace(f.Index(i)) {
  1147  					return true
  1148  				}
  1149  			}
  1150  		}
  1151  	}
  1152  
  1153  	return false
  1154  }