Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201028153306-37f0764111ff / internal / lsp / cache / parse.go
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         "golang.org/x/tools/internal/event"
19         "golang.org/x/tools/internal/lsp/debug/tag"
20         "golang.org/x/tools/internal/lsp/protocol"
21         "golang.org/x/tools/internal/lsp/source"
22         "golang.org/x/tools/internal/memoize"
23         "golang.org/x/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         })
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         })
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 }