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