a06f331eb8
CI / benchmark (push) Has been skipped
install-script / posix-syntax (push) Successful in 6m1s
CI / build-onnx (push) Failing after 6m43s
init-smoke / dry-run (push) Failing after 15m57s
security / govulncheck (push) Has been cancelled
security / trivy-fs (push) Has been cancelled
CI / test (1.26, ubuntu-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
CI / test (1.26, macos-latest) (push) Has been cancelled
CI / build-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
install-script / powershell-syntax (push) Has been cancelled
install-script / install (macos-14) (push) Has been cancelled
install-script / install (ubuntu-latest) (push) Has been cancelled
149 lines
6.1 KiB
Go
149 lines
6.1 KiB
Go
package semantic
|
|
|
|
import "sync"
|
|
|
|
// Config holds configuration for the semantic enrichment layer.
|
|
type Config struct {
|
|
Enabled bool `mapstructure:"enabled" yaml:"enabled"`
|
|
TimeoutSeconds int `mapstructure:"timeout_seconds" yaml:"timeout_seconds,omitempty"`
|
|
EnrichOnWatch bool `mapstructure:"enrich_on_watch" yaml:"enrich_on_watch,omitempty"`
|
|
WatchDebounceMs int `mapstructure:"watch_debounce_ms" yaml:"watch_debounce_ms,omitempty"`
|
|
RefuteUnconfirmed bool `mapstructure:"refute_unconfirmed" yaml:"refute_unconfirmed,omitempty"`
|
|
Providers []ProviderConfig `mapstructure:"providers" yaml:"providers,omitempty"`
|
|
// ExcludeGlobs lists path globs to skip for semantic enrichment, in
|
|
// addition to the built-in generated/vendored heuristic. A file matching
|
|
// any glob is not enriched and does not count toward a repo's present
|
|
// languages (so a language server is not spawned for a repo whose only
|
|
// files of that language are excluded).
|
|
ExcludeGlobs []string `mapstructure:"exclude_globs" yaml:"exclude_globs,omitempty"`
|
|
// LSPSweep mirrors config.SemanticConfig.LSPSweep — the per-file LSP
|
|
// enrichment sweep mode ("demand" default / "full" / "off"). Threaded to
|
|
// each spawned LSP provider via the router's WithEnrichSweepMode. The
|
|
// GORTEX_LSP_SWEEP env override wins over it at enrichment time.
|
|
LSPSweep string `mapstructure:"lsp_sweep" yaml:"lsp_sweep,omitempty"`
|
|
// EagerLSP runs the subprocess LSP servers during the synchronous
|
|
// enrichment pass. Default false: LSP is the slowest part of a cold index
|
|
// (a full gopls/tsserver/rust-analyzer/pyright sweep can run for minutes to
|
|
// hours) and its net-new value over the in-process tiers is narrow — a Go
|
|
// module is served by go-types, and every language has the tree-sitter
|
|
// floor. With this off, cold/warm start pays only the fast in-process
|
|
// providers; the LSP router stays available so a query can still lazy-spawn
|
|
// a server on demand. Set true (or GORTEX_LSP_EAGER=1) to restore the
|
|
// pre-change eager behaviour.
|
|
EagerLSP bool `mapstructure:"eager_lsp" yaml:"eager_lsp,omitempty"`
|
|
}
|
|
|
|
// ProviderConfig holds configuration for a single semantic provider.
|
|
type ProviderConfig struct {
|
|
Name string `mapstructure:"name" yaml:"name"`
|
|
Command string `mapstructure:"command" yaml:"command,omitempty"`
|
|
Args []string `mapstructure:"args" yaml:"args,omitempty"`
|
|
Languages []string `mapstructure:"languages" yaml:"languages"`
|
|
Priority int `mapstructure:"priority" yaml:"priority,omitempty"`
|
|
Enabled bool `mapstructure:"enabled" yaml:"enabled"`
|
|
Mode string `mapstructure:"mode" yaml:"mode,omitempty"` // "typecheck" or "callgraph" for go-types
|
|
Daemon bool `mapstructure:"daemon" yaml:"daemon,omitempty"`
|
|
MaxParallel int `mapstructure:"max_parallel" yaml:"max_parallel,omitempty"`
|
|
// Env adds KEY=VALUE environment entries to the provider's LSP
|
|
// subprocess (e.g. JAVA_HOME for jdtls).
|
|
Env []string `mapstructure:"env" yaml:"env,omitempty"`
|
|
// Connect, when non-nil, switches this provider from spawning a
|
|
// subprocess to dialing an already-running LSP endpoint (e.g.
|
|
// the user's IDE-managed gopls). Carrier is tcp or unix.
|
|
Connect *ConnectConfig `mapstructure:"connect" yaml:"connect,omitempty"`
|
|
}
|
|
|
|
// ConnectConfig is the per-provider passive-attach block used by the
|
|
// semantic-layer Config struct. The cmd/gortex/* boot code copies it
|
|
// onto the matching lsp.ConnectSpec at router-registration time. Kept
|
|
// here rather than in lsp/* to avoid a circular import (lsp depends
|
|
// on semantic for EnrichResult).
|
|
type ConnectConfig struct {
|
|
Network string `mapstructure:"network" yaml:"network"`
|
|
Address string `mapstructure:"address" yaml:"address"`
|
|
FallbackSpawn bool `mapstructure:"fallback_spawn" yaml:"fallback_spawn,omitempty"`
|
|
}
|
|
|
|
// DefaultConfig returns a default semantic config with auto-detection enabled.
|
|
//
|
|
// The order matters: per-language priority sorts ascending, so go-types
|
|
// (priority 1) wins for Go even when scip-go and gopls are also
|
|
// available. Every known LSP server is enumerated via
|
|
// RegisterDefaultProviders so that, when its binary is on PATH, the
|
|
// daemon spins it up automatically without users editing
|
|
// `.gortex.yaml`.
|
|
func DefaultConfig() Config {
|
|
cfg := Config{
|
|
Enabled: true,
|
|
TimeoutSeconds: 120,
|
|
EnrichOnWatch: false,
|
|
WatchDebounceMs: 500,
|
|
RefuteUnconfirmed: false,
|
|
Providers: []ProviderConfig{
|
|
{
|
|
Name: "go-types",
|
|
Languages: []string{"go"},
|
|
Priority: 1,
|
|
Enabled: true,
|
|
Mode: "typecheck",
|
|
},
|
|
{
|
|
Name: "scip-go",
|
|
Command: "scip-go",
|
|
Languages: []string{"go"},
|
|
Priority: 2,
|
|
Enabled: true,
|
|
},
|
|
{
|
|
Name: "scip-typescript",
|
|
Command: "scip-typescript",
|
|
Args: []string{"index", "--infer-tsconfig"},
|
|
Languages: []string{"typescript", "javascript"},
|
|
Priority: 1,
|
|
Enabled: true,
|
|
},
|
|
{
|
|
Name: "scip-python",
|
|
Command: "scip-python",
|
|
Languages: []string{"python"},
|
|
Priority: 1,
|
|
Enabled: true,
|
|
},
|
|
},
|
|
}
|
|
cfg.Providers = append(cfg.Providers, defaultLSPProviders()...)
|
|
return cfg
|
|
}
|
|
|
|
// defaultLSPProviders returns LSP-flavored ProviderConfig entries
|
|
// contributed by sub-packages via RegisterDefaultProviders. The
|
|
// `internal/semantic/lsp` package registers its `Servers` list at
|
|
// init time. The indirection avoids a circular import — lsp depends
|
|
// on semantic for EnrichResult etc.
|
|
func defaultLSPProviders() []ProviderConfig {
|
|
defaultRegMu.RLock()
|
|
defer defaultRegMu.RUnlock()
|
|
out := make([]ProviderConfig, 0)
|
|
for _, fn := range defaultRegistrations {
|
|
out = append(out, fn()...)
|
|
}
|
|
return out
|
|
}
|
|
|
|
// RegisterDefaultProviders lets sub-packages contribute provider entries
|
|
// to DefaultConfig. Each registered function is called when DefaultConfig
|
|
// is invoked. Registration order is preserved.
|
|
func RegisterDefaultProviders(fn func() []ProviderConfig) {
|
|
if fn == nil {
|
|
return
|
|
}
|
|
defaultRegMu.Lock()
|
|
defaultRegistrations = append(defaultRegistrations, fn)
|
|
defaultRegMu.Unlock()
|
|
}
|
|
|
|
var (
|
|
defaultRegMu sync.RWMutex
|
|
defaultRegistrations []func() []ProviderConfig
|
|
)
|