sourcecode 1.4.0__tar.gz → 1.5.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-1.4.0 → sourcecode-1.5.0}/PKG-INFO +1 -1
- {sourcecode-1.4.0 → sourcecode-1.5.0}/pyproject.toml +1 -1
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/__init__.py +1 -1
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/architecture_analyzer.py +12 -1
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/ast_extractor.py +55 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/contract_pipeline.py +10 -1
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/dependency_analyzer.py +12 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/detectors/java.py +7 -5
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/serializer.py +27 -1
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_contract_pipeline.py +4 -4
- {sourcecode-1.4.0 → sourcecode-1.5.0}/.agents/skills/source-command-gsd-join-discord/SKILL.md +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/.agents/skills/source-command-gsd-review-backlog/SKILL.md +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/.agents/skills/source-command-gsd-workstreams/SKILL.md +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/.github/workflows/build-windows.yml +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/.gitignore +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/.ruff.toml +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/CONTRIBUTING.md +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/LICENSE +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/README.md +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/SECURITY.md +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/docs/privacy.md +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/docs/schema.md +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/raw +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/run_cli.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/adaptive_scanner.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/architecture_summary.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/classifier.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/cli.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/code_notes_analyzer.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/confidence_analyzer.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/context_scorer.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/context_summarizer.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/contract_model.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/coverage_parser.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/detectors/__init__.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/detectors/base.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/detectors/csproj_parser.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/detectors/dart.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/detectors/dotnet.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/detectors/elixir.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/detectors/go.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/detectors/heuristic.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/detectors/hybrid.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/detectors/jvm_ext.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/detectors/nodejs.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/detectors/parsers.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/detectors/php.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/detectors/project.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/detectors/python.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/detectors/ruby.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/detectors/rust.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/detectors/systems.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/detectors/terraform.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/detectors/tooling.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/doc_analyzer.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/entrypoint_classifier.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/env_analyzer.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/file_classifier.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/git_analyzer.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/graph_analyzer.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/metrics_analyzer.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/prepare_context.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/ranking_engine.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/redactor.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/relevance_scorer.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/repo_classifier.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/runtime_classifier.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/scanner.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/schema.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/semantic_analyzer.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/summarizer.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/telemetry/__init__.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/telemetry/config.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/telemetry/consent.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/telemetry/events.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/telemetry/filters.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/telemetry/transport.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/tree_utils.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/src/sourcecode/workspace.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/__init__.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/conftest.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/fixtures/coverage.xml +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/fixtures/fastapi_app/pyproject.toml +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/fixtures/fastapi_app/src/main.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/fixtures/go_service/cmd/api/main.go +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/fixtures/go_service/go.mod +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/fixtures/jacoco.xml +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/fixtures/lcov.info +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/fixtures/nextjs_app/app/page.tsx +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/fixtures/nextjs_app/package.json +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/fixtures/nextjs_app/pnpm-lock.yaml +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/fixtures/pnpm_monorepo/apps/web/app/page.tsx +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/fixtures/pnpm_monorepo/apps/web/package.json +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/fixtures/pnpm_monorepo/packages/api/main.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/fixtures/pnpm_monorepo/packages/api/pyproject.toml +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/fixtures/pnpm_monorepo/pnpm-workspace.yaml +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/fixtures/spring_boot_minimal/pom.xml +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/application/service/FindAusenteService.java +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/domain/entities/Ausente.java +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/infrastructure/rest/AusenteRestController.java +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/application/service/FindAutocoberturasService.java +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/domain/entities/Autocoberturas.java +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/infrastructure/rest/AutocoberturasRestController.java +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/application/service/FindCalendarioTrabajadorService.java +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/domain/entities/CalendarioTrabajador.java +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/infrastructure/rest/CalendarioTrabajadorRestController.java +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/application/service/FindDepartamentoService.java +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/domain/entities/Departamento.java +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/infrastructure/rest/DepartamentoRestController.java +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/application/service/FindEmpleadoService.java +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/domain/entities/Empleado.java +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/infrastructure/rest/EmpleadoRestController.java +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/DemoApplication.java +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/domain/Health.java +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/mapper/HealthMapper.java +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/repository/HealthRepository.java +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/service/HealthService.java +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/web/HealthRestController.java +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/fixtures/spring_boot_minimal/src/main/resources/application-dev.yml +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/fixtures/spring_boot_minimal/src/main/resources/application.yml +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_architecture_analyzer.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_architecture_summary.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_ast_extractor.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_block1_reliability.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_block2_coverage.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_block5_quality.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_classifier.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_cli.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_code_notes_analyzer.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_context_scorer.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_coverage_parser.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_cross_consistency.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_dependency_analyzer_node_python.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_dependency_analyzer_polyglot.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_dependency_schema.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_detector_dotnet.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_detector_go_rust_java.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_detector_nodejs.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_detector_php_ruby_dart.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_detector_python.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_detector_universal_managed.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_detector_universal_systems.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_detectors_base.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_doc_analyzer_jsdom.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_doc_analyzer_python.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_graph_analyzer_polyglot.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_graph_analyzer_python_node.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_graph_schema.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_hybrid_inference.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_integration.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_integration_dependencies.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_integration_detection.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_integration_docs.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_integration_graph_modules.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_integration_lqn.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_integration_metrics.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_integration_multistack.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_integration_semantics.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_integration_universal.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_java_spring_integration.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_metrics_analyzer.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_packaging.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_phase1_improvements.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_pipeline_integrity.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_real_projects.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_redactor.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_scanner.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_schema.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_schema_normalization.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_semantic_analyzer_node.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_semantic_analyzer_python.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_semantic_import_resolution.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_semantic_schema.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_signal_hierarchy.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_summarizer.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_telemetry.py +0 -0
- {sourcecode-1.4.0 → sourcecode-1.5.0}/tests/test_workspace_analyzer.py +0 -0
|
@@ -182,8 +182,19 @@ class ArchitectureAnalyzer:
|
|
|
182
182
|
ddd_result = self._detect_ddd(sm.file_paths)
|
|
183
183
|
if ddd_result is not None:
|
|
184
184
|
ddd_pattern, ddd_layers, ddd_contexts, ddd_layer_names = ddd_result
|
|
185
|
-
domains_for_ddd = self._cluster_domains(filtered) if len(filtered) >= 2 else []
|
|
186
185
|
module_files = self._build_ddd_module_files(sm.file_paths, ddd_contexts)
|
|
186
|
+
# Use DDD bounded context names as domains so --architecture shows each
|
|
187
|
+
# context as a distinct domain instead of collapsing all files under
|
|
188
|
+
# the Maven path segment (e.g. "java").
|
|
189
|
+
domains_for_ddd = [
|
|
190
|
+
ArchitectureDomain(
|
|
191
|
+
name=n,
|
|
192
|
+
files=module_files.get(n, []),
|
|
193
|
+
role="DDD bounded context",
|
|
194
|
+
confidence="high",
|
|
195
|
+
)
|
|
196
|
+
for n in ddd_contexts
|
|
197
|
+
]
|
|
187
198
|
bc_list = [
|
|
188
199
|
BoundedContext(name=n, modules=module_files.get(n, []), confidence="high")
|
|
189
200
|
for n in ddd_contexts
|
|
@@ -1172,6 +1172,51 @@ def _detect_role(path: str, contract: FileContract) -> str:
|
|
|
1172
1172
|
return "util"
|
|
1173
1173
|
|
|
1174
1174
|
|
|
1175
|
+
# ---------------------------------------------------------------------------
|
|
1176
|
+
# MyBatis XML mapper extractor
|
|
1177
|
+
# ---------------------------------------------------------------------------
|
|
1178
|
+
|
|
1179
|
+
def _extract_mybatis_xml(rel_path: str, source: str) -> FileContract:
|
|
1180
|
+
"""Extract namespace and SQL operations from a MyBatis *Mapper.xml file."""
|
|
1181
|
+
import re as _re
|
|
1182
|
+
from xml.etree import ElementTree
|
|
1183
|
+
|
|
1184
|
+
_NS_STRIP = _re.compile(r"\{[^}]+\}")
|
|
1185
|
+
_SQL_OPS = frozenset({"select", "insert", "update", "delete"})
|
|
1186
|
+
|
|
1187
|
+
exports: list[ExportRecord] = []
|
|
1188
|
+
namespace: str | None = None
|
|
1189
|
+
|
|
1190
|
+
try:
|
|
1191
|
+
root_elem = ElementTree.fromstring(source.encode("utf-8"))
|
|
1192
|
+
namespace = root_elem.get("namespace") or None
|
|
1193
|
+
for elem in root_elem:
|
|
1194
|
+
tag = _NS_STRIP.sub("", elem.tag).lower()
|
|
1195
|
+
if tag in _SQL_OPS:
|
|
1196
|
+
op_id = (elem.get("id") or "").strip()
|
|
1197
|
+
if op_id:
|
|
1198
|
+
# type_ref carries select/insert/update/delete for the serializer
|
|
1199
|
+
exports.append(ExportRecord(kind="query", name=op_id, type_ref=tag))
|
|
1200
|
+
except Exception:
|
|
1201
|
+
return FileContract(
|
|
1202
|
+
path=rel_path,
|
|
1203
|
+
language="mybatis-xml",
|
|
1204
|
+
role="mybatis-mapper",
|
|
1205
|
+
extraction_method="heuristic",
|
|
1206
|
+
limitations=["xml_parse_error: failed to parse mapper XML"],
|
|
1207
|
+
)
|
|
1208
|
+
|
|
1209
|
+
deps = [f"namespace:{namespace}"] if namespace else []
|
|
1210
|
+
return FileContract(
|
|
1211
|
+
path=rel_path,
|
|
1212
|
+
language="mybatis-xml",
|
|
1213
|
+
role="mybatis-mapper",
|
|
1214
|
+
exports=exports,
|
|
1215
|
+
dependencies=deps,
|
|
1216
|
+
extraction_method="heuristic",
|
|
1217
|
+
)
|
|
1218
|
+
|
|
1219
|
+
|
|
1175
1220
|
# ---------------------------------------------------------------------------
|
|
1176
1221
|
# AstExtractor public class
|
|
1177
1222
|
# ---------------------------------------------------------------------------
|
|
@@ -1191,6 +1236,16 @@ class AstExtractor:
|
|
|
1191
1236
|
return self._ts_ok
|
|
1192
1237
|
|
|
1193
1238
|
def extract(self, path: Path, root: Optional[Path] = None) -> Optional[FileContract]:
|
|
1239
|
+
# MyBatis mapper XML — handled before the language map lookup so .xml
|
|
1240
|
+
# files are only processed when they match the mapper naming convention.
|
|
1241
|
+
if path.suffix.lower() == ".xml" and path.name.endswith("Mapper.xml"):
|
|
1242
|
+
try:
|
|
1243
|
+
source = path.read_text(encoding="utf-8", errors="replace")
|
|
1244
|
+
except OSError:
|
|
1245
|
+
return None
|
|
1246
|
+
rel_path = str(path.relative_to(root)).replace("\\", "/") if root else path.name
|
|
1247
|
+
return _extract_mybatis_xml(rel_path, source)
|
|
1248
|
+
|
|
1194
1249
|
ext = path.suffix.lower()
|
|
1195
1250
|
language = _LANGUAGE_MAP.get(ext)
|
|
1196
1251
|
if language is None:
|
|
@@ -219,9 +219,18 @@ class ContractPipeline:
|
|
|
219
219
|
fname = Path(pn).name
|
|
220
220
|
return any(fname.startswith(pat) or f".{pat.strip('.')}" in fname for pat in _TEST_PATTERNS)
|
|
221
221
|
|
|
222
|
+
def _is_extractable(p: str) -> bool:
|
|
223
|
+
suf = Path(p).suffix.lower()
|
|
224
|
+
if suf in _SRC_EXTENSIONS:
|
|
225
|
+
return True
|
|
226
|
+
# MyBatis mapper XML files — only *Mapper.xml, not all XML
|
|
227
|
+
if suf == ".xml" and p.endswith("Mapper.xml"):
|
|
228
|
+
return True
|
|
229
|
+
return False
|
|
230
|
+
|
|
222
231
|
src_paths = [
|
|
223
232
|
p for p in file_paths
|
|
224
|
-
if
|
|
233
|
+
if _is_extractable(p)
|
|
225
234
|
and not scorer.is_noise(p)
|
|
226
235
|
and (symbol is not None or changed_only or not _is_test(p))
|
|
227
236
|
]
|
|
@@ -1191,6 +1191,18 @@ class DependencyAnalyzer:
|
|
|
1191
1191
|
limitations: list[str] = []
|
|
1192
1192
|
if not records:
|
|
1193
1193
|
limitations.append("java: pom.xml sin dependencias parseables (puede usar BOM o propiedades)")
|
|
1194
|
+
|
|
1195
|
+
# Warn when Spring Boot BOM manages transitive deps — they can't be resolved statically.
|
|
1196
|
+
parent_artifact_local = (
|
|
1197
|
+
root_elem.findtext(f"{ns}parent/{ns}artifactId") or ""
|
|
1198
|
+
).strip() if parent_elem is not None else ""
|
|
1199
|
+
if parent_artifact_local == "spring-boot-starter-parent" and parent_version:
|
|
1200
|
+
limitations.append(
|
|
1201
|
+
f"spring_boot_bom_detected: transitive deps managed by Spring Boot BOM "
|
|
1202
|
+
f"v{parent_version}, not resolved statically. "
|
|
1203
|
+
"Run 'mvn dependency:tree' for the full transitive tree."
|
|
1204
|
+
)
|
|
1205
|
+
|
|
1194
1206
|
return records, limitations
|
|
1195
1207
|
|
|
1196
1208
|
def _analyze_gradle(self, root: Path) -> tuple[list[DependencyRecord], list[str]]:
|
|
@@ -18,7 +18,7 @@ _NS_TAG_RE = re.compile(r"\{[^}]+\}")
|
|
|
18
18
|
|
|
19
19
|
_MAX_FILE_SIZE = 256 * 1024 # 256 KB
|
|
20
20
|
_MAX_JAVA_ENTRY_SCAN = 1000
|
|
21
|
-
_MAX_ANNOTATION_ENTRY_POINTS =
|
|
21
|
+
_MAX_ANNOTATION_ENTRY_POINTS = 1000
|
|
22
22
|
|
|
23
23
|
_REST_CONTROLLER_RE = re.compile(r'@RestController\b')
|
|
24
24
|
_MVC_CONTROLLER_RE = re.compile(r'@Controller\b')
|
|
@@ -236,10 +236,12 @@ class JavaDetector(AbstractDetector):
|
|
|
236
236
|
]
|
|
237
237
|
|
|
238
238
|
# 2. Annotation-based scan: @RestController, @WebFilter, FilterRegistrationBean
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
239
|
+
# Prioritize Controller-named files so all REST controllers are detected
|
|
240
|
+
# even in large codebases where total files > _MAX_JAVA_ENTRY_SCAN.
|
|
241
|
+
_non_test = [p for p in all_java if "/test/" not in p and "/tests/" not in p]
|
|
242
|
+
_ctrl_files = [p for p in _non_test if "Controller" in p]
|
|
243
|
+
_other_files = [p for p in _non_test if "Controller" not in p]
|
|
244
|
+
scan_candidates = _ctrl_files + _other_files[:max(0, _MAX_JAVA_ENTRY_SCAN - len(_ctrl_files))]
|
|
243
245
|
|
|
244
246
|
annotation_eps: list[EntryPoint] = []
|
|
245
247
|
for rel_path in scan_candidates:
|
|
@@ -1439,10 +1439,31 @@ def _serialize_contract_java(c: Any) -> dict[str, Any]:
|
|
|
1439
1439
|
return item
|
|
1440
1440
|
|
|
1441
1441
|
|
|
1442
|
+
def _serialize_contract_mybatis_xml(c: Any) -> dict[str, Any]:
|
|
1443
|
+
"""Serialize a MyBatis *Mapper.xml contract."""
|
|
1444
|
+
item: dict[str, Any] = {"path": c.path, "language": "mybatis-xml"}
|
|
1445
|
+
# Extract namespace stored as "namespace:<fqn>" in dependencies
|
|
1446
|
+
for dep in (c.dependencies or []):
|
|
1447
|
+
if dep.startswith("namespace:"):
|
|
1448
|
+
item["namespace"] = dep[len("namespace:"):]
|
|
1449
|
+
break
|
|
1450
|
+
exports_out: list[dict] = []
|
|
1451
|
+
for e in c.exports:
|
|
1452
|
+
entry: dict = {"kind": e.kind, "name": e.name}
|
|
1453
|
+
if getattr(e, "type_ref", None):
|
|
1454
|
+
entry["type"] = e.type_ref
|
|
1455
|
+
exports_out.append(entry)
|
|
1456
|
+
if exports_out:
|
|
1457
|
+
item["exports"] = exports_out
|
|
1458
|
+
return item
|
|
1459
|
+
|
|
1460
|
+
|
|
1442
1461
|
def _serialize_contract_minimal(c: Any) -> dict[str, Any]:
|
|
1443
1462
|
"""Serialize one FileContract to minimal format."""
|
|
1444
1463
|
if getattr(c, "language", None) == "java":
|
|
1445
1464
|
return _serialize_contract_java(c)
|
|
1465
|
+
if getattr(c, "language", None) == "mybatis-xml":
|
|
1466
|
+
return _serialize_contract_mybatis_xml(c)
|
|
1446
1467
|
item: dict[str, Any] = {"path": c.path, "role": c.role}
|
|
1447
1468
|
|
|
1448
1469
|
if c.is_changed:
|
|
@@ -1560,6 +1581,11 @@ def _contract_view_standard(
|
|
|
1560
1581
|
if contracts:
|
|
1561
1582
|
serialized: list[dict[str, Any]] = []
|
|
1562
1583
|
for c in contracts:
|
|
1584
|
+
if getattr(c, "language", None) == "mybatis-xml":
|
|
1585
|
+
item = _serialize_contract_mybatis_xml(c)
|
|
1586
|
+
item["relevance_score"] = round(c.relevance_score, 3)
|
|
1587
|
+
serialized.append(item)
|
|
1588
|
+
continue
|
|
1563
1589
|
item: dict[str, Any] = {
|
|
1564
1590
|
"path": c.path,
|
|
1565
1591
|
"language": c.language,
|
|
@@ -1609,7 +1635,7 @@ def _contract_view_standard(
|
|
|
1609
1635
|
item["ranking_reasons"] = non_trivial
|
|
1610
1636
|
item["method"] = c.extraction_method
|
|
1611
1637
|
serialized.append(item)
|
|
1612
|
-
result["
|
|
1638
|
+
result["contracts"] = serialized
|
|
1613
1639
|
|
|
1614
1640
|
# Optional analysis sections (deep mode or when analyzers ran)
|
|
1615
1641
|
if include_optional:
|
|
@@ -188,7 +188,7 @@ def test_cli_raw_mode_preserves_standard_output(tmp_path: Path) -> None:
|
|
|
188
188
|
data = json.loads(result.output)
|
|
189
189
|
assert "metadata" in data
|
|
190
190
|
assert data["metadata"]["schema_version"] == "1.0"
|
|
191
|
-
assert "
|
|
191
|
+
assert "contracts" not in data
|
|
192
192
|
|
|
193
193
|
|
|
194
194
|
def test_cli_max_symbols_flag(tmp_path: Path) -> None:
|
|
@@ -198,11 +198,11 @@ def test_cli_max_symbols_flag(tmp_path: Path) -> None:
|
|
|
198
198
|
f"def func{i}a(): pass\ndef func{i}b(): pass\n"
|
|
199
199
|
)
|
|
200
200
|
|
|
201
|
-
# Use --mode standard to get
|
|
201
|
+
# Use --mode standard to get contracts with full per-symbol detail
|
|
202
202
|
result = runner.invoke(app, ["--mode", "standard", "--max-symbols", "5", str(tmp_path)])
|
|
203
203
|
assert result.exit_code == 0, result.output
|
|
204
204
|
data = json.loads(result.output)
|
|
205
|
-
contracts = data.get("
|
|
205
|
+
contracts = data.get("contracts", [])
|
|
206
206
|
total = sum(
|
|
207
207
|
len(c.get("exports", [])) + len(c.get("functions", [])) + len(c.get("types", []))
|
|
208
208
|
for c in contracts
|
|
@@ -250,7 +250,7 @@ def test_cli_standard_mode_includes_detail_fields(tmp_path: Path) -> None:
|
|
|
250
250
|
assert "schema_version" in data
|
|
251
251
|
assert "stacks" in data
|
|
252
252
|
assert "entry_points" in data
|
|
253
|
-
assert "
|
|
253
|
+
assert "contracts" in data
|
|
254
254
|
|
|
255
255
|
|
|
256
256
|
def test_cli_invalid_mode_exits_nonzero(tmp_path: Path) -> None:
|
{sourcecode-1.4.0 → sourcecode-1.5.0}/.agents/skills/source-command-gsd-join-discord/SKILL.md
RENAMED
|
File without changes
|
{sourcecode-1.4.0 → sourcecode-1.5.0}/.agents/skills/source-command-gsd-review-backlog/SKILL.md
RENAMED
|
File without changes
|
{sourcecode-1.4.0 → sourcecode-1.5.0}/.agents/skills/source-command-gsd-workstreams/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sourcecode-1.4.0 → sourcecode-1.5.0}/tests/fixtures/pnpm_monorepo/packages/api/pyproject.toml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|