@voodocs/cli 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +205 -0
- package/README.md +305 -137
- package/lib/cli/__init__.py +6 -2
- package/lib/cli/init.py +228 -0
- package/lib/darkarts/annotations/parser.py +9 -9
- package/lib/darkarts/annotations/translator.py +32 -5
- package/lib/darkarts/annotations/types.py +1 -1
- package/lib/darkarts/cli_darkarts.py +142 -14
- package/lib/darkarts/core/interface.py +1 -1
- package/lib/darkarts/core/loader.py +1 -1
- package/lib/darkarts/core/plugin.py +1 -1
- package/lib/darkarts/core/registry.py +1 -1
- package/lib/darkarts/exceptions.py +1 -1
- package/lib/darkarts/plugins/voodocs/ai_native_plugin.py +1 -1
- package/lib/darkarts/plugins/voodocs/annotation_validator.py +1 -1
- package/lib/darkarts/plugins/voodocs/api_spec_generator.py +1 -1
- package/lib/darkarts/plugins/voodocs/documentation_generator.py +1 -1
- package/lib/darkarts/plugins/voodocs/html_exporter.py +1 -1
- package/lib/darkarts/plugins/voodocs/pdf_exporter.py +1 -1
- package/lib/darkarts/plugins/voodocs/test_generator.py +1 -1
- package/lib/darkarts/telemetry.py +1 -1
- package/package.json +1 -1
- package/voodocs_cli.py +3 -2
package/lib/cli/init.py
ADDED
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
"""@darkarts
|
|
2
|
+
⊢{cli:init}
|
|
3
|
+
∂{click,pathlib,json}
|
|
4
|
+
⚠{write-access:cwd}
|
|
5
|
+
⊨{idempotent:config-creation}
|
|
6
|
+
🔒{read-write:filesystem}
|
|
7
|
+
⚡{O(1):file-creation}
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
"""
|
|
11
|
+
VooDocs Init Command
|
|
12
|
+
|
|
13
|
+
Initialize a new project with VooDocs configuration and example annotations.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
import click
|
|
17
|
+
import json
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@click.command()
|
|
22
|
+
@click.option(
|
|
23
|
+
'--format',
|
|
24
|
+
type=click.Choice(['voodocs', 'darkarts'], case_sensitive=False),
|
|
25
|
+
default='voodocs',
|
|
26
|
+
help='Annotation format to use (voodocs or darkarts symbolic)'
|
|
27
|
+
)
|
|
28
|
+
@click.option(
|
|
29
|
+
'--config-only',
|
|
30
|
+
is_flag=True,
|
|
31
|
+
help='Only create configuration file, skip example files'
|
|
32
|
+
)
|
|
33
|
+
def init(format, config_only):
|
|
34
|
+
"""
|
|
35
|
+
Initialize a new project with VooDocs.
|
|
36
|
+
|
|
37
|
+
Creates a .voodocs.json configuration file and optionally generates
|
|
38
|
+
example annotated files to help you get started.
|
|
39
|
+
|
|
40
|
+
Examples:
|
|
41
|
+
voodocs init # Initialize with @voodocs format
|
|
42
|
+
voodocs init --format darkarts # Initialize with symbolic @darkarts format
|
|
43
|
+
voodocs init --config-only # Only create config file
|
|
44
|
+
"""
|
|
45
|
+
cwd = Path.cwd()
|
|
46
|
+
config_path = cwd / '.voodocs.json'
|
|
47
|
+
|
|
48
|
+
# Check if config already exists
|
|
49
|
+
if config_path.exists():
|
|
50
|
+
click.echo(click.style('⚠ .voodocs.json already exists', fg='yellow'))
|
|
51
|
+
if not click.confirm('Overwrite existing configuration?'):
|
|
52
|
+
click.echo('Aborted.')
|
|
53
|
+
return
|
|
54
|
+
|
|
55
|
+
# Create default configuration
|
|
56
|
+
config = {
|
|
57
|
+
"version": "1.0",
|
|
58
|
+
"format": format,
|
|
59
|
+
"validation": {
|
|
60
|
+
"semantic": True,
|
|
61
|
+
"performance": True,
|
|
62
|
+
"strict": False
|
|
63
|
+
},
|
|
64
|
+
"generation": {
|
|
65
|
+
"output_format": "markdown",
|
|
66
|
+
"include_toc": True,
|
|
67
|
+
"include_examples": True
|
|
68
|
+
},
|
|
69
|
+
"exclude": [
|
|
70
|
+
"node_modules",
|
|
71
|
+
"dist",
|
|
72
|
+
"build",
|
|
73
|
+
"__pycache__",
|
|
74
|
+
".git",
|
|
75
|
+
"*.min.js"
|
|
76
|
+
]
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
# Write configuration
|
|
80
|
+
with open(config_path, 'w') as f:
|
|
81
|
+
json.dump(config, f, indent=2)
|
|
82
|
+
|
|
83
|
+
click.echo(click.style('✓ Created .voodocs.json', fg='green'))
|
|
84
|
+
|
|
85
|
+
if not config_only:
|
|
86
|
+
# Create example files
|
|
87
|
+
examples_dir = cwd / 'voodocs-examples'
|
|
88
|
+
examples_dir.mkdir(exist_ok=True)
|
|
89
|
+
|
|
90
|
+
if format == 'voodocs':
|
|
91
|
+
create_voodocs_example(examples_dir)
|
|
92
|
+
else:
|
|
93
|
+
create_darkarts_example(examples_dir)
|
|
94
|
+
|
|
95
|
+
click.echo(click.style(f'✓ Created example files in {examples_dir}/', fg='green'))
|
|
96
|
+
|
|
97
|
+
click.echo()
|
|
98
|
+
click.echo(click.style('🎉 VooDocs initialized successfully!', fg='green', bold=True))
|
|
99
|
+
click.echo()
|
|
100
|
+
click.echo('Next steps:')
|
|
101
|
+
click.echo(' 1. Review .voodocs.json configuration')
|
|
102
|
+
click.echo(' 2. Add annotations to your code')
|
|
103
|
+
click.echo(' 3. Run: voodocs validate .')
|
|
104
|
+
click.echo(' 4. Run: voodocs generate . ./docs')
|
|
105
|
+
click.echo()
|
|
106
|
+
click.echo('Documentation: https://voodocs.com/docs')
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def create_voodocs_example(examples_dir: Path):
|
|
110
|
+
"""Create example files with @voodocs annotations."""
|
|
111
|
+
|
|
112
|
+
# TypeScript example
|
|
113
|
+
ts_example = '''/**@voodocs
|
|
114
|
+
module_purpose: "Example TypeScript module demonstrating @voodocs annotations"
|
|
115
|
+
dependencies: []
|
|
116
|
+
assumptions: ["TypeScript environment available"]
|
|
117
|
+
*/
|
|
118
|
+
|
|
119
|
+
/**@voodocs
|
|
120
|
+
preconditions: [
|
|
121
|
+
"name must be a non-empty string",
|
|
122
|
+
"age must be a positive number"
|
|
123
|
+
]
|
|
124
|
+
postconditions: [
|
|
125
|
+
"Returns a greeting message",
|
|
126
|
+
"Message includes the provided name"
|
|
127
|
+
]
|
|
128
|
+
invariants: [
|
|
129
|
+
"Does not modify input parameters"
|
|
130
|
+
]
|
|
131
|
+
side_effects: []
|
|
132
|
+
complexity: "O(1)"
|
|
133
|
+
*/
|
|
134
|
+
export function greet(name: string, age: number): string {
|
|
135
|
+
return `Hello, ${name}! You are ${age} years old.`;
|
|
136
|
+
}
|
|
137
|
+
'''
|
|
138
|
+
|
|
139
|
+
(examples_dir / 'example.ts').write_text(ts_example)
|
|
140
|
+
|
|
141
|
+
# Python example
|
|
142
|
+
py_example = '''"""@voodocs
|
|
143
|
+
module_purpose: "Example Python module demonstrating @voodocs annotations"
|
|
144
|
+
dependencies: []
|
|
145
|
+
assumptions: ["Python 3.7+"]
|
|
146
|
+
"""
|
|
147
|
+
|
|
148
|
+
def calculate_total(prices: list[float], tax_rate: float) -> float:
|
|
149
|
+
"""@voodocs
|
|
150
|
+
preconditions: [
|
|
151
|
+
"prices is a non-empty list of positive numbers",
|
|
152
|
+
"tax_rate is between 0 and 1"
|
|
153
|
+
]
|
|
154
|
+
postconditions: [
|
|
155
|
+
"Returns the total with tax applied",
|
|
156
|
+
"Result is greater than or equal to sum of prices"
|
|
157
|
+
]
|
|
158
|
+
invariants: [
|
|
159
|
+
"Does not modify the prices list"
|
|
160
|
+
]
|
|
161
|
+
side_effects: []
|
|
162
|
+
complexity: "O(n) where n is the length of prices"
|
|
163
|
+
"""
|
|
164
|
+
subtotal = sum(prices)
|
|
165
|
+
return subtotal * (1 + tax_rate)
|
|
166
|
+
'''
|
|
167
|
+
|
|
168
|
+
(examples_dir / 'example.py').write_text(py_example)
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def create_darkarts_example(examples_dir: Path):
|
|
172
|
+
"""Create example files with symbolic @darkarts annotations."""
|
|
173
|
+
|
|
174
|
+
# TypeScript example
|
|
175
|
+
ts_example = '''/**@darkarts
|
|
176
|
+
⊢{Example TypeScript module demonstrating symbolic @darkarts annotations}
|
|
177
|
+
∂{}
|
|
178
|
+
⚠{TypeScript environment available}
|
|
179
|
+
*/
|
|
180
|
+
|
|
181
|
+
/**@darkarts
|
|
182
|
+
⊳{
|
|
183
|
+
name must be a non-empty string
|
|
184
|
+
age must be a positive number
|
|
185
|
+
}
|
|
186
|
+
⊲{
|
|
187
|
+
Returns a greeting message
|
|
188
|
+
Message includes the provided name
|
|
189
|
+
}
|
|
190
|
+
⊨{
|
|
191
|
+
Does ¬ modify input parameters
|
|
192
|
+
}
|
|
193
|
+
⚡{}
|
|
194
|
+
*/
|
|
195
|
+
export function greet(name: string, age: number): string {
|
|
196
|
+
return `Hello, ${name}! You are ${age} years old.`;
|
|
197
|
+
}
|
|
198
|
+
'''
|
|
199
|
+
|
|
200
|
+
(examples_dir / 'example.ts').write_text(ts_example)
|
|
201
|
+
|
|
202
|
+
# Python example
|
|
203
|
+
py_example = '''"""@darkarts
|
|
204
|
+
⊢{Example Python module demonstrating symbolic @darkarts annotations}
|
|
205
|
+
∂{}
|
|
206
|
+
⚠{Python 3.7+}
|
|
207
|
+
"""
|
|
208
|
+
|
|
209
|
+
def calculate_total(prices: list[float], tax_rate: float) -> float:
|
|
210
|
+
"""@darkarts
|
|
211
|
+
⊳{
|
|
212
|
+
prices is a non-empty list ∧ ∀ p ∈ prices: p > 0
|
|
213
|
+
tax_rate ∈ [0, 1]
|
|
214
|
+
}
|
|
215
|
+
⊲{
|
|
216
|
+
Returns the total with tax applied
|
|
217
|
+
result ≥ sum(prices)
|
|
218
|
+
}
|
|
219
|
+
⊨{
|
|
220
|
+
Does ¬ modify the prices list
|
|
221
|
+
}
|
|
222
|
+
⚡{O(n) where n = len(prices)}
|
|
223
|
+
"""
|
|
224
|
+
subtotal = sum(prices)
|
|
225
|
+
return subtotal * (1 + tax_rate)
|
|
226
|
+
'''
|
|
227
|
+
|
|
228
|
+
(examples_dir / 'example.py').write_text(py_example)
|
|
@@ -50,16 +50,16 @@ class AnnotationParser:
|
|
|
50
50
|
Language.PYTHON: r'"""@voodocs\s*(.*?)\s*"""',
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
# DarkArts patterns (symbolic annotations)
|
|
53
|
+
# DarkArts patterns (symbolic annotations) - support both @voodocs and @darkarts
|
|
54
54
|
DARKARTS_PATTERNS = {
|
|
55
|
-
Language.PYTHON: r'"""@darkarts\s*(.*?)\s*"""',
|
|
56
|
-
Language.TYPESCRIPT: r'
|
|
57
|
-
Language.JAVASCRIPT: r'
|
|
58
|
-
Language.JAVA: r'
|
|
59
|
-
Language.CPP: r'
|
|
60
|
-
Language.CSHARP: r'
|
|
61
|
-
Language.GO: r'
|
|
62
|
-
Language.RUST: r'
|
|
55
|
+
Language.PYTHON: r'"""@(?:darkarts|voodocs)\s*(.*?)\s*"""',
|
|
56
|
+
Language.TYPESCRIPT: r'/\*\*@(?:darkarts|voodocs)\s*(.*?)\s*\*/',
|
|
57
|
+
Language.JAVASCRIPT: r'/\*\*@(?:darkarts|voodocs)\s*(.*?)\s*\*/',
|
|
58
|
+
Language.JAVA: r'/\*\*@(?:darkarts|voodocs)\s*(.*?)\s*\*/',
|
|
59
|
+
Language.CPP: r'/\*\*@(?:darkarts|voodocs)\s*(.*?)\s*\*/',
|
|
60
|
+
Language.CSHARP: r'/\*\*@(?:darkarts|voodocs)\s*(.*?)\s*\*/',
|
|
61
|
+
Language.GO: r'/\*\*@(?:darkarts|voodocs)\s*(.*?)\s*\*/',
|
|
62
|
+
Language.RUST: r'/\*\*@(?:darkarts|voodocs)\s*(.*?)\s*\*/',
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
def __init__(self):
|
|
@@ -209,7 +209,7 @@ class DarkArtsTranslator:
|
|
|
209
209
|
Returns:
|
|
210
210
|
Symbolic notation
|
|
211
211
|
"""
|
|
212
|
-
result = text
|
|
212
|
+
result = text
|
|
213
213
|
|
|
214
214
|
# Replace English phrases with symbols
|
|
215
215
|
# Sort by length (longest first) to avoid partial matches
|
|
@@ -217,7 +217,14 @@ class DarkArtsTranslator:
|
|
|
217
217
|
key=lambda x: len(x[0]), reverse=True)
|
|
218
218
|
|
|
219
219
|
for english, symbol in phrases:
|
|
220
|
-
|
|
220
|
+
# Use word boundaries to avoid mid-word replacements
|
|
221
|
+
# This prevents "or" in "authenticated" from being replaced
|
|
222
|
+
pattern = r'\b' + re.escape(english) + r'\b'
|
|
223
|
+
try:
|
|
224
|
+
result = re.sub(pattern, symbol, result, flags=re.IGNORECASE)
|
|
225
|
+
except re.error:
|
|
226
|
+
# Fallback for patterns that don't work with word boundaries
|
|
227
|
+
pass
|
|
221
228
|
|
|
222
229
|
return result
|
|
223
230
|
|
|
@@ -311,15 +318,35 @@ class DarkArtsTranslator:
|
|
|
311
318
|
symbolic = [self._convert_invariant(inv) for inv in invariants]
|
|
312
319
|
lines.append(f"⊨{{{','.join(symbolic)}}}")
|
|
313
320
|
|
|
321
|
+
# Preconditions
|
|
322
|
+
if 'preconditions' in voodocs_dict:
|
|
323
|
+
preconditions = voodocs_dict['preconditions']
|
|
324
|
+
if isinstance(preconditions, list):
|
|
325
|
+
symbolic = [self._convert_invariant(pre) for pre in preconditions]
|
|
326
|
+
lines.append(f"⊳{{{','.join(symbolic)}}}")
|
|
327
|
+
|
|
328
|
+
# Postconditions
|
|
329
|
+
if 'postconditions' in voodocs_dict:
|
|
330
|
+
postconditions = voodocs_dict['postconditions']
|
|
331
|
+
if isinstance(postconditions, list):
|
|
332
|
+
symbolic = [self._convert_invariant(post) for post in postconditions]
|
|
333
|
+
lines.append(f"⊲{{{','.join(symbolic)}}}")
|
|
334
|
+
|
|
314
335
|
# Security
|
|
315
|
-
if 'security_model' in voodocs_dict:
|
|
316
|
-
security =
|
|
336
|
+
if 'security_model' in voodocs_dict or 'security_implications' in voodocs_dict:
|
|
337
|
+
security = voodocs_dict.get('security_model') or voodocs_dict.get('security_implications')
|
|
338
|
+
if isinstance(security, list):
|
|
339
|
+
security = ', '.join(security)
|
|
340
|
+
security = self._simplify_text(str(security))
|
|
317
341
|
lines.append(f"🔒{{{security}}}")
|
|
318
342
|
|
|
319
|
-
# Performance
|
|
343
|
+
# Performance/Complexity
|
|
320
344
|
if 'performance_model' in voodocs_dict:
|
|
321
345
|
perf = voodocs_dict['performance_model']
|
|
322
346
|
lines.append(f"⚡{{{perf}}}")
|
|
347
|
+
elif 'complexity' in voodocs_dict:
|
|
348
|
+
complexity = voodocs_dict['complexity']
|
|
349
|
+
lines.append(f"⚡{{{complexity}}}")
|
|
323
350
|
|
|
324
351
|
lines.append('"""')
|
|
325
352
|
return '\n'.join(lines)
|
|
@@ -15,7 +15,7 @@ Data structures for parsed @darkarts/@voodocs annotations with:
|
|
|
15
15
|
- State transitions (from_state → to_state with conditions)
|
|
16
16
|
- Error cases (condition, error_type, description)
|
|
17
17
|
- Structured representations (FunctionAnnotation, ClassAnnotation, ModuleAnnotation)
|
|
18
|
-
"""
|
|
18
|
+
"""
|
|
19
19
|
|
|
20
20
|
from dataclasses import dataclass, field
|
|
21
21
|
from typing import List, Dict, Optional, Any
|
|
@@ -12,6 +12,7 @@ Provides CLI commands for DarkArts symbolic documentation.
|
|
|
12
12
|
"""
|
|
13
13
|
|
|
14
14
|
import sys
|
|
15
|
+
import re
|
|
15
16
|
from pathlib import Path
|
|
16
17
|
from typing import List, Optional
|
|
17
18
|
|
|
@@ -22,6 +23,7 @@ from darkarts.annotations import (
|
|
|
22
23
|
convert_voodocs_to_darkarts,
|
|
23
24
|
)
|
|
24
25
|
from darkarts.annotations.parser import AnnotationParser
|
|
26
|
+
from darkarts.annotations.types import Language
|
|
25
27
|
|
|
26
28
|
|
|
27
29
|
def cmd_darkarts_translate(args):
|
|
@@ -93,6 +95,12 @@ def cmd_darkarts_convert(args):
|
|
|
93
95
|
|
|
94
96
|
Usage:
|
|
95
97
|
voodocs darkarts convert <files> [--in-place]
|
|
98
|
+
|
|
99
|
+
Improvements:
|
|
100
|
+
- Supports Python, TypeScript, JavaScript
|
|
101
|
+
- Preserves ALL annotation fields (not just module-level)
|
|
102
|
+
- Fixed symbol conversion (no mid-word replacements)
|
|
103
|
+
- Working --in-place flag for all languages
|
|
96
104
|
"""
|
|
97
105
|
print("🔄 DarkArts Conversion")
|
|
98
106
|
print("=" * 60)
|
|
@@ -116,41 +124,161 @@ def cmd_darkarts_convert(args):
|
|
|
116
124
|
# Parse VooDocs annotations
|
|
117
125
|
parser = AnnotationParser()
|
|
118
126
|
annotations = parser.parse_file(str(path))
|
|
127
|
+
language = parser.detect_language(str(path))
|
|
119
128
|
|
|
120
129
|
if not annotations.module:
|
|
121
130
|
print(" ⚠️ No @voodocs annotations found")
|
|
122
131
|
continue
|
|
123
132
|
|
|
124
|
-
# Convert
|
|
125
|
-
|
|
126
|
-
'module_purpose': annotations.module.module_purpose,
|
|
127
|
-
'dependencies': annotations.module.dependencies,
|
|
128
|
-
'assumptions': annotations.module.assumptions,
|
|
129
|
-
}
|
|
133
|
+
# Convert module-level annotation
|
|
134
|
+
converted_annotations = []
|
|
130
135
|
|
|
131
|
-
|
|
136
|
+
if annotations.module:
|
|
137
|
+
module_dict = {}
|
|
138
|
+
|
|
139
|
+
# Include ALL fields
|
|
140
|
+
if hasattr(annotations.module, 'module_purpose') and annotations.module.module_purpose:
|
|
141
|
+
module_dict['module_purpose'] = annotations.module.module_purpose
|
|
142
|
+
if hasattr(annotations.module, 'dependencies') and annotations.module.dependencies:
|
|
143
|
+
module_dict['dependencies'] = annotations.module.dependencies
|
|
144
|
+
if hasattr(annotations.module, 'assumptions') and annotations.module.assumptions:
|
|
145
|
+
module_dict['assumptions'] = annotations.module.assumptions
|
|
146
|
+
if hasattr(annotations.module, 'invariants') and annotations.module.invariants:
|
|
147
|
+
module_dict['invariants'] = annotations.module.invariants
|
|
148
|
+
if hasattr(annotations.module, 'security_model') and annotations.module.security_model:
|
|
149
|
+
module_dict['security_model'] = annotations.module.security_model
|
|
150
|
+
if hasattr(annotations.module, 'performance_model') and annotations.module.performance_model:
|
|
151
|
+
module_dict['performance_model'] = annotations.module.performance_model
|
|
152
|
+
|
|
153
|
+
if module_dict:
|
|
154
|
+
darkarts = convert_voodocs_to_darkarts(module_dict)
|
|
155
|
+
converted_annotations.append(('module', darkarts, 0))
|
|
156
|
+
|
|
157
|
+
# Convert function-level annotations
|
|
158
|
+
for func in annotations.module.functions:
|
|
159
|
+
func_dict = {}
|
|
160
|
+
|
|
161
|
+
if hasattr(func, 'preconditions') and func.preconditions:
|
|
162
|
+
func_dict['preconditions'] = func.preconditions
|
|
163
|
+
if hasattr(func, 'postconditions') and func.postconditions:
|
|
164
|
+
func_dict['postconditions'] = func.postconditions
|
|
165
|
+
if hasattr(func, 'invariants') and func.invariants:
|
|
166
|
+
func_dict['invariants'] = func.invariants
|
|
167
|
+
if hasattr(func, 'security_implications') and func.security_implications:
|
|
168
|
+
func_dict['security_implications'] = func.security_implications
|
|
169
|
+
if hasattr(func, 'complexity') and func.complexity:
|
|
170
|
+
# Convert ComplexityAnnotation to string
|
|
171
|
+
if hasattr(func.complexity, 'time'):
|
|
172
|
+
func_dict['complexity'] = func.complexity.time
|
|
173
|
+
else:
|
|
174
|
+
func_dict['complexity'] = str(func.complexity)
|
|
175
|
+
|
|
176
|
+
if func_dict:
|
|
177
|
+
darkarts = convert_voodocs_to_darkarts(func_dict)
|
|
178
|
+
converted_annotations.append(('function', darkarts, func.line_number if hasattr(func, 'line_number') else 0))
|
|
179
|
+
|
|
180
|
+
# Convert class-level annotations
|
|
181
|
+
for cls in annotations.module.classes:
|
|
182
|
+
cls_dict = {}
|
|
183
|
+
|
|
184
|
+
if hasattr(cls, 'invariants') and cls.invariants:
|
|
185
|
+
cls_dict['invariants'] = cls.invariants
|
|
186
|
+
if hasattr(cls, 'assumptions') and cls.assumptions:
|
|
187
|
+
cls_dict['assumptions'] = cls.assumptions
|
|
188
|
+
|
|
189
|
+
if cls_dict:
|
|
190
|
+
darkarts = convert_voodocs_to_darkarts(cls_dict)
|
|
191
|
+
converted_annotations.append(('class', darkarts, cls.line_number if hasattr(cls, 'line_number') else 0))
|
|
192
|
+
|
|
193
|
+
if not converted_annotations:
|
|
194
|
+
print(" ⚠️ No convertible annotations found")
|
|
195
|
+
continue
|
|
132
196
|
|
|
133
197
|
if in_place:
|
|
134
198
|
# Replace @voodocs with @darkarts in file
|
|
135
|
-
|
|
136
|
-
new_content = content.replace(
|
|
137
|
-
'"""@voodocs',
|
|
138
|
-
darkarts.replace('"""@darkarts\n', '').replace('\n"""', '')
|
|
139
|
-
)
|
|
199
|
+
new_content = _replace_annotations_in_file(content, converted_annotations, language)
|
|
140
200
|
path.write_text(new_content)
|
|
141
|
-
print(" ✅ Converted in place")
|
|
201
|
+
print(f" ✅ Converted {len(converted_annotations)} annotation(s) in place")
|
|
142
202
|
else:
|
|
143
203
|
# Print to console
|
|
144
|
-
|
|
204
|
+
for ann_type, darkarts, line_num in converted_annotations:
|
|
205
|
+
print(f"\n {ann_type.capitalize()} annotation (line {line_num}):")
|
|
206
|
+
print(f" {darkarts}")
|
|
145
207
|
|
|
146
208
|
except Exception as e:
|
|
147
209
|
print(f" ❌ Error: {e}")
|
|
210
|
+
import traceback
|
|
211
|
+
traceback.print_exc()
|
|
148
212
|
|
|
149
213
|
print()
|
|
150
214
|
|
|
151
215
|
return 0
|
|
152
216
|
|
|
153
217
|
|
|
218
|
+
|
|
219
|
+
from darkarts.annotations.types import Language
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def _replace_annotations_in_file(content: str, converted_annotations: list, language: Language) -> str:
|
|
223
|
+
"""
|
|
224
|
+
Replace @voodocs annotations with @darkarts in file content.
|
|
225
|
+
|
|
226
|
+
Args:
|
|
227
|
+
content: Original file content
|
|
228
|
+
converted_annotations: List of (type, darkarts_text, line_num) tuples
|
|
229
|
+
language: Programming language
|
|
230
|
+
|
|
231
|
+
Returns:
|
|
232
|
+
Modified content with @darkarts annotations
|
|
233
|
+
"""
|
|
234
|
+
# Determine comment syntax based on language
|
|
235
|
+
if language == Language.PYTHON:
|
|
236
|
+
voodocs_pattern = r'"""@voodocs\s*(.*?)\s*"""'
|
|
237
|
+
|
|
238
|
+
def create_darkarts(darkarts_text):
|
|
239
|
+
# darkarts_text already has """@darkarts format
|
|
240
|
+
return darkarts_text
|
|
241
|
+
|
|
242
|
+
else: # TypeScript, JavaScript, etc.
|
|
243
|
+
voodocs_pattern = r'/\*\*@voodocs\s*(.*?)\s*\*/'
|
|
244
|
+
|
|
245
|
+
def create_darkarts(darkarts_text):
|
|
246
|
+
# Convert Python-style to JS-style
|
|
247
|
+
lines = darkarts_text.strip().split('\n')
|
|
248
|
+
if lines and lines[0] == '"""@darkarts':
|
|
249
|
+
lines[0] = '/**@darkarts'
|
|
250
|
+
if lines and lines[-1] == '"""':
|
|
251
|
+
lines[-1] = '*/'
|
|
252
|
+
return '\n'.join(lines)
|
|
253
|
+
|
|
254
|
+
# Find all @voodocs annotations
|
|
255
|
+
matches = list(re.finditer(voodocs_pattern, content, re.DOTALL))
|
|
256
|
+
|
|
257
|
+
if not matches:
|
|
258
|
+
return content
|
|
259
|
+
|
|
260
|
+
# Replace each annotation
|
|
261
|
+
result = content
|
|
262
|
+
offset = 0
|
|
263
|
+
|
|
264
|
+
for i, match in enumerate(matches):
|
|
265
|
+
if i < len(converted_annotations):
|
|
266
|
+
_, darkarts_text, _ = converted_annotations[i]
|
|
267
|
+
darkarts_formatted = create_darkarts(darkarts_text)
|
|
268
|
+
|
|
269
|
+
# Calculate positions with offset
|
|
270
|
+
start = match.start() + offset
|
|
271
|
+
end = match.end() + offset
|
|
272
|
+
|
|
273
|
+
# Replace
|
|
274
|
+
result = result[:start] + darkarts_formatted + result[end:]
|
|
275
|
+
|
|
276
|
+
# Update offset
|
|
277
|
+
offset += len(darkarts_formatted) - (end - start)
|
|
278
|
+
|
|
279
|
+
return result
|
|
280
|
+
|
|
281
|
+
|
|
154
282
|
def cmd_darkarts_stats(args):
|
|
155
283
|
"""
|
|
156
284
|
Show statistics about DarkArts annotations.
|
|
@@ -14,7 +14,7 @@ Provides high-level API for problem solving with automatic plugin routing:
|
|
|
14
14
|
- Explanation generation for solutions
|
|
15
15
|
- Learning mode for pattern recognition
|
|
16
16
|
- Built-in plugin discovery and loading
|
|
17
|
-
"""
|
|
17
|
+
"""
|
|
18
18
|
|
|
19
19
|
from typing import Any, Dict, List, Optional
|
|
20
20
|
from .plugin import DarkArtsPlugin, PluginInput, PluginOutput, PluginMetadata, PluginError
|
|
@@ -15,7 +15,7 @@ Defines the base classes and interfaces for the DarkArts plugin system with:
|
|
|
15
15
|
- Plugin metadata (name, version, description, dependencies, capabilities)
|
|
16
16
|
- Exception hierarchy (ParseError, ExecutionError, PluginError)
|
|
17
17
|
- Lifecycle management (initialization, execution, cleanup)
|
|
18
|
-
"""
|
|
18
|
+
"""
|
|
19
19
|
|
|
20
20
|
from abc import ABC, abstractmethod
|
|
21
21
|
from dataclasses import dataclass, field
|
|
@@ -15,7 +15,7 @@ Central registry for plugin lifecycle management with:
|
|
|
15
15
|
- Plugin enumeration and discovery
|
|
16
16
|
- Thread-safe operations (dict-based)
|
|
17
17
|
- Global singleton registry pattern
|
|
18
|
-
"""
|
|
18
|
+
"""
|
|
19
19
|
|
|
20
20
|
from typing import Dict, List, Optional
|
|
21
21
|
from .plugin import DarkArtsPlugin, PluginMetadata, PluginError
|
|
@@ -15,7 +15,7 @@ Enhanced documentation plugin supporting:
|
|
|
15
15
|
- Test generation from annotations (preconditions/postconditions → tests)
|
|
16
16
|
- API specification generation (OpenAPI from annotations)
|
|
17
17
|
- Multi-format output (docs, tests, specs)
|
|
18
|
-
"""
|
|
18
|
+
"""
|
|
19
19
|
|
|
20
20
|
from darkarts.core import (
|
|
21
21
|
DarkArtsPlugin,
|
|
@@ -15,7 +15,7 @@ Quality assurance for @voodocs annotations with:
|
|
|
15
15
|
- Complexity notation validation (Big-O format)
|
|
16
16
|
- Security model checking (valid security declarations)
|
|
17
17
|
- Best practice recommendations (suggestions for improvement)
|
|
18
|
-
"""
|
|
18
|
+
"""
|
|
19
19
|
|
|
20
20
|
from typing import List, Dict, Any, Optional
|
|
21
21
|
from darkarts.annotations.types import ParsedAnnotations, FunctionAnnotation, ClassAnnotation
|
|
@@ -15,7 +15,7 @@ Automatic API specification generation from @voodocs annotations with:
|
|
|
15
15
|
- Parameter extraction (from preconditions)
|
|
16
16
|
- Response schema generation (from postconditions)
|
|
17
17
|
- Error documentation (from error_cases)
|
|
18
|
-
"""
|
|
18
|
+
"""
|
|
19
19
|
|
|
20
20
|
from typing import List, Optional, Dict, Any
|
|
21
21
|
from pathlib import Path
|
|
@@ -15,7 +15,7 @@ Translates @voodocs annotations (DarkArts language) into human-readable document
|
|
|
15
15
|
- Complexity notation explanation (Big-O → plain English)
|
|
16
16
|
- Security model documentation (clear security implications)
|
|
17
17
|
- Cross-reference generation (links between related items)
|
|
18
|
-
"""
|
|
18
|
+
"""
|
|
19
19
|
|
|
20
20
|
from typing import List, Optional, Dict
|
|
21
21
|
from pathlib import Path
|
|
@@ -15,7 +15,7 @@ Markdown to HTML conversion with styling:
|
|
|
15
15
|
- Responsive CSS (mobile-friendly styling)
|
|
16
16
|
- Full HTML document wrapping (complete pages)
|
|
17
17
|
- Graceful degradation (basic conversion if markdown lib unavailable)
|
|
18
|
-
"""
|
|
18
|
+
"""
|
|
19
19
|
|
|
20
20
|
from pathlib import Path
|
|
21
21
|
from typing import Optional
|
|
@@ -15,7 +15,7 @@ Markdown to PDF conversion with print-ready formatting:
|
|
|
15
15
|
- Embedded fonts and styling (professional appearance)
|
|
16
16
|
- Multi-method fallback (tries multiple libraries)
|
|
17
17
|
- Error handling (clear messages if dependencies missing)
|
|
18
|
-
"""
|
|
18
|
+
"""
|
|
19
19
|
|
|
20
20
|
from pathlib import Path
|
|
21
21
|
from typing import Optional
|
|
@@ -15,7 +15,7 @@ Automatic test generation from @voodocs annotations with:
|
|
|
15
15
|
- Error case tests (ensure proper error handling)
|
|
16
16
|
- Property-based tests (Hypothesis/QuickCheck-style)
|
|
17
17
|
- Multi-framework support (pytest, unittest, jest, junit)
|
|
18
|
-
"""
|
|
18
|
+
"""
|
|
19
19
|
|
|
20
20
|
from typing import List, Optional, Dict, Any, Tuple
|
|
21
21
|
from pathlib import Path
|
|
@@ -15,7 +15,7 @@ Privacy-respecting anonymous usage analytics with:
|
|
|
15
15
|
- Supabase backend (anonymous data storage)
|
|
16
16
|
- Fail-silent network (no impact on user experience if offline)
|
|
17
17
|
- First-run notice (transparent disclosure to users)
|
|
18
|
-
"""
|
|
18
|
+
"""
|
|
19
19
|
|
|
20
20
|
import os
|
|
21
21
|
import sys
|
package/package.json
CHANGED