Files changed (1) hide show
  1. troviku_helpers.py +851 -0
troviku_helpers.py ADDED
@@ -0,0 +1,851 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Troviku Helper Utilities
3
+ =========================
4
+
5
+ A collection of useful helper functions and utilities that make working
6
+ with Troviku easier and more convenient. These helpers handle common tasks
7
+ like code parsing, template management, snippet generation, and more.
8
+
9
+ Author: OpenTrouter Research Team
10
+ License: Apache 2.0
11
+ Version: 1.1.0
12
+ """
13
+
14
+ import re
15
+ import json
16
+ import hashlib
17
+ from typing import List, Dict, Any, Optional, Tuple, Set
18
+ from dataclasses import dataclass
19
+ from pathlib import Path
20
+
21
+
22
+ # ============================================================================
23
+ # CODE PARSING AND ANALYSIS
24
+ # ============================================================================
25
+
26
+ class CodeParser:
27
+ """Parse and analyze code structure."""
28
+
29
+ @staticmethod
30
+ def extract_functions(code: str, language: str = "python") -> List[Dict[str, Any]]:
31
+ """
32
+ Extract function definitions from code.
33
+
34
+ Args:
35
+ code: Source code
36
+ language: Programming language
37
+
38
+ Returns:
39
+ List of function information dictionaries
40
+ """
41
+ functions = []
42
+
43
+ if language == "python":
44
+ pattern = r'def\s+(\w+)\s*\((.*?)\):'
45
+ matches = re.finditer(pattern, code)
46
+
47
+ for match in matches:
48
+ name = match.group(1)
49
+ params = match.group(2)
50
+ start_pos = match.start()
51
+
52
+ # Extract docstring if present
53
+ docstring = CodeParser._extract_python_docstring(code, start_pos)
54
+
55
+ functions.append({
56
+ "name": name,
57
+ "parameters": [p.strip() for p in params.split(',') if p.strip()],
58
+ "docstring": docstring,
59
+ "line": code[:start_pos].count('\n') + 1
60
+ })
61
+
62
+ elif language in ["javascript", "typescript"]:
63
+ # Match function declarations and arrow functions
64
+ patterns = [
65
+ r'function\s+(\w+)\s*\((.*?)\)',
66
+ r'const\s+(\w+)\s*=\s*\((.*?)\)\s*=>',
67
+ r'(\w+)\s*:\s*function\s*\((.*?)\)'
68
+ ]
69
+
70
+ for pattern in patterns:
71
+ matches = re.finditer(pattern, code)
72
+ for match in matches:
73
+ functions.append({
74
+ "name": match.group(1),
75
+ "parameters": [p.strip() for p in match.group(2).split(',') if p.strip()],
76
+ "line": code[:match.start()].count('\n') + 1
77
+ })
78
+
79
+ return functions
80
+
81
+ @staticmethod
82
+ def extract_classes(code: str, language: str = "python") -> List[Dict[str, Any]]:
83
+ """
84
+ Extract class definitions from code.
85
+
86
+ Args:
87
+ code: Source code
88
+ language: Programming language
89
+
90
+ Returns:
91
+ List of class information dictionaries
92
+ """
93
+ classes = []
94
+
95
+ if language == "python":
96
+ pattern = r'class\s+(\w+)(?:\((.*?)\))?:'
97
+ matches = re.finditer(pattern, code)
98
+
99
+ for match in matches:
100
+ name = match.group(1)
101
+ bases = match.group(2) or ""
102
+ start_pos = match.start()
103
+
104
+ classes.append({
105
+ "name": name,
106
+ "bases": [b.strip() for b in bases.split(',') if b.strip()],
107
+ "line": code[:start_pos].count('\n') + 1
108
+ })
109
+
110
+ elif language == "java":
111
+ pattern = r'class\s+(\w+)(?:\s+extends\s+(\w+))?(?:\s+implements\s+([\w,\s]+))?'
112
+ matches = re.finditer(pattern, code)
113
+
114
+ for match in matches:
115
+ classes.append({
116
+ "name": match.group(1),
117
+ "extends": match.group(2),
118
+ "implements": match.group(3),
119
+ "line": code[:match.start()].count('\n') + 1
120
+ })
121
+
122
+ return classes
123
+
124
+ @staticmethod
125
+ def extract_imports(code: str, language: str = "python") -> List[str]:
126
+ """
127
+ Extract import statements.
128
+
129
+ Args:
130
+ code: Source code
131
+ language: Programming language
132
+
133
+ Returns:
134
+ List of imported modules/packages
135
+ """
136
+ imports = []
137
+
138
+ if language == "python":
139
+ # Match "import x" and "from x import y"
140
+ patterns = [
141
+ r'import\s+([\w.]+)',
142
+ r'from\s+([\w.]+)\s+import'
143
+ ]
144
+
145
+ for pattern in patterns:
146
+ matches = re.finditer(pattern, code)
147
+ imports.extend(match.group(1) for match in matches)
148
+
149
+ elif language in ["javascript", "typescript"]:
150
+ # Match ES6 imports
151
+ patterns = [
152
+ r'import\s+.*?\s+from\s+["\'](.+?)["\']',
153
+ r'require\(["\'](.+?)["\']\)'
154
+ ]
155
+
156
+ for pattern in patterns:
157
+ matches = re.finditer(pattern, code)
158
+ imports.extend(match.group(1) for match in matches)
159
+
160
+ return list(set(imports)) # Remove duplicates
161
+
162
+ @staticmethod
163
+ def _extract_python_docstring(code: str, func_start: int) -> Optional[str]:
164
+ """Extract Python docstring after function definition."""
165
+ # Find the first triple-quote after function definition
166
+ rest = code[func_start:]
167
+ match = re.search(r'"""(.*?)"""|\'\'\'(.*?)\'\'\'', rest, re.DOTALL)
168
+ if match:
169
+ return (match.group(1) or match.group(2)).strip()
170
+ return None
171
+
172
+ @staticmethod
173
+ def count_complexity(code: str, language: str = "python") -> int:
174
+ """
175
+ Calculate cyclomatic complexity (simplified).
176
+
177
+ Args:
178
+ code: Source code
179
+ language: Programming language
180
+
181
+ Returns:
182
+ Complexity score
183
+ """
184
+ complexity = 1 # Base complexity
185
+
186
+ # Keywords that increase complexity
187
+ keywords = {
188
+ "python": [r'\bif\b', r'\belif\b', r'\bfor\b', r'\bwhile\b', r'\band\b', r'\bor\b', r'\bexcept\b'],
189
+ "javascript": [r'\bif\b', r'\belse if\b', r'\bfor\b', r'\bwhile\b', r'\b&&\b', r'\b\|\|\b', r'\bcatch\b'],
190
+ "java": [r'\bif\b', r'\belse if\b', r'\bfor\b', r'\bwhile\b', r'\b&&\b', r'\b\|\|\b', r'\bcatch\b']
191
+ }
192
+
193
+ patterns = keywords.get(language, keywords["python"])
194
+
195
+ for pattern in patterns:
196
+ complexity += len(re.findall(pattern, code))
197
+
198
+ return complexity
199
+
200
+
201
+ # ============================================================================
202
+ # TEMPLATE MANAGEMENT
203
+ # ============================================================================
204
+
205
+ class TemplateManager:
206
+ """Manage code templates for common patterns."""
207
+
208
+ TEMPLATES = {
209
+ "python": {
210
+ "function": """def {name}({params}):
211
+ \"\"\"
212
+ {description}
213
+
214
+ Args:
215
+ {args_doc}
216
+
217
+ Returns:
218
+ {return_doc}
219
+ \"\"\"
220
+ {body}
221
+ """,
222
+ "class": """class {name}:
223
+ \"\"\"
224
+ {description}
225
+ \"\"\"
226
+
227
+ def __init__(self{init_params}):
228
+ \"\"\"Initialize {name}.\"\"\"
229
+ {init_body}
230
+
231
+ {methods}
232
+ """,
233
+ "test": """import pytest
234
+
235
+ def test_{name}():
236
+ \"\"\"Test {description}.\"\"\"
237
+ # Arrange
238
+ {arrange}
239
+
240
+ # Act
241
+ {act}
242
+
243
+ # Assert
244
+ {assert_}
245
+ """,
246
+ "api_endpoint": """@app.route('/{path}', methods=['{method}'])
247
+ def {name}():
248
+ \"\"\"
249
+ {description}
250
+ \"\"\"
251
+ try:
252
+ {body}
253
+ return jsonify({{
254
+ 'success': True,
255
+ 'data': result
256
+ }}), 200
257
+ except Exception as e:
258
+ return jsonify({{
259
+ 'success': False,
260
+ 'error': str(e)
261
+ }}), 400
262
+ """
263
+ },
264
+ "javascript": {
265
+ "function": """/**
266
+ * {description}
267
+ * @param {{{param_types}}} {params}
268
+ * @returns {{{return_type}}}
269
+ */
270
+ function {name}({params}) {{
271
+ {body}
272
+ }}
273
+ """,
274
+ "class": """/**
275
+ * {description}
276
+ */
277
+ class {name} {{
278
+ constructor({params}) {{
279
+ {constructor_body}
280
+ }}
281
+
282
+ {methods}
283
+ }}
284
+ """,
285
+ "react_component": """import React from 'react';
286
+
287
+ /**
288
+ * {description}
289
+ */
290
+ const {name} = ({{ {props} }}) => {{
291
+ {body}
292
+
293
+ return (
294
+ {jsx}
295
+ );
296
+ }};
297
+
298
+ export default {name};
299
+ """
300
+ }
301
+ }
302
+
303
+ @staticmethod
304
+ def get_template(language: str, template_type: str) -> Optional[str]:
305
+ """
306
+ Get a code template.
307
+
308
+ Args:
309
+ language: Programming language
310
+ template_type: Type of template
311
+
312
+ Returns:
313
+ Template string or None
314
+ """
315
+ return TemplateManager.TEMPLATES.get(language, {}).get(template_type)
316
+
317
+ @staticmethod
318
+ def fill_template(template: str, **kwargs) -> str:
319
+ """
320
+ Fill template with values.
321
+
322
+ Args:
323
+ template: Template string
324
+ **kwargs: Values to fill
325
+
326
+ Returns:
327
+ Filled template
328
+ """
329
+ try:
330
+ return template.format(**kwargs)
331
+ except KeyError as e:
332
+ raise ValueError(f"Missing template parameter: {e}")
333
+
334
+ @staticmethod
335
+ def create_from_template(
336
+ language: str,
337
+ template_type: str,
338
+ **kwargs
339
+ ) -> str:
340
+ """
341
+ Create code from template.
342
+
343
+ Args:
344
+ language: Programming language
345
+ template_type: Type of template
346
+ **kwargs: Template parameters
347
+
348
+ Returns:
349
+ Generated code
350
+ """
351
+ template = TemplateManager.get_template(language, template_type)
352
+ if not template:
353
+ raise ValueError(f"Template not found: {language}/{template_type}")
354
+
355
+ return TemplateManager.fill_template(template, **kwargs)
356
+
357
+
358
+ # ============================================================================
359
+ # SNIPPET LIBRARY
360
+ # ============================================================================
361
+
362
+ class SnippetLibrary:
363
+ """Library of common code snippets."""
364
+
365
+ SNIPPETS = {
366
+ "python": {
367
+ "read_file": """with open('{filename}', 'r') as f:
368
+ content = f.read()""",
369
+
370
+ "write_file": """with open('{filename}', 'w') as f:
371
+ f.write(content)""",
372
+
373
+ "http_get": """import requests
374
+ response = requests.get('{url}')
375
+ data = response.json()""",
376
+
377
+ "parse_json": """import json
378
+ data = json.loads(json_string)""",
379
+
380
+ "list_comprehension": """result = [{expression} for {item} in {iterable} if {condition}]""",
381
+
382
+ "error_handling": """try:
383
+ {code}
384
+ except {exception} as e:
385
+ {handler}""",
386
+
387
+ "class_property": """@property
388
+ def {name}(self):
389
+ return self._{name}
390
+
391
+ @{name}.setter
392
+ def {name}(self, value):
393
+ self._{name} = value""",
394
+
395
+ "context_manager": """class {name}:
396
+ def __enter__(self):
397
+ {enter_code}
398
+ return self
399
+
400
+ def __exit__(self, exc_type, exc_val, exc_tb):
401
+ {exit_code}""",
402
+
403
+ "decorator": """def {name}(func):
404
+ def wrapper(*args, **kwargs):
405
+ {before}
406
+ result = func(*args, **kwargs)
407
+ {after}
408
+ return result
409
+ return wrapper""",
410
+ },
411
+ "javascript": {
412
+ "fetch_api": """fetch('{url}')
413
+ .then(response => response.json())
414
+ .then(data => console.log(data))
415
+ .catch(error => console.error('Error:', error));""",
416
+
417
+ "async_function": """async function {name}({params}) {{
418
+ try {{
419
+ const result = await {async_call};
420
+ return result;
421
+ }} catch (error) {{
422
+ console.error('Error:', error);
423
+ }}
424
+ }}""",
425
+
426
+ "array_methods": """// Map
427
+ const mapped = array.map(item => item * 2);
428
+
429
+ // Filter
430
+ const filtered = array.filter(item => item > 0);
431
+
432
+ // Reduce
433
+ const sum = array.reduce((acc, item) => acc + item, 0);""",
434
+
435
+ "promise": """const {name} = new Promise((resolve, reject) => {{
436
+ {code}
437
+ if (success) {{
438
+ resolve(result);
439
+ }} else {{
440
+ reject(error);
441
+ }}
442
+ }});""",
443
+ }
444
+ }
445
+
446
+ @staticmethod
447
+ def get_snippet(language: str, snippet_name: str, **kwargs) -> str:
448
+ """
449
+ Get and optionally fill a code snippet.
450
+
451
+ Args:
452
+ language: Programming language
453
+ snippet_name: Name of snippet
454
+ **kwargs: Values to fill in snippet
455
+
456
+ Returns:
457
+ Code snippet
458
+ """
459
+ snippet = SnippetLibrary.SNIPPETS.get(language, {}).get(snippet_name)
460
+ if not snippet:
461
+ raise ValueError(f"Snippet not found: {language}/{snippet_name}")
462
+
463
+ if kwargs:
464
+ try:
465
+ return snippet.format(**kwargs)
466
+ except KeyError:
467
+ return snippet
468
+
469
+ return snippet
470
+
471
+ @staticmethod
472
+ def list_snippets(language: str) -> List[str]:
473
+ """List available snippets for a language."""
474
+ return list(SnippetLibrary.SNIPPETS.get(language, {}).keys())
475
+
476
+
477
+ # ============================================================================
478
+ # CODE QUALITY ANALYZER
479
+ # ============================================================================
480
+
481
+ class QualityAnalyzer:
482
+ """Analyze code quality and provide suggestions."""
483
+
484
+ @staticmethod
485
+ def analyze(code: str, language: str = "python") -> Dict[str, Any]:
486
+ """
487
+ Analyze code quality.
488
+
489
+ Args:
490
+ code: Source code
491
+ language: Programming language
492
+
493
+ Returns:
494
+ Analysis results dictionary
495
+ """
496
+ results = {
497
+ "language": language,
498
+ "metrics": QualityAnalyzer._calculate_metrics(code),
499
+ "issues": QualityAnalyzer._find_issues(code, language),
500
+ "suggestions": QualityAnalyzer._generate_suggestions(code, language),
501
+ "score": 0
502
+ }
503
+
504
+ # Calculate overall quality score (0-100)
505
+ results["score"] = QualityAnalyzer._calculate_score(results)
506
+
507
+ return results
508
+
509
+ @staticmethod
510
+ def _calculate_metrics(code: str) -> Dict[str, Any]:
511
+ """Calculate code metrics."""
512
+ lines = code.split('\n')
513
+ non_empty = [l for l in lines if l.strip()]
514
+
515
+ return {
516
+ "total_lines": len(lines),
517
+ "code_lines": len(non_empty),
518
+ "blank_lines": len(lines) - len(non_empty),
519
+ "average_line_length": sum(len(l) for l in lines) / len(lines) if lines else 0,
520
+ "max_line_length": max(len(l) for l in lines) if lines else 0,
521
+ "comment_ratio": QualityAnalyzer._calculate_comment_ratio(code)
522
+ }
523
+
524
+ @staticmethod
525
+ def _calculate_comment_ratio(code: str) -> float:
526
+ """Calculate ratio of comment lines to code lines."""
527
+ lines = code.split('\n')
528
+ comment_lines = sum(1 for l in lines if l.strip().startswith('#') or l.strip().startswith('//'))
529
+ code_lines = sum(1 for l in lines if l.strip() and not l.strip().startswith('#'))
530
+
531
+ return comment_lines / code_lines if code_lines > 0 else 0
532
+
533
+ @staticmethod
534
+ def _find_issues(code: str, language: str) -> List[Dict[str, str]]:
535
+ """Find potential issues in code."""
536
+ issues = []
537
+ lines = code.split('\n')
538
+
539
+ for i, line in enumerate(lines, 1):
540
+ # Long lines
541
+ if len(line) > 120:
542
+ issues.append({
543
+ "line": i,
544
+ "type": "style",
545
+ "message": f"Line too long ({len(line)} characters)"
546
+ })
547
+
548
+ # Multiple statements on one line (Python)
549
+ if language == "python" and ';' in line and not line.strip().startswith('#'):
550
+ issues.append({
551
+ "line": i,
552
+ "type": "style",
553
+ "message": "Multiple statements on one line"
554
+ })
555
+
556
+ # TODO/FIXME comments
557
+ if 'TODO' in line or 'FIXME' in line:
558
+ issues.append({
559
+ "line": i,
560
+ "type": "todo",
561
+ "message": "TODO or FIXME comment found"
562
+ })
563
+
564
+ return issues
565
+
566
+ @staticmethod
567
+ def _generate_suggestions(code: str, language: str) -> List[str]:
568
+ """Generate improvement suggestions."""
569
+ suggestions = []
570
+
571
+ metrics = QualityAnalyzer._calculate_metrics(code)
572
+
573
+ # Comment ratio
574
+ if metrics["comment_ratio"] < 0.1:
575
+ suggestions.append("Consider adding more comments to explain complex logic")
576
+
577
+ # Line length
578
+ if metrics["max_line_length"] > 120:
579
+ suggestions.append("Break long lines into multiple lines for better readability")
580
+
581
+ # Code complexity
582
+ complexity = CodeParser.count_complexity(code, language)
583
+ if complexity > 10:
584
+ suggestions.append("High complexity detected. Consider refactoring into smaller functions")
585
+
586
+ # Function extraction
587
+ if metrics["code_lines"] > 50:
588
+ suggestions.append("Consider breaking code into smaller, reusable functions")
589
+
590
+ return suggestions
591
+
592
+ @staticmethod
593
+ def _calculate_score(results: Dict[str, Any]) -> int:
594
+ """Calculate overall quality score."""
595
+ score = 100
596
+
597
+ # Deduct points for issues
598
+ score -= len(results["issues"]) * 5
599
+
600
+ # Deduct for poor metrics
601
+ if results["metrics"]["comment_ratio"] < 0.1:
602
+ score -= 10
603
+ if results["metrics"]["max_line_length"] > 120:
604
+ score -= 10
605
+
606
+ return max(0, min(100, score))
607
+
608
+
609
+ # ============================================================================
610
+ # DEPENDENCY ANALYZER
611
+ # ============================================================================
612
+
613
+ class DependencyAnalyzer:
614
+ """Analyze code dependencies."""
615
+
616
+ @staticmethod
617
+ def analyze_imports(code: str, language: str = "python") -> Dict[str, Any]:
618
+ """
619
+ Analyze import dependencies.
620
+
621
+ Args:
622
+ code: Source code
623
+ language: Programming language
624
+
625
+ Returns:
626
+ Dependency analysis
627
+ """
628
+ imports = CodeParser.extract_imports(code, language)
629
+
630
+ return {
631
+ "total_imports": len(imports),
632
+ "imports": imports,
633
+ "stdlib": DependencyAnalyzer._classify_stdlib(imports, language),
634
+ "third_party": DependencyAnalyzer._classify_third_party(imports, language),
635
+ "circular": [] # Would need full codebase to detect
636
+ }
637
+
638
+ @staticmethod
639
+ def _classify_stdlib(imports: List[str], language: str) -> List[str]:
640
+ """Classify standard library imports."""
641
+ stdlib = {
642
+ "python": {
643
+ "os", "sys", "re", "json", "time", "datetime", "math", "random",
644
+ "collections", "itertools", "functools", "pathlib", "typing",
645
+ "logging", "unittest", "argparse", "threading", "subprocess"
646
+ },
647
+ "javascript": {
648
+ "fs", "path", "http", "https", "url", "crypto", "util",
649
+ "events", "stream", "buffer", "process"
650
+ }
651
+ }
652
+
653
+ std_modules = stdlib.get(language, set())
654
+ return [imp for imp in imports if imp.split('.')[0] in std_modules]
655
+
656
+ @staticmethod
657
+ def _classify_third_party(imports: List[str], language: str) -> List[str]:
658
+ """Classify third-party imports."""
659
+ stdlib = DependencyAnalyzer._classify_stdlib(imports, language)
660
+ return [imp for imp in imports if imp not in stdlib]
661
+
662
+
663
+ # ============================================================================
664
+ # DOCUMENTATION GENERATOR
665
+ # ============================================================================
666
+
667
+ class DocGenerator:
668
+ """Generate documentation from code."""
669
+
670
+ @staticmethod
671
+ def generate_function_doc(func_info: Dict[str, Any], language: str = "python") -> str:
672
+ """Generate documentation for a function."""
673
+ if language == "python":
674
+ params_doc = "\n ".join(
675
+ f"{param}: Description of {param}"
676
+ for param in func_info.get("parameters", [])
677
+ )
678
+
679
+ return f"""\"\"\"
680
+ {func_info['name']} - Brief description.
681
+
682
+ Args:
683
+ {params_doc}
684
+
685
+ Returns:
686
+ Description of return value.
687
+
688
+ Raises:
689
+ Exception: Description of when exception is raised.
690
+ \"\"\""""
691
+
692
+ elif language in ["javascript", "typescript"]:
693
+ params_doc = "\n * ".join(
694
+ f"@param {{{}}}} {param} - Description of {param}"
695
+ for param in func_info.get("parameters", [])
696
+ )
697
+
698
+ return f"""/**
699
+ * {func_info['name']} - Brief description.
700
+ *
701
+ * {params_doc}
702
+ * @returns {{}} Description of return value.
703
+ */"""
704
+
705
+ return ""
706
+
707
+ @staticmethod
708
+ def generate_readme(
709
+ project_name: str,
710
+ description: str,
711
+ functions: List[Dict[str, Any]]
712
+ ) -> str:
713
+ """Generate README.md content."""
714
+ func_list = "\n".join(
715
+ f"- `{func['name']}({', '.join(func.get('parameters', []))})`: {func.get('docstring', 'No description')}"
716
+ for func in functions
717
+ )
718
+
719
+ return f"""# {project_name}
720
+
721
+ {description}
722
+
723
+ ## Functions
724
+
725
+ {func_list}
726
+
727
+ ## Installation
728
+
729
+ ```bash
730
+ pip install {project_name.lower().replace(' ', '-')}
731
+ ```
732
+
733
+ ## Usage
734
+
735
+ ```python
736
+ from {project_name.lower().replace(' ', '_')} import *
737
+
738
+ # Example usage here
739
+ ```
740
+
741
+ ## License
742
+
743
+ MIT License
744
+ """
745
+
746
+
747
+ # ============================================================================
748
+ # UTILITY FUNCTIONS
749
+ # ============================================================================
750
+
751
+ def generate_file_hash(content: str) -> str:
752
+ """Generate hash for file content."""
753
+ return hashlib.sha256(content.encode()).hexdigest()
754
+
755
+
756
+ def find_similar_code(code: str, code_library: List[str], threshold: float = 0.8) -> List[int]:
757
+ """
758
+ Find similar code snippets.
759
+
760
+ Args:
761
+ code: Code to compare
762
+ code_library: List of code snippets
763
+ threshold: Similarity threshold (0-1)
764
+
765
+ Returns:
766
+ List of indices of similar code
767
+ """
768
+ similar = []
769
+ code_hash = set(code.split())
770
+
771
+ for i, snippet in enumerate(code_library):
772
+ snippet_hash = set(snippet.split())
773
+
774
+ # Jaccard similarity
775
+ intersection = len(code_hash & snippet_hash)
776
+ union = len(code_hash | snippet_hash)
777
+ similarity = intersection / union if union > 0 else 0
778
+
779
+ if similarity >= threshold:
780
+ similar.append(i)
781
+
782
+ return similar
783
+
784
+
785
+ def estimate_execution_time(code: str, language: str = "python") -> str:
786
+ """
787
+ Estimate code execution time complexity.
788
+
789
+ Args:
790
+ code: Source code
791
+ language: Programming language
792
+
793
+ Returns:
794
+ Time complexity estimate (e.g., "O(n)", "O(n^2)")
795
+ """
796
+ # Simple heuristic based on nested loops
797
+ loops = len(re.findall(r'\bfor\b|\bwhile\b', code))
798
+
799
+ if loops == 0:
800
+ return "O(1)"
801
+ elif loops == 1:
802
+ return "O(n)"
803
+ elif loops == 2:
804
+ return "O(n²)"
805
+ else:
806
+ return f"O(n^{loops})"
807
+
808
+
809
+ def beautify_output(response_dict: Dict[str, Any]) -> str:
810
+ """
811
+ Create beautiful formatted output.
812
+
813
+ Args:
814
+ response_dict: Response dictionary
815
+
816
+ Returns:
817
+ Formatted string
818
+ """
819
+ output = []
820
+ output.append("=" * 70)
821
+ output.append("TROVIKU CODE GENERATION RESULT")
822
+ output.append("=" * 70)
823
+ output.append(f"Language: {response_dict.get('language', 'unknown')}")
824
+ output.append(f"Task: {response_dict.get('task_type', 'unknown')}")
825
+ output.append(f"Tokens: {response_dict.get('tokens_used', 0)}")
826
+ output.append(f"Time: {response_dict.get('execution_time', 0):.2f}s")
827
+ output.append("-" * 70)
828
+ output.append("CODE:")
829
+ output.append("-" * 70)
830
+ output.append(response_dict.get('code', ''))
831
+ output.append("=" * 70)
832
+
833
+ return "\n".join(output)
834
+
835
+
836
+ # ============================================================================
837
+ # EXPORT
838
+ # ============================================================================
839
+
840
+ __all__ = [
841
+ "CodeParser",
842
+ "TemplateManager",
843
+ "SnippetLibrary",
844
+ "QualityAnalyzer",
845
+ "DependencyAnalyzer",
846
+ "DocGenerator",
847
+ "generate_file_hash",
848
+ "find_similar_code",
849
+ "estimate_execution_time",
850
+ "beautify_output",
851
+ ]