github.com/jd-ly/tools@v0.5.7/internal/lsp/source/completion/util.go (about)

     1  // Copyright 2020 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 completion
     6  
     7  import (
     8  	"go/ast"
     9  	"go/token"
    10  	"go/types"
    11  
    12  	"github.com/jd-ly/tools/internal/lsp/source"
    13  )
    14  
    15  // exprAtPos returns the index of the expression containing pos.
    16  func exprAtPos(pos token.Pos, args []ast.Expr) int {
    17  	for i, expr := range args {
    18  		if expr.Pos() <= pos && pos <= expr.End() {
    19  			return i
    20  		}
    21  	}
    22  	return len(args)
    23  }
    24  
    25  // eachField invokes fn for each field that can be selected from a
    26  // value of type T.
    27  func eachField(T types.Type, fn func(*types.Var)) {
    28  	// TODO(adonovan): this algorithm doesn't exclude ambiguous
    29  	// selections that match more than one field/method.
    30  	// types.NewSelectionSet should do that for us.
    31  
    32  	// for termination on recursive types
    33  	var seen map[*types.Struct]bool
    34  
    35  	var visit func(T types.Type)
    36  	visit = func(T types.Type) {
    37  		if T, ok := source.Deref(T).Underlying().(*types.Struct); ok {
    38  			if seen[T] {
    39  				return
    40  			}
    41  
    42  			for i := 0; i < T.NumFields(); i++ {
    43  				f := T.Field(i)
    44  				fn(f)
    45  				if f.Anonymous() {
    46  					if seen == nil {
    47  						// Lazily create "seen" since it is only needed for
    48  						// embedded structs.
    49  						seen = make(map[*types.Struct]bool)
    50  					}
    51  					seen[T] = true
    52  					visit(f.Type())
    53  				}
    54  			}
    55  		}
    56  	}
    57  	visit(T)
    58  }
    59  
    60  // typeIsValid reports whether typ doesn't contain any Invalid types.
    61  func typeIsValid(typ types.Type) bool {
    62  	// Check named types separately, because we don't want
    63  	// to call Underlying() on them to avoid problems with recursive types.
    64  	if _, ok := typ.(*types.Named); ok {
    65  		return true
    66  	}
    67  
    68  	switch typ := typ.Underlying().(type) {
    69  	case *types.Basic:
    70  		return typ.Kind() != types.Invalid
    71  	case *types.Array:
    72  		return typeIsValid(typ.Elem())
    73  	case *types.Slice:
    74  		return typeIsValid(typ.Elem())
    75  	case *types.Pointer:
    76  		return typeIsValid(typ.Elem())
    77  	case *types.Map:
    78  		return typeIsValid(typ.Key()) && typeIsValid(typ.Elem())
    79  	case *types.Chan:
    80  		return typeIsValid(typ.Elem())
    81  	case *types.Signature:
    82  		return typeIsValid(typ.Params()) && typeIsValid(typ.Results())
    83  	case *types.Tuple:
    84  		for i := 0; i < typ.Len(); i++ {
    85  			if !typeIsValid(typ.At(i).Type()) {
    86  				return false
    87  			}
    88  		}
    89  		return true
    90  	case *types.Struct, *types.Interface:
    91  		// Don't bother checking structs, interfaces for validity.
    92  		return true
    93  	default:
    94  		return false
    95  	}
    96  }
    97  
    98  // resolveInvalid traverses the node of the AST that defines the scope
    99  // containing the declaration of obj, and attempts to find a user-friendly
   100  // name for its invalid type. The resulting Object and its Type are fake.
   101  func resolveInvalid(fset *token.FileSet, obj types.Object, node ast.Node, info *types.Info) types.Object {
   102  	var resultExpr ast.Expr
   103  	ast.Inspect(node, func(node ast.Node) bool {
   104  		switch n := node.(type) {
   105  		case *ast.ValueSpec:
   106  			for _, name := range n.Names {
   107  				if info.Defs[name] == obj {
   108  					resultExpr = n.Type
   109  				}
   110  			}
   111  			return false
   112  		case *ast.Field: // This case handles parameters and results of a FuncDecl or FuncLit.
   113  			for _, name := range n.Names {
   114  				if info.Defs[name] == obj {
   115  					resultExpr = n.Type
   116  				}
   117  			}
   118  			return false
   119  		default:
   120  			return true
   121  		}
   122  	})
   123  	// Construct a fake type for the object and return a fake object with this type.
   124  	typename := source.FormatNode(fset, resultExpr)
   125  	typ := types.NewNamed(types.NewTypeName(token.NoPos, obj.Pkg(), typename, nil), types.Typ[types.Invalid], nil)
   126  	return types.NewVar(obj.Pos(), obj.Pkg(), obj.Name(), typ)
   127  }
   128  
   129  func isPointer(T types.Type) bool {
   130  	_, ok := T.(*types.Pointer)
   131  	return ok
   132  }
   133  
   134  func isVar(obj types.Object) bool {
   135  	_, ok := obj.(*types.Var)
   136  	return ok
   137  }
   138  
   139  func isTypeName(obj types.Object) bool {
   140  	_, ok := obj.(*types.TypeName)
   141  	return ok
   142  }
   143  
   144  func isFunc(obj types.Object) bool {
   145  	_, ok := obj.(*types.Func)
   146  	return ok
   147  }
   148  
   149  func isEmptyInterface(T types.Type) bool {
   150  	intf, _ := T.(*types.Interface)
   151  	return intf != nil && intf.NumMethods() == 0
   152  }
   153  
   154  func isUntyped(T types.Type) bool {
   155  	if basic, ok := T.(*types.Basic); ok {
   156  		return basic.Info()&types.IsUntyped > 0
   157  	}
   158  	return false
   159  }
   160  
   161  func isPkgName(obj types.Object) bool {
   162  	_, ok := obj.(*types.PkgName)
   163  	return ok
   164  }
   165  
   166  func isASTFile(n ast.Node) bool {
   167  	_, ok := n.(*ast.File)
   168  	return ok
   169  }
   170  
   171  func deslice(T types.Type) types.Type {
   172  	if slice, ok := T.Underlying().(*types.Slice); ok {
   173  		return slice.Elem()
   174  	}
   175  	return nil
   176  }
   177  
   178  // isSelector returns the enclosing *ast.SelectorExpr when pos is in the
   179  // selector.
   180  func enclosingSelector(path []ast.Node, pos token.Pos) *ast.SelectorExpr {
   181  	if len(path) == 0 {
   182  		return nil
   183  	}
   184  
   185  	if sel, ok := path[0].(*ast.SelectorExpr); ok {
   186  		return sel
   187  	}
   188  
   189  	if _, ok := path[0].(*ast.Ident); ok && len(path) > 1 {
   190  		if sel, ok := path[1].(*ast.SelectorExpr); ok && pos >= sel.Sel.Pos() {
   191  			return sel
   192  		}
   193  	}
   194  
   195  	return nil
   196  }
   197  
   198  func enclosingValueSpec(path []ast.Node) *ast.ValueSpec {
   199  	for _, n := range path {
   200  		if vs, ok := n.(*ast.ValueSpec); ok {
   201  			return vs
   202  		}
   203  	}
   204  
   205  	return nil
   206  }
   207  
   208  // exprObj returns the types.Object associated with the *ast.Ident or
   209  // *ast.SelectorExpr e.
   210  func exprObj(info *types.Info, e ast.Expr) types.Object {
   211  	var ident *ast.Ident
   212  	switch expr := e.(type) {
   213  	case *ast.Ident:
   214  		ident = expr
   215  	case *ast.SelectorExpr:
   216  		ident = expr.Sel
   217  	default:
   218  		return nil
   219  	}
   220  
   221  	return info.ObjectOf(ident)
   222  }
   223  
   224  // typeConversion returns the type being converted to if call is a type
   225  // conversion expression.
   226  func typeConversion(call *ast.CallExpr, info *types.Info) types.Type {
   227  	// Type conversion (e.g. "float64(foo)").
   228  	if fun, _ := exprObj(info, call.Fun).(*types.TypeName); fun != nil {
   229  		return fun.Type()
   230  	}
   231  
   232  	return nil
   233  }
   234  
   235  // fieldsAccessible returns whether s has at least one field accessible by p.
   236  func fieldsAccessible(s *types.Struct, p *types.Package) bool {
   237  	for i := 0; i < s.NumFields(); i++ {
   238  		f := s.Field(i)
   239  		if f.Exported() || f.Pkg() == p {
   240  			return true
   241  		}
   242  	}
   243  	return false
   244  }
   245  
   246  // prevStmt returns the statement that precedes the statement containing pos.
   247  // For example:
   248  //
   249  //     foo := 1
   250  //     bar(1 + 2<>)
   251  //
   252  // If "<>" is pos, prevStmt returns "foo := 1"
   253  func prevStmt(pos token.Pos, path []ast.Node) ast.Stmt {
   254  	var blockLines []ast.Stmt
   255  	for i := 0; i < len(path) && blockLines == nil; i++ {
   256  		switch n := path[i].(type) {
   257  		case *ast.BlockStmt:
   258  			blockLines = n.List
   259  		case *ast.CommClause:
   260  			blockLines = n.Body
   261  		case *ast.CaseClause:
   262  			blockLines = n.Body
   263  		}
   264  	}
   265  
   266  	for i := len(blockLines) - 1; i >= 0; i-- {
   267  		if blockLines[i].End() < pos {
   268  			return blockLines[i]
   269  		}
   270  	}
   271  
   272  	return nil
   273  }
   274  
   275  // formatZeroValue produces Go code representing the zero value of T. It
   276  // returns the empty string if T is invalid.
   277  func formatZeroValue(T types.Type, qf types.Qualifier) string {
   278  	switch u := T.Underlying().(type) {
   279  	case *types.Basic:
   280  		switch {
   281  		case u.Info()&types.IsNumeric > 0:
   282  			return "0"
   283  		case u.Info()&types.IsString > 0:
   284  			return `""`
   285  		case u.Info()&types.IsBoolean > 0:
   286  			return "false"
   287  		default:
   288  			return ""
   289  		}
   290  	case *types.Pointer, *types.Interface, *types.Chan, *types.Map, *types.Slice, *types.Signature:
   291  		return "nil"
   292  	default:
   293  		return types.TypeString(T, qf) + "{}"
   294  	}
   295  }
   296  
   297  // isBasicKind returns whether t is a basic type of kind k.
   298  func isBasicKind(t types.Type, k types.BasicInfo) bool {
   299  	b, _ := t.Underlying().(*types.Basic)
   300  	return b != nil && b.Info()&k > 0
   301  }