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