Skip to main content

lean_ctx/core/config/
semantic.rs

1// SPDX-License-Identifier: Apache-2.0
2//! Semantic code-intelligence mode (`semantic_mode` in `config.toml`).
3
4use serde::{Deserialize, Serialize};
5
6use super::Config;
7
8/// How the code graph uses local semantic backends (language servers, a live
9/// JetBrains IDE) on top of the always-on tree-sitter structure.
10/// - `off`: structural only; no semantic backend is ever queried.
11/// - `auto`: (Default) background enrichment uses only backends already
12///   running — a warm language server or a live IDE — and never spawns one.
13/// - `eager`: background enrichment may start the project's language servers.
14#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
15#[serde(rename_all = "lowercase")]
16pub enum SemanticMode {
17    Off,
18    #[default]
19    Auto,
20    Eager,
21}
22
23impl SemanticMode {
24    pub fn from_env() -> Option<Self> {
25        std::env::var("LEAN_CTX_SEMANTIC_MODE").ok().and_then(|v| {
26            match v.trim().to_lowercase().as_str() {
27                "off" => Some(Self::Off),
28                "auto" => Some(Self::Auto),
29                "eager" => Some(Self::Eager),
30                _ => None,
31            }
32        })
33    }
34
35    pub fn effective(config: &Config) -> Self {
36        Self::from_env().unwrap_or(config.semantic_mode)
37    }
38
39    /// Effective mode for `project_root` specifically (its own, trust-gated
40    /// `.lean-ctx.toml`), independent of the process's working directory.
41    ///
42    /// `eager` lets background work start the project's language servers,
43    /// which execute project code (build scripts, proc macros). Whatever
44    /// requested it — global config, `LEAN_CTX_SEMANTIC_MODE`, or the
45    /// project — it applies only to a trusted workspace (`lean-ctx trust`);
46    /// an untrusted one runs as `auto`. Explicit tools such as `ctx_refactor`
47    /// are unaffected.
48    pub fn for_project(project_root: &str) -> Self {
49        let mode = Self::from_env()
50            .unwrap_or_else(|| Config::load_for_project_root(project_root).semantic_mode);
51        if mode == Self::Eager
52            && !crate::core::workspace_trust::is_trusted(std::path::Path::new(project_root))
53        {
54            return Self::Auto;
55        }
56        mode
57    }
58}