func()

in src/go/cmd/pkg.go [108:213]


func (p *Pkg) indexFile(f *ast.File) {
	// map import aliases to full import paths e.g. "shared" => "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared"
	imports := map[string]string{}
	for _, imp := range f.Imports {
		p := strings.Trim(imp.Path.Value, `"`)
		if imp.Name != nil {
			imports[imp.Name.String()] = p
		} else {
			imports[filepath.Base(p)] = p
		}
	}

	ast.Inspect(f, func(n ast.Node) bool {
		switch x := n.(type) {
		case *ast.FuncDecl:
			p.c.addFunc(*p, x, imports)
			// children can't be exported, let's not inspect them
			return false
		case *ast.GenDecl:
			if x.Tok == token.CONST || x.Tok == token.VAR {
				// const or var declaration
				for _, s := range x.Specs {
					p.c.addGenDecl(*p, x.Tok, s.(*ast.ValueSpec), imports)
				}
			}
		case *ast.TypeSpec:
			switch t := x.Type.(type) {
			case *ast.ArrayType:
				// "type UUID [16]byte"
				txt := p.getText(t.Pos(), t.End())
				p.types[x.Name.Name] = typeDef{n: x, p: p}
				p.c.addSimpleType(*p, x.Name.Name, p.Name(), txt, imports)
			case *ast.FuncType:
				// "type PolicyFunc func(*Request) (*http.Response, error)"
				txt := p.getText(t.Pos(), t.End())
				p.types[x.Name.Name] = typeDef{n: x, p: p}
				p.c.addSimpleType(*p, x.Name.Name, p.Name(), txt, imports)
			case *ast.Ident:
				// "type ETag string"
				p.types[x.Name.Name] = typeDef{n: x, p: p}
				p.c.addSimpleType(*p, x.Name.Name, p.Name(), t.Name, imports)
			case *ast.IndexExpr, *ast.IndexListExpr:
				// "type Client GenericClient[BaseClient]"
				// "type Client CompositeClient[BaseClient1, BaseClient2]"
				txt := p.getText(t.Pos(), t.End())
				p.types[x.Name.Name] = typeDef{n: x, p: p}
				p.c.addSimpleType(*p, x.Name.Name, p.Name(), txt, imports)
			case *ast.InterfaceType:
				p.types[x.Name.Name] = typeDef{n: x, p: p}
				in := p.c.addInterface(*p, x.Name.Name, p.Name(), t, imports)
				if in.Sealed {
					p.diagnostics = append(p.diagnostics, CodeDiagnostic{
						TargetID: in.ID(),
						Level:    CodeDiagnosticLevelInfo,
						Text:     sealedInterface,
					})
				}
			case *ast.MapType:
				// "type opValues map[reflect.Type]interface{}"
				txt := p.getText(t.Pos(), t.End())
				p.c.addSimpleType(*p, x.Name.Name, p.Name(), txt, imports)
			case *ast.SelectorExpr:
				if ident, ok := t.X.(*ast.Ident); ok {
					if impPath, ok := imports[ident.Name]; ok {
						// alias in the same module could use type navigator directly
						if _, _, found := strings.Cut(impPath, p.modulePath); found && !strings.Contains(impPath, "internal") {
							expr := p.getText(t.Pos(), t.End())
							p.c.addSimpleType(*p, x.Name.Name, p.Name(), expr, imports)
						}

						// This is a re-exported type e.g. "type TokenCredential = shared.TokenCredential".
						// Track it as an alias so we can later hoist its definition into this package.
						ta := TypeAlias{
							Name:          x.Name.Name,
							Package:       p,
							QualifiedName: impPath + "." + t.Sel.Name,
						}
						p.TypeAliases = append(p.TypeAliases, &ta)
					} else {
						// Non-SDK underlying type e.g. "type EDMDateTime time.Time". Handle it like a simple type
						// because we don't want to hoist its definition into this package.
						expr := p.getText(t.Pos(), t.End())
						p.c.addSimpleType(*p, x.Name.Name, p.Name(), expr, imports)
					}
				}
			case *ast.StructType:
				p.types[x.Name.Name] = typeDef{n: x, p: p}
				s := p.c.addStruct(*p, x.Name.Name, p.Name(), x, imports)
				for _, t := range s.AnonymousFields {
					// if t contains "." it must be exported
					if !strings.Contains(t, ".") && unicode.IsLower(rune(t[0])) {
						p.diagnostics = append(p.diagnostics, CodeDiagnostic{
							Level:    CodeDiagnosticLevelError,
							TargetID: s.ID(),
							Text:     embedsUnexportedStruct + t,
						})
					}
				}
			default:
				txt := p.getText(x.Pos(), x.End())
				fmt.Printf("unhandled node type %T: %s\n", t, txt)
			}
		}
		return true
	})
}