Documentation
¶
Overview ¶
Package scanner drives the first phase of the code-generation pipeline.
It invokes xcrun clang with -ast-dump=json on a framework's umbrella header, unmarshals the resulting Clang JSON AST, and walks it to produce a meta.FrameworkMeta value that captures the framework's complete public API: classes, protocols, enums, structs, free functions, extern constants, block types, and typedefs.
Extraction is restricted to declarations whose source file belongs to the named framework's own headers (filter.go), so re-exported types from other frameworks are skipped and attributed to their true owner during the load phase.
Key entry points:
- DumpAST — invokes xcrun clang and returns the parsed AST root node.
- Extract — walks an AST value and returns a populated meta.FrameworkMeta.
Index ¶
- func CLibraryHeader(sdkPath, name string) string
- func CLibraryHeaderDir(sdkPath, name string) string
- func CLibraryHeaderRelative(name string) string
- func ClangVersion() (string, error)
- func DetectSubFrameworkNames(bundlePath string) []string
- func Extract(root *ASTNode, sdkPath, frameworkName, sdkVersion, arch string) *meta.FrameworkMeta
- func FrameworkBundlePath(sdkPath, name string) string
- func FrameworkHeader(sdkPath, framework string) string
- func FrameworkHeaderDir(sdkPath, framework string) string
- func IsCLibrary(sdkPath, name string) bool
- func IsCLibraryName(name string) bool
- func IsSubFramework(name string) bool
- func IsSwiftOnly(bundlePath string) bool
- func ListCLibraries(sdkPath string) ([]string, error)
- func ListFrameworks(sdkPath string) ([]string, error)
- func LoadCLibrariesFile(path string) (bool, error)
- func LoadScanConfigFile(path string) (bool, error)
- func SDKPath() (string, error)
- func SDKVersion() (string, error)
- func SubFrameworkParts(name string) (parent, child string)
- func XcodeVersion() (string, error)
- type ASTNode
- type ASTRef
- type ASTType
- type CLibraryDef
- type IncludedFromRef
- type Location
- type RawValue
- type ScanConfig
- type SrcRange
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CLibraryHeader ¶
CLibraryHeader returns the umbrella header path for a known Apple C library. If the library definition specifies a custom Header path, that is used; otherwise the default {Name}/{Name}.h convention applies.
func CLibraryHeaderDir ¶
CLibraryHeaderDir returns the filter path for a known Apple C library. This is the path prefix used to decide whether an AST node belongs to the library. It may be a directory (e.g. "bsm/") or an exact file (e.g. "sandbox.h") depending on how the library's headers are laid out.
func CLibraryHeaderRelative ¶
CLibraryHeaderRelative returns the umbrella header include path for a known Apple C library, relative to {SDK}/usr/include/ and slash-separated — the form used in a generated "#include <…>" directive (e.g. "compression.h", "os/log.h", "bsm/libbsm.h"). Defaults to the {Name}/{Name}.h convention when the library definition has no custom Header.
func ClangVersion ¶
ClangVersion returns the version line of the clang binary that DumpAST invokes (e.g. "Apple clang version 21.0.0 (clang-2100.3.9.2)"). Recorded in scanned metadata because clang releases have changed AST output in ways that affect extraction (Clang 21 stopped emitting availability versions).
func DetectSubFrameworkNames ¶
DetectSubFrameworkNames returns the names of sub-frameworks inside bundlePath/Frameworks/ that have a valid umbrella header. Returns nil when the framework is not an umbrella.
func Extract ¶
func Extract(root *ASTNode, sdkPath, frameworkName, sdkVersion, arch string) *meta.FrameworkMeta
Extract walks the Clang AST root node and produces a FrameworkMeta containing only declarations that originate from the named framework's headers.
func FrameworkBundlePath ¶
FrameworkBundlePath returns the path to a framework's .framework bundle. It handles both top-level frameworks and "Parent/Child" sub-frameworks.
func FrameworkHeader ¶
FrameworkHeader returns the path to the umbrella header for a framework. framework may be "Name" (top-level) or "Parent/Child" (sub-framework). Falls back to the C library header path for known Apple C libraries.
func FrameworkHeaderDir ¶
FrameworkHeaderDir returns the directory containing all headers for a framework. framework may be "Name" (top-level) or "Parent/Child" (sub-framework). Falls back to the C library header directory for known Apple C libraries.
func IsCLibrary ¶
IsCLibrary reports whether name is a known Apple C library whose umbrella header exists on the filesystem.
func IsCLibraryName ¶
IsCLibraryName reports whether name is registered as a known Apple C library, without performing any filesystem check. Use this when an SDK path is not available (e.g. when constructing metadata output paths during a scan).
func IsSubFramework ¶
IsSubFramework reports whether name uses "Parent/Child" sub-framework notation.
func IsSwiftOnly ¶
IsSwiftOnly reports whether the framework at bundlePath has no ObjC surface and is implemented entirely in Swift (indicated by a .swiftmodule directory).
func ListCLibraries ¶
ListCLibraries returns the sorted names of known Apple C libraries present in sdkPath. If sdkPath is empty it is auto-detected via xcrun.
func ListFrameworks ¶
ListFrameworks returns the sorted names of all frameworks available in sdkPath that have a valid umbrella header (Framework.framework/Headers/Framework.h). If sdkPath is empty it is auto-detected via xcrun. Sub-frameworks nested inside umbrella frameworks (e.g. Carbon/HIToolbox) are included using "Parent/Child" notation so the scanner can locate them.
func LoadCLibrariesFile ¶
LoadCLibrariesFile replaces the active C library registry with the contents of a JSON config file (map of library name → CLibraryDef). Adding a new Apple C library is then a data change plus re-scan, not a Go change. Returns false without error when the file does not exist.
func LoadScanConfigFile ¶
LoadScanConfigFile replaces the active per-framework scan configuration with the contents of a JSON config file (map of framework name → ScanConfig). Returns false without error when the file does not exist.
func SDKVersion ¶
SDKVersion returns the macOS SDK version string (e.g. "26.5").
func SubFrameworkParts ¶
SubFrameworkParts splits a "Parent/Child" name into parent and child.
func XcodeVersion ¶
XcodeVersion returns the active Xcode version and build, joined on one line (e.g. "Xcode 26.0 Build version 17A321"). Recorded in scanned metadata as toolchain provenance.
Types ¶
type ASTNode ¶
type ASTNode struct {
ID string `json:"id"`
Kind string `json:"kind"`
Loc *Location `json:"loc"`
Range *SrcRange `json:"range"`
Name string `json:"name"`
MangledName string `json:"mangledName"`
Type *ASTType `json:"type"`
ReturnType *ASTType `json:"returnType"`
Inner []ASTNode `json:"inner"`
// PreviousDecl is the hex ID string of the previous declaration of this
// name in the same translation unit. When set, this node is a redeclaration
// (e.g. @class Foo; repeated after the canonical @interface Foo...@end, or
// an empty @class Foo; that precedes the canonical definition). Used in
// extractClass to distinguish canonical definitions from foreign-class
// forward declarations.
PreviousDecl string `json:"previousDecl"`
// ObjCInterfaceDecl / ObjCCategoryDecl
Super *ASTRef `json:"super"`
Protocols []ASTRef `json:"protocols"`
// ObjCCategoryDecl: the class this category extends
Interface *ASTRef `json:"interface"`
// ObjCMethodDecl — Clang uses "instance": true for instance methods,
// absence of the field (or false) means class method.
IsInstance bool `json:"instance"`
IsVariadic bool `json:"variadic"`
IsImplicit bool `json:"implicit"`
// ObjCPropertyDecl
Getter *ASTRef `json:"getter"`
Setter *ASTRef `json:"setter"`
// property attribute flags: "readonly", "copy", "weak", "assign", etc.
PropertyAttributes []string `json:"propertyAttributes"`
// EnumDecl
FixedUnderlyingType *ASTType `json:"fixedUnderlyingType"`
// RecordDecl (struct/union)
TagUsed string `json:"tagUsed"` // "struct" or "union"
CompleteDefinition bool `json:"completeDefinition"` // true for full record decl, false/missing for forward decl
// VarDecl
StorageClass string `json:"storageClass"` // "extern"
// IntegerLiteral / FloatingLiteral / ConstantExpr
// Clang emits numeric literals as JSON numbers; use RawMessage to handle both
// number and string variants uniformly.
Value RawValue `json:"value"`
// Availability
Availability []ASTNode `json:"availability"` // AvailabilityAttr nodes
// AvailabilityAttr fields
Platform string `json:"platform"` // "macos", "ios"
Introduced string `json:"introduced"`
Deprecated string `json:"deprecated"`
Obsoleted string `json:"obsoleted"`
Message string `json:"message"`
// ObjCTypeParamDecl — generic type params on a class
// appears as inner nodes of ObjCInterfaceDecl
Bound *ASTType `json:"bound"` // upper bound (usually "id")
// Nullability qualifier attached to a type
NullabilityQual string `json:"nullabilityQual"` // "nullable", "nonnull", "unspecified"
// SwiftNameAttr carries the NS_SWIFT_NAME value; appears as an inner node.
SwiftName string `json:"swiftName,omitempty"`
}
ASTNode is a node in the Clang JSON AST produced by clang -ast-dump=json. Only fields we actually use are decoded; unknown fields are silently ignored.
type CLibraryDef ¶
type CLibraryDef struct {
// LinkLib is the dylib name passed to -l (e.g. "EndpointSecurity" → -lEndpointSecurity).
LinkLib string `json:"link_lib"`
// Header is the umbrella header path relative to {SDK}/usr/include/.
// Empty means use the default {Name}/{Name}.h convention.
Header string `json:"header,omitempty"`
// HeaderDir is the filter path relative to {SDK}/usr/include/ used to decide
// whether an AST node belongs to this library. Empty means derive from Header.
// Use a directory path (e.g. "bsm/") to accept all headers under that directory,
// or a file path (e.g. "sandbox.h") to match only that exact file.
HeaderDir string `json:"header_dir,omitempty"`
}
CLibraryDef describes a known Apple C library under {SDK}/usr/include/.
type IncludedFromRef ¶
type IncludedFromRef struct {
File string `json:"file"`
}
IncludedFromRef holds the file that directly includes the file containing a source location. Clang emits this when the declaration file is not the translation unit root.
type Location ¶
type Location struct {
FilePath string `json:"file"`
Line int `json:"line"`
Col int `json:"col"`
// When the loc is a macro expansion the actual file is in ExpansionLoc
ExpansionLoc *Location `json:"expansionLoc"`
// Spelling location (pre-macro-expansion)
SpellingLoc *Location `json:"spellingLoc"`
// IncludedFrom is the file that directly includes the file this loc is in.
// Present when loc.file is absent (Clang cursor optimisation) or when Clang
// wants to indicate the include chain.
IncludedFrom *IncludedFromRef `json:"includedFrom"`
}
func (*Location) IncludedFromFile ¶
IncludedFromFile returns the path of the file that directly includes the file this location is in, or "" if none was recorded. Used by the framework filter to determine true framework ownership when loc.file is absent.
func (*Location) ResolvedFile ¶
ResolvedFile returns the most useful file path from this location, unwrapping macro expansions to find the real header file. For macro-expanded declarations (NS_ENUM, NS_OPTIONS, etc.) the expansion location is the call site in the SDK header, while the spelling location is the macro definition inside CoreFoundation. We want the call site.
func (*Location) ResolvedLine ¶
ResolvedLine returns the source line number, preferring spellingLoc over expansionLoc.
type RawValue ¶
type RawValue string
RawValue holds an AST literal value which Clang may emit as a JSON number or as a JSON string. It normalises both to a plain string.
func (RawValue) MarshalJSON ¶
MarshalJSON writes the value as a JSON string.
func (*RawValue) UnmarshalJSON ¶
type ScanConfig ¶
type ScanConfig struct {
// ExtraIncludeDirs lists additional directories (relative to the SDK root,
// slash-separated) whose headers count as belonging to this framework.
ExtraIncludeDirs []string `json:"extra_include_dirs,omitempty"`
}
ScanConfig holds per-framework scan customisations.