Skip to content

Instantly share code, notes, and snippets.

@podhmo
Last active September 20, 2025 12:51
Show Gist options
  • Save podhmo/63692370e15a7275847f2b0ac36dfb94 to your computer and use it in GitHub Desktop.
Save podhmo/63692370e15a7275847f2b0ac36dfb94 to your computer and use it in GitHub Desktop.
goscanのScannerのcallgraphを作りたいと言ったらcopilotがなんか生成してきた
package main
import (
"context"
"fmt"
"go/ast"
"go/parser"
"go/token"
"log"
"os"
"path/filepath"
"sort"
"strings"
)
// MethodCall represents a method call from one method to another
type MethodCall struct {
From string // Method that makes the call
To string // Method that is called
}
// MethodInfo holds information about a method
type MethodInfo struct {
Name string // Method name
Receiver string // Receiver type (e.g., "Scanner")
Package string // Package name (e.g., "goscan" or "scanner")
Calls []string // Methods called from this method
}
// CallGraph represents the entire call graph
type CallGraph struct {
Methods map[string]*MethodInfo // key: package.receiver.method
Calls []MethodCall
}
func main() {
if len(os.Args) < 2 {
log.Fatal("Usage: go run main.go <root-dir>")
}
rootDir := os.Args[1]
ctx := context.Background()
callGraph, err := analyzeCallGraph(ctx, rootDir)
if err != nil {
log.Fatalf("Error analyzing call graph: %v", err)
}
// Output results
fmt.Println("# Scanner Methods Call Graph")
fmt.Println()
// List all Scanner methods
fmt.Println("## All Scanner Methods")
fmt.Println()
var allMethods []string
for _, method := range callGraph.Methods {
if method.Receiver == "Scanner" {
allMethods = append(allMethods, fmt.Sprintf("- %s.%s.%s", method.Package, method.Receiver, method.Name))
}
}
sort.Strings(allMethods)
for _, method := range allMethods {
fmt.Println(method)
}
fmt.Println()
// Output call relationships
fmt.Println("## Method Call Relationships")
fmt.Println()
// Group calls by the calling method
callMap := make(map[string][]string)
for _, call := range callGraph.Calls {
callMap[call.From] = append(callMap[call.From], call.To)
}
var callers []string
for caller := range callMap {
callers = append(callers, caller)
}
sort.Strings(callers)
for _, caller := range callers {
targets := callMap[caller]
sort.Strings(targets)
fmt.Printf("### %s\n", caller)
fmt.Println("Calls:")
for _, target := range targets {
fmt.Printf("- %s\n", target)
}
fmt.Println()
}
// Output in Mermaid format
fmt.Println("## Mermaid Diagram")
fmt.Println()
fmt.Println("```mermaid")
fmt.Println("graph TD")
// Create node definitions
nodeMap := make(map[string]string)
for key, method := range callGraph.Methods {
if method.Receiver == "Scanner" {
nodeId := strings.ReplaceAll(key, ".", "_")
nodeMap[key] = nodeId
fmt.Printf(" %s[\"%s.%s\"]\n", nodeId, method.Package, method.Name)
}
}
// Create edges
for _, call := range callGraph.Calls {
fromNode, fromExists := nodeMap[call.From]
toNode, toExists := nodeMap[call.To]
if fromExists && toExists {
fmt.Printf(" %s --> %s\n", fromNode, toNode)
}
}
fmt.Println("```")
}
func analyzeCallGraph(ctx context.Context, rootDir string) (*CallGraph, error) {
fset := token.NewFileSet()
// Parse relevant Go files
files := []string{
filepath.Join(rootDir, "goscan.go"),
filepath.Join(rootDir, "scanner", "scanner.go"),
}
callGraph := &CallGraph{
Methods: make(map[string]*MethodInfo),
Calls: []MethodCall{},
}
for _, filePath := range files {
if err := analyzeFile(fset, filePath, callGraph); err != nil {
return nil, fmt.Errorf("error analyzing file %s: %w", filePath, err)
}
}
return callGraph, nil
}
func analyzeFile(fset *token.FileSet, filePath string, callGraph *CallGraph) error {
src, err := os.ReadFile(filePath)
if err != nil {
return fmt.Errorf("reading file: %w", err)
}
// Parse the file
file, err := parser.ParseFile(fset, filePath, src, parser.ParseComments)
if err != nil {
return fmt.Errorf("parsing file: %w", err)
}
packageName := file.Name.Name
// Walk the AST to find method definitions and calls
ast.Inspect(file, func(n ast.Node) bool {
switch node := n.(type) {
case *ast.FuncDecl:
if node.Recv != nil && len(node.Recv.List) > 0 {
// This is a method
methodName := node.Name.Name
receiverType := extractReceiverType(node.Recv.List[0].Type)
if receiverType == "Scanner" {
methodKey := fmt.Sprintf("%s.%s.%s", packageName, receiverType, methodName)
method := &MethodInfo{
Name: methodName,
Receiver: receiverType,
Package: packageName,
Calls: []string{},
}
// Find method calls within this method
ast.Inspect(node, func(inner ast.Node) bool {
if callExpr, ok := inner.(*ast.CallExpr); ok {
if targetMethod := extractMethodCall(callExpr, packageName); targetMethod != "" {
method.Calls = append(method.Calls, targetMethod)
// Add to call graph
callGraph.Calls = append(callGraph.Calls, MethodCall{
From: methodKey,
To: targetMethod,
})
}
}
return true
})
callGraph.Methods[methodKey] = method
}
}
}
return true
})
return nil
}
func extractReceiverType(expr ast.Expr) string {
switch t := expr.(type) {
case *ast.StarExpr:
return extractReceiverType(t.X)
case *ast.Ident:
return t.Name
default:
return ""
}
}
func extractMethodCall(callExpr *ast.CallExpr, currentPackage string) string {
switch fun := callExpr.Fun.(type) {
case *ast.SelectorExpr:
// Check if it's a method call on 's' (the scanner receiver)
if ident, ok := fun.X.(*ast.Ident); ok {
if ident.Name == "s" {
// This is a call to another Scanner method
return fmt.Sprintf("%s.Scanner.%s", currentPackage, fun.Sel.Name)
}
// Check for calls to s.scanner (internal scanner)
if ident.Name == "s" {
// Look for s.scanner.Method() pattern by checking if the selector is on a field
return ""
}
}
// Check for s.scanner.Method() calls
if selectorExpr, ok := fun.X.(*ast.SelectorExpr); ok {
if ident, ok := selectorExpr.X.(*ast.Ident); ok && ident.Name == "s" {
if selectorExpr.Sel.Name == "scanner" {
// This is s.scanner.Method()
return fmt.Sprintf("scanner.Scanner.%s", fun.Sel.Name)
}
}
}
}
return ""
}
@podhmo
Copy link
Author

podhmo commented Sep 20, 2025

# Scanner Methods Call Graph

## All Scanner Methods

- goscan.Scanner.AddDeclarationsOnlyPackages
- goscan.Scanner.AllSeenPackages
- goscan.Scanner.BuildImportLookup
- goscan.Scanner.FindSymbolDefinitionLocation
- goscan.Scanner.FindSymbolInPackage
- goscan.Scanner.Fset
- goscan.Scanner.IsWorkspace
- goscan.Scanner.ListExportedSymbols
- goscan.Scanner.Locator
- goscan.Scanner.LookupOverride
- goscan.Scanner.ModulePath
- goscan.Scanner.ModuleRoots
- goscan.Scanner.Modules
- goscan.Scanner.ResolveType
- goscan.Scanner.RootDir
- goscan.Scanner.SaveSymbolCache
- goscan.Scanner.Scan
- goscan.Scanner.ScanFiles
- goscan.Scanner.ScanPackageFromFilePath
- goscan.Scanner.ScanPackageFromImportPath
- goscan.Scanner.SetExternalTypeOverrides
- goscan.Scanner.TypeInfoFromExpr
- goscan.Scanner.UnscannedGoFiles
- goscan.Scanner.getOrCreateSymbolCache
- goscan.Scanner.locatorForImportPath
- goscan.Scanner.privateScan
- goscan.Scanner.resolveFilePath
- goscan.Scanner.updateSymbolCacheWithPackageInfo
- scanner.Scanner.BuildImportLookup
- scanner.Scanner.FileSet
- scanner.Scanner.ResolveType
- scanner.Scanner.ScanFiles
- scanner.Scanner.ScanFilesWithKnownImportPath
- scanner.Scanner.ScanPackageFromFilePathImports
- scanner.Scanner.ScanPackageFromImportPath
- scanner.Scanner.TypeInfoFromExpr
- scanner.Scanner.buildKey
- scanner.Scanner.evalConstExpr
- scanner.Scanner.evaluateAllConstants
- scanner.Scanner.evaluateConstant
- scanner.Scanner.fillTypeInfoFromSpec
- scanner.Scanner.parseFieldList
- scanner.Scanner.parseFuncDecl
- scanner.Scanner.parseFuncType
- scanner.Scanner.parseGenDecl
- scanner.Scanner.parseInterfaceType
- scanner.Scanner.parseStructType
- scanner.Scanner.parseTypeParamList
- scanner.Scanner.parseTypeSpec
- scanner.Scanner.resolveEnums
- scanner.Scanner.resolveFieldType
- scanner.Scanner.safeEvalConstExpr
- scanner.Scanner.scanGoFiles

## Method Call Relationships

### goscan.Scanner.BuildImportLookup
Calls:
- scanner.Scanner.BuildImportLookup

### goscan.Scanner.FindSymbolDefinitionLocation
Calls:
- goscan.Scanner.ScanPackageFromImportPath
- goscan.Scanner.getOrCreateSymbolCache

### goscan.Scanner.FindSymbolInPackage
Calls:
- goscan.Scanner.ScanFiles
- goscan.Scanner.UnscannedGoFiles
- goscan.Scanner.updateSymbolCacheWithPackageInfo
- scanner.Scanner.ScanFilesWithKnownImportPath

### goscan.Scanner.ListExportedSymbols
Calls:
- goscan.Scanner.ScanPackageFromImportPath

### goscan.Scanner.ResolveType
Calls:
- scanner.Scanner.ResolveType

### goscan.Scanner.SaveSymbolCache
Calls:
- goscan.Scanner.getOrCreateSymbolCache

### goscan.Scanner.Scan
Calls:
- goscan.Scanner.ScanFiles
- goscan.Scanner.ScanPackageFromFilePath
- goscan.Scanner.ScanPackageFromFilePath

### goscan.Scanner.ScanFiles
Calls:
- goscan.Scanner.resolveFilePath
- goscan.Scanner.updateSymbolCacheWithPackageInfo
- scanner.Scanner.ScanFiles

### goscan.Scanner.ScanPackageFromFilePath
Calls:
- goscan.Scanner.privateScan

### goscan.Scanner.ScanPackageFromImportPath
Calls:
- goscan.Scanner.locatorForImportPath
- goscan.Scanner.privateScan

### goscan.Scanner.TypeInfoFromExpr
Calls:
- scanner.Scanner.TypeInfoFromExpr

### goscan.Scanner.privateScan
Calls:
- goscan.Scanner.RootDir
- goscan.Scanner.updateSymbolCacheWithPackageInfo
- scanner.Scanner.ScanFiles
- scanner.Scanner.ScanFilesWithKnownImportPath

### goscan.Scanner.updateSymbolCacheWithPackageInfo
Calls:
- goscan.Scanner.getOrCreateSymbolCache

### scanner.Scanner.ScanFiles
Calls:
- scanner.Scanner.scanGoFiles

### scanner.Scanner.ScanFilesWithKnownImportPath
Calls:
- scanner.Scanner.scanGoFiles

### scanner.Scanner.TypeInfoFromExpr
Calls:
- scanner.Scanner.buildKey
- scanner.Scanner.resolveFieldType

### scanner.Scanner.buildKey
Calls:
- scanner.Scanner.buildKey
- scanner.Scanner.buildKey
- scanner.Scanner.buildKey
- scanner.Scanner.buildKey
- scanner.Scanner.buildKey
- scanner.Scanner.buildKey
- scanner.Scanner.buildKey
- scanner.Scanner.buildKey
- scanner.Scanner.buildKey
- scanner.Scanner.buildKey
- scanner.Scanner.buildKey
- scanner.Scanner.buildKey
- scanner.Scanner.buildKey
- scanner.Scanner.buildKey

### scanner.Scanner.evalConstExpr
Calls:
- scanner.Scanner.evalConstExpr
- scanner.Scanner.evalConstExpr
- scanner.Scanner.evalConstExpr
- scanner.Scanner.evalConstExpr
- scanner.Scanner.evaluateConstant

### scanner.Scanner.evaluateAllConstants
Calls:
- scanner.Scanner.evaluateConstant

### scanner.Scanner.evaluateConstant
Calls:
- scanner.Scanner.safeEvalConstExpr

### scanner.Scanner.fillTypeInfoFromSpec
Calls:
- scanner.Scanner.TypeInfoFromExpr
- scanner.Scanner.parseFuncType
- scanner.Scanner.parseInterfaceType
- scanner.Scanner.parseStructType
- scanner.Scanner.parseTypeParamList

### scanner.Scanner.parseFieldList
Calls:
- scanner.Scanner.TypeInfoFromExpr

### scanner.Scanner.parseFuncDecl
Calls:
- scanner.Scanner.TypeInfoFromExpr
- scanner.Scanner.TypeInfoFromExpr
- scanner.Scanner.parseFuncType
- scanner.Scanner.parseFuncType
- scanner.Scanner.parseTypeParamList
- scanner.Scanner.parseTypeSpec

### scanner.Scanner.parseFuncType
Calls:
- scanner.Scanner.parseFieldList
- scanner.Scanner.parseFieldList

### scanner.Scanner.parseGenDecl
Calls:
- scanner.Scanner.TypeInfoFromExpr
- scanner.Scanner.TypeInfoFromExpr
- scanner.Scanner.parseTypeSpec

### scanner.Scanner.parseInterfaceType
Calls:
- scanner.Scanner.TypeInfoFromExpr
- scanner.Scanner.parseFuncType

### scanner.Scanner.parseStructType
Calls:
- scanner.Scanner.TypeInfoFromExpr

### scanner.Scanner.parseTypeParamList
Calls:
- scanner.Scanner.TypeInfoFromExpr

### scanner.Scanner.parseTypeSpec
Calls:
- scanner.Scanner.fillTypeInfoFromSpec

### scanner.Scanner.resolveFieldType
Calls:
- scanner.Scanner.TypeInfoFromExpr
- scanner.Scanner.TypeInfoFromExpr
- scanner.Scanner.TypeInfoFromExpr
- scanner.Scanner.TypeInfoFromExpr
- scanner.Scanner.TypeInfoFromExpr
- scanner.Scanner.TypeInfoFromExpr
- scanner.Scanner.TypeInfoFromExpr
- scanner.Scanner.TypeInfoFromExpr
- scanner.Scanner.TypeInfoFromExpr
- scanner.Scanner.TypeInfoFromExpr
- scanner.Scanner.parseInterfaceType
- scanner.Scanner.parseStructType

### scanner.Scanner.safeEvalConstExpr
Calls:
- scanner.Scanner.evalConstExpr

### scanner.Scanner.scanGoFiles
Calls:
- scanner.Scanner.BuildImportLookup
- scanner.Scanner.BuildImportLookup
- scanner.Scanner.evaluateAllConstants
- scanner.Scanner.fillTypeInfoFromSpec
- scanner.Scanner.parseFuncDecl
- scanner.Scanner.parseGenDecl
- scanner.Scanner.resolveEnums

## Mermaid Diagram

```mermaid
graph TD
    goscan_Scanner_SetExternalTypeOverrides["goscan.SetExternalTypeOverrides"]
    goscan_Scanner_Modules["goscan.Modules"]
    goscan_Scanner_TypeInfoFromExpr["goscan.TypeInfoFromExpr"]
    goscan_Scanner_RootDir["goscan.RootDir"]
    goscan_Scanner_LookupOverride["goscan.LookupOverride"]
    goscan_Scanner_Scan["goscan.Scan"]
    goscan_Scanner_ResolveType["goscan.ResolveType"]
    goscan_Scanner_FindSymbolDefinitionLocation["goscan.FindSymbolDefinitionLocation"]
    goscan_Scanner_locatorForImportPath["goscan.locatorForImportPath"]
    goscan_Scanner_resolveFilePath["goscan.resolveFilePath"]
    goscan_Scanner_UnscannedGoFiles["goscan.UnscannedGoFiles"]
    scanner_Scanner_ScanFiles["scanner.ScanFiles"]
    scanner_Scanner_BuildImportLookup["scanner.BuildImportLookup"]
    scanner_Scanner_evaluateConstant["scanner.evaluateConstant"]
    scanner_Scanner_parseTypeSpec["scanner.parseTypeSpec"]
    scanner_Scanner_TypeInfoFromExpr["scanner.TypeInfoFromExpr"]
    goscan_Scanner_BuildImportLookup["goscan.BuildImportLookup"]
    goscan_Scanner_ModulePath["goscan.ModulePath"]
    goscan_Scanner_privateScan["goscan.privateScan"]
    goscan_Scanner_ScanFiles["goscan.ScanFiles"]
    goscan_Scanner_updateSymbolCacheWithPackageInfo["goscan.updateSymbolCacheWithPackageInfo"]
    scanner_Scanner_ScanFilesWithKnownImportPath["scanner.ScanFilesWithKnownImportPath"]
    scanner_Scanner_buildKey["scanner.buildKey"]
    scanner_Scanner_resolveFieldType["scanner.resolveFieldType"]
    goscan_Scanner_Locator["goscan.Locator"]
    goscan_Scanner_AddDeclarationsOnlyPackages["goscan.AddDeclarationsOnlyPackages"]
    goscan_Scanner_ScanPackageFromImportPath["goscan.ScanPackageFromImportPath"]
    scanner_Scanner_FileSet["scanner.FileSet"]
    scanner_Scanner_ScanPackageFromImportPath["scanner.ScanPackageFromImportPath"]
    scanner_Scanner_safeEvalConstExpr["scanner.safeEvalConstExpr"]
    scanner_Scanner_evalConstExpr["scanner.evalConstExpr"]
    scanner_Scanner_fillTypeInfoFromSpec["scanner.fillTypeInfoFromSpec"]
    goscan_Scanner_AllSeenPackages["goscan.AllSeenPackages"]
    goscan_Scanner_FindSymbolInPackage["goscan.FindSymbolInPackage"]
    goscan_Scanner_IsWorkspace["goscan.IsWorkspace"]
    goscan_Scanner_ScanPackageFromFilePath["goscan.ScanPackageFromFilePath"]
    goscan_Scanner_getOrCreateSymbolCache["goscan.getOrCreateSymbolCache"]
    goscan_Scanner_ListExportedSymbols["goscan.ListExportedSymbols"]
    scanner_Scanner_parseFuncDecl["scanner.parseFuncDecl"]
    scanner_Scanner_parseFieldList["scanner.parseFieldList"]
    goscan_Scanner_Fset["goscan.Fset"]
    scanner_Scanner_ScanPackageFromFilePathImports["scanner.ScanPackageFromFilePathImports"]
    scanner_Scanner_resolveEnums["scanner.resolveEnums"]
    scanner_Scanner_evaluateAllConstants["scanner.evaluateAllConstants"]
    goscan_Scanner_SaveSymbolCache["goscan.SaveSymbolCache"]
    scanner_Scanner_scanGoFiles["scanner.scanGoFiles"]
    scanner_Scanner_parseTypeParamList["scanner.parseTypeParamList"]
    scanner_Scanner_parseInterfaceType["scanner.parseInterfaceType"]
    scanner_Scanner_parseStructType["scanner.parseStructType"]
    goscan_Scanner_ModuleRoots["goscan.ModuleRoots"]
    scanner_Scanner_ResolveType["scanner.ResolveType"]
    scanner_Scanner_parseGenDecl["scanner.parseGenDecl"]
    scanner_Scanner_parseFuncType["scanner.parseFuncType"]
    goscan_Scanner_BuildImportLookup --> scanner_Scanner_BuildImportLookup
    goscan_Scanner_TypeInfoFromExpr --> scanner_Scanner_TypeInfoFromExpr
    goscan_Scanner_Scan --> goscan_Scanner_ScanPackageFromFilePath
    goscan_Scanner_Scan --> goscan_Scanner_ScanPackageFromFilePath
    goscan_Scanner_Scan --> goscan_Scanner_ScanFiles
    goscan_Scanner_ResolveType --> scanner_Scanner_ResolveType
    goscan_Scanner_privateScan --> goscan_Scanner_RootDir
    goscan_Scanner_privateScan --> scanner_Scanner_ScanFilesWithKnownImportPath
    goscan_Scanner_privateScan --> scanner_Scanner_ScanFiles
    goscan_Scanner_privateScan --> goscan_Scanner_updateSymbolCacheWithPackageInfo
    goscan_Scanner_ScanPackageFromFilePath --> goscan_Scanner_privateScan
    goscan_Scanner_ScanFiles --> goscan_Scanner_resolveFilePath
    goscan_Scanner_ScanFiles --> scanner_Scanner_ScanFiles
    goscan_Scanner_ScanFiles --> goscan_Scanner_updateSymbolCacheWithPackageInfo
    goscan_Scanner_ScanPackageFromImportPath --> goscan_Scanner_locatorForImportPath
    goscan_Scanner_ScanPackageFromImportPath --> goscan_Scanner_privateScan
    goscan_Scanner_updateSymbolCacheWithPackageInfo --> goscan_Scanner_getOrCreateSymbolCache
    goscan_Scanner_SaveSymbolCache --> goscan_Scanner_getOrCreateSymbolCache
    goscan_Scanner_ListExportedSymbols --> goscan_Scanner_ScanPackageFromImportPath
    goscan_Scanner_FindSymbolDefinitionLocation --> goscan_Scanner_getOrCreateSymbolCache
    goscan_Scanner_FindSymbolDefinitionLocation --> goscan_Scanner_ScanPackageFromImportPath
    goscan_Scanner_FindSymbolInPackage --> goscan_Scanner_UnscannedGoFiles
    goscan_Scanner_FindSymbolInPackage --> scanner_Scanner_ScanFilesWithKnownImportPath
    goscan_Scanner_FindSymbolInPackage --> goscan_Scanner_updateSymbolCacheWithPackageInfo
    goscan_Scanner_FindSymbolInPackage --> goscan_Scanner_ScanFiles
    scanner_Scanner_ScanFiles --> scanner_Scanner_scanGoFiles
    scanner_Scanner_ScanFilesWithKnownImportPath --> scanner_Scanner_scanGoFiles
    scanner_Scanner_scanGoFiles --> scanner_Scanner_BuildImportLookup
    scanner_Scanner_scanGoFiles --> scanner_Scanner_fillTypeInfoFromSpec
    scanner_Scanner_scanGoFiles --> scanner_Scanner_BuildImportLookup
    scanner_Scanner_scanGoFiles --> scanner_Scanner_parseGenDecl
    scanner_Scanner_scanGoFiles --> scanner_Scanner_parseFuncDecl
    scanner_Scanner_scanGoFiles --> scanner_Scanner_evaluateAllConstants
    scanner_Scanner_scanGoFiles --> scanner_Scanner_resolveEnums
    scanner_Scanner_parseGenDecl --> scanner_Scanner_TypeInfoFromExpr
    scanner_Scanner_parseGenDecl --> scanner_Scanner_parseTypeSpec
    scanner_Scanner_parseGenDecl --> scanner_Scanner_TypeInfoFromExpr
    scanner_Scanner_evaluateAllConstants --> scanner_Scanner_evaluateConstant
    scanner_Scanner_safeEvalConstExpr --> scanner_Scanner_evalConstExpr
    scanner_Scanner_evaluateConstant --> scanner_Scanner_safeEvalConstExpr
    scanner_Scanner_evalConstExpr --> scanner_Scanner_evaluateConstant
    scanner_Scanner_evalConstExpr --> scanner_Scanner_evalConstExpr
    scanner_Scanner_evalConstExpr --> scanner_Scanner_evalConstExpr
    scanner_Scanner_evalConstExpr --> scanner_Scanner_evalConstExpr
    scanner_Scanner_evalConstExpr --> scanner_Scanner_evalConstExpr
    scanner_Scanner_parseTypeSpec --> scanner_Scanner_fillTypeInfoFromSpec
    scanner_Scanner_fillTypeInfoFromSpec --> scanner_Scanner_parseTypeParamList
    scanner_Scanner_fillTypeInfoFromSpec --> scanner_Scanner_parseStructType
    scanner_Scanner_fillTypeInfoFromSpec --> scanner_Scanner_parseInterfaceType
    scanner_Scanner_fillTypeInfoFromSpec --> scanner_Scanner_parseFuncType
    scanner_Scanner_fillTypeInfoFromSpec --> scanner_Scanner_TypeInfoFromExpr
    scanner_Scanner_parseTypeParamList --> scanner_Scanner_TypeInfoFromExpr
    scanner_Scanner_parseInterfaceType --> scanner_Scanner_parseFuncType
    scanner_Scanner_parseInterfaceType --> scanner_Scanner_TypeInfoFromExpr
    scanner_Scanner_parseStructType --> scanner_Scanner_TypeInfoFromExpr
    scanner_Scanner_parseFuncDecl --> scanner_Scanner_parseTypeParamList
    scanner_Scanner_parseFuncDecl --> scanner_Scanner_parseFuncType
    scanner_Scanner_parseFuncDecl --> scanner_Scanner_parseTypeSpec
    scanner_Scanner_parseFuncDecl --> scanner_Scanner_TypeInfoFromExpr
    scanner_Scanner_parseFuncDecl --> scanner_Scanner_TypeInfoFromExpr
    scanner_Scanner_parseFuncDecl --> scanner_Scanner_parseFuncType
    scanner_Scanner_parseFuncType --> scanner_Scanner_parseFieldList
    scanner_Scanner_parseFuncType --> scanner_Scanner_parseFieldList
    scanner_Scanner_parseFieldList --> scanner_Scanner_TypeInfoFromExpr
    scanner_Scanner_buildKey --> scanner_Scanner_buildKey
    scanner_Scanner_buildKey --> scanner_Scanner_buildKey
    scanner_Scanner_buildKey --> scanner_Scanner_buildKey
    scanner_Scanner_buildKey --> scanner_Scanner_buildKey
    scanner_Scanner_buildKey --> scanner_Scanner_buildKey
    scanner_Scanner_buildKey --> scanner_Scanner_buildKey
    scanner_Scanner_buildKey --> scanner_Scanner_buildKey
    scanner_Scanner_buildKey --> scanner_Scanner_buildKey
    scanner_Scanner_buildKey --> scanner_Scanner_buildKey
    scanner_Scanner_buildKey --> scanner_Scanner_buildKey
    scanner_Scanner_buildKey --> scanner_Scanner_buildKey
    scanner_Scanner_buildKey --> scanner_Scanner_buildKey
    scanner_Scanner_buildKey --> scanner_Scanner_buildKey
    scanner_Scanner_buildKey --> scanner_Scanner_buildKey
    scanner_Scanner_TypeInfoFromExpr --> scanner_Scanner_buildKey
    scanner_Scanner_TypeInfoFromExpr --> scanner_Scanner_resolveFieldType
    scanner_Scanner_resolveFieldType --> scanner_Scanner_TypeInfoFromExpr
    scanner_Scanner_resolveFieldType --> scanner_Scanner_TypeInfoFromExpr
    scanner_Scanner_resolveFieldType --> scanner_Scanner_TypeInfoFromExpr
    scanner_Scanner_resolveFieldType --> scanner_Scanner_TypeInfoFromExpr
    scanner_Scanner_resolveFieldType --> scanner_Scanner_TypeInfoFromExpr
    scanner_Scanner_resolveFieldType --> scanner_Scanner_TypeInfoFromExpr
    scanner_Scanner_resolveFieldType --> scanner_Scanner_TypeInfoFromExpr
    scanner_Scanner_resolveFieldType --> scanner_Scanner_TypeInfoFromExpr
    scanner_Scanner_resolveFieldType --> scanner_Scanner_TypeInfoFromExpr
    scanner_Scanner_resolveFieldType --> scanner_Scanner_parseInterfaceType
    scanner_Scanner_resolveFieldType --> scanner_Scanner_parseStructType
    scanner_Scanner_resolveFieldType --> scanner_Scanner_TypeInfoFromExpr

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment