Documentation
¶
Index ¶
- Constants
- Variables
- func CacheDir(repoDir string) (string, error)
- func CachePath(scanPaths []string) string
- func CacheStats(cacheDir string) (count int, bytes int64, err error)
- func CollectKtFiles(sourceDirs []string) ([]string, error)
- func ContentHash(path string) (string, error)
- func FindJar(scanPaths []string) string
- func FindRepoDir(scanPaths []string) string
- func FindSourceDirs(scanPaths []string) []string
- func IndexCacheHashes(cacheDir string) map[string]bool
- func Invoke(jarPath string, sourceDirs []string, outputPath string, verbose bool) (string, error)
- func InvokeCached(jarPath string, sourceDirs []string, repoDir string, outputPath string, ...) (string, error)
- func InvokeCachedWithOptions(jarPath string, sourceDirs []string, repoDir string, outputPath string, ...) (string, error)
- func InvokeWithFiles(jarPath string, sourceDirs []string, outputPath, filesListPath string, ...) (string, error)
- func InvokeWithFilesWithOptions(jarPath string, sourceDirs []string, outputPath, filesListPath string, ...) (string, error)
- func PreloadPath(path string)
- func RenderSignatureStub(jarPath, fqn string, cls *Class) string
- func SetReporter(r *diag.Reporter)
- func StableFingerprint(paths []string, root string) string
- func VerifyClosure(entry *CacheEntry, hashCache map[string]string) bool
- func WriteCallTargetFilterFile(summary CallTargetFilterSummary, tmpDir string) (string, error)
- func WriteEntry(cacheDir string, entry *CacheEntry) error
- func WriteEntryToStore(s *store.FileStore, entry *CacheEntry) error
- func WriteFilterListFile(summary FilterSummary, tmpDir string) (string, error)
- func WriteFreshEntries(cacheDir string, fresh *Data, deps *CacheDepsFile) (int, error)
- func WriteFreshEntriesToStore(s *store.FileStore, cacheDir string, fresh *Data, deps *CacheDepsFile) (int, error)
- func WriteFreshEntriesToStoreWithTracker(s *store.FileStore, cacheDir string, fresh *Data, deps *CacheDepsFile, ...) (int, error)
- func WriteFreshEntriesToStoreWithTrackerScoped(s *store.FileStore, cacheDir string, fresh *Data, deps *CacheDepsFile, ...) (int, error)
- func WriteFreshEntriesToStoreWithTrackerScopedV2(s *store.FileStore, cacheDir string, fresh *Data, deps *CacheDepsFile, ...) (int, error)
- func WriteFreshEntriesWithTracker(cacheDir string, fresh *Data, deps *CacheDepsFile, tracker perf.Tracker) (int, error)
- func WriteFreshEntriesWithTrackerScoped(cacheDir string, fresh *Data, deps *CacheDepsFile, tracker perf.Tracker, ...) (int, error)
- func WriteFreshEntriesWithTrackerScopedV2(cacheDir string, fresh *Data, deps *CacheDepsFile, tracker perf.Tracker, ...) (int, error)
- type CacheClosure
- type CacheDepsEntry
- type CacheDepsFile
- type CacheEntry
- func ClassifyFiles(cacheDir string, paths []string) (hits []*CacheEntry, misses []string)
- func ClassifyFilesScoped(cacheDir string, paths []string, callFilterFingerprint string) (hits []*CacheEntry, misses []string)
- func ClassifyFilesScopedV2(cacheDir string, paths []string, ...) (hits []*CacheEntry, misses []string)
- func ClassifyFilesWithStore(s *store.FileStore, cacheDir string, paths []string) (hits []*CacheEntry, misses []string)
- func ClassifyFilesWithStoreScoped(s *store.FileStore, cacheDir string, paths []string, ...) (hits []*CacheEntry, misses []string)
- func ClassifyFilesWithStoreScopedV2(s *store.FileStore, cacheDir string, paths []string, ...) (hits []*CacheEntry, misses []string)
- func LoadEntry(cacheDir, hash string) (*CacheEntry, error)
- func LoadEntryFromStore(s *store.FileStore, contentHash string) (*CacheEntry, error)
- type CacheWriter
- func (w *CacheWriter) AddPerfEntries(t perf.Tracker, storeBacked bool)
- func (w *CacheWriter) Close() error
- func (w *CacheWriter) Flush(ctx context.Context) error
- func (w *CacheWriter) QueueFreshEntries(cacheDir string, fresh *Data, deps *CacheDepsFile) (int, error)
- func (w *CacheWriter) QueueFreshEntriesToStore(s *store.FileStore, cacheDir string, fresh *Data, deps *CacheDepsFile) (int, error)
- func (w *CacheWriter) QueueFreshEntriesToStoreScoped(s *store.FileStore, cacheDir string, fresh *Data, deps *CacheDepsFile, ...) (int, error)
- func (w *CacheWriter) QueueFreshEntriesToStoreScopedV2(s *store.FileStore, cacheDir string, fresh *Data, deps *CacheDepsFile, ...) (int, error)
- func (w *CacheWriter) Stats() CacheWriterStats
- type CacheWriterStats
- type CallTargetFilterSummary
- type CallTargetRuleProfile
- type Class
- type CompositeResolver
- func (c *CompositeResolver) AnnotationValueFlat(idx uint32, file *scanner.File, annotationName, argName string) string
- func (c *CompositeResolver) ClassHierarchy(typeName string) *typeinfer.ClassInfo
- func (c *CompositeResolver) EnumEntries(enumTypeName string) []string
- func (c *CompositeResolver) Fallback() typeinfer.TypeResolver
- func (c *CompositeResolver) IndexFilesParallel(files []*scanner.File, workers int)
- func (c *CompositeResolver) IndexFilesParallelWithTracker(files []*scanner.File, workers int, tracker perf.Tracker)
- func (c *CompositeResolver) IsExceptionSubtype(a, b string) bool
- func (c *CompositeResolver) IsNullableFlat(idx uint32, file *scanner.File) *bool
- func (c *CompositeResolver) Oracle() Lookup
- func (c *CompositeResolver) ResolveByNameFlat(name string, idx uint32, file *scanner.File) *typeinfer.ResolvedType
- func (c *CompositeResolver) ResolveFlatNode(idx uint32, file *scanner.File) *typeinfer.ResolvedType
- func (c *CompositeResolver) ResolveImport(simpleName string, file *scanner.File) string
- func (c *CompositeResolver) SealedVariants(sealedTypeName string) []string
- type Daemon
- func ConnectOrStartDaemon(jarPath string, sourceDirs []string, classpath []string, verbose bool) (*Daemon, error)
- func InvokeDaemon(scanPaths []string, verbose bool) (*Daemon, error)
- func InvokePersistentDaemon(scanPaths []string, verbose bool) (*Daemon, error)
- func StartDaemon(jarPath string, sourceDirs []string, classpath []string, verbose bool) (*Daemon, error)
- func StartDaemonWithPort(jarPath string, sourceDirs []string, classpath []string, verbose bool) (*Daemon, error)
- func StartDaemonWithPortSlot(jarPath string, sourceDirs []string, classpath []string, verbose bool, ...) (*Daemon, error)
- func (d *Daemon) Analyze(files []string) (*Data, error)
- func (d *Daemon) AnalyzeAll() (*Data, error)
- func (d *Daemon) AnalyzeAllWithCallFilter(callFilter *CallTargetFilterSummary) (*Data, error)
- func (d *Daemon) AnalyzeWithDeps(files []string) (*Data, *CacheDepsFile, error)
- func (d *Daemon) AnalyzeWithDepsWithTimings(files []string, collectTimings bool, callFilter *CallTargetFilterSummary, ...) (*Data, *CacheDepsFile, []perf.TimingEntry, error)
- func (d *Daemon) Checkpoint() error
- func (d *Daemon) Close() error
- func (d *Daemon) DecompileJar(jarPath, fqn string) (string, error)
- func (d *Daemon) MatchesRepo(sourceDirs []string) bool
- func (d *Daemon) Ping() error
- func (d *Daemon) Rebuild() error
- func (d *Daemon) Release() error
- func (d *Daemon) ResolveExpressionTypes(positions map[string][]ExpressionPosition) (map[string]map[ExpressionPosition]*typeinfer.ResolvedType, error)
- func (d *Daemon) Shutdown() error
- type DaemonDecompiler
- type DaemonPool
- type Data
- type DeclLocation
- type DeclarationProfile
- type DeclarationProfileSummary
- type DecompileCache
- type Decompiler
- type Diagnostic
- type ExpressionPosition
- type ExpressionType
- type FakeOracle
- func (f *FakeOracle) Dependencies() map[string]*Class
- func (f *FakeOracle) IsSubtype(a, b string) bool
- func (f *FakeOracle) LookupAnnotations(key string) []string
- func (f *FakeOracle) LookupCallTarget(filePath string, line, col int) string
- func (f *FakeOracle) LookupCallTargetAnnotations(filePath string, line, col int) []string
- func (f *FakeOracle) LookupCallTargetAnnotationsFlat(file *scanner.File, idx uint32) []string
- func (f *FakeOracle) LookupCallTargetFlat(file *scanner.File, idx uint32) string
- func (f *FakeOracle) LookupCallTargetSuspend(filePath string, line, col int) (bool, bool)
- func (f *FakeOracle) LookupCallTargetSuspendFlat(file *scanner.File, idx uint32) (bool, bool)
- func (f *FakeOracle) LookupClass(name string) *typeinfer.ClassInfo
- func (f *FakeOracle) LookupDiagnostics(filePath string) []Diagnostic
- func (f *FakeOracle) LookupDiagnosticsForFlatRange(file *scanner.File, _ uint32) []Diagnostic
- func (f *FakeOracle) LookupEnumEntries(name string) []string
- func (f *FakeOracle) LookupExpression(filePath string, line, col int) *typeinfer.ResolvedType
- func (f *FakeOracle) LookupExpressionFlat(file *scanner.File, idx uint32) *typeinfer.ResolvedType
- func (f *FakeOracle) LookupFunction(key string) *typeinfer.ResolvedType
- func (f *FakeOracle) LookupSealedVariants(name string) []string
- type FallbackDecompiler
- type File
- type FilterRule
- type FilterSpec
- type FilterSummary
- type Index
- func (idx *Index) ApplyFileUpdate(path string, file *File)
- func (idx *Index) FindDeclarationByFQN(fqn string) (*DeclLocation, bool)
- func (idx *Index) FindDeclarationBySimpleName(name string) []*DeclLocation
- func (idx *Index) FindReferencesByFQN(fqn string) []ReferenceLocation
- func (idx *Index) RemoveFile(path string)
- func (idx *Index) TypeAtExpression(exprID string) (TypeInfo, bool)
- type InvocationOptions
- type LazyLookup
- func (l *LazyLookup) Dependencies() map[string]*Class
- func (l *LazyLookup) Err() error
- func (l *LazyLookup) IsSubtype(a, b string) bool
- func (l *LazyLookup) Loaded() bool
- func (l *LazyLookup) LookupAnnotations(key string) []string
- func (l *LazyLookup) LookupCallTarget(filePath string, line, col int) string
- func (l *LazyLookup) LookupCallTargetAnnotations(filePath string, line, col int) []string
- func (l *LazyLookup) LookupCallTargetAnnotationsFlat(file *scanner.File, idx uint32) []string
- func (l *LazyLookup) LookupCallTargetFlat(file *scanner.File, idx uint32) string
- func (l *LazyLookup) LookupCallTargetSuspend(filePath string, line, col int) (bool, bool)
- func (l *LazyLookup) LookupCallTargetSuspendFlat(file *scanner.File, idx uint32) (bool, bool)
- func (l *LazyLookup) LookupClass(name string) *typeinfer.ClassInfo
- func (l *LazyLookup) LookupDiagnostics(filePath string) []Diagnostic
- func (l *LazyLookup) LookupDiagnosticsForFlatRange(file *scanner.File, idx uint32) []Diagnostic
- func (l *LazyLookup) LookupEnumEntries(name string) []string
- func (l *LazyLookup) LookupExpression(filePath string, line, col int) *typeinfer.ResolvedType
- func (l *LazyLookup) LookupExpressionFlat(file *scanner.File, idx uint32) *typeinfer.ResolvedType
- func (l *LazyLookup) LookupFunction(key string) *typeinfer.ResolvedType
- func (l *LazyLookup) LookupSealedVariants(name string) []string
- func (l *LazyLookup) Preload()
- func (l *LazyLookup) Stats() Stats
- type Lookup
- type Member
- type Oracle
- func (o *Oracle) Dependencies() map[string]*Class
- func (o *Oracle) Index() *Index
- func (o *Oracle) IsSubtype(a, b string) bool
- func (o *Oracle) LookupAnnotations(key string) []string
- func (o *Oracle) LookupCallTarget(filePath string, line, col int) string
- func (o *Oracle) LookupCallTargetAnnotations(filePath string, line, col int) []string
- func (o *Oracle) LookupCallTargetAnnotationsFlat(file *scanner.File, idx uint32) []string
- func (o *Oracle) LookupCallTargetFlat(file *scanner.File, idx uint32) string
- func (o *Oracle) LookupCallTargetSuspend(filePath string, line, col int) (isSuspend bool, ok bool)
- func (o *Oracle) LookupCallTargetSuspendFlat(file *scanner.File, idx uint32) (bool, bool)
- func (o *Oracle) LookupClass(name string) *typeinfer.ClassInfo
- func (o *Oracle) LookupDiagnostics(filePath string) []Diagnostic
- func (o *Oracle) LookupDiagnosticsForFlatRange(file *scanner.File, idx uint32) []Diagnostic
- func (o *Oracle) LookupEnumEntries(name string) []string
- func (o *Oracle) LookupExpression(filePath string, line, col int) *typeinfer.ResolvedType
- func (o *Oracle) LookupExpressionFlat(file *scanner.File, idx uint32) *typeinfer.ResolvedType
- func (o *Oracle) LookupFunction(key string) *typeinfer.ResolvedType
- func (o *Oracle) LookupSealedVariants(name string) []string
- func (o *Oracle) SetExpressionFact(filePath string, line, col int, t *typeinfer.ResolvedType)
- func (o *Oracle) Stats() Stats
- type Param
- type ReferenceLocation
- type SignatureStubDecompiler
- type Stats
- type TypeInfo
Constants ¶
const CacheVersion = 2
CacheVersion is bumped whenever the on-disk entry layout changes in a way that invalidates previously-written entries. A version mismatch on read is treated as a miss and the offending entry is deleted.
Variables ¶
var ErrDaemonFileNotInSession = errors.New("daemon: file not in source module")
ErrDaemonFileNotInSession is returned by Daemon.AnalyzeWithDeps when the daemon's response errors map contains any "File not found in source module" entries. Callers use errors.Is to recognize the condition and trigger a daemon Rebuild + retry before falling through to one-shot.
Functions ¶
func CacheDir ¶
CacheDir returns the cache root for a repo. The directory is created if it doesn't exist.
func CacheStats ¶
CacheStats walks the entries directory for reporting (count, byte size). Used by the CLI -verbose path and by the end-to-end benchmark script.
func CollectKtFiles ¶
CollectKtFiles walks the given source directories and returns absolute paths of all .kt files. Mirrors the directory pruning FindSourceDirs does (build/.gradle/.git/node_modules) so the Go-side enumeration matches what the JVM side will actually see. Also applies the krit-types default exclude patterns so excluded files don't leak into the cache miss list.
func ContentHash ¶
ContentHash returns the content hash of the file at path in lowercase hex. Used both as the cache key and as the building block for closure fingerprints. Routed through the process-scoped hashutil.Memo so the same file hashed by multiple cache subsystems within one run only pays the hash cost once.
func FindJar ¶
FindJar locates the krit-types shadow JAR by checking: 1. Next to the krit binary (tools/krit-types/build/libs/krit-types.jar) 2. In the project being scanned (.krit/krit-types.jar) 3. Relative to the krit binary's directory
func FindRepoDir ¶
FindRepoDir picks the repo root for repo-local Krit state.
func FindSourceDirs ¶
FindSourceDirs discovers Kotlin source directories under the given paths.
func IndexCacheHashes ¶
IndexCacheHashes walks the legacy cache entries directory once and returns a set of content hashes that have a legacy JSON entry on disk. Packed entries are indexed per shard when the shard is loaded.
Returned map is nil on directory walk error; callers treat nil the same as "don't trust the index, fall back to per-file LoadEntry".
func Invoke ¶
Invoke runs krit-types.jar to produce a type oracle JSON file. It enforces a hard timeout (KRIT_TYPES_TIMEOUT, default 5m) and a soft grace period (KRIT_TYPES_GRACE_EXIT, default 15s) that starts once the output file appears on disk. The grace period exists because krit-types.jar has been observed to hang after writing its output when Analysis API background threads keep the JVM alive — once the output is complete we can force-kill the subprocess without losing work.
On failure, the returned error includes the first few lines of the subprocess's captured stderr (up to 8 KB tail) so the caller can surface a diagnostic instead of a bare exit code. On success the output path is returned even when the grace period fired — the caller is responsible for validating the JSON via oracle.Load / oracle.LoadFromData.
func InvokeCached ¶
func InvokeCached( jarPath string, sourceDirs []string, repoDir string, outputPath string, filterListPath string, verbose bool, s *store.FileStore, ) (string, error)
InvokeCached is the cache-aware variant of Invoke. It walks sourceDirs, classifies .kt files into hits and misses via the on-disk cache, runs krit-types only on misses (with --files + --cache-deps-out), writes new cache entries, and assembles the final oracle JSON at outputPath.
filterListPath (optional, "" = no filter) is a path to a newline-separated list of absolute .kt paths produced by the rule-classification pre-scan. When present, it narrows the universe of files the cache classifies — files not in the filter are neither looked up nor analyzed, since no enabled rule cares about them. Rule filtering and per-file caching thus compose: filter narrows first, cache dedupes what remains.
Returns the output path on success. If no files were discovered or the cache can't be created, the function falls back to a plain Invoke so the caller still gets a complete oracle. InvokeCached is the cache-aware variant of Invoke. s is the optional unified store; when non-nil, oracle cache entries are read from and written to s instead of the legacy cacheDir file layout.
func InvokeCachedWithOptions ¶
func InvokeCachedWithOptions( jarPath string, sourceDirs []string, repoDir string, outputPath string, filterListPath string, verbose bool, s *store.FileStore, opts InvocationOptions, ) (string, error)
InvokeCachedWithOptions is InvokeCached plus optional deep perf instrumentation for the cache/filter/JVM path.
func InvokeWithFiles ¶
func InvokeWithFiles(jarPath string, sourceDirs []string, outputPath, filesListPath string, verbose bool) (string, error)
InvokeWithFiles is identical to Invoke but additionally passes a --files LISTFILE flag to krit-types if filesListPath is non-empty. LISTFILE is expected to contain one absolute .kt path per line and is produced by the rule-classification oracle filter (oracle.CollectOracleFiles + oracle.WriteFilterListFile). krit-types still builds the FIR session from the full --sources tree so that cross-file resolution works; the flag only narrows which files contribute expressions/declarations to the output JSON.
func InvokeWithFilesWithOptions ¶
func InvokeWithFilesWithOptions(jarPath string, sourceDirs []string, outputPath, filesListPath string, verbose bool, opts InvocationOptions) (string, error)
InvokeWithFilesWithOptions is InvokeWithFiles plus optional perf instrumentation. The krit-types output schema stays unchanged; Kotlin-side timings are captured through a temporary --timings-out sidecar when a tracker is enabled.
func PreloadPath ¶ added in v0.2.0
func PreloadPath(path string)
PreloadPath kicks off oracle JSON deserialization for path and keeps the result available for any later LazyLookup created for the same file.
func RenderSignatureStub ¶
RenderSignatureStub produces the placeholder Kotlin source for one FQN. Exposed for tests and for callers that want to render without going through the cache.
func SetReporter ¶
SetReporter installs r as the package-level Reporter used for verbose and warning output. Passing nil restores a default warnings-only Reporter so library code never panics on a nil dereference.
func StableFingerprint ¶
StableFingerprint returns a fingerprint of paths that is invariant under repository checkout location: each path is rewritten relative to root (slash-normalised) before hashing. Paths outside root fall back to their basename. An empty input returns the fingerprint of the empty set (matches fingerprintPaths(nil)).
The CI oracle-fingerprint gate uses this instead of the absolute- path fingerprint emitted in perf output, since baseline files are checked in and must match across every contributor's checkout.
func VerifyClosure ¶
func VerifyClosure(entry *CacheEntry, hashCache map[string]string) bool
VerifyClosure recomputes the dep-closure fingerprint from disk and compares against the entry's stored fingerprint. Returns true iff the two match. Any I/O error while reading deps is treated as a miss. Crashed entries bypass closure verification: they have no dep list by construction (the crash happened before any deps were collected), and their validity is content-hash-only — if the bytes that crashed before are unchanged, the same crash will deterministically recur.
hashCache can be nil (cold path) or a shared map (ClassifyFiles passes its own map so multiple VerifyClosure calls share content-hash results across the whole classify pass).
func WriteCallTargetFilterFile ¶
func WriteCallTargetFilterFile(summary CallTargetFilterSummary, tmpDir string) (string, error)
WriteCallTargetFilterFile writes the callee filter JSON consumed by krit-types --call-filter. Disabled summaries return an empty path.
func WriteEntry ¶
func WriteEntry(cacheDir string, entry *CacheEntry) error
WriteEntry atomically writes a cache entry: temp file in the same directory, then rename into place. This avoids torn writes if the process crashes mid-write.
func WriteEntryToStore ¶
func WriteEntryToStore(s *store.FileStore, entry *CacheEntry) error
WriteEntryToStore persists a CacheEntry in s keyed by its content hash.
func WriteFilterListFile ¶
func WriteFilterListFile(summary FilterSummary, tmpDir string) (string, error)
WriteFilterListFile writes the filter's matched paths to a temp file that krit-types can read via its --files flag. Returns the written path or an error. Callers should clean up the file after the oracle run. When AllFiles is true or the Paths list is nil, returns an empty string and no error — the caller is expected to skip the --files flag entirely in that case.
func WriteFreshEntries ¶
func WriteFreshEntries( cacheDir string, fresh *Data, deps *CacheDepsFile, ) (int, error)
WriteFreshEntries writes cache entries for the files that krit-types just analyzed. For each fresh FileResult, it looks up the corresponding dep fragment in the CacheDepsFile, computes the closure fingerprint from the current disk state of the dep paths, and writes an atomic entry under cacheDir. Shares a content-hash memoization across all per-entry closure computations so shared dependency closures are read once.
func WriteFreshEntriesToStore ¶
func WriteFreshEntriesToStore( s *store.FileStore, cacheDir string, fresh *Data, deps *CacheDepsFile, ) (int, error)
WriteFreshEntriesToStore is like WriteFreshEntries but writes to s instead of the legacy cacheDir layout. Falls back to WriteFreshEntries when s is nil.
Types ¶
type CacheClosure ¶
type CacheClosure struct {
DepPaths []string `json:"dep_paths"`
Fingerprint string `json:"fingerprint"`
}
CacheClosure records this file's direct source-file dependencies and the fingerprint computed over their content at write time.
type CacheDepsEntry ¶
type CacheDepsEntry struct {
DepPaths []string `json:"depPaths"`
PerFileDeps map[string]*Class `json:"perFileDeps"`
}
CacheDepsEntry is one file's dep-closure fragment.
type CacheDepsFile ¶
type CacheDepsFile struct {
Version int `json:"version"`
Approximation string `json:"approximation"`
Files map[string]*CacheDepsEntry `json:"files"`
Crashed map[string]string `json:"crashed,omitempty"`
}
CacheDepsFile is the schema of the --cache-deps-out JSON emitted by krit-types. Keys in Files are source file paths. Crashed maps a file path to the short error string for files whose analyzeKtFile outer catch fired — those get poison-marker entries instead of regular ones.
func LoadCacheDeps ¶
func LoadCacheDeps(path string) (*CacheDepsFile, error)
LoadCacheDeps reads the --cache-deps-out JSON produced by krit-types.
type CacheEntry ¶
type CacheEntry struct {
V int `json:"v"`
ContentHash string `json:"content_hash"`
FilePath string `json:"file_path"`
FileResult *File `json:"file_result"`
PerFileDeps map[string]*Class `json:"per_file_deps,omitempty"`
Closure CacheClosure `json:"closure"`
// CallFilterFingerprint is empty for unfiltered/broad oracle entries.
// Filtered entries only satisfy lookups for the same filter. Unfiltered
// entries are a safe superset and can satisfy filtered runs.
CallFilterFingerprint string `json:"call_filter_fingerprint,omitempty"`
// DeclarationProfileFingerprint is empty for entries produced with the
// full declaration export profile (pre-profile behavior). Narrow-profile
// entries only satisfy lookups at the same fingerprint — the
// broader-superset rule that applies to CallFilterFingerprint also
// applies here: empty = contains every field = satisfies any lookup.
DeclarationProfileFingerprint string `json:"declaration_profile_fingerprint,omitempty"`
// Approximation tags the dep-closure tracking method used when the
// entry was written. Any mismatch with the current runtime's
// approximation is treated as a miss — lets us upgrade the tracker
// without leaving stale entries from a weaker approximation lying
// around.
Approximation string `json:"approximation,omitempty"`
// Crashed marks this entry as a poison marker: the file with this
// exact content deterministically crashes krit-types during analysis.
// FileResult and PerFileDeps are nil for crash entries; they contribute
// nothing to the assembled oracle. ClassifyFiles still returns them as
// hits so the caller skips JVM launch. Invalidated automatically on a
// content-hash change (content edit) or a CacheVersion bump (Kotlin or
// krit-types upgrade).
Crashed bool `json:"crashed,omitempty"`
CrashError string `json:"crash_error,omitempty"`
}
CacheEntry is one file's cached oracle analysis. The JSON field names are intentionally short because there can be tens of thousands of these in a single repo.
func ClassifyFiles ¶
func ClassifyFiles(cacheDir string, paths []string) (hits []*CacheEntry, misses []string)
ClassifyFiles partitions paths into cache hits and cache misses. For each input path it computes the content hash, loads any matching entry, and verifies the closure fingerprint. Errors on individual files degrade to a miss for that file (with a best-effort cleanup of the corrupt entry) so a single bad entry can't poison the whole run.
Performance: ClassifyFiles keeps one pack store per pass, so each requested pack shard is loaded at most once, and builds an in-memory index for the legacy fallback directory. It also shares a single content-hash memoization map across all VerifyClosure calls in the pass.
The returned `hits` slice has one entry per hit with `FilePath` already set to the canonical path (synthesized if the stored entry was written for a content-identical but differently-named file). The `misses` slice contains the subset of `paths` that need to be sent to krit-types.
func ClassifyFilesScoped ¶
func ClassifyFilesScoped(cacheDir string, paths []string, callFilterFingerprint string) (hits []*CacheEntry, misses []string)
func ClassifyFilesScopedV2 ¶
func ClassifyFilesScopedV2(cacheDir string, paths []string, callFilterFingerprint, declarationProfileFingerprint string) (hits []*CacheEntry, misses []string)
func ClassifyFilesWithStore ¶
func ClassifyFilesWithStore(s *store.FileStore, cacheDir string, paths []string) (hits []*CacheEntry, misses []string)
ClassifyFilesWithStore is like ClassifyFiles but reads from s instead of the legacy cacheDir layout. Falls back to ClassifyFiles(cacheDir, paths) when s is nil.
func ClassifyFilesWithStoreScopedV2 ¶
func ClassifyFilesWithStoreScopedV2(s *store.FileStore, cacheDir string, paths []string, callFilterFingerprint, declarationProfileFingerprint string) (hits []*CacheEntry, misses []string)
ClassifyFilesWithStoreScopedV2 is ClassifyFilesWithStoreScoped extended with the declaration profile fingerprint. Entries are treated as hits only when both the call filter and declaration profile scopes are compatible; the usual "empty fingerprint = broad superset" rule applies to both axes.
func LoadEntry ¶
func LoadEntry(cacheDir, hash string) (*CacheEntry, error)
LoadEntry reads and parses a cache entry from the packed backend, falling back to the legacy per-entry JSON file if the pack is missing or corrupt. Returns (nil, nil) if neither backend has the entry. Corrupt JSON returns an error so the caller can degrade to a miss.
func LoadEntryFromStore ¶
func LoadEntryFromStore(s *store.FileStore, contentHash string) (*CacheEntry, error)
LoadEntryFromStore retrieves a CacheEntry from s by content hash. Returns (nil, nil) on a miss. Treats any malformed value as a miss.
type CacheWriter ¶
type CacheWriter struct {
// contains filtered or unexported fields
}
CacheWriter defers per-file oracle cache-entry writes out of the caller's critical path. It keeps entry-level counters on top of the generic async writer, whose stats are job-oriented.
func NewCacheWriter ¶
func NewCacheWriter(workers int) *CacheWriter
NewCacheWriter starts a bounded writer for oracle cache entries. Worker counts below one are clamped and counts above four are capped to keep cold-cache persistence from competing too aggressively with analysis work.
func (*CacheWriter) AddPerfEntries ¶
func (w *CacheWriter) AddPerfEntries(t perf.Tracker, storeBacked bool)
func (*CacheWriter) Close ¶
func (w *CacheWriter) Close() error
func (*CacheWriter) Flush ¶
func (w *CacheWriter) Flush(ctx context.Context) error
Flush waits for queued writes to finish. A canceled context returns early, but the underlying writer continues draining in its goroutine.
func (*CacheWriter) QueueFreshEntries ¶
func (w *CacheWriter) QueueFreshEntries(cacheDir string, fresh *Data, deps *CacheDepsFile) (int, error)
QueueFreshEntries queues fresh oracle cache entries. If the writer is nil, the existing synchronous path is used.
func (*CacheWriter) QueueFreshEntriesToStore ¶
func (w *CacheWriter) QueueFreshEntriesToStore(s *store.FileStore, cacheDir string, fresh *Data, deps *CacheDepsFile) (int, error)
QueueFreshEntriesToStore queues fresh oracle cache entries, writing to the unified store when s is non-nil. Queue saturation falls back to running that batch synchronously so cache persistence remains best-effort complete.
func (*CacheWriter) QueueFreshEntriesToStoreScoped ¶
func (w *CacheWriter) QueueFreshEntriesToStoreScoped(s *store.FileStore, cacheDir string, fresh *Data, deps *CacheDepsFile, callFilterFingerprint string) (int, error)
QueueFreshEntriesToStoreScoped is QueueFreshEntriesToStore with cache compatibility metadata for filtered oracle call-target output.
func (*CacheWriter) QueueFreshEntriesToStoreScopedV2 ¶
func (w *CacheWriter) QueueFreshEntriesToStoreScopedV2(s *store.FileStore, cacheDir string, fresh *Data, deps *CacheDepsFile, callFilterFingerprint, declarationProfileFingerprint string) (int, error)
QueueFreshEntriesToStoreScopedV2 extends QueueFreshEntriesToStoreScoped with the declaration profile fingerprint. Entries written here carry both scope fingerprints so classify lookups can gate on either axis.
func (*CacheWriter) Stats ¶
func (w *CacheWriter) Stats() CacheWriterStats
type CacheWriterStats ¶
type CacheWriterStats struct {
Queued int64
Completed int64
Failed int64
Bytes int64
PoisonWrites int64
DepPaths int64
UniqueDepPaths int64
ContentHashDuration time.Duration
ClosureFingerprintTime time.Duration
MarshalDuration time.Duration
StorePutDuration time.Duration
AtomicWriteDuration time.Duration
PackWrites int64
}
CacheWriterStats is a point-in-time snapshot of deferred oracle cache writes. Durations are aggregate worker time, not wall-clock flush duration.
type CallTargetFilterSummary ¶
type CallTargetFilterSummary struct {
Enabled bool
DisabledBy []string
CalleeNames []string
TargetFQNs []string
LexicalHintsByCallee map[string][]string
LexicalSkipByCallee map[string][]string
RuleProfiles []CallTargetRuleProfile
Fingerprint string
}
CallTargetFilterSummary is the Go-side contract for narrowing JVM resolveToCall() work. Enabled=false means at least one active rule needs broad call targets, so krit-types must preserve the pre-filter behavior.
func FinalizeCallTargetFilter ¶
func FinalizeCallTargetFilter(summary CallTargetFilterSummary) CallTargetFilterSummary
FinalizeCallTargetFilter sorts, deduplicates, derives simple callee names from FQNs, and computes a stable fingerprint. Callers that build summaries directly should run this before writing or passing the filter onward.
type CallTargetRuleProfile ¶
type CallTargetRuleProfile struct {
RuleID string `json:"ruleID"`
AllCalls bool `json:"allCalls"`
DiscardedOnly bool `json:"discardedOnly,omitempty"`
CalleeNames []string `json:"calleeNames,omitempty"`
TargetFQNs []string `json:"targetFQNs,omitempty"`
LexicalHintsByCallee map[string][]string `json:"lexicalHintsByCallee,omitempty"`
LexicalSkipByCallee map[string][]string `json:"lexicalSkipByCallee,omitempty"`
AnnotatedIdentifiers []string `json:"annotatedIdentifiers,omitempty"`
DerivedCalleeNames []string `json:"derivedCalleeNames,omitempty"`
DisabledReason string `json:"disabledReason,omitempty"`
}
CallTargetRuleProfile carries per-rule filtering metadata. The JVM uses these profiles to decide whether a matching lexical call site should be resolved, so they are part of the effective filter fingerprint.
type Class ¶
type Class struct {
FQN string `json:"fqn"`
Kind string `json:"kind"` // class, interface, object, enum, sealed class, sealed interface
Supertypes []string `json:"supertypes"`
IsSealed bool `json:"isSealed"`
IsData bool `json:"isData"`
IsOpen bool `json:"isOpen"`
IsAbstract bool `json:"isAbstract"`
Visibility string `json:"visibility"`
TypeParameters []string `json:"typeParameters,omitempty"`
Members []*Member `json:"members,omitempty"`
Annotations []string `json:"annotations,omitempty"` // FQNs
Line int `json:"line,omitempty"` // 1-based source line when known
Column int `json:"column,omitempty"` // 1-based source column when known
JARPath string `json:"jarPath,omitempty"` // dependency JAR containing this class, when known
}
Class describes a class, interface, object, or enum.
type CompositeResolver ¶
type CompositeResolver struct {
// contains filtered or unexported fields
}
CompositeResolver wraps a Lookup oracle with a fallback TypeResolver. Oracle provides dependency types; fallback provides source-level inference.
func NewCompositeResolver ¶
func NewCompositeResolver(oracle Lookup, fallback typeinfer.TypeResolver) *CompositeResolver
NewCompositeResolver creates a resolver that checks the oracle first for dependency types and falls back to the tree-sitter resolver for source types.
func (*CompositeResolver) AnnotationValueFlat ¶
func (*CompositeResolver) ClassHierarchy ¶
func (c *CompositeResolver) ClassHierarchy(typeName string) *typeinfer.ClassInfo
ClassHierarchy checks oracle first (has dependency types), then fallback.
func (*CompositeResolver) EnumEntries ¶
func (c *CompositeResolver) EnumEntries(enumTypeName string) []string
EnumEntries checks oracle first, then fallback.
func (*CompositeResolver) Fallback ¶
func (c *CompositeResolver) Fallback() typeinfer.TypeResolver
Fallback returns the source-level TypeResolver wrapped by this composite. The dispatcher hands this out as ctx.Resolver for rules that declare TypeInfo.PreferBackend = PreferResolver so they avoid the oracle IPC for every lookup.
func (*CompositeResolver) IndexFilesParallel ¶
func (c *CompositeResolver) IndexFilesParallel(files []*scanner.File, workers int)
IndexFilesParallel delegates to the fallback resolver's indexing.
func (*CompositeResolver) IndexFilesParallelWithTracker ¶
func (*CompositeResolver) IsExceptionSubtype ¶
func (c *CompositeResolver) IsExceptionSubtype(a, b string) bool
IsExceptionSubtype checks oracle first (full hierarchy), then fallback.
func (*CompositeResolver) IsNullableFlat ¶
func (c *CompositeResolver) IsNullableFlat(idx uint32, file *scanner.File) *bool
func (*CompositeResolver) Oracle ¶
func (c *CompositeResolver) Oracle() Lookup
Oracle returns the underlying oracle Lookup, allowing rules to call LookupAnnotations, LookupCallTarget, etc. directly.
func (*CompositeResolver) ResolveByNameFlat ¶
func (c *CompositeResolver) ResolveByNameFlat(name string, idx uint32, file *scanner.File) *typeinfer.ResolvedType
func (*CompositeResolver) ResolveFlatNode ¶
func (c *CompositeResolver) ResolveFlatNode(idx uint32, file *scanner.File) *typeinfer.ResolvedType
func (*CompositeResolver) ResolveImport ¶
func (c *CompositeResolver) ResolveImport(simpleName string, file *scanner.File) string
ResolveImport checks fallback first, then oracle dependencies.
func (*CompositeResolver) SealedVariants ¶
func (c *CompositeResolver) SealedVariants(sealedTypeName string) []string
SealedVariants checks oracle first, then fallback.
type Daemon ¶
type Daemon struct {
// contains filtered or unexported fields
}
Daemon manages a long-lived krit-types JVM process for on-demand type resolution.
func ConnectOrStartDaemon ¶
func ConnectOrStartDaemon(jarPath string, sourceDirs []string, classpath []string, verbose bool) (*Daemon, error)
ConnectOrStartDaemon tries to reuse an existing persistent daemon for the given sourceDirs. Each repo has its own PID file under ~/.krit/cache/daemons/{hash}.{pid,port} so multiple daemons (one per repo) can coexist; krit invocations targeting different repos don't fight over a shared PID file. If no daemon is running (or the existing one is unresponsive), cleanStaleDaemon wipes just this repo's entry and StartDaemonWithPort starts a fresh one.
func InvokeDaemon ¶
InvokeDaemon finds the JAR and source directories, then starts a long-lived krit-types daemon process. The caller is responsible for calling Close() on the returned Daemon.
func InvokePersistentDaemon ¶
InvokePersistentDaemon finds the JAR and source directories, then either connects to an existing persistent daemon or starts a new one. The daemon survives across krit invocations and is reused via PID file + TCP port. The caller is responsible for calling Close() on the returned Daemon.
func StartDaemon ¶
func StartDaemon(jarPath string, sourceDirs []string, classpath []string, verbose bool) (*Daemon, error)
StartDaemon launches the krit-types JVM process in daemon mode.
func StartDaemonWithPort ¶
func StartDaemonWithPort(jarPath string, sourceDirs []string, classpath []string, verbose bool) (*Daemon, error)
StartDaemonWithPort launches the krit-types JVM process in daemon mode with a TCP listener. The daemon auto-assigns a port and reports it on stdout.
func StartDaemonWithPortSlot ¶
func (*Daemon) AnalyzeAll ¶
AnalyzeAll sends a full analysis request for all files.
func (*Daemon) AnalyzeAllWithCallFilter ¶
func (d *Daemon) AnalyzeAllWithCallFilter(callFilter *CallTargetFilterSummary) (*Data, error)
AnalyzeAllWithCallFilter sends a full analysis request for all files, optionally narrowing call-target resolution in the JVM oracle.
func (*Daemon) AnalyzeWithDeps ¶
func (d *Daemon) AnalyzeWithDeps(files []string) (*Data, *CacheDepsFile, error)
AnalyzeWithDeps is the cache-aware variant of Analyze. It asks the daemon to run analysis with a DepTracker instrumented per file and returns both the Data AND the per-file dep closure the Go-side cache layer needs to write fresh entries.
The response envelope has a flat shape with `result`, `errors`, and `cacheDeps` as siblings (unlike the legacy `analyze` which nests errors inside result). A missing `cacheDeps` field on a successful response is a protocol-version error — the caller should fall back to the one-shot path.
If the daemon's errors map contains any file-not-in-session entries, this method returns ErrDaemonFileNotInSession wrapping the count. The caller (typically runMissAnalysis) uses errors.Is to recognize the condition and trigger a daemon Rebuild + retry before falling through to one-shot.
func (*Daemon) AnalyzeWithDepsWithTimings ¶
func (d *Daemon) AnalyzeWithDepsWithTimings(files []string, collectTimings bool, callFilter *CallTargetFilterSummary, declarationProfile *DeclarationProfileSummary) (*Data, *CacheDepsFile, []perf.TimingEntry, error)
AnalyzeWithDepsWithTimings is AnalyzeWithDeps plus optional Kotlin-side timing entries returned by newer daemon processes.
func (*Daemon) Checkpoint ¶
Checkpoint asks the daemon to create a CRaC checkpoint. If the JDK does not support CRaC the daemon returns an error which we silently ignore.
func (*Daemon) Close ¶
Close shuts down and cleans up. For shared (reused) daemons, only the TCP connection is closed — the daemon process keeps running for future clients. For owned daemons, the process is shut down and PID files are removed.
func (*Daemon) DecompileJar ¶
DecompileJar asks krit-types to produce Kotlin source for a class resolved from the daemon's library module.
func (*Daemon) MatchesRepo ¶
MatchesRepo returns true if this Daemon was started for (or is currently connected to) a daemon whose sourceDirs fingerprint matches the given set. Used by runMissAnalysis to reject daemon reuse across krit invocations that target different repos — when the fingerprints disagree the caller falls back to one-shot for the current invocation rather than trusting a daemon whose sourceModule walks a different file set.
An empty sourcesHash (older daemon that predates Phase 3 sources tagging) always returns false so callers conservatively fall back. The old daemon keeps running for its original consumer.
func (*Daemon) Rebuild ¶
Rebuild tells the daemon to rebuild its Analysis API session (after file changes).
func (*Daemon) Release ¶
Release drops this Go-side handle to the daemon but leaves the daemon process alive. Closes the TCP connection (releasing the socket) and the log file handle. Does NOT call Shutdown, does NOT remove the PID file. The daemon stays discoverable by the next krit invocation via the per-repo PID files under ~/.krit/cache/daemons/, and eventually self-terminates on its 30-minute idle timeout (serverSocket.soTimeout in Main.kt:117-124).
This is the correct cleanup for short-lived CLI invocations that want to benefit from daemon reuse across sequential runs: Close() shuts the daemon down on exit (losing all the warmup benefit), Release() leaves it alive.
func (*Daemon) ResolveExpressionTypes ¶
func (d *Daemon) ResolveExpressionTypes(positions map[string][]ExpressionPosition) (map[string]map[ExpressionPosition]*typeinfer.ResolvedType, error)
ResolveExpressionTypes sends a batched resolveExpressionTypes RPC to the daemon and returns the resolved facts keyed by (file path, position). Positions that did not resolve to a fact are silently omitted — the caller treats absence as "no fact at this position."
On RPC error (timeout, daemon dead, malformed response), returns (nil, err); the caller should fall through to source-only inference.
type DaemonDecompiler ¶
type DaemonDecompiler struct {
Daemon *Daemon
}
type DaemonPool ¶
DaemonPool is an opt-in set of persistent krit-types daemons for parallel warm miss analysis. Slot 0 intentionally uses the legacy single-daemon PID files; additional slots use {sourcesHash}.{slot}.{pid,port}.
func ConnectOrStartDaemonPool ¶
func ConnectOrStartDaemonPool(jarPath string, sourceDirs []string, classpath []string, size int, verbose bool) (*DaemonPool, error)
ConnectOrStartDaemonPool connects or starts each requested pool slot. It is deliberately separate from ConnectOrStartDaemon so the default path keeps exactly one daemon and the old PID-file layout.
func (*DaemonPool) AnalyzeWithDepsSharded ¶
func (p *DaemonPool) AnalyzeWithDepsSharded(files []string, collectTimings bool, callFilter *CallTargetFilterSummary, declarationProfile *DeclarationProfileSummary, tracker perf.Tracker) (*Data, *CacheDepsFile, error)
func (*DaemonPool) MatchesRepo ¶
func (p *DaemonPool) MatchesRepo(sourceDirs []string) bool
func (*DaemonPool) Release ¶
func (p *DaemonPool) Release() error
type Data ¶
type Data struct {
Version int `json:"version"`
KotlinVersion string `json:"kotlinVersion"`
Files map[string]*File `json:"files"` // source file path → declarations
Dependencies map[string]*Class `json:"dependencies"` // FQN → class info from JARs
}
Data is the top-level JSON structure produced by krit-types.
func AssembleOracle ¶
func AssembleOracle(hits []*CacheEntry, fresh *Data) *Data
AssembleOracle builds an Data from a set of cache hits plus any freshly-analyzed files from a krit-types run. Dependencies are unioned across all sources, with cache hits losing to fresh data on conflict (fresh wins so a re-analysis with new classpath is reflected). Crashed (poison) entries contribute nothing — they're in `hits` only so the caller skips re-analysis, not because they have data to emit.
type DeclLocation ¶
type DeclLocation struct {
FQN string
Kind string
File string
JARPath string
Line int
Column int
Signature string
}
DeclLocation describes where a declaration was defined.
Line and Column are 1-based when known. The current oracle JSON does not emit per-declaration source positions, so Line and Column are zero until krit-types starts emitting them; File and Signature are always populated.
type DeclarationProfile ¶
type DeclarationProfile struct {
// ClassShell is the class FQN/kind/visibility/modality header. Always
// on in practice (the class result cannot be synthesized without it),
// but carried as a flag for symmetry with the Kotlin-side profile.
ClassShell bool
// Supertypes records direct supertype FQNs (excluding kotlin.Any).
Supertypes bool
// ClassAnnotations records class-level annotation FQNs.
ClassAnnotations bool
// Members gates traversal of symbol.memberScope. When false, the
// member list is returned empty regardless of the other member flags.
Members bool
// MemberSignatures gates return-type rendering and parameter-type
// extraction for each included member.
MemberSignatures bool
// MemberAnnotations records annotation FQNs on each included member.
MemberAnnotations bool
// SourceDependencyClosure keeps the library-supertype walk that feeds
// the oracle cache closure. Disabling it breaks incremental cache
// invalidation and should be reserved for experiments.
SourceDependencyClosure bool
}
DeclarationProfile gates which KAA symbol fields krit-types extracts per class/member. Extracting a smaller profile saves JVM-side time by skipping member-scope traversal, type rendering, and annotation walks that no active rule consumes.
Default zero-value is treated as "empty" — callers should construct profiles through FullDeclarationProfile() or by setting fields explicitly.
func FullDeclarationProfile ¶
func FullDeclarationProfile() DeclarationProfile
FullDeclarationProfile returns the profile that matches pre-profile extraction behavior — every field populated. A run with this profile writes cache entries with an empty DeclarationProfileFingerprint, so they satisfy any subsequent lookup (broader set satisfies narrower).
func MergeDeclarationProfiles ¶
func MergeDeclarationProfiles(profiles ...DeclarationProfile) DeclarationProfile
MergeDeclarationProfiles returns the union of the given profiles. The resulting profile contains every feature that any input contains — this is the safe default when deriving a profile from a heterogeneous rule set, since the broadest-needing rule wins.
func ParseDeclarationProfile ¶
func ParseDeclarationProfile(value string) DeclarationProfile
ParseDeclarationProfile parses the comma-separated feature string used on the CLI (and in tests). Unknown feature names are ignored. An empty input returns the zero profile, not the full profile — callers that want "no flag passed ⇒ full" must check upstream.
func (DeclarationProfile) CLIValue ¶
func (p DeclarationProfile) CLIValue() string
CLIValue returns the comma-separated feature list passed to krit-types via --declaration-profile. Returns "" for the full profile so callers can omit the flag entirely (preserving the pre-profile CLI shape).
func (DeclarationProfile) IsFull ¶
func (p DeclarationProfile) IsFull() bool
IsFull reports whether the profile is equivalent to FullDeclarationProfile. Full profiles write unfingerprinted cache entries.
type DeclarationProfileSummary ¶
type DeclarationProfileSummary struct {
Profile DeclarationProfile
Fingerprint string
}
DeclarationProfileSummary is the plumbing wrapper passed through InvocationOptions. The fingerprint is empty when the profile is full, matching the CallFilterFingerprint convention (empty = broad = satisfies any lookup).
func FinalizeDeclarationProfile ¶
func FinalizeDeclarationProfile(profile DeclarationProfile) DeclarationProfileSummary
FinalizeDeclarationProfile computes the stable fingerprint for a profile. Full profiles get an empty fingerprint so their cache entries are treated as unfiltered/broad.
type DecompileCache ¶
type DecompileCache struct {
// contains filtered or unexported fields
}
DecompileCache wraps a Decompiler with a content-addressed disk cache. JAR contents are immutable per content hash, so cached decompiles never need invalidating: a cache entry under {jar-sha}/{fqn}.kt is correct forever for that JAR's bytes.
func NewDecompileCache ¶
func NewDecompileCache(root string, source Decompiler) *DecompileCache
NewDecompileCache wires a cache rooted at root. root is created lazily on first write; callers typically point this at ".krit/jar-decompile" inside the project.
func (*DecompileCache) Get ¶
func (c *DecompileCache) Get(jarPath, fqn string) (string, error)
Get returns the decompiled source for {jarPath, fqn}, reading from disk when available and otherwise calling the underlying Decompiler and persisting the result. When the JAR file itself is missing, Get falls back to the supplied source — this is the "signature-stub" path the proposal describes for unresolved classpath entries.
func (*DecompileCache) JARMissing ¶
func (c *DecompileCache) JARMissing(jarPath string) bool
JARMissing reports whether Get has previously observed jarPath to be unreadable. The LSP server uses this to log unresolved classpath entries without spamming the log on every request.
type Decompiler ¶
Decompiler turns a {jar, fqn} pair into Kotlin-shaped source text. The production implementation will RPC into krit-types and use the Kotlin Analysis API's KotlinDecompiledLightClassSupport. Until that lands the LSP path uses a signature-stub renderer driven entirely from data the oracle already collects in Data.Dependencies — enough for editors to render a recognisable virtual document.
type Diagnostic ¶
type Diagnostic struct {
FactoryName string `json:"factoryName"` // e.g. "UNREACHABLE_CODE", "USELESS_ELVIS"
Severity string `json:"severity"` // "ERROR", "WARNING", "INFO"
Message string `json:"message"`
Line int `json:"line"` // 1-based
Col int `json:"col"` // 1-based
StartByte int `json:"startByte,omitempty"`
EndByte int `json:"endByte,omitempty"`
}
Diagnostic holds a compiler diagnostic emitted by the Kotlin Analysis API.
type ExpressionPosition ¶
ExpressionPosition identifies a single oracle expression-type query by 1-based line and column. Mirrors api.ExpressionPosition (the rule-side equivalent) so callers can convert by struct literal. Kept independent of v2 here to avoid an oracle → rules-package dependency direction.
type ExpressionType ¶
type ExpressionType struct {
Type string `json:"type"` // FQN like "kotlin.String"
Nullable bool `json:"nullable"`
StartByte int `json:"startByte,omitempty"`
EndByte int `json:"endByte,omitempty"`
CallTarget string `json:"callTarget,omitempty"` // FQN of resolved function or lexical fallback
CallTargetResolved bool `json:"callTargetResolved,omitempty"` // true when callTarget came from KAA resolution
CallTargetSuspend bool `json:"callTargetSuspend,omitempty"` // true when the resolved callable symbol is suspend
Annotations []string `json:"annotations,omitempty"` // FQNs of annotations on the resolved symbol
}
ExpressionType holds a compiler-resolved type for an expression at a source position.
type FakeOracle ¶
type FakeOracle struct {
Classes map[string]*typeinfer.ClassInfo
Sealed map[string][]string
Enums map[string][]string
Subtypes map[string][]string // type → supertypes (for IsSubtype)
Functions map[string]*typeinfer.ResolvedType
Deps map[string]*Class
Expressions map[string]map[string]*typeinfer.ResolvedType // file → ("line:col" → type)
Annotations map[string][]string // "ClassName.memberName" → annotation FQNs
CallTargets map[string]map[string]string // file → ("line:col" → call target FQN)
CallTargetSuspend map[string]map[string]bool // file → ("line:col" → suspend status for resolved call target)
CallTargetAnnotations map[string]map[string][]string // file → ("line:col" → annotation FQNs on symbol)
Diagnostics map[string][]Diagnostic // file → diagnostics
}
FakeOracle is a configurable test double for the Lookup interface. Set up responses before using in tests.
func NewFakeOracle ¶
func NewFakeOracle() *FakeOracle
NewFakeOracle creates a FakeOracle with all maps initialized.
func (*FakeOracle) Dependencies ¶
func (f *FakeOracle) Dependencies() map[string]*Class
func (*FakeOracle) IsSubtype ¶
func (f *FakeOracle) IsSubtype(a, b string) bool
func (*FakeOracle) LookupAnnotations ¶
func (f *FakeOracle) LookupAnnotations(key string) []string
func (*FakeOracle) LookupCallTarget ¶
func (f *FakeOracle) LookupCallTarget(filePath string, line, col int) string
func (*FakeOracle) LookupCallTargetAnnotations ¶
func (f *FakeOracle) LookupCallTargetAnnotations(filePath string, line, col int) []string
func (*FakeOracle) LookupCallTargetAnnotationsFlat ¶
func (f *FakeOracle) LookupCallTargetAnnotationsFlat(file *scanner.File, idx uint32) []string
func (*FakeOracle) LookupCallTargetFlat ¶
func (f *FakeOracle) LookupCallTargetFlat(file *scanner.File, idx uint32) string
func (*FakeOracle) LookupCallTargetSuspend ¶
func (f *FakeOracle) LookupCallTargetSuspend(filePath string, line, col int) (bool, bool)
func (*FakeOracle) LookupCallTargetSuspendFlat ¶
func (*FakeOracle) LookupClass ¶
func (f *FakeOracle) LookupClass(name string) *typeinfer.ClassInfo
func (*FakeOracle) LookupDiagnostics ¶
func (f *FakeOracle) LookupDiagnostics(filePath string) []Diagnostic
func (*FakeOracle) LookupDiagnosticsForFlatRange ¶
func (f *FakeOracle) LookupDiagnosticsForFlatRange(file *scanner.File, _ uint32) []Diagnostic
func (*FakeOracle) LookupEnumEntries ¶
func (f *FakeOracle) LookupEnumEntries(name string) []string
func (*FakeOracle) LookupExpression ¶
func (f *FakeOracle) LookupExpression(filePath string, line, col int) *typeinfer.ResolvedType
func (*FakeOracle) LookupExpressionFlat ¶
func (f *FakeOracle) LookupExpressionFlat(file *scanner.File, idx uint32) *typeinfer.ResolvedType
func (*FakeOracle) LookupFunction ¶
func (f *FakeOracle) LookupFunction(key string) *typeinfer.ResolvedType
func (*FakeOracle) LookupSealedVariants ¶
func (f *FakeOracle) LookupSealedVariants(name string) []string
type FallbackDecompiler ¶
type FallbackDecompiler struct {
Primary Decompiler
Fallback Decompiler
}
type File ¶
type File struct {
Package string `json:"package"`
Declarations []*Class `json:"declarations"`
Expressions map[string]*ExpressionType `json:"expressions,omitempty"` // "line:col" → type
Diagnostics []*Diagnostic `json:"diagnostics,omitempty"` // compiler diagnostics
}
File holds declarations extracted from a single source file.
type FilterRule ¶
type FilterRule struct {
// Name is the rule identifier, used only for verbose reporting.
Name string
// Filter is the rule's declared oracle filter. A nil Filter (or
// AllFiles: true) means the rule wants every file — the caller
// should set AllFiles: true explicitly when no narrowing applies.
Filter *FilterSpec
}
FilterRule is a minimal view of a rule that declared NeedsOracle. The caller (internal/rules.BuildFilterRulesV2) pre-filters the registered v2 rules and passes only oracle-needing rules here — the filter inversion (roadmap: core-infra/oracle-filter-inversion.md) means rules without NeedsOracle never reach this package.
type FilterSpec ¶
FilterSpec is an in-package mirror of api.OracleFilter. The value types are decoupled so internal/oracle does not import internal/rules. The fields match api.OracleFilter 1:1.
type FilterSummary ¶
type FilterSummary struct {
// TotalFiles is len(files).
TotalFiles int
// MarkedFiles is the number of files at least one rule wants oracle
// access on. Always <= TotalFiles.
MarkedFiles int
// AllFiles is true when any enabled rule declared AllFiles: true
// and the filter was short-circuited to the full set.
AllFiles bool
// Paths is the sorted list of absolute paths that any rule marked
// for oracle access. When AllFiles is true, Paths is nil (the caller
// should fall back to the unfiltered set).
Paths []string
// Fingerprint is a short hex-encoded SHA-256 prefix over the sorted
// Paths. It is a stable identity for the oracle input set: narrowing
// PRs can diff fingerprints to detect which files moved in or out
// without a full finding diff. Empty when AllFiles is true (the
// "full corpus" set is not fingerprinted — its identity is implicit).
Fingerprint string
}
FilterSummary describes the outcome of a filter evaluation. Returned from CollectOracleFiles so the caller can decide whether to skip the filtering round trip (no reduction) and emit a verbose log.
func CollectOracleFiles ¶
func CollectOracleFiles(rules []FilterRule, files []*scanner.File) FilterSummary
CollectOracleFiles returns the subset of files any enabled rule wants oracle access on. Rules are represented by FilterRule (the caller is expected to build this slice from api.Registry via rules.GetOracleFilter).
Matching semantics:
- If any rule has AllFiles: true, the short-circuit returns AllFiles: true and Paths: nil. Callers should treat this as "no reduction — feed the full file set to the oracle".
- Otherwise each file is marked when any rule's Identifiers list contains a substring of the file's raw bytes. bytes.Contains is conservative: false positives waste oracle work but never lose findings.
- Files that no rule marks are dropped from the returned Paths.
The returned Paths are absolute (via filepath.Abs) so that krit-types can match them against its own source tree regardless of how the caller passed them in.
type Index ¶
type Index struct {
// contains filtered or unexported fields
}
Index provides O(1) reverse lookups from FQN to declaration and references, plus O(1) expression-id to type lookups, over an assembled Data.
Index is safe for concurrent reads alongside ApplyFileUpdate / RemoveFile mutations from a single writer (typically the LSP didChange handler).
func BuildIndex ¶
BuildIndex constructs the reverse lookup from an assembled Data. One linear pass over declarations and one pass over every file's expressions.
func (*Index) ApplyFileUpdate ¶
ApplyFileUpdate replaces every entry sourced from path with entries derived from file. Passing a nil file is equivalent to RemoveFile(path). Safe to call concurrently with reads.
func (*Index) FindDeclarationByFQN ¶
func (idx *Index) FindDeclarationByFQN(fqn string) (*DeclLocation, bool)
FindDeclarationByFQN returns the declaration record for fqn.
func (*Index) FindDeclarationBySimpleName ¶
func (idx *Index) FindDeclarationBySimpleName(name string) []*DeclLocation
FindDeclarationBySimpleName returns every declaration whose FQN ends in `.name` (or whose FQN equals name for top-level declarations without a package).
func (*Index) FindReferencesByFQN ¶
func (idx *Index) FindReferencesByFQN(fqn string) []ReferenceLocation
FindReferencesByFQN returns every recorded use of fqn, including the declaration site itself. The returned slice is a copy; the caller may retain it across subsequent index mutations.
func (*Index) RemoveFile ¶
RemoveFile evicts every decl, ref, and expression entry that originated from path. Linear in the number of entries removed, not in total index size. Safe to call concurrently with reads.
type InvocationOptions ¶
type InvocationOptions struct {
Tracker perf.Tracker
CacheWriter *CacheWriter
CallFilter *CallTargetFilterSummary
ExtraJVMArgs []string
// DisableDiagnostics skips krit-types collectDiagnostics(), which is
// expensive on large projects and only needed by rules that consume
// compiler diagnostic facts.
DisableDiagnostics bool
// DeclarationProfile narrows which fields krit-types populates per
// class/member. Nil or a full profile preserves pre-profile extraction;
// narrow profiles skip KAA traversal for unused sections.
DeclarationProfile *DeclarationProfileSummary
}
InvocationOptions carries optional diagnostics for oracle invocations. A nil or disabled tracker keeps the existing low-overhead behavior.
type LazyLookup ¶
type LazyLookup struct {
// contains filtered or unexported fields
}
LazyLookup defers oracle JSON deserialization until the first semantic lookup. Warm runs with complete findings-cache hits can carry this through the resolver without paying jsonLoad at all.
func NewLazyLookup ¶
func NewLazyLookup(path string, onError func(error)) *LazyLookup
NewLazyLookup returns a Lookup backed by path. onError is called once if the load fails; nil is accepted.
func (*LazyLookup) Dependencies ¶
func (l *LazyLookup) Dependencies() map[string]*Class
func (*LazyLookup) Err ¶
func (l *LazyLookup) Err() error
Err reports the load error after a lookup attempts to load the JSON.
func (*LazyLookup) IsSubtype ¶
func (l *LazyLookup) IsSubtype(a, b string) bool
func (*LazyLookup) Loaded ¶
func (l *LazyLookup) Loaded() bool
Loaded reports whether the JSON has been deserialized successfully.
func (*LazyLookup) LookupAnnotations ¶
func (l *LazyLookup) LookupAnnotations(key string) []string
func (*LazyLookup) LookupCallTarget ¶
func (l *LazyLookup) LookupCallTarget(filePath string, line, col int) string
func (*LazyLookup) LookupCallTargetAnnotations ¶
func (l *LazyLookup) LookupCallTargetAnnotations(filePath string, line, col int) []string
func (*LazyLookup) LookupCallTargetAnnotationsFlat ¶
func (l *LazyLookup) LookupCallTargetAnnotationsFlat(file *scanner.File, idx uint32) []string
func (*LazyLookup) LookupCallTargetFlat ¶
func (l *LazyLookup) LookupCallTargetFlat(file *scanner.File, idx uint32) string
func (*LazyLookup) LookupCallTargetSuspend ¶
func (l *LazyLookup) LookupCallTargetSuspend(filePath string, line, col int) (bool, bool)
func (*LazyLookup) LookupCallTargetSuspendFlat ¶
func (*LazyLookup) LookupClass ¶
func (l *LazyLookup) LookupClass(name string) *typeinfer.ClassInfo
func (*LazyLookup) LookupDiagnostics ¶
func (l *LazyLookup) LookupDiagnostics(filePath string) []Diagnostic
func (*LazyLookup) LookupDiagnosticsForFlatRange ¶
func (l *LazyLookup) LookupDiagnosticsForFlatRange(file *scanner.File, idx uint32) []Diagnostic
func (*LazyLookup) LookupEnumEntries ¶
func (l *LazyLookup) LookupEnumEntries(name string) []string
func (*LazyLookup) LookupExpression ¶
func (l *LazyLookup) LookupExpression(filePath string, line, col int) *typeinfer.ResolvedType
func (*LazyLookup) LookupExpressionFlat ¶
func (l *LazyLookup) LookupExpressionFlat(file *scanner.File, idx uint32) *typeinfer.ResolvedType
func (*LazyLookup) LookupFunction ¶
func (l *LazyLookup) LookupFunction(key string) *typeinfer.ResolvedType
func (*LazyLookup) LookupSealedVariants ¶
func (l *LazyLookup) LookupSealedVariants(name string) []string
func (*LazyLookup) Preload ¶ added in v0.2.0
func (l *LazyLookup) Preload()
Preload kicks off the JSON deserialization in a background goroutine so the first lookup observes a warm sync.Once instead of paying the load latency itself. On large repos (Kotlin compiler: ~41 MB types.json) the deferred load was ~500 ms, surfacing in per-rule timings as whichever rule happened to fire first — Preload moves that wall time off the rule path. Idempotent: multiple Preload calls (or Preload followed by a real lookup) coalesce on the same sync.Once.
func (*LazyLookup) Stats ¶
func (l *LazyLookup) Stats() Stats
type Lookup ¶
type Lookup interface {
LookupClass(name string) *typeinfer.ClassInfo
LookupSealedVariants(name string) []string
LookupEnumEntries(name string) []string
IsSubtype(a, b string) bool
Dependencies() map[string]*Class
LookupFunction(key string) *typeinfer.ResolvedType
LookupExpression(filePath string, line, col int) *typeinfer.ResolvedType
LookupAnnotations(key string) []string
LookupCallTarget(filePath string, line, col int) string
// LookupCallTargetSuspend returns suspend-call evidence for a resolved
// callable at the given source position. The second return value is false
// when the oracle has no resolved callable metadata for the position.
LookupCallTargetSuspend(filePath string, line, col int) (bool, bool)
// LookupCallTargetAnnotations returns the annotation FQNs recorded directly
// on the resolved call-target symbol at the given source position. Unlike
// LookupAnnotations (which requires Members+MemberAnnotations in the
// declaration profile), these annotations are captured during call resolution
// and require no declaration extraction at all.
LookupCallTargetAnnotations(filePath string, line, col int) []string
LookupDiagnostics(filePath string) []Diagnostic
}
Lookup is the interface for querying oracle type information. Implementations: *Oracle (real), *FakeOracle (test double).
type Member ¶
type Member struct {
Name string `json:"name"`
Kind string `json:"kind"` // function, property
ReturnType string `json:"returnType"`
Nullable bool `json:"nullable"`
Visibility string `json:"visibility"`
IsOverride bool `json:"isOverride,omitempty"`
IsAbstract bool `json:"isAbstract,omitempty"`
Params []*Param `json:"params,omitempty"`
Annotations []string `json:"annotations,omitempty"` // FQNs
Line int `json:"line,omitempty"` // 1-based source line when known
Column int `json:"column,omitempty"` // 1-based source column when known
}
Member describes a function or property within a class.
type Oracle ¶
type Oracle struct {
// contains filtered or unexported fields
}
Oracle holds pre-computed type information from the Kotlin compiler.
func LoadFromData ¶
LoadFromData builds an Oracle from an already-parsed Data struct (e.g., from a daemon response) without reading from disk.
func (*Oracle) Dependencies ¶
Dependencies returns the raw dependency map for reporting.
func (*Oracle) IsSubtype ¶
IsSubtype checks if type a is a subtype of type b using the precomputed ancestor set. Constant-time after Load.
func (*Oracle) LookupAnnotations ¶
LookupAnnotations returns annotation FQNs for a class or member key (e.g., "ClassName" or "ClassName.memberName").
func (*Oracle) LookupCallTarget ¶
LookupCallTarget returns the FQN of the resolved call target for an expression at a specific source position (1-based line and column).
func (*Oracle) LookupCallTargetAnnotations ¶
LookupCallTargetAnnotations returns annotation FQNs recorded directly on the resolved call-target symbol at the given source position. These are captured during krit-types call resolution and require no declaration extraction.
func (*Oracle) LookupCallTargetAnnotationsFlat ¶
LookupCallTargetAnnotationsFlat returns annotations recorded on the resolved symbol for the FlatNode's byte range, falling back to line/column lookup.
func (*Oracle) LookupCallTargetFlat ¶
LookupCallTargetFlat returns the FQN of the resolved call target for a FlatNode's byte range, falling back to line/column lookup.
func (*Oracle) LookupCallTargetSuspend ¶
LookupCallTargetSuspend returns whether a KAA-resolved callable target is suspend at a specific source position. ok is false when the target is absent or came from lexical fallback rather than KAA resolution.
func (*Oracle) LookupCallTargetSuspendFlat ¶
LookupCallTargetSuspendFlat returns suspend-call evidence for the FlatNode's byte range, falling back to line/column lookup.
func (*Oracle) LookupClass ¶
LookupClass returns ClassInfo for a type by FQN or simple name.
func (*Oracle) LookupDiagnostics ¶
func (o *Oracle) LookupDiagnostics(filePath string) []Diagnostic
LookupDiagnostics returns compiler diagnostics for a source file.
func (*Oracle) LookupDiagnosticsForFlatRange ¶
func (o *Oracle) LookupDiagnosticsForFlatRange(file *scanner.File, idx uint32) []Diagnostic
LookupDiagnosticsForFlatRange returns diagnostics whose byte range is inside the FlatNode. When old oracle data has no byte ranges it falls back to row containment so existing caches remain usable.
func (*Oracle) LookupEnumEntries ¶
LookupEnumEntries returns known enum entries.
func (*Oracle) LookupExpression ¶
func (o *Oracle) LookupExpression(filePath string, line, col int) *typeinfer.ResolvedType
LookupExpression returns the compiler-resolved type for an expression at a specific source position (1-based line and column).
func (*Oracle) LookupExpressionFlat ¶
LookupExpressionFlat returns the compiler-resolved type for the FlatNode's byte range when byte-range oracle data is available, falling back to the legacy line/column lookup otherwise.
func (*Oracle) LookupFunction ¶
func (o *Oracle) LookupFunction(key string) *typeinfer.ResolvedType
LookupFunction returns the return type of a function by key (e.g., "ClassName.methodName").
func (*Oracle) LookupSealedVariants ¶
LookupSealedVariants returns known sealed variants.
func (*Oracle) SetExpressionFact ¶
func (o *Oracle) SetExpressionFact(filePath string, line, col int, t *typeinfer.ResolvedType)
SetExpressionFact injects a single resolved expression fact into the oracle's expression map. Intended to be called from the targeted- resolution pre-pass, between Oracle.Load and the start of dispatch — there are no concurrent readers of expressions during that window. Calling this concurrently with rule dispatch is undefined.
A nil type is silently ignored so callers can pass through "no fact" markers from the resolver without checking each entry.
type Param ¶
type Param struct {
Name string `json:"name"`
Type string `json:"type"`
Nullable bool `json:"nullable"`
}
Param describes a function parameter.
type ReferenceLocation ¶
ReferenceLocation is a single use of a symbol.
type SignatureStubDecompiler ¶
type SignatureStubDecompiler struct {
// Lookup returns the Class for an FQN, or nil if unknown.
Lookup func(fqn string) *Class
}
SignatureStubDecompiler renders Kotlin-shaped source from the oracle's own Dependencies map. It is deliberately schematic: it shows the kind, modifiers, supertypes, and members so a navigation result is recognisable in an editor, but it does not reconstruct method bodies. When the real KAA-backed decompiler is wired through krit-types this implementation remains useful as a fallback for entries the daemon can't resolve.
Source Files
¶
- cache.go
- cache_pack.go
- cache_writer.go
- call_filter.go
- composite.go
- daemon.go
- daemon_jvm.go
- daemon_pool.go
- daemon_protocol.go
- daemon_registry.go
- declaration_profile.go
- decompile.go
- exprresolve.go
- fake.go
- filter.go
- index.go
- instrumentation.go
- invoke.go
- invoke_cached.go
- lazy.go
- oracle.go
- process_resources.go
- reporter.go
- types.go
Directories
¶
| Path | Synopsis |
|---|---|
|
Package oracletest provides a shared contract test that every implementation of oracle.Lookup must satisfy.
|
Package oracletest provides a shared contract test that every implementation of oracle.Lookup must satisfy. |