analysis.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  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. // Package analysisinternal exposes internal-only fields from go/analysis.
  5. package analysisinternal
  6. import (
  7. "bytes"
  8. "fmt"
  9. "go/ast"
  10. "go/token"
  11. "go/types"
  12. "strconv"
  13. )
  14. // Flag to gate diagnostics for fuzz tests in 1.18.
  15. var DiagnoseFuzzTests bool = false
  16. var (
  17. GetTypeErrors func(p interface{}) []types.Error
  18. SetTypeErrors func(p interface{}, errors []types.Error)
  19. )
  20. func TypeErrorEndPos(fset *token.FileSet, src []byte, start token.Pos) token.Pos {
  21. // Get the end position for the type error.
  22. offset, end := fset.PositionFor(start, false).Offset, start
  23. if offset >= len(src) {
  24. return end
  25. }
  26. if width := bytes.IndexAny(src[offset:], " \n,():;[]+-*"); width > 0 {
  27. end = start + token.Pos(width)
  28. }
  29. return end
  30. }
  31. func ZeroValue(f *ast.File, pkg *types.Package, typ types.Type) ast.Expr {
  32. under := typ
  33. if n, ok := typ.(*types.Named); ok {
  34. under = n.Underlying()
  35. }
  36. switch u := under.(type) {
  37. case *types.Basic:
  38. switch {
  39. case u.Info()&types.IsNumeric != 0:
  40. return &ast.BasicLit{Kind: token.INT, Value: "0"}
  41. case u.Info()&types.IsBoolean != 0:
  42. return &ast.Ident{Name: "false"}
  43. case u.Info()&types.IsString != 0:
  44. return &ast.BasicLit{Kind: token.STRING, Value: `""`}
  45. default:
  46. panic("unknown basic type")
  47. }
  48. case *types.Chan, *types.Interface, *types.Map, *types.Pointer, *types.Signature, *types.Slice, *types.Array:
  49. return ast.NewIdent("nil")
  50. case *types.Struct:
  51. texpr := TypeExpr(f, pkg, typ) // typ because we want the name here.
  52. if texpr == nil {
  53. return nil
  54. }
  55. return &ast.CompositeLit{
  56. Type: texpr,
  57. }
  58. }
  59. return nil
  60. }
  61. // IsZeroValue checks whether the given expression is a 'zero value' (as determined by output of
  62. // analysisinternal.ZeroValue)
  63. func IsZeroValue(expr ast.Expr) bool {
  64. switch e := expr.(type) {
  65. case *ast.BasicLit:
  66. return e.Value == "0" || e.Value == `""`
  67. case *ast.Ident:
  68. return e.Name == "nil" || e.Name == "false"
  69. default:
  70. return false
  71. }
  72. }
  73. func TypeExpr(f *ast.File, pkg *types.Package, typ types.Type) ast.Expr {
  74. switch t := typ.(type) {
  75. case *types.Basic:
  76. switch t.Kind() {
  77. case types.UnsafePointer:
  78. return &ast.SelectorExpr{X: ast.NewIdent("unsafe"), Sel: ast.NewIdent("Pointer")}
  79. default:
  80. return ast.NewIdent(t.Name())
  81. }
  82. case *types.Pointer:
  83. x := TypeExpr(f, pkg, t.Elem())
  84. if x == nil {
  85. return nil
  86. }
  87. return &ast.UnaryExpr{
  88. Op: token.MUL,
  89. X: x,
  90. }
  91. case *types.Array:
  92. elt := TypeExpr(f, pkg, t.Elem())
  93. if elt == nil {
  94. return nil
  95. }
  96. return &ast.ArrayType{
  97. Len: &ast.BasicLit{
  98. Kind: token.INT,
  99. Value: fmt.Sprintf("%d", t.Len()),
  100. },
  101. Elt: elt,
  102. }
  103. case *types.Slice:
  104. elt := TypeExpr(f, pkg, t.Elem())
  105. if elt == nil {
  106. return nil
  107. }
  108. return &ast.ArrayType{
  109. Elt: elt,
  110. }
  111. case *types.Map:
  112. key := TypeExpr(f, pkg, t.Key())
  113. value := TypeExpr(f, pkg, t.Elem())
  114. if key == nil || value == nil {
  115. return nil
  116. }
  117. return &ast.MapType{
  118. Key: key,
  119. Value: value,
  120. }
  121. case *types.Chan:
  122. dir := ast.ChanDir(t.Dir())
  123. if t.Dir() == types.SendRecv {
  124. dir = ast.SEND | ast.RECV
  125. }
  126. value := TypeExpr(f, pkg, t.Elem())
  127. if value == nil {
  128. return nil
  129. }
  130. return &ast.ChanType{
  131. Dir: dir,
  132. Value: value,
  133. }
  134. case *types.Signature:
  135. var params []*ast.Field
  136. for i := 0; i < t.Params().Len(); i++ {
  137. p := TypeExpr(f, pkg, t.Params().At(i).Type())
  138. if p == nil {
  139. return nil
  140. }
  141. params = append(params, &ast.Field{
  142. Type: p,
  143. Names: []*ast.Ident{
  144. {
  145. Name: t.Params().At(i).Name(),
  146. },
  147. },
  148. })
  149. }
  150. var returns []*ast.Field
  151. for i := 0; i < t.Results().Len(); i++ {
  152. r := TypeExpr(f, pkg, t.Results().At(i).Type())
  153. if r == nil {
  154. return nil
  155. }
  156. returns = append(returns, &ast.Field{
  157. Type: r,
  158. })
  159. }
  160. return &ast.FuncType{
  161. Params: &ast.FieldList{
  162. List: params,
  163. },
  164. Results: &ast.FieldList{
  165. List: returns,
  166. },
  167. }
  168. case *types.Named:
  169. if t.Obj().Pkg() == nil {
  170. return ast.NewIdent(t.Obj().Name())
  171. }
  172. if t.Obj().Pkg() == pkg {
  173. return ast.NewIdent(t.Obj().Name())
  174. }
  175. pkgName := t.Obj().Pkg().Name()
  176. // If the file already imports the package under another name, use that.
  177. for _, cand := range f.Imports {
  178. if path, _ := strconv.Unquote(cand.Path.Value); path == t.Obj().Pkg().Path() {
  179. if cand.Name != nil && cand.Name.Name != "" {
  180. pkgName = cand.Name.Name
  181. }
  182. }
  183. }
  184. if pkgName == "." {
  185. return ast.NewIdent(t.Obj().Name())
  186. }
  187. return &ast.SelectorExpr{
  188. X: ast.NewIdent(pkgName),
  189. Sel: ast.NewIdent(t.Obj().Name()),
  190. }
  191. case *types.Struct:
  192. return ast.NewIdent(t.String())
  193. case *types.Interface:
  194. return ast.NewIdent(t.String())
  195. default:
  196. return nil
  197. }
  198. }
  199. type TypeErrorPass string
  200. const (
  201. NoNewVars TypeErrorPass = "nonewvars"
  202. NoResultValues TypeErrorPass = "noresultvalues"
  203. UndeclaredName TypeErrorPass = "undeclaredname"
  204. )
  205. // StmtToInsertVarBefore returns the ast.Stmt before which we can safely insert a new variable.
  206. // Some examples:
  207. //
  208. // Basic Example:
  209. // z := 1
  210. // y := z + x
  211. // If x is undeclared, then this function would return `y := z + x`, so that we
  212. // can insert `x := ` on the line before `y := z + x`.
  213. //
  214. // If stmt example:
  215. // if z == 1 {
  216. // } else if z == y {}
  217. // If y is undeclared, then this function would return `if z == 1 {`, because we cannot
  218. // insert a statement between an if and an else if statement. As a result, we need to find
  219. // the top of the if chain to insert `y := ` before.
  220. func StmtToInsertVarBefore(path []ast.Node) ast.Stmt {
  221. enclosingIndex := -1
  222. for i, p := range path {
  223. if _, ok := p.(ast.Stmt); ok {
  224. enclosingIndex = i
  225. break
  226. }
  227. }
  228. if enclosingIndex == -1 {
  229. return nil
  230. }
  231. enclosingStmt := path[enclosingIndex]
  232. switch enclosingStmt.(type) {
  233. case *ast.IfStmt:
  234. // The enclosingStmt is inside of the if declaration,
  235. // We need to check if we are in an else-if stmt and
  236. // get the base if statement.
  237. return baseIfStmt(path, enclosingIndex)
  238. case *ast.CaseClause:
  239. // Get the enclosing switch stmt if the enclosingStmt is
  240. // inside of the case statement.
  241. for i := enclosingIndex + 1; i < len(path); i++ {
  242. if node, ok := path[i].(*ast.SwitchStmt); ok {
  243. return node
  244. } else if node, ok := path[i].(*ast.TypeSwitchStmt); ok {
  245. return node
  246. }
  247. }
  248. }
  249. if len(path) <= enclosingIndex+1 {
  250. return enclosingStmt.(ast.Stmt)
  251. }
  252. // Check if the enclosing statement is inside another node.
  253. switch expr := path[enclosingIndex+1].(type) {
  254. case *ast.IfStmt:
  255. // Get the base if statement.
  256. return baseIfStmt(path, enclosingIndex+1)
  257. case *ast.ForStmt:
  258. if expr.Init == enclosingStmt || expr.Post == enclosingStmt {
  259. return expr
  260. }
  261. }
  262. return enclosingStmt.(ast.Stmt)
  263. }
  264. // baseIfStmt walks up the if/else-if chain until we get to
  265. // the top of the current if chain.
  266. func baseIfStmt(path []ast.Node, index int) ast.Stmt {
  267. stmt := path[index]
  268. for i := index + 1; i < len(path); i++ {
  269. if node, ok := path[i].(*ast.IfStmt); ok && node.Else == stmt {
  270. stmt = node
  271. continue
  272. }
  273. break
  274. }
  275. return stmt.(ast.Stmt)
  276. }
  277. // WalkASTWithParent walks the AST rooted at n. The semantics are
  278. // similar to ast.Inspect except it does not call f(nil).
  279. func WalkASTWithParent(n ast.Node, f func(n ast.Node, parent ast.Node) bool) {
  280. var ancestors []ast.Node
  281. ast.Inspect(n, func(n ast.Node) (recurse bool) {
  282. if n == nil {
  283. ancestors = ancestors[:len(ancestors)-1]
  284. return false
  285. }
  286. var parent ast.Node
  287. if len(ancestors) > 0 {
  288. parent = ancestors[len(ancestors)-1]
  289. }
  290. ancestors = append(ancestors, n)
  291. return f(n, parent)
  292. })
  293. }
  294. // FindMatchingIdents finds all identifiers in 'node' that match any of the given types.
  295. // 'pos' represents the position at which the identifiers may be inserted. 'pos' must be within
  296. // the scope of each of identifier we select. Otherwise, we will insert a variable at 'pos' that
  297. // is unrecognized.
  298. func FindMatchingIdents(typs []types.Type, node ast.Node, pos token.Pos, info *types.Info, pkg *types.Package) map[types.Type][]*ast.Ident {
  299. matches := map[types.Type][]*ast.Ident{}
  300. // Initialize matches to contain the variable types we are searching for.
  301. for _, typ := range typs {
  302. if typ == nil {
  303. continue
  304. }
  305. matches[typ] = []*ast.Ident{}
  306. }
  307. seen := map[types.Object]struct{}{}
  308. ast.Inspect(node, func(n ast.Node) bool {
  309. if n == nil {
  310. return false
  311. }
  312. // Prevent circular definitions. If 'pos' is within an assignment statement, do not
  313. // allow any identifiers in that assignment statement to be selected. Otherwise,
  314. // we could do the following, where 'x' satisfies the type of 'f0':
  315. //
  316. // x := fakeStruct{f0: x}
  317. //
  318. assignment, ok := n.(*ast.AssignStmt)
  319. if ok && pos > assignment.Pos() && pos <= assignment.End() {
  320. return false
  321. }
  322. if n.End() > pos {
  323. return n.Pos() <= pos
  324. }
  325. ident, ok := n.(*ast.Ident)
  326. if !ok || ident.Name == "_" {
  327. return true
  328. }
  329. obj := info.Defs[ident]
  330. if obj == nil || obj.Type() == nil {
  331. return true
  332. }
  333. if _, ok := obj.(*types.TypeName); ok {
  334. return true
  335. }
  336. // Prevent duplicates in matches' values.
  337. if _, ok = seen[obj]; ok {
  338. return true
  339. }
  340. seen[obj] = struct{}{}
  341. // Find the scope for the given position. Then, check whether the object
  342. // exists within the scope.
  343. innerScope := pkg.Scope().Innermost(pos)
  344. if innerScope == nil {
  345. return true
  346. }
  347. _, foundObj := innerScope.LookupParent(ident.Name, pos)
  348. if foundObj != obj {
  349. return true
  350. }
  351. // The object must match one of the types that we are searching for.
  352. if idents, ok := matches[obj.Type()]; ok {
  353. matches[obj.Type()] = append(idents, ast.NewIdent(ident.Name))
  354. }
  355. // If the object type does not exactly match any of the target types, greedily
  356. // find the first target type that the object type can satisfy.
  357. for typ := range matches {
  358. if obj.Type() == typ {
  359. continue
  360. }
  361. if equivalentTypes(obj.Type(), typ) {
  362. matches[typ] = append(matches[typ], ast.NewIdent(ident.Name))
  363. }
  364. }
  365. return true
  366. })
  367. return matches
  368. }
  369. func equivalentTypes(want, got types.Type) bool {
  370. if want == got || types.Identical(want, got) {
  371. return true
  372. }
  373. // Code segment to help check for untyped equality from (golang/go#32146).
  374. if rhs, ok := want.(*types.Basic); ok && rhs.Info()&types.IsUntyped > 0 {
  375. if lhs, ok := got.Underlying().(*types.Basic); ok {
  376. return rhs.Info()&types.IsConstType == lhs.Info()&types.IsConstType
  377. }
  378. }
  379. return types.AssignableTo(want, got)
  380. }