Skip to content

Commit e63a27a

Browse files
feat(docs): code analysis engine
changes: - file: config.py area: config modified: [Code2LlmConfig, to_yaml, Code2DocsConfig, from_yaml] - file: code2llm_gen.py area: docs added: [parse_gitignore] modified: [_run_code2llm, Code2LlmGenerator] stats: lines: "+44110/-547 (net +43563)" files: 31 complexity: "Large structural change (normalized)"
1 parent 917a185 commit e63a27a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+44142
-551
lines changed

CHANGELOG.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,34 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [0.2.10] - 2026-03-08
11+
12+
### Docs
13+
- Update CONTRIBUTING.md
14+
- Update README.md
15+
- Update code2docs/README.md
16+
- Update code2docs/project/README.md
17+
- Update code2docs/project/context.md
18+
- Update docs/api.md
19+
- Update docs/architecture.md
20+
- Update docs/configuration.md
21+
- Update docs/coverage.md
22+
- Update docs/dependency-graph.md
23+
- ... and 3 more files
24+
25+
### Other
26+
- Update code2docs/config.py
27+
- Update code2docs/generators/code2llm_gen.py
28+
- Update code2docs/project/analysis.json
29+
- Update code2docs/project/analysis.toon
30+
- Update code2docs/project/analysis.yaml
31+
- Update code2docs/project/calls.mmd
32+
- Update code2docs/project/compact_flow.mmd
33+
- Update code2docs/project/dashboard.html
34+
- Update code2docs/project/evolution.toon
35+
- Update code2docs/project/flow.mmd
36+
- ... and 23 more files
37+
1038
## [0.2.9] - 2026-03-07
1139

1240
## [0.2.8] - 2026-03-07

CONTRIBUTING.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Contributing to code2docs
2+
3+
## Development Setup
4+
5+
```bash
6+
git clone <repository-url>
7+
cd code2docs
8+
python -m venv .venv
9+
source .venv/bin/activate # or .venv\Scripts\activate on Windows
10+
pip install -e ".[dev]"
11+
```
12+
13+
## Development Workflow
14+
15+
1. Create a feature branch from `main`
16+
2. Make your changes
17+
3. Add or update tests
18+
4. Run the test suite
19+
5. Submit a pull request
20+
21+
## Testing
22+
23+
```bash
24+
# Run all tests
25+
pytest
26+
27+
# Run with coverage
28+
pytest --cov --cov-report=term-missing
29+
30+
# Run a specific test file
31+
pytest tests/test_specific.py -v
32+
```
33+
34+
## Code Style
35+
36+
- **Formatting:** [Black](https://black.readthedocs.io/)`black .`
37+
- **Linting:** [Ruff](https://docs.astral.sh/ruff/)`ruff check .`
38+
- **Type checking:** [mypy](https://mypy.readthedocs.io/)`mypy .`
39+
40+
## Pull Request Guidelines
41+
42+
- Keep PRs focused — one feature or fix per PR
43+
- Include tests for new functionality
44+
- Update documentation if needed
45+
- Ensure all tests pass before submitting
46+
- Use descriptive commit messages

README.md

Lines changed: 518 additions & 33 deletions
Large diffs are not rendered by default.

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.2.9
1+
0.2.10

code2docs/README.md

Lines changed: 734 additions & 2 deletions
Large diffs are not rendered by default.

code2docs/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
README.md, API references, module docs, examples, and architecture diagrams.
66
"""
77

8-
__version__ = "0.2.9"
8+
__version__ = "0.2.10"
99
__author__ = "Tom Sapletta"
1010

1111
from .config import Code2DocsConfig

code2docs/config.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,17 @@ class Code2LlmConfig:
6262
output_dir: str = "project" # Relative to project root
6363
chunk: bool = False # Enable chunking for large repos
6464
no_png: bool = True # Skip PNG generation (faster)
65+
max_depth: int = 3 # Maximum directory depth to scan (default 3 levels)
66+
exclude_patterns: List[str] = field(default_factory=lambda: [
67+
"venv", ".venv", "env", ".env",
68+
"node_modules", "bower_components",
69+
"__pycache__", ".pytest_cache", ".mypy_cache",
70+
".git", ".hg", ".svn",
71+
"dist", "build", "target", "out",
72+
".tox", ".eggs", "*.egg-info",
73+
"vendor", "third_party", "third-party",
74+
"site-packages", "lib/python*",
75+
]) # Patterns to exclude from scanning
6576

6677

6778
@dataclass
@@ -214,6 +225,17 @@ def from_yaml(cls, path: str) -> "Code2DocsConfig":
214225
output_dir=code2llm_data.get("output_dir", "project"),
215226
chunk=code2llm_data.get("chunk", False),
216227
no_png=code2llm_data.get("no_png", True),
228+
max_depth=code2llm_data.get("max_depth", 3),
229+
exclude_patterns=code2llm_data.get("exclude_patterns", [
230+
"venv", ".venv", "env", ".env",
231+
"node_modules", "bower_components",
232+
"__pycache__", ".pytest_cache", ".mypy_cache",
233+
".git", ".hg", ".svn",
234+
"dist", "build", "target", "out",
235+
".tox", ".eggs", "*.egg-info",
236+
"vendor", "third_party", "third-party",
237+
"site-packages", "lib/python*",
238+
]),
217239
)
218240

219241
return config
@@ -266,6 +288,8 @@ def to_yaml(self, path: str) -> None:
266288
"output_dir": self.code2llm.output_dir,
267289
"chunk": self.code2llm.chunk,
268290
"no_png": self.code2llm.no_png,
291+
"max_depth": self.code2llm.max_depth,
292+
"exclude_patterns": self.code2llm.exclude_patterns,
269293
},
270294
}
271295
with open(path, "w", encoding="utf-8") as f:

code2docs/generators/code2llm_gen.py

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,63 @@
22

33
import subprocess
44
from pathlib import Path
5-
from typing import List, Optional, Dict
5+
from typing import List, Optional, Dict, Set
66

77
from code2llm.api import AnalysisResult
88

99
from ..config import Code2DocsConfig
1010

1111

12+
def parse_gitignore(project_path: Path) -> List[str]:
13+
"""Parse .gitignore file and return list of patterns to exclude.
14+
15+
Filters out:
16+
- Empty lines
17+
- Comments (lines starting with #)
18+
- Negation patterns (starting with !)
19+
- Complex patterns with ** or regex
20+
21+
Returns simple directory/file patterns that can be passed to --skip-subprojects.
22+
"""
23+
gitignore_path = project_path / ".gitignore"
24+
if not gitignore_path.exists():
25+
return []
26+
27+
patterns = []
28+
try:
29+
content = gitignore_path.read_text(encoding="utf-8")
30+
for line in content.split("\n"):
31+
line = line.strip()
32+
# Skip empty lines and comments
33+
if not line or line.startswith("#"):
34+
continue
35+
# Skip negation patterns (too complex)
36+
if line.startswith("!"):
37+
continue
38+
# Skip patterns with ** (globstar - too complex)
39+
if "**" in line:
40+
continue
41+
# Skip file-specific patterns (with wildcards)
42+
if "*" in line and "/" not in line:
43+
# Wildcard without path - likely file pattern, skip
44+
continue
45+
# Clean up the pattern
46+
pattern = line.rstrip("/") # Remove trailing slash
47+
# Skip patterns starting with / (root-only patterns)
48+
if pattern.startswith("/"):
49+
pattern = pattern[1:]
50+
# Skip if still has special characters
51+
if any(c in pattern for c in "[]?*"):
52+
continue
53+
# Valid directory pattern
54+
if pattern and len(pattern) > 1:
55+
patterns.append(pattern)
56+
except Exception:
57+
pass # Silently fail if can't read gitignore
58+
59+
return patterns
60+
61+
1262
class Code2LlmGenerator:
1363
"""Generate code2llm analysis files in project/ directory.
1464
@@ -81,6 +131,7 @@ def _run_code2llm(self, project_path: Path, output_dir: Path) -> None:
81131
"-f", ",".join(cfg.formats),
82132
"-o", str(output_dir),
83133
"--strategy", cfg.strategy,
134+
"--max-depth", str(cfg.max_depth),
84135
]
85136

86137
# Add options based on config
@@ -91,6 +142,24 @@ def _run_code2llm(self, project_path: Path, output_dir: Path) -> None:
91142
if self.config.verbose:
92143
cmd.append("-v")
93144

145+
# Add exclude patterns as skip-subprojects if specified
146+
if cfg.exclude_patterns:
147+
# Convert patterns to skip-subprojects (folders to skip)
148+
skip_dirs = [p for p in cfg.exclude_patterns if not p.startswith(".") and not p.startswith("*")]
149+
if skip_dirs:
150+
cmd.extend(["--skip-subprojects"] + skip_dirs[:10]) # Limit to 10
151+
152+
# Add patterns from .gitignore
153+
gitignore_patterns = parse_gitignore(project_path)
154+
if gitignore_patterns:
155+
# Merge with existing patterns, remove duplicates
156+
existing = set(skip_dirs) if cfg.exclude_patterns else set()
157+
new_patterns = [p for p in gitignore_patterns if p not in existing][:10]
158+
if new_patterns:
159+
if "--skip-subprojects" not in cmd:
160+
cmd.append("--skip-subprojects")
161+
cmd.extend(new_patterns)
162+
94163
# Run the command
95164
result = subprocess.run(
96165
cmd,

0 commit comments

Comments
 (0)