Skip to content

Commit 0b1f3af

Browse files
authored
Merge pull request #59 from sonesuke/feat/lsp-realtime-diagnostics
feat(lsp): implement real-time diagnostics and decouple core
2 parents cba014a + 75c14c3 commit 0b1f3af

12 files changed

Lines changed: 127 additions & 23 deletions

File tree

.devcontainer/Dockerfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ COPY Cargo.toml Cargo.lock ./
3535
RUN echo "fn main() {}" > src/main.rs \
3636
&& echo "fn main() {}" > benches/performance.rs \
3737
&& cargo build --release \
38+
&& cargo build \
3839
&& cd / && rm -rf /tmp/build
3940

4041
# Install cargo-binstall as vscode

.github/workflows/ci.yml

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ env:
1111

1212
permissions:
1313
contents: read
14+
packages: read
1415

1516
jobs:
1617
lint:
@@ -19,11 +20,18 @@ jobs:
1920
steps:
2021
- uses: actions/checkout@v4
2122

23+
- name: Log in to GitHub Container Registry
24+
uses: docker/login-action@v3
25+
with:
26+
registry: ghcr.io
27+
username: ${{ github.actor }}
28+
password: ${{ secrets.GITHUB_TOKEN }}
29+
2230
- name: Build and Run Dev Container (Lint)
2331
uses: devcontainers/ci@v0.3
2432
with:
25-
imageName: docgraph-dev
26-
cacheFrom: docgraph-dev
33+
imageName: ghcr.io/${{ github.repository }}/docgraph-dev
34+
cacheFrom: ghcr.io/${{ github.repository }}/docgraph-dev
2735
push: never
2836
runCmd: |
2937
cargo fmt -- --check
@@ -38,11 +46,18 @@ jobs:
3846
steps:
3947
- uses: actions/checkout@v4
4048

49+
- name: Log in to GitHub Container Registry
50+
uses: docker/login-action@v3
51+
with:
52+
registry: ghcr.io
53+
username: ${{ github.actor }}
54+
password: ${{ secrets.GITHUB_TOKEN }}
55+
4156
- name: Build and Run Dev Container (Test)
4257
uses: devcontainers/ci@v0.3
4358
with:
44-
imageName: docgraph-dev
45-
cacheFrom: docgraph-dev
59+
imageName: ghcr.io/${{ github.repository }}/docgraph-dev
60+
cacheFrom: ghcr.io/${{ github.repository }}/docgraph-dev
4661
push: never
4762
runCmd: |
4863
cargo llvm-cov --all-features --workspace --lcov --output-path lcov.info

Cargo.lock

Lines changed: 16 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ thiserror = "2.0"
1616
toml = "0.9.11"
1717
tower-lsp = "0.20.0"
1818
tokio = { version = "1.37.0", features = ["full"] }
19+
dashmap = "6.1.0"
1920

2021
[dev-dependencies]
2122
tempfile = "3.24.0"

src/cli/handlers/check.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ fn try_check(
2222
) -> anyhow::Result<ExitCode> {
2323
let config = config::Config::load(&path).context("failed to load docgraph.toml")?;
2424

25-
let diagnostics = lint::check_workspace(&path, fix, rule, true, &config);
25+
let diagnostics = lint::check_workspace(&path, fix, rule, true, &config, None);
2626

2727
if json {
2828
let json_out = serde_json::to_string_pretty(&diagnostics)
@@ -89,7 +89,7 @@ pub fn handle_fmt(path: PathBuf, rule: Option<Vec<String>>) -> ExitCode {
8989

9090
fn try_fmt(path: PathBuf, rule: Option<Vec<String>>) -> anyhow::Result<ExitCode> {
9191
let config = config::Config::load(&path).context("failed to load docgraph.toml")?;
92-
let diagnostics = lint::check_workspace(&path, true, rule, false, &config);
92+
let diagnostics = lint::check_workspace(&path, true, rule, false, &config, None);
9393
print_diagnostics(&diagnostics);
9494
Ok(ExitCode::SUCCESS)
9595
}

src/cli/handlers/describe.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pub fn handle_describe(id: String, path: PathBuf) -> ExitCode {
1515

1616
fn try_describe(id: String, path: PathBuf) -> anyhow::Result<ExitCode> {
1717
let config = config::Config::load(&path).context("failed to load docgraph.toml")?;
18-
let (blocks, _refs) = collect::collect_workspace_all(&path, &config.graph.ignore);
18+
let (blocks, _refs) = collect::collect_workspace_all(&path, &config.graph.ignore, None);
1919

2020
let target_block = blocks
2121
.iter()

src/cli/handlers/graph.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pub fn handle_graph(path: PathBuf) -> ExitCode {
1515

1616
fn try_graph(path: PathBuf) -> anyhow::Result<ExitCode> {
1717
let config = config::Config::load(&path).context("failed to load docgraph.toml")?;
18-
let (blocks, _refs) = collect::collect_workspace_all(&path, &config.graph.ignore);
18+
let (blocks, _refs) = collect::collect_workspace_all(&path, &config.graph.ignore, None);
1919
let json_out =
2020
serde_json::to_string_pretty(&blocks).context("failed to serialize graph to JSON")?;
2121
println!("{}", json_out);

src/cli/handlers/list.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ pub fn handle_list(query: String, path: PathBuf) -> ExitCode {
1616

1717
fn try_list(query: String, path: PathBuf) -> anyhow::Result<ExitCode> {
1818
let config = config::Config::load(&path).context("failed to load docgraph.toml")?;
19-
let (blocks, _refs) = collect::collect_workspace_all(&path, &config.graph.ignore);
19+
let (blocks, _refs) = collect::collect_workspace_all(&path, &config.graph.ignore, None);
2020
let regex_str = glob_to_regex(&query);
2121
let re = regex::Regex::new(&regex_str)
2222
.with_context(|| format!("Invalid query pattern: '{}'", query))?;

src/cli/handlers/trace.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ fn try_trace(
2121
direction: String,
2222
) -> anyhow::Result<ExitCode> {
2323
let config = config::Config::load(&path).context("failed to load docgraph.toml")?;
24-
let (blocks, _refs) = collect::collect_workspace_all(&path, &config.graph.ignore);
24+
let (blocks, _refs) = collect::collect_workspace_all(&path, &config.graph.ignore, None);
2525
let target_regex_str = glob_to_regex(&to);
2626
let target_re = regex::Regex::new(&target_regex_str)
2727
.with_context(|| format!("Invalid target pattern: '{}'", to))?;

src/core/collect.rs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,33 @@
11
use crate::core::parse::extract_all;
22
use crate::core::types::{RefUse, SpecBlock};
33
use crate::core::walk::find_markdown_files;
4+
use std::collections::HashMap;
45
use std::fs;
5-
use std::path::Path;
6+
use std::path::{Path, PathBuf};
67

78
/// Collect all SpecBlocks and standalone RefUses from the workspace
89
pub fn collect_workspace_all(
910
root: &Path,
1011
ignore_patterns: &[String],
12+
overrides: Option<&HashMap<PathBuf, String>>,
1113
) -> (Vec<SpecBlock>, Vec<RefUse>) {
1214
let files = find_markdown_files(root, ignore_patterns);
1315
let mut all_blocks = Vec::new();
1416
let mut all_refs = Vec::new();
1517

1618
for file_path in files {
17-
match fs::read_to_string(&file_path) {
19+
// Canonicalize the path for lookup to match the keys in overrides
20+
let lookup_path = fs::canonicalize(&file_path).unwrap_or_else(|_| file_path.clone());
21+
22+
let content_result = if let Some(map) = overrides
23+
&& let Some(content) = map.get(lookup_path.as_path())
24+
{
25+
Ok(content.clone())
26+
} else {
27+
fs::read_to_string(&file_path)
28+
};
29+
30+
match content_result {
1831
Ok(content) => {
1932
let (blocks, refs) = extract_all(&content, &file_path);
2033
all_blocks.extend(blocks);
@@ -40,7 +53,7 @@ mod tests {
4053
let mut file = File::create(&file_path).unwrap();
4154
writeln!(file, "<a id=\"ID-1\"></a>\n# Heading\n[Ref](#ID-2)").unwrap();
4255

43-
let (blocks, refs) = collect_workspace_all(dir.path(), &[]);
56+
let (blocks, refs) = collect_workspace_all(dir.path(), &[], None);
4457

4558
assert_eq!(blocks.len(), 1);
4659
assert_eq!(blocks[0].id, "ID-1");

0 commit comments

Comments
 (0)