sourcecode 0.8.0__tar.gz → 0.9.0__tar.gz
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.
- {sourcecode-0.8.0 → sourcecode-0.9.0}/PKG-INFO +1 -1
- {sourcecode-0.8.0 → sourcecode-0.9.0}/docs/schema.md +2 -2
- {sourcecode-0.8.0 → sourcecode-0.9.0}/pyproject.toml +1 -1
- {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/__init__.py +1 -1
- {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/cli.py +49 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/schema.py +65 -0
- sourcecode-0.9.0/src/sourcecode/semantic_analyzer.py +1887 -0
- sourcecode-0.9.0/tests/test_integration_semantics.py +185 -0
- sourcecode-0.9.0/tests/test_semantic_analyzer_node.py +493 -0
- sourcecode-0.9.0/tests/test_semantic_analyzer_python.py +302 -0
- sourcecode-0.9.0/tests/test_semantic_import_resolution.py +355 -0
- sourcecode-0.9.0/tests/test_semantic_schema.py +129 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/.gitignore +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/.ruff.toml +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/README.md +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/classifier.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/coverage_parser.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/dependency_analyzer.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/detectors/__init__.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/detectors/base.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/detectors/dart.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/detectors/dotnet.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/detectors/elixir.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/detectors/go.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/detectors/heuristic.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/detectors/java.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/detectors/jvm_ext.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/detectors/nodejs.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/detectors/parsers.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/detectors/php.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/detectors/project.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/detectors/python.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/detectors/ruby.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/detectors/rust.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/detectors/systems.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/detectors/terraform.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/detectors/tooling.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/doc_analyzer.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/graph_analyzer.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/metrics_analyzer.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/redactor.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/scanner.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/serializer.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/summarizer.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/tree_utils.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/src/sourcecode/workspace.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/__init__.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/conftest.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/fixtures/coverage.xml +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/fixtures/fastapi_app/pyproject.toml +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/fixtures/fastapi_app/src/main.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/fixtures/go_service/cmd/api/main.go +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/fixtures/go_service/go.mod +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/fixtures/jacoco.xml +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/fixtures/lcov.info +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/fixtures/nextjs_app/app/page.tsx +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/fixtures/nextjs_app/package.json +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/fixtures/nextjs_app/pnpm-lock.yaml +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/fixtures/pnpm_monorepo/apps/web/app/page.tsx +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/fixtures/pnpm_monorepo/apps/web/package.json +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/fixtures/pnpm_monorepo/packages/api/main.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/fixtures/pnpm_monorepo/packages/api/pyproject.toml +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/fixtures/pnpm_monorepo/pnpm-workspace.yaml +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_classifier.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_cli.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_coverage_parser.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_dependency_analyzer_node_python.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_dependency_analyzer_polyglot.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_dependency_schema.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_detector_go_rust_java.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_detector_nodejs.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_detector_php_ruby_dart.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_detector_python.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_detector_universal_managed.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_detector_universal_systems.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_detectors_base.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_doc_analyzer_jsdom.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_doc_analyzer_python.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_graph_analyzer_polyglot.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_graph_analyzer_python_node.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_graph_schema.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_integration.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_integration_dependencies.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_integration_detection.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_integration_docs.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_integration_graph_modules.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_integration_lqn.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_integration_metrics.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_integration_multistack.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_integration_universal.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_metrics_analyzer.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_packaging.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_real_projects.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_redactor.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_scanner.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_schema.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_summarizer.py +0 -0
- {sourcecode-0.8.0 → sourcecode-0.9.0}/tests/test_workspace_analyzer.py +0 -0
|
@@ -61,7 +61,7 @@ Campos:
|
|
|
61
61
|
{
|
|
62
62
|
"schema_version": "1.0",
|
|
63
63
|
"generated_at": "2026-04-07T19:41:05.686277+00:00",
|
|
64
|
-
"sourcecode_version": "0.
|
|
64
|
+
"sourcecode_version": "0.9.0",
|
|
65
65
|
"analyzed_path": "/abs/path/to/project"
|
|
66
66
|
}
|
|
67
67
|
```
|
|
@@ -582,7 +582,7 @@ Ejemplo de salida para un monorepo con web Node.js y API Python con `--dependenc
|
|
|
582
582
|
"metadata": {
|
|
583
583
|
"schema_version": "1.0",
|
|
584
584
|
"generated_at": "2026-04-07T19:41:05.686277+00:00",
|
|
585
|
-
"sourcecode_version": "0.
|
|
585
|
+
"sourcecode_version": "0.9.0",
|
|
586
586
|
"analyzed_path": "/abs/path/to/project"
|
|
587
587
|
},
|
|
588
588
|
"file_tree": {
|
|
@@ -112,6 +112,11 @@ def main(
|
|
|
112
112
|
"--full-metrics",
|
|
113
113
|
help="Incluir metricas de calidad: LOC, simbolos, complejidad, tests y cobertura por fichero",
|
|
114
114
|
),
|
|
115
|
+
semantics: bool = typer.Option(
|
|
116
|
+
False,
|
|
117
|
+
"--semantics",
|
|
118
|
+
help="Incluir call graph semantico, linking cross-file de simbolos y resolucion avanzada de imports",
|
|
119
|
+
),
|
|
115
120
|
) -> None:
|
|
116
121
|
"""Genera un mapa de contexto estructurado del proyecto en formato JSON o YAML."""
|
|
117
122
|
# Validar formato
|
|
@@ -228,6 +233,9 @@ def main(
|
|
|
228
233
|
doc_analyzer = DocAnalyzer() if docs else None
|
|
229
234
|
metrics_analyzer = MetricsAnalyzer() if full_metrics else None
|
|
230
235
|
|
|
236
|
+
from sourcecode.semantic_analyzer import SemanticAnalyzer
|
|
237
|
+
semantic_analyzer = SemanticAnalyzer() if semantics else None
|
|
238
|
+
|
|
231
239
|
root_manifests = [
|
|
232
240
|
manifest
|
|
233
241
|
for manifest in manifests
|
|
@@ -424,6 +432,47 @@ def main(
|
|
|
424
432
|
metrics_summary=metrics_summary,
|
|
425
433
|
)
|
|
426
434
|
|
|
435
|
+
# Semantic analysis (--semantics flag)
|
|
436
|
+
if semantic_analyzer is not None:
|
|
437
|
+
if workspace_analysis.workspaces:
|
|
438
|
+
all_sem_calls: list[Any] = []
|
|
439
|
+
all_sem_symbols: list[Any] = []
|
|
440
|
+
all_sem_links: list[Any] = []
|
|
441
|
+
all_sem_summaries: list[Any] = []
|
|
442
|
+
for ws in workspace_analysis.workspaces:
|
|
443
|
+
ws_calls, ws_syms, ws_links, ws_sum = semantic_analyzer.analyze(
|
|
444
|
+
target / ws.path,
|
|
445
|
+
(
|
|
446
|
+
filter_sensitive_files(
|
|
447
|
+
FileScanner(target / ws.path, max_depth=depth).scan_tree()
|
|
448
|
+
)
|
|
449
|
+
),
|
|
450
|
+
workspace=ws.path,
|
|
451
|
+
)
|
|
452
|
+
all_sem_calls.extend(ws_calls)
|
|
453
|
+
all_sem_symbols.extend(ws_syms)
|
|
454
|
+
all_sem_links.extend(ws_links)
|
|
455
|
+
all_sem_summaries.append(ws_sum)
|
|
456
|
+
merged_sem = semantic_analyzer.merge_summaries(all_sem_summaries)
|
|
457
|
+
sm = replace(
|
|
458
|
+
sm,
|
|
459
|
+
semantic_calls=all_sem_calls,
|
|
460
|
+
semantic_symbols=all_sem_symbols,
|
|
461
|
+
semantic_links=all_sem_links,
|
|
462
|
+
semantic_summary=merged_sem,
|
|
463
|
+
)
|
|
464
|
+
else:
|
|
465
|
+
sem_calls, sem_syms, sem_links, sem_sum = semantic_analyzer.analyze(
|
|
466
|
+
target, file_tree
|
|
467
|
+
)
|
|
468
|
+
sm = replace(
|
|
469
|
+
sm,
|
|
470
|
+
semantic_calls=sem_calls,
|
|
471
|
+
semantic_symbols=sem_syms,
|
|
472
|
+
semantic_links=sem_links,
|
|
473
|
+
semantic_summary=sem_sum,
|
|
474
|
+
)
|
|
475
|
+
|
|
427
476
|
# Phase 9: LLM Output Quality — poblar campos derivados
|
|
428
477
|
from sourcecode.summarizer import ProjectSummarizer
|
|
429
478
|
from sourcecode.tree_utils import flatten_file_tree
|
|
@@ -236,6 +236,66 @@ class DocSummary:
|
|
|
236
236
|
limitations: list[str] = field(default_factory=list)
|
|
237
237
|
|
|
238
238
|
|
|
239
|
+
@dataclass
|
|
240
|
+
class SymbolRecord:
|
|
241
|
+
"""Symbol definition found in a source file."""
|
|
242
|
+
|
|
243
|
+
symbol: str # local name: "MyClass" or "my_func"
|
|
244
|
+
kind: str # "function" | "class" | "constant" | "method"
|
|
245
|
+
language: str
|
|
246
|
+
path: str # relative path to defining file
|
|
247
|
+
line: Optional[int] = None
|
|
248
|
+
qualified_name: Optional[str] = None # "pkg.module.MyClass"
|
|
249
|
+
exported: bool = True # False if name starts with _ and no __all__ override
|
|
250
|
+
workspace: Optional[str] = None
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
@dataclass
|
|
254
|
+
class CallRecord:
|
|
255
|
+
"""A resolved call from one symbol to another, possibly across files."""
|
|
256
|
+
|
|
257
|
+
caller_path: str
|
|
258
|
+
caller_symbol: str
|
|
259
|
+
callee_path: str
|
|
260
|
+
callee_symbol: str
|
|
261
|
+
call_line: Optional[int] = None
|
|
262
|
+
confidence: Literal["high", "medium", "low"] = "medium"
|
|
263
|
+
method: Literal["ast", "heuristic", "unresolved"] = "heuristic"
|
|
264
|
+
args: list[str] = field(default_factory=list)
|
|
265
|
+
kwargs: dict[str, str] = field(default_factory=dict)
|
|
266
|
+
workspace: Optional[str] = None
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
@dataclass
|
|
270
|
+
class SymbolLink:
|
|
271
|
+
"""A symbol imported in one file, resolved to its definition in another."""
|
|
272
|
+
|
|
273
|
+
importer_path: str
|
|
274
|
+
symbol: str
|
|
275
|
+
source_path: Optional[str] = None
|
|
276
|
+
source_line: Optional[int] = None
|
|
277
|
+
is_external: bool = False
|
|
278
|
+
confidence: Literal["high", "medium", "low"] = "high"
|
|
279
|
+
method: Literal["ast", "heuristic", "unresolved"] = "ast"
|
|
280
|
+
workspace: Optional[str] = None
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
@dataclass
|
|
284
|
+
class SemanticSummary:
|
|
285
|
+
"""Summary of the --semantics analysis."""
|
|
286
|
+
|
|
287
|
+
requested: bool = False
|
|
288
|
+
call_count: int = 0
|
|
289
|
+
symbol_count: int = 0
|
|
290
|
+
link_count: int = 0
|
|
291
|
+
languages: list[str] = field(default_factory=list)
|
|
292
|
+
language_coverage: dict[str, str] = field(default_factory=dict)
|
|
293
|
+
files_analyzed: int = 0
|
|
294
|
+
files_skipped: int = 0
|
|
295
|
+
truncated: bool = False
|
|
296
|
+
limitations: list[str] = field(default_factory=list)
|
|
297
|
+
|
|
298
|
+
|
|
239
299
|
@dataclass
|
|
240
300
|
class SourceMap:
|
|
241
301
|
"""Schema completo del output v1.0.
|
|
@@ -266,3 +326,8 @@ class SourceMap:
|
|
|
266
326
|
# Phase 10: Code Quality Metrics
|
|
267
327
|
file_metrics: list[FileMetrics] = field(default_factory=list)
|
|
268
328
|
metrics_summary: Optional[MetricsSummary] = None
|
|
329
|
+
# Phase 12: Static Semantics
|
|
330
|
+
semantic_calls: list[CallRecord] = field(default_factory=list)
|
|
331
|
+
semantic_symbols: list[SymbolRecord] = field(default_factory=list)
|
|
332
|
+
semantic_links: list[SymbolLink] = field(default_factory=list)
|
|
333
|
+
semantic_summary: Optional[SemanticSummary] = None
|