Skip to content

Commit 2bf6dae

Browse files
committed
feat: Implement comprehensive LSP server and watch mode
- Add LSP server with Doxygen tag auto-completion and quick fixes - Introduce native file watching for watch mode using inotify for Linux - Implement polling-based file watching for other platforms - Add ignore patterns to watch mode configuration - Refactor `stig check` to `stig lsp` for explicit LSP server startup - Implement multi-line tag continuation for Doxygen docstring parser - Support escaped `@@` and `\\` characters in docstrings - Extract `@ref` from all relevant tag content in docstrings (brief, details, params, returns, etc.) - Add `@defgroup` and `@addtogroup` support for documentation grouping - Implement duplicate `@param` and `@tparam` detection in linter - Add checks for empty `@param`, `@tparam`, and `@return` descriptions - Enable per-rule severity configuration in `stig.toml` for linting rules - Add parsing for C++ `union` types - Extract `requires` clause from C++ template declarations - Extract `override`, `final`, and `pure virtual` specifiers for C++ methods - Support multiple comment styles for snippet markers (e.g., `# [anchor]`, `/* [anchor] */`, `<!-- [anchor] -->`) - Implement incremental document sync for LSP `textDocument/didChange` - Provide code actions for generating documentation stubs for undocumented entities - Provide code actions for adding missing `@param` and `@return` tags - Provide code actions for fixing mismatched parameter names in `@param` tags - Remove HTML output format generator - Extend CLI argument parsing to support dedicated `lsp` subcommand help - Update README with detailed feature list and usage examples for new features
1 parent 9027c01 commit 2bf6dae

18 files changed

Lines changed: 4695 additions & 203 deletions

README.md

Lines changed: 248 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,82 @@ Tree-sitter based C and C++ documentation generator focused on header files and
44

55
## Overview
66

7-
Stig parses C and C++ headers with Tree-sitter, extracts Doxygen-style documentation, and produces Markdown, mdBook, HTML, or JSON output. Documentation checks and linting help enforce coverage requirements, and an LSP mode provides real-time diagnostics in editors. Implementation files (`.cpp`, `.cc`, `.cxx`) are skipped automatically so documentation stays with declarations in headers (`.h`, `.hpp`, `.hxx`, `.hh`, `.H`).
7+
Stig parses C and C++ headers with Tree-sitter, extracts Doxygen-style documentation, and produces Markdown, mdBook, or JSON output. Documentation checks and linting help enforce coverage requirements, and an LSP mode provides real-time diagnostics in editors. Implementation files (`.cpp`, `.cc`, `.cxx`) are skipped automatically so documentation stays with declarations in headers (`.h`, `.hpp`, `.hxx`, `.hh`, `.H`).
88

99
## Features
1010

11-
- Header-first parsing with Tree-sitter (no libclang dependency)
12-
- Multiple output formats: Markdown, mdBook, HTML, JSON
13-
- Cross-references, snippet extraction, Mermaid diagrams, optional Godbolt links
14-
- Coverage analysis and linting with configurable thresholds
15-
- Language Server Protocol support (`stig check` with no arguments)
16-
- Watch mode with incremental caching for mdBook generation
17-
- mdBook preprocessor integration
18-
- Configurable behaviour through `stig.toml`
11+
### Core Features
12+
- **Header-first parsing** with Tree-sitter (no libclang dependency)
13+
- **Multiple output formats**: Markdown, mdBook, JSON
14+
- **Cross-references** with `@ref`, `@see`, `@copydoc` support
15+
- **Snippet extraction** from external files with multi-language comment support
16+
- **Mermaid diagrams** embedded in documentation
17+
- **Godbolt integration** for live code examples
18+
- **Coverage analysis** and **linting** with configurable thresholds
19+
- **Language Server Protocol** support for editor integration
20+
- **Watch mode** with native file watching and incremental caching
21+
- **mdBook preprocessor** integration
22+
23+
### Parser Features
24+
- Full C and C++ header parsing via Tree-sitter
25+
- **Union type** parsing and documentation
26+
- **Template support** with `requires` clause extraction
27+
- **Virtual function specifiers**: `override`, `final`, `pure virtual`
28+
- **Namespace** and **class** hierarchy tracking
29+
- **Enum** and **typedef/using** alias support
30+
31+
### Docstring Features
32+
- Standard Doxygen tags: `@brief`, `@details`, `@param`, `@tparam`, `@return`, `@retval`
33+
- Additional tags: `@throws`, `@see`, `@note`, `@warning`, `@deprecated`, `@since`, `@author`
34+
- **Multi-line tag continuation** with proper line joining
35+
- **Escaped characters**: `@@` and `\\` for literal @ and \
36+
- **Group support**: `@defgroup`, `@addtogroup`, `@ingroup`
37+
- **Cross-references**: `@ref` extraction from all tag content
38+
- **Code blocks**: `@code`/`@endcode`, `@mermaid`/`@endmermaid`
39+
- **Snippet inclusion**: `@snippet` with multi-language comment style support
40+
41+
### LSP Features
42+
- Real-time diagnostics for documentation issues
43+
- **Auto-completion** for 37 Doxygen tags with snippets
44+
- **Quick fixes** (code actions) for common issues:
45+
- Generate documentation stubs for undocumented entities
46+
- Add missing `@param` documentation
47+
- Add missing `@return` documentation
48+
- Fix mismatched parameter names
49+
- **Incremental document sync** for better performance
50+
- Dedicated `stig lsp` command for LSP server mode
51+
52+
### Linting Features
53+
- Missing documentation detection (brief, param, tparam, return)
54+
- **Duplicate `@param`** detection
55+
- **Empty description** checks
56+
- Broken cross-reference validation
57+
- **Per-rule configuration** with severity overrides:
58+
```toml
59+
[lint.rules]
60+
W001 = "ignore" # Ignore missing docs
61+
W003 = "error" # Treat missing @param as error
62+
E001 = "warning" # Downgrade param mismatch to warning
63+
```
64+
65+
### Watch Mode Features
66+
- **Native file watching** using inotify on Linux (polling fallback on other platforms)
67+
- **Ignore patterns** for filtering out build artifacts:
68+
```toml
69+
[watch]
70+
debounce_ms = 200
71+
ignore_patterns = [".git/**", "node_modules/**", "build/**", "*.o"]
72+
```
73+
- Incremental rebuilds with file caching
74+
- Automatic mdbook serve integration
75+
76+
### Snippet Comment Styles
77+
Stig supports multiple comment styles for snippet markers based on file type:
78+
- **C/C++/Zig/Rust/Go/Java/JS/TS**: `// [anchor]`
79+
- **Python/Shell/Ruby/YAML/Makefile**: `# [anchor]`
80+
- **CSS/SCSS/LESS**: `/* [anchor] */`
81+
- **HTML/XML/SVG**: `<!-- [anchor] -->`
82+
- **SQL/Lua**: `-- [anchor]`
1983

2084
## Installation
2185

@@ -55,8 +119,8 @@ stig check -f compiler include/*.h
55119
# Watch headers and regenerate mdBook output
56120
stig generate include/*.h -f mdbook -o docs/ --watch
57121

58-
# Start the LSP server for editor integration (stdin/stdout)
59-
stig check
122+
# Start the LSP server for editor integration
123+
stig lsp
60124
```
61125

62126
> Stig only processes header files. Any `.cpp`, `.cc`, or `.cxx` file is reported as skipped so that documentation remains in headers alongside declarations.
@@ -72,9 +136,9 @@ stig [OPTIONS] <INPUT_FILES>... # generate is the default subcommand
72136

73137
Common options:
74138

75-
- `-o, --output <PATH>`: Output file or directory (default: stdout for Markdown/HTML/JSON)
76-
- `-f, --format <FMT>`: `markdown`, `mdbook`, `json`, or `html` (default: `markdown`)
77-
- `--title <TITLE>`: Document title for mdBook/HTML output
139+
- `-o, --output <PATH>`: Output file or directory (default: stdout for Markdown/JSON)
140+
- `-f, --format <FMT>`: `markdown`, `mdbook`, or `json` (default: `markdown`)
141+
- `--title <TITLE>`: Document title for mdBook output
78142
- `-c, --config <FILE>`: Alternate configuration file (default: `stig.toml`)
79143
- `-w, --watch`: Watch for file changes and regenerate (mdBook only)
80144
- `--serve`: Watch plus `mdbook serve` for live preview (implies `--watch`)
@@ -101,28 +165,37 @@ Exit codes:
101165
- `1`: Errors detected (undocumented entities, invalid references)
102166
- `2`: Coverage below threshold or warnings present when `--strict` is set
103167

104-
### Language Server Protocol (LSP)
168+
### Language Server Protocol (`stig lsp`)
105169

106-
Running `stig check` with no additional arguments starts the Language Server Protocol server over standard input/output. The server reuses the same coverage and lint engines that power the CLI, so the thresholds and toggles in `stig.toml` immediately affect editor diagnostics. Only header files are analyzed; when an implementation file is opened Stig clears diagnostics to avoid false positives.
170+
```
171+
stig lsp
172+
```
173+
174+
Starts the Language Server Protocol server over standard input/output. The server provides:
107175

108-
Use any editor that supports stdio-based LSP servers. Configure it to execute `stig check` in the project root (or a directory containing `stig.toml`).
176+
- **Real-time diagnostics** for documentation issues
177+
- **Auto-completion** for Doxygen tags (`@brief`, `@param`, etc.) with snippet support
178+
- **Code actions** for quick fixes (generate doc stubs, add missing params)
179+
- **Incremental document sync** for efficient updates
180+
181+
The server reuses the same coverage and lint engines that power the CLI, so thresholds and toggles in `stig.toml` immediately affect editor diagnostics.
109182

110183
Example Neovim configuration:
111184

112185
```lua
113186
vim.lsp.start({
114187
name = "stig",
115-
cmd = { "stig", "check" },
188+
cmd = { "stig", "lsp" },
116189
root_dir = vim.fs.dirname(vim.fs.find({ "stig.toml" }, { upward = true })[1]),
117190
})
118191
```
119192

120-
Example `coc.nvim` or VS Code style command:
193+
Example VS Code / coc.nvim configuration:
121194

122195
```json
123196
{
124197
"command": "stig",
125-
"args": ["check"],
198+
"args": ["lsp"],
126199
"options": {
127200
"cwd": "${workspaceRoot}"
128201
}
@@ -132,9 +205,10 @@ Example `coc.nvim` or VS Code style command:
132205
Diagnostics include:
133206

134207
- Missing `@brief`, `@param`, `@tparam`, and `@return` documentation
208+
- Duplicate `@param` tags for the same parameter
209+
- Empty descriptions in documentation tags
135210
- Coverage failures based on the configured minimum percentage
136211
- Broken cross references or invalid snippet references
137-
- Coverage and lint warnings promoted to errors when `--strict` (or `lint.treat_warnings_as_errors`) is enabled
138212

139213
### mdBook preprocessor (`stig preprocessor`)
140214

@@ -151,7 +225,7 @@ The preprocessor reads JSON from stdin and writes JSON to stdout. It allows Stig
151225

152226
## Configuration (`stig.toml`)
153227

154-
Stig looks for `stig.toml` in the current directory. CLI flags override configuration values. A minimal example:
228+
Stig looks for `stig.toml` in the current directory. CLI flags override configuration values. A comprehensive example:
155229

156230
```toml
157231
title = "My Library API"
@@ -162,6 +236,12 @@ inputs = ["include/**/*.hpp"]
162236
generate_intro = true
163237
grouping = "by_header"
164238

239+
# Filtering options
240+
blacklist_namespace = ["detail", "internal", "impl"]
241+
blacklist_pattern = ["*_internal", "test_*"]
242+
extract_private = false
243+
extract_protected = true
244+
165245
[coverage]
166246
min_coverage = 85
167247
require_param_docs = true
@@ -173,7 +253,28 @@ enabled = true
173253
require_brief = true
174254
require_param_docs = true
175255
require_return_docs = true
256+
require_tparam_docs = true
176257
check_cross_references = true
258+
max_brief_length = 80
259+
require_brief_period = false
260+
261+
# Per-rule severity overrides
262+
[lint.rules]
263+
W001 = "ignore" # Ignore missing documentation warnings
264+
W003 = "error" # Treat missing @param as error
265+
W005 = "warning" # Missing @return as warning
266+
E001 = "info" # Param name mismatch as info
267+
268+
[watch]
269+
debounce_ms = 100
270+
ignore_patterns = [
271+
".git/**",
272+
"node_modules/**",
273+
"build/**",
274+
"zig-out/**",
275+
"*.o",
276+
"*.obj"
277+
]
177278

178279
[godbolt]
179280
enabled = true
@@ -186,21 +287,104 @@ See `config.zig` for all supported keys, including module grouping, external doc
186287

187288
## Doc comment support
188289

189-
Stig understands standard Doxygen-style tags such as `@brief`, `@details`, `@param`, `@tparam`, `@return`, `@throws`, `@see`, `@note`, `@warning`, `@deprecated`, `@since`, `@example`, and `@code`/`@endcode`. Both `@tag` and `\tag` forms are accepted. Additional commands include `@ref` for cross references, `@snippet` for embedding external code blocks, `@copydoc`, `@group`, `@page`, `@mainpage`, and `@mermaid`/`@endmermaid` for diagrams.
290+
Stig understands standard Doxygen-style tags:
291+
292+
### Basic Tags
293+
- `@brief` / `@short`: Brief description
294+
- `@details`: Detailed description
295+
- `@param` / `@p`: Parameter documentation
296+
- `@tparam`: Template parameter documentation
297+
- `@return` / `@returns`: Return value documentation
298+
- `@retval`: Specific return value documentation
299+
300+
### Semantic Tags
301+
- `@throws` / `@throw` / `@exception`: Exception documentation
302+
- `@pre`: Preconditions
303+
- `@post`: Postconditions
304+
- `@requires`: Requirements (C++20 concepts)
305+
- `@effects`: Side effects
306+
- `@complexity`: Algorithmic complexity
307+
- `@invariant`: Class invariants
308+
- `@threadsafety` / `@sync`: Thread safety notes
309+
310+
### Informational Tags
311+
- `@note`: Additional notes
312+
- `@warning`: Warning messages
313+
- `@deprecated`: Deprecation notices
314+
- `@since`: Version introduced
315+
- `@author`: Author information
316+
- `@version`: Version information
317+
- `@date`: Date information
318+
- `@copyright`: Copyright notice
319+
- `@see` / `@sa`: See also references
320+
- `@todo`: TODO items
321+
- `@bug`: Known bugs
322+
323+
### Cross-Reference Tags
324+
- `@ref`: Cross-reference to another symbol
325+
- `@copydoc`: Copy documentation from another symbol
326+
327+
### Grouping Tags
328+
- `@defgroup`: Define a documentation group
329+
- `@addtogroup`: Add to an existing group
330+
- `@ingroup`: Mark entity as belonging to a group
331+
- `@{` / `@}`: Group member markers
332+
333+
### Code Tags
334+
- `@code` / `@endcode`: Code blocks
335+
- `@snippet`: Include code from external file
336+
- `@mermaid` / `@endmermaid`: Mermaid diagrams
337+
- `@example`: Example code
338+
339+
### Other Tags
340+
- `@file`: File-level documentation
341+
- `@page` / `@mainpage`: Page documentation
342+
- `@exclude`: Exclude from documentation
343+
- `@synopsis`: Custom synopsis override
344+
- `@unique_name`: Custom anchor name
345+
346+
Both `@tag` and `\tag` forms are accepted. Multi-line continuation is supported by indentation.
190347

191348
## Watch mode and incremental builds
192349

193350
When generating mdBook output without `--force`, Stig caches file contents and parsed modules in `.stig-cache`. Only changed headers are reparsed, which keeps watch-mode rebuilds fast. Use `--force` to ignore the cache.
194351

352+
Watch mode features:
353+
- **Native file watching** using inotify on Linux for instant change detection
354+
- **Polling fallback** on other platforms (200ms interval)
355+
- **Ignore patterns** to filter out build artifacts and VCS directories
356+
- **Debouncing** to coalesce rapid changes
357+
- **Include dependency tracking** to rebuild when included headers change
358+
195359
## Linting and coverage
196360

197361
`stig check` combines coverage analysis and linting:
198362

199-
- Coverage tracks documented versus undocumented entities by type and reports missing parameter, template parameter, and return documentation.
200-
- Linting validates comment quality (brief length, missing sections, broken references). Enable strict mode to treat warnings as build failures.
363+
- **Coverage** tracks documented versus undocumented entities by type and reports missing parameter, template parameter, and return documentation.
364+
- **Linting** validates comment quality:
365+
- Brief length limits
366+
- Missing required sections
367+
- Duplicate parameter documentation
368+
- Empty descriptions
369+
- Broken cross-references
370+
- Parameter name mismatches
201371

202372
The compiler-style format (`-f compiler`) is suitable for CI systems that expect `file:line:col: severity: message` diagnostics.
203373

374+
### Lint Rules
375+
376+
| Code | Severity | Description |
377+
|------|----------|-------------|
378+
| W001 | Warning | Missing documentation |
379+
| W002 | Warning | Missing @brief |
380+
| W003 | Warning | Missing @param for parameter |
381+
| W004 | Warning | Missing @tparam for template parameter |
382+
| W005 | Warning | Missing @return for non-void function |
383+
| W006 | Warning | Empty description |
384+
| W007 | Warning | Duplicate @param |
385+
| E001 | Error | Parameter name mismatch |
386+
| E002 | Error | Broken cross-reference |
387+
204388
## GitHub Actions
205389

206390
The repository includes `.github/actions/stig-docs`, which can be used from workflows:
@@ -236,6 +420,45 @@ stig_add_docs(
236420

237421
Run `cmake --build . --target api_docs` to generate the documentation. See `cmake/README.md` for details.
238422

423+
## Recent Changes (v0.1.0)
424+
425+
### Phase 1: Cleanup & Removal
426+
- Removed HTML output generator (1055 lines deleted)
427+
- Extracted common parser utilities into shared module
428+
429+
### Phase 2: Critical Bug Fixes
430+
- Fixed `getExternalLink` URL substitution bug
431+
- Fixed Godbolt `generateSimpleUrl` encoding issues
432+
- Added include dependency tracking to cache
433+
434+
### Phase 3: Parser Enhancements
435+
- Added union type parsing
436+
- Extract `requires` clause from templates
437+
- Extract `override`/`final`/`pure virtual` specifiers
438+
- Added comprehensive C++ parser tests
439+
440+
### Phase 4: Docstring Extraction Improvements
441+
- Support multi-line tag continuation
442+
- Support escaped `@@` and `\\` characters
443+
- Extract `@ref` from all tag content
444+
- Added `@defgroup` and `@addtogroup` support
445+
446+
### Phase 5: Lint & Coverage Improvements
447+
- Added duplicate `@param` detection
448+
- Added empty description checks
449+
- Added per-rule lint configuration with severity overrides
450+
451+
### Phase 6: LSP Enhancements
452+
- Added `textDocument/completion` for 37 Doxygen tags
453+
- Added `textDocument/codeAction` for quick fixes
454+
- Added incremental document sync
455+
- Separated `stig lsp` from `stig check`
456+
457+
### Phase 7: Infrastructure & Performance
458+
- Added OS-native file watching (inotify on Linux)
459+
- Added watch mode ignore patterns
460+
- Support multiple snippet comment styles (Python, Shell, CSS, HTML, SQL, etc.)
461+
239462
## License
240463

241464
Stig is distributed under the MIT license. See `LICENSE` for the complete text.

0 commit comments

Comments
 (0)