kythe.io@v0.0.68-0.20240422202219-7225dbc01741/kythe/go/indexer/emit.go (about) 1 /* 2 * Copyright 2016 The Kythe Authors. All rights reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package indexer 18 19 import ( 20 "context" 21 "fmt" 22 "go/ast" 23 "go/doc/comment" 24 "go/token" 25 "go/types" 26 "net/url" 27 "path" 28 "regexp" 29 "strconv" 30 "strings" 31 32 "kythe.io/kythe/go/extractors/govname" 33 "kythe.io/kythe/go/util/kytheuri" 34 "kythe.io/kythe/go/util/log" 35 "kythe.io/kythe/go/util/metadata" 36 "kythe.io/kythe/go/util/schema/edges" 37 "kythe.io/kythe/go/util/schema/facts" 38 "kythe.io/kythe/go/util/schema/nodes" 39 40 "github.com/golang/protobuf/proto" 41 "golang.org/x/tools/go/types/typeutil" 42 43 cpb "kythe.io/kythe/proto/common_go_proto" 44 gopb "kythe.io/kythe/proto/go_go_proto" 45 spb "kythe.io/kythe/proto/storage_go_proto" 46 ) 47 48 // EmitOptions control the behaviour of the Emit function. A nil options 49 // pointer provides default values. 50 type EmitOptions struct { 51 // If true, emit nodes for standard library packages when they are first 52 // encountered. This is helpful if you want to index a package in isolation 53 // where data for the standard library are not available. 54 EmitStandardLibs bool 55 56 // If true, emit code facts containing MarkedSource messages. 57 EmitMarkedSource bool 58 59 // If true, emit linkages specified by metadata rules. 60 EmitLinkages bool 61 62 // If true, emit childof edges for an anchor's semantic scope. 63 EmitAnchorScopes bool 64 65 // If true, use the enclosing file for top-level callsite scopes. 66 UseFileAsTopLevelScope bool 67 68 // If set, use this as the base URL for links to godoc. The import path is 69 // appended to the path of this URL to obtain the target URL to link to. 70 DocBase *url.URL 71 72 // If true, the doc/uri fact is only emitted for go std library packages. 73 OnlyEmitDocURIsForStandardLibs bool 74 75 // If enabled, all VNames emitted by the indexer are assigned the 76 // compilation unit's corpus. 77 UseCompilationCorpusForAll bool 78 79 // If set, all stdlib nodes are assigned this corpus. This takes precedence 80 // over UseCompilationCorpusForAll for stdlib nodes. 81 OverrideStdlibCorpus string 82 83 // EmitRefCallOverIdentifier determines whether ref/call anchors are emitted 84 // over function identifiers (or the legacy behavior of over the entire 85 // callsite). 86 EmitRefCallOverIdentifier bool 87 88 // FlagConstructors is a set of known flag constructor functions. 89 FlagConstructors *gopb.FlagConstructors 90 91 // Verbose determines whether verbose logging is enabled. 92 Verbose bool 93 } 94 95 func (e *EmitOptions) emitMarkedSource() bool { 96 if e == nil { 97 return false 98 } 99 return e.EmitMarkedSource 100 } 101 102 func (e *EmitOptions) emitAnchorScopes() bool { 103 if e == nil { 104 return false 105 } 106 return e.EmitAnchorScopes 107 } 108 109 func (e *EmitOptions) emitRefCallOverIdentifier() bool { 110 if e == nil { 111 return false 112 } 113 return e.EmitRefCallOverIdentifier 114 } 115 116 func (e *EmitOptions) emitFlagNodes() bool { 117 if e == nil { 118 return false 119 } 120 return e.FlagConstructors != nil 121 } 122 123 func (e *EmitOptions) useFileAsTopLevelScope() bool { 124 if e == nil { 125 return false 126 } 127 return e.UseFileAsTopLevelScope 128 } 129 130 // shouldEmit reports whether the indexer should emit a node for the given 131 // vname. Presently this is true if vname denotes a standard library and the 132 // corresponding option is enabled. 133 func (e *EmitOptions) shouldEmit(vname *spb.VName) bool { 134 return e != nil && e.EmitStandardLibs && govname.IsStandardLibrary(vname) 135 } 136 137 func (e *EmitOptions) docBase() string { 138 if e == nil || e.DocBase == nil { 139 return "" 140 } 141 return e.DocBase.String() 142 } 143 144 // docURL returns a documentation URL for the specified package, if one is 145 // specified by the options, or "" if not. 146 func (e *EmitOptions) docURL(pi *PackageInfo) string { 147 if e == nil || e.DocBase == nil { 148 return "" 149 } 150 if e.OnlyEmitDocURIsForStandardLibs && !govname.IsStandardLibrary(pi.VName) { 151 return "" 152 } 153 154 u := *e.DocBase 155 u.Path = path.Join(u.Path, pi.ImportPath) 156 return u.String() 157 } 158 159 func (e *EmitOptions) verbose() bool { 160 if e == nil { 161 return false 162 } 163 return e.Verbose 164 } 165 166 // An impl records that a type A implements an interface B. 167 type impl struct{ A, B types.Object } 168 169 // Emit generates Kythe facts and edges to represent pi, and writes them to 170 // sink. In case of errors, processing continues as far as possible before the 171 // first error encountered is reported. 172 func (pi *PackageInfo) Emit(ctx context.Context, sink Sink, opts *EmitOptions) error { 173 if opts == nil { 174 opts = &EmitOptions{} 175 } 176 e := &emitter{ 177 ctx: ctx, 178 pi: pi, 179 sink: sink, 180 opts: opts, 181 impl: make(map[impl]struct{}), 182 anchored: make(map[ast.Node]struct{}), 183 fmeta: make(map[*ast.File]bool), 184 variadics: make(map[*types.Slice]bool), 185 } 186 187 // Emit a node to represent the package as a whole. 188 e.writeFact(pi.VName, facts.NodeKind, nodes.Package) 189 if url := e.opts.docURL(pi); url != "" { 190 e.writeFact(pi.VName, facts.DocURI, url) 191 } 192 e.emitPackageMarkedSource(pi) 193 194 // Emit facts for all the source files claimed by this package. 195 for file, text := range pi.SourceText { 196 vname := pi.FileVName(file) 197 e.writeFact(vname, facts.NodeKind, nodes.File) 198 e.writeFact(vname, facts.Text, text) 199 // All Go source files are encoded as UTF-8, which is the default. 200 201 e.writeEdge(vname, pi.VName, edges.ChildOf) 202 } 203 204 // Traverse the AST of each file in the package for xref entries. 205 for _, file := range pi.Files { 206 e.cmap = ast.NewCommentMap(pi.FileSet, file, file.Comments) 207 e.writeDoc(file.Doc, pi.VName) // capture package comments 208 e.writeRef(file.Name, pi.VName, edges.DefinesBinding) // define a binding for the package 209 ast.Walk(newASTVisitor(func(node ast.Node, stack stackFunc) bool { 210 switch n := node.(type) { 211 case *ast.Ident: 212 e.visitIdent(n, stack) 213 case *ast.FuncDecl: 214 e.visitFuncDecl(n, stack) 215 case *ast.FuncLit: 216 e.visitFuncLit(n, stack) 217 case *ast.ValueSpec: 218 e.visitValueSpec(n, stack) 219 case *ast.TypeSpec: 220 e.visitTypeSpec(n, stack) 221 case *ast.ImportSpec: 222 e.visitImportSpec(n, stack) 223 case *ast.AssignStmt: 224 e.visitAssignStmt(n, stack) 225 case *ast.RangeStmt: 226 e.visitRangeStmt(n, stack) 227 case *ast.CompositeLit: 228 e.visitCompositeLit(n, stack) 229 case *ast.IndexExpr: 230 e.visitIndexExpr(n, stack) 231 case *ast.IndexListExpr: 232 e.visitIndexListExpr(n, stack) 233 case *ast.ArrayType: 234 e.visitArrayType(n, stack) 235 case *ast.CallExpr: 236 e.visitCallExpr(n, stack) 237 } 238 return true 239 }), file) 240 } 241 242 // Emit edges from each named type to the interface types it satisfies, for 243 // those interface types that are known to this compiltion. 244 e.emitSatisfactions() 245 246 // TODO(fromberger): Add diagnostics for type-checker errors. 247 if opts.verbose() { 248 for _, err := range pi.Errors { 249 log.WarningContextf(ctx, "Type resolution error: %v", err) 250 } 251 } 252 return e.firstErr 253 } 254 255 type emitter struct { 256 ctx context.Context 257 pi *PackageInfo 258 sink Sink 259 opts *EmitOptions 260 impl map[impl]struct{} // see checkImplements 261 rmap map[*ast.File]map[int]metadata.Rules // see applyRules 262 fmeta map[*ast.File]bool // see applyRules 263 anchored map[ast.Node]struct{} // see writeAnchor 264 firstErr error 265 cmap ast.CommentMap // current file's CommentMap 266 267 // lazily-initialized lookup table based on opts.FlagConstructors 268 flagConstructors map[string]map[string]*gopb.FlagConstructor 269 270 variadics map[*types.Slice]bool 271 } 272 273 type refKind int 274 275 const ( 276 readRef refKind = iota 277 writeRef 278 readWriteRef 279 ) 280 281 func exprRefKind(tgt ast.Expr, stack stackFunc, depth int) refKind { 282 switch parent := stack(depth + 1).(type) { 283 case *ast.AssignStmt: 284 // Check if identifier is being assigned; we assume this is not a definition 285 // and checked by the caller. 286 for _, lhs := range parent.Lhs { 287 if lhs == tgt { 288 switch parent.Tok { 289 case token.ASSIGN, token.DEFINE: 290 return writeRef 291 default: // +=, etc. 292 return readWriteRef 293 } 294 } 295 } 296 case *ast.IncDecStmt: 297 return readWriteRef 298 case *ast.SelectorExpr: 299 if id, ok := tgt.(*ast.Ident); ok && id == parent.Sel { 300 return exprRefKind(parent, stack, depth+1) 301 } 302 case *ast.KeyValueExpr: 303 if tgt == parent.Key { 304 if c, ok := stack(depth + 2).(*ast.CompositeLit); ok { 305 if _, isMap := c.Type.(*ast.MapType); !isMap { 306 return writeRef 307 } 308 } 309 } 310 } 311 return readRef 312 } 313 314 // visitIdent handles referring identifiers. Declaring identifiers are handled 315 // as part of their parent syntax. 316 func (e *emitter) visitIdent(id *ast.Ident, stack stackFunc) { 317 obj := e.pi.Info.Uses[id] 318 if obj == nil { 319 // Defining identifiers are handled by their parent nodes. 320 return 321 } 322 323 if sig, ok := obj.Type().(*types.Signature); ok && sig.Recv() != nil && sig.RecvTypeParams().Len() > 0 { 324 // Lookup the original non-instantiated method to reference. 325 if n, ok := deref(sig.Recv().Type()).(*types.Named); ok { 326 f, _, _ := types.LookupFieldOrMethod(n.Origin(), true, obj.Pkg(), obj.Name()) 327 if f != nil { 328 obj = f 329 } 330 } 331 } 332 333 // Receiver type parameter identifiers are both usages and definitions; take 334 // the opportunity to emit a binding and do not continue to emit a Ref edge. 335 if def, ok := e.pi.Info.Defs[id].(*types.TypeName); ok && def == obj { 336 e.writeBinding(id, nodes.TVar, nil) 337 return 338 } 339 340 var target *spb.VName 341 if n, ok := obj.(*types.TypeName); ok && obj.Pkg() == nil { 342 // Handle type arguments in instantiated types. 343 target = e.emitType(n.Type()) 344 } else { 345 target = e.pi.ObjectVName(obj) 346 } 347 348 if target == nil { 349 // This should not happen in well-formed packages, but can if the 350 // extractor gets confused. Avoid emitting confusing references in such 351 // cases. Note that in this case we need to emit a fresh anchor, since 352 // we aren't otherwise emitting a reference. 353 e.writeNodeDiagnostic(id, diagnostic{ 354 Message: fmt.Sprintf("Unable to identify the package for %q", id.Name), 355 }) 356 return 357 } 358 359 var refs []*spb.VName 360 refKind := exprRefKind(id, stack, 0) 361 if refKind == readRef || refKind == readWriteRef { 362 refs = append(refs, e.writeRef(id, target, edges.Ref)) 363 } 364 if refKind == writeRef || refKind == readWriteRef { 365 refs = append(refs, e.writeRef(id, target, edges.RefWrites)) 366 } 367 368 if e.opts.emitAnchorScopes() { 369 parent := e.callContext(stack).vname 370 for _, ref := range refs { 371 e.writeEdge(ref, parent, edges.ChildOf) 372 } 373 } 374 if call, ok := isCall(id, obj, stack); ok { 375 var callAnchor *spb.VName 376 if e.opts.emitRefCallOverIdentifier() { 377 callAnchor = e.writeRef(id, target, edges.RefCall) 378 } else { 379 callAnchor = e.writeRef(call, target, edges.RefCall) 380 } 381 382 // Paint an edge to the function blamed for the call, or if there is 383 // none then to the package initializer. 384 e.writeEdge(callAnchor, e.callContext(stack).vname, edges.ChildOf) 385 } 386 } 387 388 // visitFuncDecl handles function and method declarations and their parameters. 389 func (e *emitter) visitFuncDecl(decl *ast.FuncDecl, stack stackFunc) { 390 info := &funcInfo{vname: new(spb.VName)} 391 e.pi.function[decl] = info 392 393 // Get the type of this function, even if its name is blank. 394 obj, _ := e.pi.Info.Defs[decl.Name].(*types.Func) 395 if obj == nil { 396 return // a redefinition, for example 397 } 398 399 // Special case: There may be multiple package-level init functions, so 400 // override the normal signature generation to include a discriminator. 401 if decl.Recv == nil && obj.Name() == "init" { 402 e.pi.numInits++ 403 e.pi.sigs[obj] = fmt.Sprintf("%s#%d", e.pi.Signature(obj), e.pi.numInits) 404 } 405 406 info.vname = e.mustWriteBinding(decl.Name, nodes.Function, nil) 407 e.writeDef(decl, info.vname) 408 e.writeDoc(decl.Doc, info.vname) 409 410 // For concrete methods: Emit the receiver if named, and connect the method 411 // to its declaring type. 412 sig := obj.Type().(*types.Signature) 413 if sig.Recv() != nil { 414 // The receiver is treated as parameter 0. 415 if names := decl.Recv.List[0].Names; names != nil { 416 if recv := e.writeVarBinding(names[0], nodes.LocalParameter, info.vname); recv != nil { 417 e.writeEdge(info.vname, recv, edges.ParamIndex(0)) 418 } 419 } 420 421 // The method should be a child of its (named) enclosing type. 422 if named, _ := deref(sig.Recv().Type()).(*types.Named); named != nil { 423 base := e.pi.ObjectVName(named.Obj()) 424 e.writeEdge(info.vname, base, edges.ChildOf) 425 } 426 } 427 e.emitParameters(decl.Type, sig, info) 428 } 429 430 // rewrittenCorpusForVName returns the new corpus that should be assigned to the 431 // given vname based on the OverrideStdlibCorpus and UseCompilationCorpusForAll options 432 func (e *emitter) rewrittenCorpusForVName(v *spb.VName) string { 433 if e.opts.OverrideStdlibCorpus != "" && v.GetCorpus() == govname.GolangCorpus { 434 return e.opts.OverrideStdlibCorpus 435 } 436 if e.opts.UseCompilationCorpusForAll { 437 return e.pi.VName.GetCorpus() 438 } 439 if v.GetCorpus() == "" { 440 // If the VName doesn't specify a corpus, use the compilation unit's corpus 441 return e.pi.VName.GetCorpus() 442 } 443 return v.GetCorpus() 444 } 445 446 // emitTApp emits a tapp node and returns its VName. The new tapp is emitted 447 // with given constructor and parameters. The constructor's kind is also 448 // emitted if this is the first time seeing it. 449 func (e *emitter) emitTApp(ms *cpb.MarkedSource, ctorKind string, ctor *spb.VName, params ...*spb.VName) *spb.VName { 450 if ctorKind != "" && e.pi.typeEmitted.Add(ctor.Signature) { 451 e.writeFact(ctor, facts.NodeKind, ctorKind) 452 if ctorKind == nodes.TBuiltin { 453 e.emitBuiltinMarkedSource(ctor) 454 } 455 } 456 components := []any{ctor} 457 for _, p := range params { 458 components = append(components, p) 459 } 460 v := &spb.VName{Language: govname.Language, Signature: hashSignature(components)} 461 v.Corpus = e.rewrittenCorpusForVName(v) 462 if e.pi.typeEmitted.Add(v.Signature) { 463 e.writeFact(v, facts.NodeKind, nodes.TApp) 464 e.writeEdge(v, ctor, edges.ParamIndex(0)) 465 for i, p := range params { 466 e.writeEdge(v, p, edges.ParamIndex(i+1)) 467 } 468 if ms != nil && e.opts.emitMarkedSource() { 469 e.emitCode(v, ms) 470 } 471 } 472 return v 473 } 474 475 // emitType emits the type as a node and returns its VName. VNames are cached 476 // so the type nodes are only emitted the first time they are seen. 477 func (e *emitter) emitType(typ types.Type) *spb.VName { 478 v, ok := e.pi.typeVName[typ] 479 if ok { 480 return v 481 } 482 483 switch typ := typ.(type) { 484 case *types.Named: 485 if typ.TypeArgs().Len() == 0 { 486 v = e.pi.ObjectVName(typ.Obj()) 487 } else { 488 // Instantiated Named types produce tapps 489 ctor := e.emitType(typ.Origin()) 490 args := typ.TypeArgs() 491 var params []*spb.VName 492 for i := 0; i < args.Len(); i++ { 493 params = append(params, e.emitType(args.At(i))) 494 } 495 v = e.emitTApp(genericTAppMS, "", ctor, params...) 496 } 497 case *types.Basic: 498 v = govname.BasicType(typ) 499 if e.pi.typeEmitted.Add(v.Signature) { 500 e.writeFact(v, facts.NodeKind, nodes.TBuiltin) 501 e.emitBuiltinMarkedSource(v) 502 } 503 case *types.Array: 504 v = e.emitTApp(arrayTAppMS(typ.Len()), nodes.TBuiltin, govname.ArrayConstructorType(typ.Len()), e.emitType(typ.Elem())) 505 case *types.Slice: 506 if e.variadics[typ] { 507 v = e.emitTApp(variadicTAppMS, nodes.TBuiltin, govname.VariadicConstructorType(), e.emitType(typ.Elem())) 508 } else { 509 v = e.emitTApp(sliceTAppMS, nodes.TBuiltin, govname.SliceConstructorType(), e.emitType(typ.Elem())) 510 } 511 case *types.Pointer: 512 v = e.emitTApp(pointerTAppMS, nodes.TBuiltin, govname.PointerConstructorType(), e.emitType(typ.Elem())) 513 case *types.Chan: 514 v = e.emitTApp(chanTAppMS(typ.Dir()), nodes.TBuiltin, govname.ChanConstructorType(typ.Dir()), e.emitType(typ.Elem())) 515 case *types.Map: 516 v = e.emitTApp(mapTAppMS, nodes.TBuiltin, govname.MapConstructorType(), e.emitType(typ.Key()), e.emitType(typ.Elem())) 517 case *types.Tuple: // function return types 518 v = e.emitTApp(tupleTAppMS, nodes.TBuiltin, govname.TupleConstructorType(), e.visitTuple(typ)...) 519 case *types.Signature: // function types 520 ms := &cpb.MarkedSource{ 521 Kind: cpb.MarkedSource_TYPE, 522 Child: []*cpb.MarkedSource{{ 523 Kind: cpb.MarkedSource_PARAMETER_LOOKUP_BY_PARAM, 524 LookupIndex: 3, 525 PreText: "func(", 526 PostChildText: ", ", 527 PostText: ")", 528 }}, 529 } 530 531 if typ.Variadic() { 532 // Mark last parameter type as variadic. 533 last := typ.Params().Len() - 1 534 if slice, ok := typ.Params().At(last).Type().(*types.Slice); ok { 535 e.variadics[slice] = true 536 } 537 } 538 params := e.visitTuple(typ.Params()) 539 540 var ret *spb.VName 541 if typ.Results().Len() == 1 { 542 ret = e.emitType(typ.Results().At(0).Type()) 543 } else { 544 ret = e.emitType(typ.Results()) 545 } 546 if typ.Results().Len() != 0 { 547 ms.Child = append(ms.Child, &cpb.MarkedSource{ 548 Kind: cpb.MarkedSource_BOX, 549 PreText: " ", 550 Child: []*cpb.MarkedSource{{ 551 Kind: cpb.MarkedSource_LOOKUP_BY_PARAM, 552 LookupIndex: 1, 553 }}, 554 }) 555 } 556 557 var recv *spb.VName 558 if r := typ.Recv(); r != nil { 559 recv = e.emitType(r.Type()) 560 ms.Child = append([]*cpb.MarkedSource{{ 561 Kind: cpb.MarkedSource_BOX, 562 PreText: "(", 563 PostText: ") ", 564 Child: []*cpb.MarkedSource{{ 565 Kind: cpb.MarkedSource_LOOKUP_BY_PARAM, 566 LookupIndex: 2, 567 }}, 568 }}, ms.Child...) 569 } else { 570 recv = e.emitType(types.NewTuple()) 571 } 572 573 v = e.emitTApp(ms, nodes.TBuiltin, govname.FunctionConstructorType(), 574 append([]*spb.VName{ret, recv}, params...)...) 575 case *types.Interface: 576 v = &spb.VName{Language: govname.Language, Signature: hashSignature(typ)} 577 if e.pi.typeEmitted.Add(v.Signature) { 578 e.writeFact(v, facts.NodeKind, nodes.Interface) 579 if e.opts.emitMarkedSource() { 580 e.emitCode(v, &cpb.MarkedSource{ 581 Kind: cpb.MarkedSource_TYPE, 582 PreText: typ.String(), 583 }) 584 } 585 } 586 case *types.Struct: 587 v = &spb.VName{Language: govname.Language, Signature: hashSignature(typ)} 588 if e.pi.typeEmitted.Add(v.Signature) { 589 e.writeFact(v, facts.NodeKind, nodes.Record) 590 if e.opts.emitMarkedSource() { 591 e.emitCode(v, &cpb.MarkedSource{ 592 Kind: cpb.MarkedSource_TYPE, 593 PreText: typ.String(), 594 }) 595 } 596 } 597 case *types.TypeParam: 598 v = e.pi.ObjectVName(typ.Obj()) 599 default: 600 log.Warningf("unknown type %T: %+v", typ, typ) 601 } 602 603 e.pi.typeVName[typ] = v 604 return v 605 } 606 607 func (e *emitter) emitTypeOf(expr ast.Expr) *spb.VName { return e.emitType(e.pi.Info.TypeOf(expr)) } 608 609 func (e *emitter) visitTuple(t *types.Tuple) []*spb.VName { 610 size := t.Len() 611 ts := make([]*spb.VName, size) 612 for i := 0; i < size; i++ { 613 ts[i] = e.emitType(t.At(i).Type()) 614 } 615 return ts 616 } 617 618 // visitFuncLit handles function literals and their parameters. The signature 619 // for a function literal is named relative to the signature of its parent 620 // function, or the file scope if the literal is at the top level. 621 func (e *emitter) visitFuncLit(flit *ast.FuncLit, stack stackFunc) { 622 fi := e.callContext(stack) 623 if fi == nil { 624 panic(fmt.Sprintf("Function literal without a context: %v", flit)) 625 } 626 627 fi.numAnons++ 628 info := &funcInfo{vname: proto.Clone(fi.vname).(*spb.VName)} 629 info.vname.Language = govname.Language 630 info.vname.Signature += "$" + strconv.Itoa(fi.numAnons) 631 e.pi.function[flit] = info 632 def := e.writeDef(flit, info.vname) 633 if e.opts.emitAnchorScopes() { 634 e.writeEdge(def, fi.vname, edges.ChildOf) 635 } 636 e.writeFact(info.vname, facts.NodeKind, nodes.Function) 637 638 if sig, ok := e.pi.Info.Types[flit].Type.(*types.Signature); ok { 639 e.emitParameters(flit.Type, sig, info) 640 } 641 } 642 643 // visitValueSpec handles variable and constant bindings. 644 func (e *emitter) visitValueSpec(spec *ast.ValueSpec, stack stackFunc) { 645 kind := nodes.Variable 646 if stack(1).(*ast.GenDecl).Tok == token.CONST { 647 kind = nodes.Constant 648 } 649 doc := specComment(spec, stack) 650 for _, id := range spec.Names { 651 ctx := e.nameContext(stack) 652 target := e.writeBinding(id, kind, ctx) 653 if target == nil { 654 continue // type error (reported elsewhere) 655 } 656 if kind == nodes.Variable && e.isNonFileOrPackage(ctx) { 657 e.writeFact(target, facts.Subkind, nodes.Local) 658 } 659 e.writeDoc(doc, target) 660 } 661 662 // Handle members of anonymous types declared in situ. 663 if spec.Type != nil { 664 e.emitAnonMembers(spec.Type) 665 } 666 for _, v := range spec.Values { 667 if lit, ok := v.(*ast.CompositeLit); ok { 668 e.emitAnonMembers(lit.Type) 669 } 670 } 671 } 672 673 func (e *emitter) isNonFileOrPackage(v *spb.VName) bool { 674 return v.GetSignature() != "" && e.pi.VName != v 675 } 676 677 // visitTypeSpec handles type declarations, including the bindings for fields 678 // of struct types and methods of interfaces. 679 func (e *emitter) visitTypeSpec(spec *ast.TypeSpec, stack stackFunc) { 680 obj := e.pi.Info.Defs[spec.Name] 681 if obj == nil { 682 return // type error 683 } 684 target := e.mustWriteBinding(spec.Name, "", e.nameContext(stack)) 685 e.writeDef(spec, target) 686 e.writeDoc(specComment(spec, stack), target) 687 688 if e.pi.ImportPath == "builtin" { 689 // Ignore everything but defs/docs in special builtin package 690 return 691 } 692 693 mapNamedFields(spec.TypeParams, func(i int, id *ast.Ident) { 694 v := e.writeBinding(id, nodes.TVar, nil) 695 e.writeEdge(target, v, edges.TParamIndex(i)) 696 }) 697 698 // Emit type-specific structure. 699 switch t := obj.Type().Underlying().(type) { 700 case *types.Struct: 701 e.writeFact(target, facts.NodeKind, nodes.Record) 702 e.writeFact(target, facts.Subkind, nodes.Struct) 703 // Add parent edges for all fields, including promoted ones. 704 for i, n := 0, t.NumFields(); i < n; i++ { 705 e.writeEdge(e.pi.ObjectVName(t.Field(i)), target, edges.ChildOf) 706 } 707 708 // Add bindings for the explicitly-named fields in this declaration. 709 // Parent edges were already added, so skip them here. 710 if st, ok := spec.Type.(*ast.StructType); ok { 711 mapNamedFields(st.Fields, func(i int, id *ast.Ident) { 712 target := e.writeVarBinding(id, nodes.Field, nil) 713 f := st.Fields.List[i] 714 e.writeDoc(firstNonEmptyComment(f.Doc, f.Comment), target) 715 e.emitAnonMembers(f.Type) 716 }) 717 718 // Handle anonymous fields. Such fields behave as if they were 719 // named by the base identifier of their type. 720 for _, field := range st.Fields.List { 721 if len(field.Names) != 0 { 722 continue // already handled above 723 } 724 id, ok := e.pi.findFieldName(field.Type) 725 obj := e.pi.Info.Defs[id] 726 if ok && obj != nil { 727 // Don't write a fresh anchor here; we already wrote one as 728 // part of the ref to the type, and we don't want duplicate 729 // outputs. 730 anchor := e.pi.AnchorVName(e.pi.Span(id)) 731 target := e.pi.ObjectVName(obj) 732 e.writeEdge(anchor, target, edges.DefinesBinding) 733 e.writeFact(target, facts.NodeKind, nodes.Variable) 734 e.writeFact(target, facts.Subkind, nodes.Field) 735 e.writeDoc(firstNonEmptyComment(field.Doc, field.Comment), target) 736 } 737 } 738 } 739 740 case *types.Interface: 741 e.writeFact(target, facts.NodeKind, nodes.Interface) 742 // Add parent edges for all methods, including inherited ones. 743 for i, n := 0, t.NumMethods(); i < n; i++ { 744 e.writeEdge(e.pi.ObjectVName(t.Method(i)), target, edges.ChildOf) 745 } 746 // Mark the interface as an extension of any embedded interfaces. 747 for i, n := 0, t.NumEmbeddeds(); i < n; i++ { 748 if named, ok := t.EmbeddedType(i).(*types.Named); ok { 749 if eobj := named.Obj(); e.checkImplements(obj, eobj) { 750 e.writeEdge(target, e.pi.ObjectVName(eobj), edges.Extends) 751 } 752 } 753 } 754 755 // Add bindings for the explicitly-named methods in this declaration. 756 // Parent edges were already added, so skip them here. 757 if it, ok := spec.Type.(*ast.InterfaceType); ok { 758 mapNamedFields(it.Methods, func(i int, id *ast.Ident) { 759 field := it.Methods.List[i] 760 target := e.writeBinding(id, nodes.Function, nil) 761 e.writeDoc(firstNonEmptyComment(field.Doc, field.Comment), target) 762 763 info := &funcInfo{vname: target} 764 765 // The interface is the anonymous receiver (param 0) 766 e.emitAnonParameter(spec.Name, 0, info) 767 768 obj := e.pi.Info.Defs[id] 769 if obj != nil { 770 sig := obj.Type().(*types.Signature) 771 if sig != nil { 772 if typ, ok := field.Type.(*ast.FuncType); ok { 773 e.emitParameters(typ, sig, info) 774 } 775 } 776 } 777 }) 778 } 779 780 default: 781 // We model a newtype form whose underlying type is not already a 782 // struct (e.g., "type Foo int") as if it were a record with a single 783 // unexported field of the underlying type. That is not really what Go 784 // does, but it is close enough for the graph model to work. Since 785 // there is no actual field declaration, however, we don't emit that. 786 e.writeFact(target, facts.NodeKind, nodes.Record) 787 e.writeFact(target, facts.Subkind, nodes.Type) 788 } 789 } 790 791 // visitImportSpec handles references to imported packages. 792 func (e *emitter) visitImportSpec(spec *ast.ImportSpec, stack stackFunc) { 793 ipath, _ := strconv.Unquote(spec.Path.Value) 794 if vPath, ok := e.pi.Vendored[ipath]; ok { 795 ipath = vPath 796 } 797 798 pkg := e.pi.Dependencies[ipath] 799 target := e.pi.PackageVName[pkg] 800 if target == nil { 801 if ipath != "C" { 802 if e.opts.verbose() { 803 log.Warningf("Unable to resolve import path %q", ipath) 804 } 805 } 806 return 807 } 808 809 e.writeRef(spec.Path, target, edges.RefImports) 810 if e.opts.shouldEmit(target) && !e.pi.standardLib.Contains(ipath) { 811 e.writeFact(target, facts.NodeKind, nodes.Package) 812 e.pi.standardLib.Add(ipath) 813 } 814 } 815 816 // visitAssignStmt handles bindings introduced by short-declaration syntax in 817 // assignment statments, e.g., "x, y := 1, 2". 818 func (e *emitter) visitAssignStmt(stmt *ast.AssignStmt, stack stackFunc) { 819 if stmt.Tok != token.DEFINE { 820 return // no new bindings in this statement 821 } 822 823 // Not all the names in a short declaration assignment may be defined here. 824 // We only add bindings for newly-defined ones, of which there must be at 825 // least one in a well-typed program. 826 up := e.nameContext(stack) 827 for _, expr := range stmt.Lhs { 828 if id, _ := expr.(*ast.Ident); id != nil { 829 // Add a binding only if this is the definition site for the name. 830 if obj := e.pi.Info.Defs[id]; obj != nil && obj.Pos() == id.Pos() { 831 var subkind string 832 if e.isNonFileOrPackage(up) { 833 subkind = nodes.Local 834 } 835 e.writeVarBinding(id, subkind, up) 836 } 837 } 838 } 839 840 // TODO(fromberger): Add information about initializers where available. 841 } 842 843 // visitRangeStmt handles the bindings introduced by a for ... range statement. 844 func (e *emitter) visitRangeStmt(stmt *ast.RangeStmt, stack stackFunc) { 845 if stmt.Tok != token.DEFINE { 846 return // no new bindings in this statement 847 } 848 849 // In a well-typed program, the key and value will always be identifiers. 850 up := e.nameContext(stack) 851 if key, _ := stmt.Key.(*ast.Ident); key != nil { 852 e.writeVarBinding(key, "", up) 853 } 854 if val, _ := stmt.Value.(*ast.Ident); val != nil { 855 e.writeVarBinding(val, "", up) 856 } 857 } 858 859 // visitCompositeLit handles references introduced by positional initializers 860 // in composite literals that construct (pointer to) struct values. Named 861 // initializers are handled separately. 862 func (e *emitter) visitCompositeLit(expr *ast.CompositeLit, stack stackFunc) { 863 if len(expr.Elts) == 0 { 864 return // no fields to initialize 865 } 866 867 tv, ok := e.pi.Info.Types[expr] 868 if !ok { 869 if e.opts.verbose() { 870 log.Warningf("Unable to determine composite literal type (%s)", e.pi.FileSet.Position(expr.Pos())) 871 } 872 return 873 } 874 sv, ok := deref(tv.Type.Underlying()).(*types.Struct) 875 if !ok { 876 return // non-struct type, e.g. a slice; nothing to do here 877 } 878 879 if n := sv.NumFields(); n < len(expr.Elts) { 880 // Embedded struct fields from an imported package may not appear in 881 // the list if the import did not succeed. To remain robust against 882 // such cases, don't try to read into the fields of a struct type if 883 // the counts don't line up. The information we emit will still be 884 // correct, we'll just miss some initializers. 885 log.Errorf("Struct has %d fields but %d initializers (skipping)", n, len(expr.Elts)) 886 return 887 } 888 for i, elt := range expr.Elts { 889 // The keys for key-value initializers are handled upstream of us, so 890 // we need only handle the values. But note that key-value initializers 891 // may not be in order, so we have to take care to get the right field. 892 // Positional fields must be in order, in well-formed code. 893 switch t := elt.(type) { 894 case *ast.KeyValueExpr: 895 f, ok := fieldIndex(t.Key, sv) 896 if !ok { 897 log.Errorf("Found no field index for %v (skipping)", t.Key) 898 continue 899 } 900 e.emitPosRef(t.Value, sv.Field(f), edges.RefInit) 901 default: 902 e.emitPosRef(t, sv.Field(i), edges.RefInit) 903 } 904 } 905 } 906 907 // visitIndexExpr handles references to instantiated types with a single type 908 // parameter. 909 func (e *emitter) visitIndexExpr(expr *ast.IndexExpr, stack stackFunc) { 910 if n, ok := e.pi.Info.TypeOf(expr).(*types.Named); ok && n.TypeArgs().Len() > 0 { 911 e.writeRef(expr, e.emitType(n), edges.Ref) 912 } 913 } 914 915 // visitIndexListExpr handles references to instantiated types with multiple 916 // type parameters. 917 func (e *emitter) visitIndexListExpr(expr *ast.IndexListExpr, stack stackFunc) { 918 if n, ok := e.pi.Info.TypeOf(expr).(*types.Named); ok && n.TypeArgs().Len() > 0 { 919 e.writeRef(expr, e.emitType(n), edges.Ref) 920 } 921 } 922 923 // visitArrayType handles references to array types. 924 func (e *emitter) visitArrayType(expr *ast.ArrayType, stack stackFunc) { 925 e.emitAnonMembers(expr.Elt) 926 } 927 928 // visitCallExpr handles call expressions 929 func (e *emitter) visitCallExpr(expr *ast.CallExpr, stack stackFunc) { 930 e.emitFlags(expr, stack) 931 } 932 933 var deprecatedFlagRE = regexp.MustCompile(`(?i)\bdeprecated\b`) 934 935 func (e *emitter) emitFlags(expr *ast.CallExpr, stack stackFunc) { 936 if !e.opts.emitFlagNodes() { 937 return 938 } 939 var funIdent *ast.Ident 940 switch expr := expr.Fun.(type) { 941 case *ast.SelectorExpr: 942 funIdent = expr.Sel 943 case *ast.Ident: 944 funIdent = expr 945 } 946 funObj, ok := e.pi.Info.Uses[funIdent].(*types.Func) 947 if !ok { 948 return 949 } 950 951 ctor := e.flagConstructor(funObj) 952 if ctor == nil { 953 sig, ok := funObj.Type().(*types.Signature) 954 if ok && sig.Recv() == nil { 955 // Check for a flag lookup/set instead. 956 e.emitFlagLookup(expr, funObj, stack) 957 e.emitFlagSet(expr, funObj, stack) 958 } 959 return 960 } 961 // Check for expected arguments. 962 if expected := int(max( 963 ctor.NameArgPosition, 964 ctor.DescriptionArgPosition, 965 ctor.GetVarArgPosition(), 966 )); len(expr.Args) <= expected { 967 log.Errorf("Expected at least %d arguments for call to %s.%s; found %d", expected, ctor.GetPkgPath(), ctor.GetFuncName(), len(expr.Args)) 968 return 969 } 970 971 // Parse the flag name 972 nameArg, ok := expr.Args[ctor.NameArgPosition].(*ast.BasicLit) 973 if !ok || nameArg.Kind != token.STRING { 974 return 975 } 976 flagName, err := strconv.Unquote(nameArg.Value) 977 if err != nil { 978 return 979 } 980 981 // Get the context of the flag to construct its VName. 982 fi := e.callContext(stack) 983 if fi == nil { 984 return 985 } 986 987 // Construct a node for the flag within the file 988 flagNode := proto.Clone(fi.vname).(*spb.VName) 989 flagNode.Language = "go" 990 flagNode.Signature = "flag " + flagName 991 e.writeFact(flagNode, facts.NodeKind, "google/gflag") 992 if e.opts.emitMarkedSource() { 993 // TODO: MarkedSource initializer 994 ms := &cpb.MarkedSource{ 995 Child: []*cpb.MarkedSource{{ 996 Kind: cpb.MarkedSource_IDENTIFIER, 997 PreText: flagName, 998 Link: []*cpb.Link{{Definition: []string{kytheuri.ToString(flagNode)}}}, 999 }}, 1000 } 1001 e.emitCode(flagNode, ms) 1002 } 1003 e.writeEdge(flagNode, e.flagNameNode(fi, flagName), edges.Named) 1004 1005 // Emit the documentation for the flag 1006 if docArg, ok := expr.Args[ctor.DescriptionArgPosition].(*ast.BasicLit); ok && docArg.Kind == token.STRING { 1007 if doc, err := strconv.Unquote(docArg.Value); err == nil { 1008 docNode := proto.Clone(flagNode).(*spb.VName) 1009 docNode.Signature += " doc" 1010 e.writeFact(docNode, facts.NodeKind, nodes.Doc) 1011 e.writeFact(docNode, facts.Text, doc) 1012 e.writeEdge(docNode, flagNode, edges.Documents) 1013 1014 if deprecatedFlagRE.MatchString(doc) { 1015 e.writeFact(flagNode, facts.Deprecated, "") 1016 } 1017 } 1018 } 1019 1020 // Write a defines/binding over the flag name string 1021 file, start, end := e.pi.Span(nameArg) 1022 anchor := e.pi.AnchorVName(file, start, end) 1023 e.writeAnchor(nameArg, anchor, start, end) 1024 e.writeEdge(anchor, flagNode, edges.DefinesBinding) 1025 1026 var identDef types.Object 1027 if ctor.VarArgPosition != nil { 1028 identDef = e.pi.Info.Uses[findIdentifier(expr.Args[ctor.GetVarArgPosition()])] 1029 } else { 1030 switch parent := stack(1).(type) { 1031 case *ast.ValueSpec: 1032 for i, name := range parent.Names { 1033 if expr == parent.Values[i] { 1034 identDef = e.pi.Info.Defs[name] 1035 break 1036 } 1037 } 1038 case *ast.AssignStmt: 1039 for i, v := range parent.Lhs { 1040 if name, ok := v.(*ast.Ident); ok && expr == parent.Rhs[i] { 1041 identDef = e.pi.Info.Defs[name] 1042 break 1043 } 1044 } 1045 } 1046 } 1047 if identDef == nil { 1048 return 1049 } 1050 1051 // If we found the flag definition in an assignment, associate the variable 1052 // node with the flag node. 1053 e.writeEdge(e.pi.ObjectVName(identDef), flagNode, edges.Denotes) 1054 } 1055 1056 func (e *emitter) emitFlagLookup(expr *ast.CallExpr, funObj *types.Func, stack stackFunc) { 1057 if !e.flagLookup(funObj) { 1058 return 1059 } 1060 // flag.Lookup(name) invocation 1061 if len(expr.Args) != 1 { 1062 return 1063 } 1064 nameArg, ok := expr.Args[0].(*ast.BasicLit) 1065 if !ok || nameArg.Kind != token.STRING { 1066 return 1067 } 1068 flagName, err := strconv.Unquote(nameArg.Value) 1069 if err != nil { 1070 return 1071 } 1072 1073 fi := e.callContext(stack) 1074 if fi == nil { 1075 return 1076 } 1077 1078 // Write a ref over the flag name string 1079 file, start, end := e.pi.Span(nameArg) 1080 anchor := e.pi.AnchorVName(file, start, end) 1081 e.writeAnchor(nameArg, anchor, start, end) 1082 e.writeEdge(anchor, e.flagNameNode(fi, flagName), edges.Ref) 1083 } 1084 1085 func (e *emitter) emitFlagSet(expr *ast.CallExpr, funObj *types.Func, stack stackFunc) { 1086 if !e.flagSet(funObj) { 1087 return 1088 } 1089 // flag.Set(name, val) invocation 1090 if len(expr.Args) != 2 { 1091 return 1092 } 1093 nameArg, ok := expr.Args[0].(*ast.BasicLit) 1094 if !ok || nameArg.Kind != token.STRING { 1095 return 1096 } 1097 flagName, err := strconv.Unquote(nameArg.Value) 1098 if err != nil { 1099 return 1100 } 1101 1102 fi := e.callContext(stack) 1103 if fi == nil { 1104 return 1105 } 1106 1107 // Write a ref/writes over the flag name string 1108 file, start, end := e.pi.Span(nameArg) 1109 anchor := e.pi.AnchorVName(file, start, end) 1110 e.writeAnchor(nameArg, anchor, start, end) 1111 e.writeEdge(anchor, e.flagNameNode(fi, flagName), edges.RefWrites) 1112 } 1113 1114 func (e *emitter) flagNameNode(caller *funcInfo, flagName string) *spb.VName { 1115 nameNode := &spb.VName{ 1116 Corpus: caller.vname.Corpus, 1117 Language: "flag", 1118 Signature: flagName, 1119 } 1120 e.writeFact(nameNode, facts.NodeKind, "name") 1121 return nameNode 1122 } 1123 1124 func findIdentifier(expr ast.Expr) *ast.Ident { 1125 for expr != nil { 1126 switch e := expr.(type) { 1127 case *ast.SelectorExpr: 1128 return e.Sel 1129 case *ast.UnaryExpr: 1130 if e.Op != token.AND { 1131 return nil 1132 } 1133 expr = e.X 1134 case *ast.Ident: 1135 return e 1136 default: 1137 return nil 1138 } 1139 } 1140 return nil 1141 } 1142 1143 func (e *emitter) flagLookup(f *types.Func) bool { 1144 pkg := f.Pkg() 1145 return pkg != nil && pkg.Name() == "flag" && f.Name() == "Lookup" 1146 } 1147 1148 func (e *emitter) flagSet(f *types.Func) bool { 1149 pkg := f.Pkg() 1150 return pkg != nil && pkg.Name() == "flag" && f.Name() == "Set" 1151 } 1152 1153 func (e *emitter) flagConstructor(f *types.Func) *gopb.FlagConstructor { 1154 if e.flagConstructors == nil { 1155 // Initial the flag constructor lookup table. 1156 e.flagConstructors = map[string]map[string]*gopb.FlagConstructor{} 1157 for _, ctor := range e.opts.FlagConstructors.GetFlag() { 1158 pkg := e.flagConstructors[ctor.GetPkgPath()] 1159 if pkg == nil { 1160 pkg = map[string]*gopb.FlagConstructor{} 1161 e.flagConstructors[ctor.GetPkgPath()] = pkg 1162 } 1163 pkg[ctor.GetFuncName()] = ctor 1164 } 1165 } 1166 pkg := f.Pkg() 1167 if pkg == nil { 1168 return nil 1169 } 1170 sig, ok := f.Type().(*types.Signature) 1171 if !ok || sig.Recv() != nil { 1172 // We only handle top-level flags 1173 return nil 1174 } 1175 return e.flagConstructors[pkg.Path()][f.Name()] 1176 } 1177 1178 // emitPosRef emits an anchor spanning loc, pointing to obj. 1179 func (e *emitter) emitPosRef(loc ast.Node, obj types.Object, kind string) { 1180 target := e.pi.ObjectVName(obj) 1181 file, start, end := e.pi.Span(loc) 1182 anchor := e.pi.AnchorVName(file, start, end) 1183 e.writeAnchor(loc, anchor, start, end) 1184 e.writeEdge(anchor, target, kind) 1185 } 1186 1187 // emitParameters emits parameter edges for the parameters of a function type, 1188 // given the type signature and info of the enclosing declaration or function 1189 // literal. 1190 func (e *emitter) emitParameters(ftype *ast.FuncType, sig *types.Signature, info *funcInfo) { 1191 paramIndex := 0 1192 1193 // If there is a receiver, it is treated as param.0. 1194 if sig.Recv() != nil { 1195 paramIndex++ 1196 } 1197 1198 // Emit bindings and parameter edges for the parameters. 1199 mapAllFields(ftype.Params, func(i int, id *ast.Ident) { 1200 if sig.Params().At(i) != nil { 1201 field := ftype.Params.List[i] 1202 e.emitAnonMembers(field.Type) 1203 1204 if param := e.writeVarBinding(id, nodes.LocalParameter, info.vname); param != nil { 1205 e.writeEdge(info.vname, param, edges.ParamIndex(paramIndex)) 1206 1207 // Field object does not associate any comments with the parameter; use CommentMap to find them 1208 e.writeDoc(firstNonEmptyComment(e.cmap.Filter(field).Comments()...), param) 1209 } else if typ, ok := field.Type.(*ast.Ident); ok { 1210 // Unnamed function parameter 1211 e.emitAnonParameter(typ, paramIndex, info) 1212 } 1213 } 1214 paramIndex++ 1215 }) 1216 // Emit bindings for any named result variables. 1217 // Results are not considered parameters. 1218 mapNamedFields(ftype.Results, func(i int, id *ast.Ident) { 1219 e.writeVarBinding(id, "", info.vname) 1220 }) 1221 // Emit bindings for type parameters 1222 mapNamedFields(ftype.TypeParams, func(i int, id *ast.Ident) { 1223 v := e.writeBinding(id, nodes.TVar, nil) 1224 e.writeEdge(info.vname, v, edges.TParamIndex(i)) 1225 }) 1226 } 1227 1228 func (e *emitter) emitAnonParameter(typ *ast.Ident, paramIndex int, info *funcInfo) { 1229 info.numAnons++ 1230 param := proto.Clone(info.vname).(*spb.VName) 1231 param.Signature += "$" + strconv.Itoa(info.numAnons) 1232 e.writeFact(param, facts.NodeKind, nodes.Variable) 1233 e.writeFact(param, facts.Subkind, nodes.LocalParameter) 1234 e.writeEdge(info.vname, param, edges.ParamIndex(paramIndex)) 1235 if e.opts.emitMarkedSource() { 1236 ms := &cpb.MarkedSource{ 1237 // An unnamed parameter will only have a MarkedSource.TYPE 1238 Child: []*cpb.MarkedSource{{ 1239 Kind: cpb.MarkedSource_TYPE, 1240 PreText: typ.String(), 1241 }}, 1242 } 1243 e.emitCode(param, ms) 1244 } 1245 } 1246 1247 // emitAnonMembers checks whether expr denotes an anonymous struct or interface 1248 // type, and if so emits bindings for its member fields/methods. The resulting 1249 // members do not parent to the type, since it has no referential identity; but 1250 // we do capture documentation in the unlikely event someone wrote any. 1251 func (e *emitter) emitAnonMembers(expr ast.Expr) { 1252 if st, ok := expr.(*ast.StructType); ok { 1253 mapNamedFields(st.Fields, func(i int, id *ast.Ident) { 1254 target := e.writeVarBinding(id, nodes.Field, nil) // no parent 1255 e.writeDoc(firstNonEmptyComment(st.Fields.List[i].Doc, st.Fields.List[i].Comment), target) 1256 }) 1257 } else if it, ok := expr.(*ast.InterfaceType); ok { 1258 mapNamedFields(it.Methods, func(i int, id *ast.Ident) { 1259 target := e.writeBinding(id, nodes.Function, nil) // no parent 1260 e.writeDoc(firstNonEmptyComment(it.Methods.List[i].Doc, it.Methods.List[i].Comment), target) 1261 }) 1262 } 1263 } 1264 1265 // An override represents the relationship that x overrides y. 1266 type override struct { 1267 x, y types.Object 1268 } 1269 1270 // overrides represents a set of override relationships we've already generated. 1271 type overrides map[override]bool 1272 1273 // seen reports whether an x overrides y was already cached, and if not adds it 1274 // to the set. 1275 func (o overrides) seen(x, y types.Object) bool { 1276 ov := override{x: x, y: y} 1277 ok := o[ov] 1278 if !ok { 1279 o[ov] = true 1280 } 1281 return ok 1282 } 1283 1284 // emitSatisfactions visits each named type known through the compilation being 1285 // indexed, and emits edges connecting it to any known interfaces its method 1286 // set satisfies. 1287 func (e *emitter) emitSatisfactions() { 1288 // Find all the Named types mentioned in this compilation. 1289 var allTypes []*types.Named 1290 1291 // For the current source package, use all names, even local ones. 1292 for _, obj := range e.pi.Info.Defs { 1293 if obj, ok := obj.(*types.TypeName); ok { 1294 if n, ok := obj.Type().(*types.Named); ok { 1295 allTypes = append(allTypes, n) 1296 } 1297 } 1298 } 1299 1300 // Include instance types. 1301 for _, t := range e.pi.Info.Types { 1302 if n, ok := t.Type.(*types.Named); ok && n.TypeArgs().Len() > 0 { 1303 allTypes = append(allTypes, n) 1304 } 1305 } 1306 1307 // For dependencies, we only have access to package-level types, not those 1308 // defined by inner scopes. 1309 for _, pkg := range e.pi.Dependencies { 1310 scope := pkg.Scope() 1311 for _, name := range scope.Names() { 1312 if obj, ok := scope.Lookup(name).(*types.TypeName); ok { 1313 // Note that the names of some "named" types that are brought 1314 // in from dependencies may not be known at this point -- the 1315 // compiled package headers omit the names if they are not 1316 // needed. Skip such cases, even though they would qualify if 1317 // we had the source package. 1318 if n, ok := obj.Type().(*types.Named); ok && obj.Name() != "" { 1319 allTypes = append(allTypes, n) 1320 } 1321 } 1322 } 1323 } 1324 1325 // Shared Context across all generic assignability checks. 1326 tctx := types.NewContext() 1327 1328 // Cache the method set of each named type in this package. 1329 var msets typeutil.MethodSetCache 1330 // Cache the overrides we've noticed to avoid duplicate entries. 1331 cache := make(overrides) 1332 for _, x := range allTypes { 1333 xobj := x.Obj() 1334 if xobj.Pkg() != e.pi.Package { 1335 continue // not from this package 1336 } 1337 1338 // Check whether x is a named type with methods; if not, skip it. 1339 if len(typeutil.IntuitiveMethodSet(x, &msets)) == 0 { 1340 continue // no methods to consider 1341 } 1342 1343 // N.B. This implementation is quadratic in the number of visible 1344 // interfaces, but that's probably OK since are only considering a 1345 // single compilation. 1346 1347 // Check the method sets of both x and pointer-to-x for overrides. 1348 xmset := msets.MethodSet(xobj.Type()) 1349 pxmset := msets.MethodSet(types.NewPointer(xobj.Type())) 1350 1351 for _, y := range allTypes { 1352 yobj := y.Obj() 1353 if xobj == yobj { 1354 continue 1355 } 1356 1357 ymset := msets.MethodSet(yobj.Type()) 1358 1359 ifx, ify := isInterface(x), isInterface(y) 1360 switch { 1361 case ifx && ify && ymset.Len() > 0: 1362 // x and y are both interfaces. Note that extension is handled 1363 // elsewhere as part of the type spec for the interface. 1364 if assignableTo(tctx, x, y) { 1365 e.writeSatisfies(xobj, yobj) 1366 } 1367 if assignableTo(tctx, y, x) { 1368 e.writeSatisfies(yobj, xobj) 1369 } 1370 1371 case ifx: 1372 // y is a concrete type 1373 pymset := msets.MethodSet(types.NewPointer(y)) 1374 if assignableTo(tctx, y, x) { 1375 e.writeSatisfies(yobj, xobj) 1376 e.emitOverrides(ymset, pymset, xmset, cache) 1377 } 1378 1379 case ify && ymset.Len() > 0: 1380 // x is a concrete type 1381 if assignableTo(tctx, x, y) { 1382 e.writeSatisfies(xobj, yobj) 1383 e.emitOverrides(xmset, pxmset, ymset, cache) 1384 } 1385 1386 default: 1387 // Both x and y are concrete. 1388 } 1389 } 1390 } 1391 } 1392 1393 // Add xm-(overrides)-ym for each concrete method xm with a corresponding 1394 // abstract method ym. 1395 func (e *emitter) emitOverrides(xmset, pxmset, ymset *types.MethodSet, cache overrides) { 1396 for i, n := 0, ymset.Len(); i < n; i++ { 1397 ym := ymset.At(i) 1398 yobj := ym.Obj() 1399 xm := xmset.Lookup(yobj.Pkg(), yobj.Name()) 1400 if xm == nil { 1401 if pxmset != nil { 1402 xm = pxmset.Lookup(yobj.Pkg(), yobj.Name()) 1403 } 1404 if xm == nil { 1405 continue // this method is not part of the interface we're probing 1406 } 1407 } 1408 1409 xobj := xm.Obj() 1410 if cache.seen(xobj, yobj) { 1411 continue 1412 } 1413 1414 xvname := e.pi.ObjectVName(xobj) 1415 yvname := e.pi.ObjectVName(yobj) 1416 if e.pi.typeEmitted.Add(xvname.Signature + "+" + yvname.Signature) { 1417 e.writeEdge(xvname, yvname, edges.Overrides) 1418 } 1419 1420 xt := e.emitType(xobj.Type()) 1421 yt := e.emitType(yobj.Type()) 1422 if e.pi.typeEmitted.Add(xt.Signature + "+" + yt.Signature) { 1423 e.writeEdge(xt, yt, edges.Satisfies) 1424 } 1425 } 1426 } 1427 1428 func isInterface(typ types.Type) bool { _, ok := typ.Underlying().(*types.Interface); return ok } 1429 1430 func (e *emitter) check(err error) { 1431 if err != nil && e.firstErr == nil { 1432 e.firstErr = err 1433 log.Errorf("indexing %q: %v", e.pi.ImportPath, err) 1434 } 1435 } 1436 1437 func (e *emitter) checkImplements(src, tgt types.Object) bool { 1438 i := impl{A: src, B: tgt} 1439 if _, ok := e.impl[i]; ok { 1440 return false 1441 } 1442 e.impl[i] = struct{}{} 1443 return true 1444 } 1445 1446 func (e *emitter) writeSatisfies(src, tgt types.Object) { 1447 if e.checkImplements(src, tgt) { 1448 e.writeEdge(e.pi.ObjectVName(src), e.pi.ObjectVName(tgt), edges.Satisfies) 1449 } 1450 } 1451 1452 func (e *emitter) writeFact(src *spb.VName, name, value string) { 1453 if corpus := e.rewrittenCorpusForVName(src); corpus != src.GetCorpus() { 1454 src = proto.Clone(src).(*spb.VName) 1455 src.Corpus = corpus 1456 } 1457 e.check(e.sink.writeFact(e.ctx, src, name, value)) 1458 } 1459 1460 func (e *emitter) writeEdge(src, tgt *spb.VName, kind string) { 1461 if corpus := e.rewrittenCorpusForVName(src); corpus != src.GetCorpus() { 1462 src = proto.Clone(src).(*spb.VName) 1463 src.Corpus = corpus 1464 } 1465 if corpus := e.rewrittenCorpusForVName(tgt); corpus != tgt.GetCorpus() { 1466 tgt = proto.Clone(tgt).(*spb.VName) 1467 tgt.Corpus = corpus 1468 } 1469 e.check(e.sink.writeEdge(e.ctx, src, tgt, kind)) 1470 } 1471 1472 func (e *emitter) writeAnchor(node ast.Node, src *spb.VName, start, end int) { 1473 if corpus := e.rewrittenCorpusForVName(src); corpus != src.GetCorpus() { 1474 src = proto.Clone(src).(*spb.VName) 1475 src.Corpus = corpus 1476 } 1477 if _, ok := e.anchored[node]; ok { 1478 return // this node already has an anchor 1479 } 1480 if node != nil { 1481 e.anchored[node] = struct{}{} 1482 } 1483 e.check(e.sink.writeAnchor(e.ctx, src, start, end)) 1484 } 1485 1486 func (e *emitter) writeDiagnostic(src *spb.VName, d diagnostic) { 1487 if corpus := e.rewrittenCorpusForVName(src); corpus != src.GetCorpus() { 1488 src = proto.Clone(src).(*spb.VName) 1489 src.Corpus = corpus 1490 } 1491 e.check(e.sink.writeDiagnostic(e.ctx, src, d)) 1492 } 1493 1494 func (e *emitter) writeNodeDiagnostic(src ast.Node, d diagnostic) { 1495 file, start, end := e.pi.Span(src) 1496 anchor := e.pi.AnchorVName(file, start, end) 1497 e.writeAnchor(src, anchor, start, end) 1498 e.writeDiagnostic(anchor, d) 1499 } 1500 1501 // writeRef emits an anchor spanning origin and referring to target with an 1502 // edge of the given kind. The vname of the anchor is returned. 1503 func (e *emitter) writeRef(origin ast.Node, target *spb.VName, kind string) *spb.VName { 1504 file, start, end := e.pi.Span(origin) 1505 anchor := e.pi.AnchorVName(file, start, end) 1506 e.writeAnchor(origin, anchor, start, end) 1507 e.writeEdge(anchor, target, kind) 1508 1509 // Check whether we are intended to emit metadata linkage edges, and if so, 1510 // whether there are any to process. 1511 e.applyRules(file, start, end, kind, func(rule metadata.Rule) { 1512 if rule.Reverse { 1513 e.writeEdge(rule.VName, target, rule.EdgeOut) 1514 } else { 1515 e.writeEdge(target, rule.VName, rule.EdgeOut) 1516 } 1517 if rule.Semantic != nil { 1518 e.writeFact(target, facts.SemanticGenerated, strings.ToLower(rule.Semantic.String())) 1519 } 1520 if rule.EdgeOut == edges.Generates && !e.fmeta[file] { 1521 e.fmeta[file] = true 1522 if rule.VName.Path != "" && target.Path != "" { 1523 ruleVName := narrowToFileVName(rule.VName) 1524 fileTarget := narrowToFileVName(anchor) 1525 if rule.Reverse { 1526 e.writeEdge(ruleVName, fileTarget, rule.EdgeOut) 1527 } else { 1528 e.writeEdge(fileTarget, ruleVName, rule.EdgeOut) 1529 } 1530 } 1531 } 1532 }) 1533 1534 return anchor 1535 } 1536 1537 func narrowToFileVName(v *spb.VName) *spb.VName { 1538 return &spb.VName{Corpus: v.GetCorpus(), Root: v.GetRoot(), Path: v.GetPath()} 1539 } 1540 1541 // mustWriteBinding is as writeBinding, but panics if id does not resolve. Use 1542 // this in cases where the object is known already to exist. 1543 func (e *emitter) mustWriteBinding(id *ast.Ident, kind string, parent *spb.VName) *spb.VName { 1544 if target := e.writeBinding(id, kind, parent); target != nil { 1545 return target 1546 } 1547 panic("unresolved definition") // logged in writeBinding 1548 } 1549 1550 // writeVarBinding is as writeBinding, assuming the kind is "variable". 1551 // If subkind != "", it is also emitted as a subkind. 1552 func (e *emitter) writeVarBinding(id *ast.Ident, subkind string, parent *spb.VName) *spb.VName { 1553 vname := e.writeBinding(id, nodes.Variable, parent) 1554 if vname != nil && subkind != "" { 1555 e.writeFact(vname, facts.Subkind, subkind) 1556 } 1557 return vname 1558 } 1559 1560 // writeBinding emits a node of the specified kind for the target of id. If 1561 // the identifier is not "_", an anchor for a binding definition of the target 1562 // is also emitted at id. If parent != nil, the target is also recorded as its 1563 // child. The target vname is returned. 1564 func (e *emitter) writeBinding(id *ast.Ident, kind string, parent *spb.VName) *spb.VName { 1565 if id == nil { 1566 return nil 1567 } 1568 obj := e.pi.Info.Defs[id] 1569 if obj == nil { 1570 loc := e.pi.FileSet.Position(id.Pos()) 1571 log.Errorf("Missing definition for id %q at %s", id.Name, loc) 1572 return nil 1573 } 1574 target := e.pi.ObjectVName(obj) 1575 if e.pi.ImportPath == "builtin" && parent != nil && (parent.GetSignature() == "package" || parent.GetSignature() == "") { 1576 // Special-case top-level builtin bindings: https://pkg.go.dev/builtin 1577 target = govname.Builtin(id.String()) 1578 kind = "tbuiltin" 1579 } 1580 if kind != "" { 1581 e.writeFact(target, facts.NodeKind, kind) 1582 } 1583 if id.Name != "_" { 1584 e.writeRef(id, target, edges.DefinesBinding) 1585 } 1586 if parent != nil { 1587 e.writeEdge(target, parent, edges.ChildOf) 1588 } 1589 if e.opts.emitMarkedSource() { 1590 e.emitCode(target, e.MarkedSource(obj)) 1591 } 1592 e.writeEdge(target, e.emitTypeOf(id), edges.Typed) 1593 return target 1594 } 1595 1596 // writeDef emits a spanning anchor and defines edge for the specified node. 1597 // This function does not create the target node. 1598 func (e *emitter) writeDef(node ast.Node, target *spb.VName) *spb.VName { 1599 return e.writeRef(node, target, edges.Defines) 1600 } 1601 1602 // writeDoc adds associations between comment groups and a documented node. 1603 // It also handles marking deprecated facts on the target. 1604 func (e *emitter) writeDoc(comments *ast.CommentGroup, target *spb.VName) { 1605 if comments == nil || len(comments.List) == 0 || target == nil { 1606 return 1607 } 1608 1609 var lines []string 1610 for _, comment := range comments.List { 1611 lines = append(lines, trimComment(comment.Text)) 1612 } 1613 trimmedComment := strings.Join(lines, "\n") 1614 1615 docNode := proto.Clone(target).(*spb.VName) 1616 docNode.Signature += " doc" 1617 e.writeFact(docNode, facts.NodeKind, nodes.Doc) 1618 e.writeFact(docNode, facts.Text, escComment.Replace(trimmedComment)) 1619 e.writeEdge(docNode, target, edges.Documents) 1620 e.emitDeprecation(target, lines) 1621 1622 e.emitDocLinks(comments, trimmedComment) 1623 } 1624 1625 func (e *emitter) emitDocLinks(comments *ast.CommentGroup, trimmedComment string) { 1626 // Tree traversal functions for [*comment.Block]s 1627 var visitBlock func(comment.Block) 1628 var visitText func(comment.Text) string 1629 1630 // Simply visit each [comment.Block] to find all [comment.Text] nodes 1631 visitBlock = func(b comment.Block) { 1632 switch b := b.(type) { 1633 case *comment.Paragraph: 1634 for _, t := range b.Text { 1635 visitText(t) 1636 } 1637 case *comment.List: 1638 for _, item := range b.Items { 1639 for _, sub := range item.Content { 1640 visitBlock(sub) 1641 } 1642 } 1643 case *comment.Heading: 1644 for _, t := range b.Text { 1645 visitText(t) 1646 } 1647 case *comment.Code: 1648 // nothing to traverse 1649 default: 1650 log.Errorf("Unknown comment.Block type: %T", b) 1651 } 1652 } 1653 1654 // Keep track of last seen doc link offset so we can handle duplicates 1655 lastOffset := -1 1656 lastLine := 0 1657 1658 // Emit refs for DocLinks; returns the text string for the visited Text 1659 visitText = func(t comment.Text) string { 1660 switch t := t.(type) { 1661 case comment.Plain: 1662 return string(t) 1663 case comment.Italic: 1664 return string(t) 1665 case *comment.Link: 1666 var text string 1667 for _, sub := range t.Text { 1668 text += visitText(sub) 1669 } 1670 return text 1671 case *comment.DocLink: 1672 // Reconstruct the text of the DocLink to find its position. 1673 text := "[" 1674 for _, sub := range t.Text { 1675 text += visitText(sub) 1676 } 1677 text += "]" 1678 1679 target := e.resolveDocLink(t) 1680 if target == nil { 1681 if e.opts.verbose() { 1682 log.Warningf("Cannot resolve DocLink: %s", t.DefaultURL(e.opts.docBase())) 1683 } 1684 return text 1685 } 1686 1687 for i := lastLine; i < len(comments.List); i++ { 1688 c := comments.List[i] 1689 file, start, end := e.pi.Span(c) 1690 lineOffset := 0 1691 if lastOffset >= start && lastOffset <= end { 1692 lineOffset = lastOffset - start 1693 } 1694 1695 pos := strings.Index(c.Text[lineOffset:], text) 1696 if pos < 0 { 1697 continue 1698 } 1699 pos += lineOffset 1700 lastOffset = start + pos + len(text) 1701 lastLine = i 1702 1703 linkStart, linkEnd := pos+start, pos+start+len(text) 1704 anchor := e.pi.AnchorVName(file, linkStart, linkEnd) 1705 e.writeAnchor(nil, anchor, linkStart, linkEnd) 1706 e.writeEdge(anchor, target, edges.RefDoc) 1707 1708 return text 1709 } 1710 1711 log.Errorf("Failed to find DocLink: %q", text) 1712 return text 1713 default: 1714 log.Errorf("Unknown comment.Text type: %T", t) 1715 return "" 1716 } 1717 } 1718 1719 parser := &comment.Parser{ 1720 LookupPackage: func(name string) (string, bool) { 1721 if e.pi.Name == name { 1722 return e.pi.ImportPath, true 1723 } 1724 for _, d := range e.pi.Dependencies { 1725 if d.Name() == name { 1726 return d.Path(), true 1727 } 1728 } 1729 return "", false 1730 }, 1731 // Assume all symbols are valid; we'll check them in [visitText] 1732 LookupSym: func(recv, name string) bool { return true }, 1733 } 1734 1735 doc := parser.Parse(trimmedComment) 1736 for _, c := range doc.Content { 1737 visitBlock(c) 1738 } 1739 } 1740 1741 func (e *emitter) resolveDocLink(link *comment.DocLink) *spb.VName { 1742 scope := e.pi.Package.Scope() 1743 if pkg := e.pi.Dependencies[link.ImportPath]; pkg != nil { 1744 scope = pkg.Scope() 1745 } 1746 1747 switch { 1748 case link.Name == "" && link.Recv == "": 1749 // Package reference 1750 if pkg := e.pi.Dependencies[link.ImportPath]; pkg != nil { 1751 return e.pi.PackageVName[pkg] 1752 } 1753 if e.pi.ImportPath == link.ImportPath { 1754 return e.pi.PackageVName[e.pi.Package] 1755 } 1756 case link.Recv != "": 1757 // Member reference 1758 if recv := scope.Lookup(link.Recv); recv != nil && recv.Pkg() != nil { 1759 if n, ok := deref(recv.Type()).(*types.Named); ok { 1760 obj, _, _ := types.LookupFieldOrMethod(n.Origin(), true, recv.Pkg(), link.Name) 1761 if obj != nil { 1762 return e.pi.ObjectVName(obj) 1763 } 1764 } 1765 } 1766 case link.Name != "": 1767 // Simple name reference 1768 if obj := scope.Lookup(link.Name); obj != nil { 1769 return e.pi.ObjectVName(obj) 1770 } 1771 default: 1772 log.Errorf("Unknown DocLink shape: %+v", link) 1773 } 1774 return nil 1775 } 1776 1777 // emitDeprecation emits a deprecated fact for the specified target if the 1778 // comment lines indicate it is deprecated per https://github.com/golang/go/wiki/Deprecated 1779 func (e *emitter) emitDeprecation(target *spb.VName, lines []string) { 1780 var deplines []string 1781 for _, line := range lines { 1782 if len(deplines) == 0 { 1783 if msg := strings.TrimPrefix(line, "Deprecated:"); msg != line { 1784 deplines = append(deplines, strings.TrimSpace(msg)) 1785 } 1786 } else if line == "" { 1787 break 1788 } else { 1789 deplines = append(deplines, strings.TrimSpace(line)) 1790 } 1791 } 1792 if len(deplines) > 0 { 1793 e.writeFact(target, facts.Deprecated, strings.Join(deplines, " ")) 1794 } 1795 } 1796 1797 // isCall reports whether id is a call to obj. This holds if id is in call 1798 // position ("id(...") or is the RHS of a selector in call position 1799 // ("x.id(...)"). If so, the nearest enclosing call expression is also 1800 // returned. 1801 // 1802 // This will not match if there are redundant parentheses in the expression. 1803 func isCall(id *ast.Ident, obj types.Object, stack stackFunc) (*ast.CallExpr, bool) { 1804 if _, ok := obj.(*types.Func); ok { 1805 if call, ok := stack(1).(*ast.CallExpr); ok && call.Fun == id { 1806 return call, true // id(...) 1807 } 1808 if sel, ok := stack(1).(*ast.SelectorExpr); ok && sel.Sel == id { 1809 if call, ok := stack(2).(*ast.CallExpr); ok && call.Fun == sel { 1810 return call, true // x.id(...) 1811 } 1812 } 1813 } 1814 return nil, false 1815 } 1816 1817 // callContext returns funcInfo for the nearest enclosing parent function, not 1818 // including the node itself, or the enclosing package initializer if the node 1819 // is at the top level. 1820 func (e *emitter) callContext(stack stackFunc) *funcInfo { 1821 for i := 1; ; i++ { 1822 switch p := stack(i).(type) { 1823 case *ast.FuncDecl, *ast.FuncLit: 1824 return e.pi.function[p] 1825 case *ast.File: 1826 if e.opts.useFileAsTopLevelScope() { 1827 return &funcInfo{vname: e.pi.FileVName(p)} 1828 } 1829 fi := e.pi.packageInit[p] 1830 if fi == nil { 1831 // Lazily emit a virtual node to represent the static 1832 // initializer for top-level expressions in this file of the 1833 // package. We only do this if there are expressions that need 1834 // to be initialized. 1835 vname := proto.Clone(e.pi.VName).(*spb.VName) 1836 vname.Signature += fmt.Sprintf(".<init>@%d", p.Package) 1837 fi = &funcInfo{vname: vname} 1838 e.pi.packageInit[p] = fi 1839 e.writeFact(vname, facts.NodeKind, nodes.Function) 1840 e.writeEdge(vname, e.pi.VName, edges.ChildOf) 1841 1842 // The callgraph requires we provide the caller with a 1843 // definition (http://www.kythe.io/docs/schema/callgraph.html). 1844 // Since there is no location, attach it to the beginning of 1845 // the file itself. 1846 anchor := e.pi.AnchorVName(p, 0, 0) 1847 e.check(e.sink.writeAnchor(e.ctx, anchor, 0, 0)) 1848 e.writeEdge(anchor, vname, edges.Defines) 1849 } 1850 return fi 1851 } 1852 } 1853 } 1854 1855 // nameContext returns the vname for the nearest enclosing parent node, not 1856 // including the node itself, or the enclosing package vname if the node is at 1857 // the top level. 1858 func (e *emitter) nameContext(stack stackFunc) *spb.VName { 1859 if fi := e.callContext(stack); !e.pi.isPackageInit(fi) { 1860 return fi.vname 1861 } 1862 return e.pi.VName 1863 } 1864 1865 // applyRules calls apply for each metadata rule matching the given combination 1866 // of location and kind. 1867 func (e *emitter) applyRules(file *ast.File, start, end int, kind string, apply func(r metadata.Rule)) { 1868 if e.opts == nil || !e.opts.EmitLinkages { 1869 return // nothing to do 1870 } else if e.rmap == nil { 1871 e.rmap = make(map[*ast.File]map[int]metadata.Rules) 1872 } 1873 1874 // Lazily populate a cache of file :: start :: rules mappings, so that we 1875 // need only scan the rules coincident on the starting point of the range 1876 // we care about. In almost all cases that will be just one, if any. 1877 rules, ok := e.rmap[file] 1878 if !ok { 1879 rules = make(map[int]metadata.Rules) 1880 for _, rule := range e.pi.Rules[file] { 1881 rules[rule.Begin] = append(rules[rule.Begin], rule) 1882 } 1883 e.rmap[file] = rules 1884 } 1885 1886 for _, rule := range rules[start] { 1887 if rule.End == end && rule.EdgeIn == kind { 1888 apply(rule) 1889 } 1890 } 1891 } 1892 1893 // A visitFunc visits a node of the Go AST. The function can use stack to 1894 // retrieve AST nodes on the path from the node up to the root. If the return 1895 // value is true, the children of node are also visited; otherwise they are 1896 // skipped. 1897 type visitFunc func(node ast.Node, stack stackFunc) bool 1898 1899 // A stackFunc returns the ith stack entry above of an AST node, where 0 1900 // denotes the node itself. If the ith entry does not exist, the function 1901 // returns nil. 1902 type stackFunc func(i int) ast.Node 1903 1904 // astVisitor implements ast.Visitor, passing each visited node to a callback 1905 // function. 1906 type astVisitor struct { 1907 stack []ast.Node 1908 visit visitFunc 1909 } 1910 1911 func newASTVisitor(f visitFunc) ast.Visitor { return &astVisitor{visit: f} } 1912 1913 // Visit implements the required method of the ast.Visitor interface. 1914 func (w *astVisitor) Visit(node ast.Node) ast.Visitor { 1915 if node == nil { 1916 w.stack = w.stack[:len(w.stack)-1] // pop 1917 return w 1918 } 1919 1920 w.stack = append(w.stack, node) // push 1921 if !w.visit(node, w.parent) { 1922 return nil 1923 } 1924 return w 1925 } 1926 1927 func (w *astVisitor) parent(i int) ast.Node { 1928 if i >= len(w.stack) { 1929 return nil 1930 } 1931 return w.stack[len(w.stack)-1-i] 1932 } 1933 1934 // deref returns the base type of T if it is a pointer, otherwise T itself. 1935 func deref(T types.Type) types.Type { 1936 if U, ok := T.Underlying().(*types.Pointer); ok { 1937 return U.Elem() 1938 } 1939 return T 1940 } 1941 1942 // mapNamedFields applies f to each identifier declared in fields. Each call to 1943 // f is given the offset and the identifier. 1944 func mapNamedFields(fields *ast.FieldList, f func(i int, id *ast.Ident)) { 1945 mapFields(fields, f, false) 1946 } 1947 1948 // mapAllFields applies f to each identifier declared in fields. Each call to f 1949 // is given the offset and the identifier. If a field has no names, nil is 1950 // passed to f as the Ident. 1951 func mapAllFields(fields *ast.FieldList, f func(i int, id *ast.Ident)) { 1952 mapFields(fields, f, true) 1953 } 1954 1955 // mapFields applies f to each identifier declared in fields. Each call to f is 1956 // given the offset and the identifier. If a field has no names and 1957 // includeUnnamed is true, nil is passed to f as the Ident. 1958 func mapFields(fields *ast.FieldList, f func(i int, id *ast.Ident), includeUnnamed bool) { 1959 if fields == nil { 1960 return 1961 } 1962 for i, field := range fields.List { 1963 if includeUnnamed && len(field.Names) == 0 { 1964 f(i, nil) 1965 } 1966 for _, id := range field.Names { 1967 f(i, id) 1968 } 1969 } 1970 } 1971 1972 // fieldIndex reports whether sv has a field named by expr, which must be of 1973 // type *ast.Ident, and returns its positional index if so. 1974 // 1975 // N.B. This is a linear scan, but the count of fields should almost always be 1976 // small enough not to worry about it. 1977 func fieldIndex(expr ast.Expr, sv *types.Struct) (int, bool) { 1978 want := expr.(*ast.Ident).Name 1979 for i := 0; i < sv.NumFields(); i++ { 1980 if sv.Field(i).Name() == want { 1981 return i, true 1982 } 1983 } 1984 return -1, false 1985 } 1986 1987 var escComment = strings.NewReplacer("[", `\[`, "]", `\]`, `\`, `\\`) 1988 1989 // trimComment removes the comment delimiters from a comment. For single-line 1990 // comments, it also removes a single leading space, if present; for multi-line 1991 // comments it discards leading and trailing whitespace. 1992 func trimComment(text string) string { 1993 if single := strings.TrimPrefix(text, "//"); single != text { 1994 return strings.TrimPrefix(single, " ") 1995 } 1996 return strings.TrimSpace(strings.TrimSuffix(strings.TrimPrefix(text, "/*"), "*/")) 1997 } 1998 1999 // specComment returns the innermost comment associated with spec, or nil. 2000 func specComment(spec ast.Spec, stack stackFunc) *ast.CommentGroup { 2001 var comment *ast.CommentGroup 2002 switch t := spec.(type) { 2003 case *ast.TypeSpec: 2004 comment = firstNonEmptyComment(t.Doc, t.Comment) 2005 case *ast.ValueSpec: 2006 comment = firstNonEmptyComment(t.Doc, t.Comment) 2007 case *ast.ImportSpec: 2008 comment = firstNonEmptyComment(t.Doc, t.Comment) 2009 } 2010 if comment == nil { 2011 if t, ok := stack(1).(*ast.GenDecl); ok { 2012 return t.Doc 2013 } 2014 } 2015 return comment 2016 } 2017 2018 func firstNonEmptyComment(cs ...*ast.CommentGroup) *ast.CommentGroup { 2019 for _, c := range cs { 2020 if c != nil && len(c.List) > 0 { 2021 return c 2022 } 2023 } 2024 return nil 2025 } 2026 2027 func canBeAssignableTo(v, t types.Type) bool { 2028 return types.AssignableTo(v, t) || types.AssignableTo(types.NewPointer(v), t) 2029 } 2030 2031 func assignableTo(tctx *types.Context, V, T types.Type) bool { 2032 // If V and T are not both named, or do not have matching non-empty type 2033 // parameter lists, fall back on types.AssignableTo. 2034 VN, Vnamed := V.(*types.Named) 2035 TN, Tnamed := T.(*types.Named) 2036 if !Vnamed || !Tnamed { 2037 return canBeAssignableTo(V, T) 2038 } 2039 2040 vtparams := VN.TypeParams() 2041 ttparams := TN.TypeParams() 2042 if vtparams.Len() == 0 || vtparams.Len() != ttparams.Len() || VN.TypeArgs().Len() != 0 || TN.TypeArgs().Len() != 0 { 2043 return canBeAssignableTo(V, T) 2044 } 2045 2046 // V and T have the same (non-zero) number of type params. Instantiate both 2047 // with the type parameters of V. This must always succeed for V, and will 2048 // succeed for T if and only if the type set of each type parameter of V is a 2049 // subset of the type set of the corresponding type parameter of T, meaning 2050 // that every instantiation of V corresponds to a valid instantiation of T. 2051 2052 targs := make([]types.Type, vtparams.Len()) 2053 for i := 0; i < vtparams.Len(); i++ { 2054 targs[i] = vtparams.At(i) 2055 } 2056 2057 vinst, err := types.Instantiate(tctx, V, targs, true) 2058 if err != nil { 2059 log.Errorf("type parameters should satisfy their own constraints: %v", err) 2060 return false 2061 } 2062 2063 tinst, err := types.Instantiate(tctx, T, targs, true) 2064 if err != nil { 2065 return false 2066 } 2067 2068 return canBeAssignableTo(vinst, tinst) 2069 }