sourcecode 1.5.0__py3-none-any.whl → 1.6.0__py3-none-any.whl
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/__init__.py +1 -1
- sourcecode/cli.py +0 -6
- sourcecode/contract_pipeline.py +12 -2
- sourcecode/detectors/java.py +40 -0
- sourcecode/serializer.py +4 -0
- {sourcecode-1.5.0.dist-info → sourcecode-1.6.0.dist-info}/METADATA +1 -1
- {sourcecode-1.5.0.dist-info → sourcecode-1.6.0.dist-info}/RECORD +10 -10
- {sourcecode-1.5.0.dist-info → sourcecode-1.6.0.dist-info}/WHEEL +0 -0
- {sourcecode-1.5.0.dist-info → sourcecode-1.6.0.dist-info}/entry_points.txt +0 -0
- {sourcecode-1.5.0.dist-info → sourcecode-1.6.0.dist-info}/licenses/LICENSE +0 -0
sourcecode/__init__.py
CHANGED
sourcecode/cli.py
CHANGED
|
@@ -1399,12 +1399,6 @@ def main(
|
|
|
1399
1399
|
))
|
|
1400
1400
|
sm = _replace(sm, pipeline_trace=_trace.build_trace())
|
|
1401
1401
|
|
|
1402
|
-
# P3-B: Auto-switch to centrality ranking when DDD layout detected
|
|
1403
|
-
if (rank_by == "relevance"
|
|
1404
|
-
and sm.architecture is not None
|
|
1405
|
-
and sm.architecture.pattern == "ddd"):
|
|
1406
|
-
rank_by = "centrality"
|
|
1407
|
-
|
|
1408
1402
|
# Contract pipeline — runs for mode=contract|standard|deep|hybrid (skip for raw)
|
|
1409
1403
|
_is_contract_mode = mode in ("contract", "standard")
|
|
1410
1404
|
_pipeline_error = False
|
sourcecode/contract_pipeline.py
CHANGED
|
@@ -240,10 +240,18 @@ class ContractPipeline:
|
|
|
240
240
|
|
|
241
241
|
# Apply max_files cap — bypass when symbol search to ensure defining files are found.
|
|
242
242
|
# A symbol query over a large repo needs all files; result set is small after filtering.
|
|
243
|
+
# MyBatis Mapper.xml contracts rank below Java files on path score alone (.xml has no
|
|
244
|
+
# suffix boost). Give them the same priority slot as entry_points so they survive the cap.
|
|
245
|
+
def _is_priority(p: str) -> bool:
|
|
246
|
+
if p in entry_paths:
|
|
247
|
+
return True
|
|
248
|
+
name = p.rsplit("/", 1)[-1]
|
|
249
|
+
return name.lower().endswith("mapper.xml")
|
|
250
|
+
|
|
243
251
|
if symbol is None and len(src_paths) > self.max_files:
|
|
244
252
|
src_paths = sorted(
|
|
245
253
|
src_paths,
|
|
246
|
-
key=lambda p: (p
|
|
254
|
+
key=lambda p: (_is_priority(p), scorer.score(p)),
|
|
247
255
|
reverse=True,
|
|
248
256
|
)[:self.max_files]
|
|
249
257
|
|
|
@@ -362,7 +370,9 @@ class ContractPipeline:
|
|
|
362
370
|
|
|
363
371
|
def _rank(self, contracts: list[FileContract], rank_by: RankStrategy) -> list[FileContract]:
|
|
364
372
|
if rank_by == "centrality":
|
|
365
|
-
|
|
373
|
+
# Entrypoints (REST controllers, main classes) surface first even in centrality mode:
|
|
374
|
+
# they have low fan_in (not imported) but are the primary API surface.
|
|
375
|
+
return sorted(contracts, key=lambda c: (-c.is_entrypoint, -(c.fan_in + c.fan_out), c.path))
|
|
366
376
|
if rank_by == "git-churn":
|
|
367
377
|
return sorted(contracts, key=lambda c: (-c.is_changed, -c.relevance_score, c.path))
|
|
368
378
|
# Default: relevance — path breaks ties deterministically
|
sourcecode/detectors/java.py
CHANGED
|
@@ -225,6 +225,12 @@ class JavaDetector(AbstractDetector):
|
|
|
225
225
|
all_paths = flatten_file_tree(context.file_tree)
|
|
226
226
|
all_java = [p for p in all_paths if p.endswith(".java")]
|
|
227
227
|
|
|
228
|
+
# Augment with a direct scan of standard Java source roots for Controller-named
|
|
229
|
+
# files that the depth-limited file_tree scanner may have missed.
|
|
230
|
+
# DDD layouts place REST controllers at depth 10+ (e.g.
|
|
231
|
+
# src/main/java/com/org/app/ddd/domain/infraestructure/rest/XxxRestController.java).
|
|
232
|
+
self._augment_deep_java_controllers(context, all_java)
|
|
233
|
+
|
|
228
234
|
# 1. @SpringBootApplication entry: Application.java / Main.java by name
|
|
229
235
|
app_candidates = [
|
|
230
236
|
p for p in all_java
|
|
@@ -270,6 +276,40 @@ class JavaDetector(AbstractDetector):
|
|
|
270
276
|
unique_eps.append(ep)
|
|
271
277
|
return unique_eps
|
|
272
278
|
|
|
279
|
+
def _augment_deep_java_controllers(self, context: DetectionContext, all_java: list[str]) -> None:
|
|
280
|
+
"""Scan standard Java source roots for *Controller*.java files not in all_java.
|
|
281
|
+
|
|
282
|
+
The depth-limited file_tree scanner misses files at depth >= max_depth.
|
|
283
|
+
DDD layouts place REST controllers deep (e.g. depth 10+), so we supplement
|
|
284
|
+
with a direct filesystem walk scoped to the standard Maven/Gradle source root.
|
|
285
|
+
"""
|
|
286
|
+
import os as _os
|
|
287
|
+
existing = set(all_java)
|
|
288
|
+
# Standard Java source root candidates (Maven first, then Gradle/other)
|
|
289
|
+
_SRC_ROOTS = ("src/main/java", "src/main/kotlin", "src/java", "src")
|
|
290
|
+
for src_root_name in _SRC_ROOTS:
|
|
291
|
+
src_root = context.root / src_root_name
|
|
292
|
+
if not src_root.is_dir():
|
|
293
|
+
continue
|
|
294
|
+
try:
|
|
295
|
+
for dirpath, _dirs, filenames in _os.walk(str(src_root)):
|
|
296
|
+
for fname in filenames:
|
|
297
|
+
if "Controller" not in fname or not fname.endswith(".java"):
|
|
298
|
+
continue
|
|
299
|
+
full = Path(dirpath) / fname
|
|
300
|
+
if full.is_symlink():
|
|
301
|
+
continue
|
|
302
|
+
try:
|
|
303
|
+
rel = str(full.relative_to(context.root)).replace("\\", "/")
|
|
304
|
+
if rel not in existing:
|
|
305
|
+
all_java.append(rel)
|
|
306
|
+
existing.add(rel)
|
|
307
|
+
except ValueError:
|
|
308
|
+
pass
|
|
309
|
+
except OSError:
|
|
310
|
+
pass
|
|
311
|
+
return # use only first matching source root
|
|
312
|
+
|
|
273
313
|
def _scan_java_file_for_entry_points(self, abs_path: Path, rel_path: str) -> list[EntryPoint]:
|
|
274
314
|
try:
|
|
275
315
|
if abs_path.stat().st_size > _MAX_FILE_SIZE:
|
sourcecode/serializer.py
CHANGED
|
@@ -1110,6 +1110,10 @@ def standard_view(sm: SourceMap, *, include_tree: bool = False) -> dict[str, Any
|
|
|
1110
1110
|
|
|
1111
1111
|
if sm.semantic_summary is not None and sm.semantic_summary.requested:
|
|
1112
1112
|
result["semantic_summary"] = asdict(sm.semantic_summary)
|
|
1113
|
+
# Backward compat: also emit hotspots at top level (moved to semantic_summary in v1.5.0).
|
|
1114
|
+
# Consumers reading d["hotspots"] directly still work.
|
|
1115
|
+
if sm.semantic_summary.hotspots:
|
|
1116
|
+
result["hotspots"] = sm.semantic_summary.hotspots[:10]
|
|
1113
1117
|
# Defensive filter: never emit objects with null required fields.
|
|
1114
1118
|
# A null entry in these arrays is worse than a shorter array — it causes
|
|
1115
1119
|
# agents to misinterpret the analysis as valid when it is not.
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
sourcecode/__init__.py,sha256=
|
|
1
|
+
sourcecode/__init__.py,sha256=s3ubr020DVq1rHjxHihNLq1cecOGqF6x7czXl3I96Sk,102
|
|
2
2
|
sourcecode/adaptive_scanner.py,sha256=6dh34C2qZXyRbw-8xBhbEwDdXanM6CRFRWayVoYITnA,10190
|
|
3
3
|
sourcecode/architecture_analyzer.py,sha256=oPmGPf9_p6y8Z7SIGHEu57nVYwxycIovDzBvlHl-l5k,32557
|
|
4
4
|
sourcecode/architecture_summary.py,sha256=J9yoLgh8wXwIRrT6q6JooB6PekivbOEYpJz4BUXdalk,20545
|
|
5
5
|
sourcecode/ast_extractor.py,sha256=XgrZg2DcWcUm9r87cRG3KGO7IK2TIL_N-CvhSbUmmh4,49901
|
|
6
6
|
sourcecode/classifier.py,sha256=GKTMN8qKZX7ponSwDJfN08RrasI4CVpq1_gFBgEopps,7093
|
|
7
|
-
sourcecode/cli.py,sha256=
|
|
7
|
+
sourcecode/cli.py,sha256=91GUbfLS86RMTurkhoMWFUPqby30AEgzkLDIvJui9Fc,74262
|
|
8
8
|
sourcecode/code_notes_analyzer.py,sha256=rRd8bFYV0krjlxxQV0wenwE9K7pVpUQSR7KvSvUQKw4,9226
|
|
9
9
|
sourcecode/confidence_analyzer.py,sha256=HcaewB2pZaZ_hfKrZWtr_yPMY2-CxS1zzTUD7c4argc,13188
|
|
10
10
|
sourcecode/context_scorer.py,sha256=QpChSpsmaAYz91rXA4Ue5xzQmNz_ZboZN09YOHScq1U,14679
|
|
11
11
|
sourcecode/context_summarizer.py,sha256=CiQrfBEzun949bWvmLabWoj2HhPn6Lw62ofqnsy0FlQ,6503
|
|
12
12
|
sourcecode/contract_model.py,sha256=nRxJKPMs1VHwFTa8AVXhGmaLjti3Lr2sjHDpWgv1bfE,3917
|
|
13
|
-
sourcecode/contract_pipeline.py,sha256=
|
|
13
|
+
sourcecode/contract_pipeline.py,sha256=GX-AyUxULywnGHYpmVlMDGsiHEsdegGUHfLVn7Ffvis,27238
|
|
14
14
|
sourcecode/coverage_parser.py,sha256=q0LeZJaX1bnntLu-ImksdBsMlpsVmk_iUfSaB4eaJGo,19702
|
|
15
15
|
sourcecode/dependency_analyzer.py,sha256=p4ljXhkcGBbFlhaZuPrsjOVjDXaKLTg0Gor2p4qFPP0,56208
|
|
16
16
|
sourcecode/doc_analyzer.py,sha256=a1CIClCNmfYM3ku4bdgwHQpmb6Js4wdJZ1V5EYLo04I,24345
|
|
@@ -29,7 +29,7 @@ sourcecode/runtime_classifier.py,sha256=zWX3r3HCKHc-qtIobErOa8aKMmaoPYREtJKvPcBG
|
|
|
29
29
|
sourcecode/scanner.py,sha256=aM3h9-DCQ3xKpeHpHYdo2vX6T5P95HA_YwZbkAVNwmo,8288
|
|
30
30
|
sourcecode/schema.py,sha256=rNxpDUgOfvJDzz6DKitL-5_0UAh0YomNwTsSSe8PafY,24066
|
|
31
31
|
sourcecode/semantic_analyzer.py,sha256=12TwXYkYbDcBdu0heX_EmfPM2EkO8a_r5osf0SaeQbs,88956
|
|
32
|
-
sourcecode/serializer.py,sha256=
|
|
32
|
+
sourcecode/serializer.py,sha256=6dHvWc-iqqCjpu9-FcAXqtpKEO4mO3AZVzWT7Tphajo,69736
|
|
33
33
|
sourcecode/summarizer.py,sha256=ZuzIdm3t8A-d5MuQL0TSNLrd-L0IQIuguIxeNXMNJf8,16070
|
|
34
34
|
sourcecode/tree_utils.py,sha256=Fj9OIuUksBvgibNd3feog0sMDjVypJzPexp5lvMoYWI,1424
|
|
35
35
|
sourcecode/workspace.py,sha256=X_6NmNnitvT3_38V-JDChydo_sR68s249hLFlrQskU0,8271
|
|
@@ -42,7 +42,7 @@ sourcecode/detectors/elixir.py,sha256=jCpvt5Yi6jvplc80ovRtWh17q-11ZGo9qX7o8b57TJ
|
|
|
42
42
|
sourcecode/detectors/go.py,sha256=2r66uRQfeTWsqxr4HDhT6vExZErby0t46QXLHVBRv9w,2782
|
|
43
43
|
sourcecode/detectors/heuristic.py,sha256=bCqqgbHavl4Sse3dqT8mwmo1wAdgeJr7VyXOmfClLKo,3387
|
|
44
44
|
sourcecode/detectors/hybrid.py,sha256=IGFRUVsAZ1ooRlFdznCeJAV6vy1yVDx-VyghvLtddXc,9101
|
|
45
|
-
sourcecode/detectors/java.py,sha256=
|
|
45
|
+
sourcecode/detectors/java.py,sha256=XAnVOmq7yXgO_4UGlIFIVgNRtyWZQEVsDDu3sa5mTsk,18669
|
|
46
46
|
sourcecode/detectors/jvm_ext.py,sha256=EgHJ5W8EE-ZTN9V607mVzohyKgZE8Mc2jCi-DF8RAZU,2616
|
|
47
47
|
sourcecode/detectors/nodejs.py,sha256=7fsyAmrGkkguX6U80HUQpIe9MRaYyi_A7zbaRtmFmGc,13097
|
|
48
48
|
sourcecode/detectors/parsers.py,sha256=ugPg8yNUf0Ai1gA7Fnn6wAkYGFjTxRodSP3IeViYJJ4,2290
|
|
@@ -60,8 +60,8 @@ sourcecode/telemetry/consent.py,sha256=wLMvGNJeSSyZoNkQXpoUioY6mMv4Qdvuw7S9jAEWn
|
|
|
60
60
|
sourcecode/telemetry/events.py,sha256=oEvvulfsv5GIDWG2174gSS6tNB95w38AIYiYeifGKlE,2294
|
|
61
61
|
sourcecode/telemetry/filters.py,sha256=Asa71oRl7q3Wt_FMwuufIZJFzSYdgRNKS8LHCIyFeYE,4805
|
|
62
62
|
sourcecode/telemetry/transport.py,sha256=KJeIPCPWMdmbCP3ySGs2iUlia34U6vWne2dZsUezesw,1560
|
|
63
|
-
sourcecode-1.
|
|
64
|
-
sourcecode-1.
|
|
65
|
-
sourcecode-1.
|
|
66
|
-
sourcecode-1.
|
|
67
|
-
sourcecode-1.
|
|
63
|
+
sourcecode-1.6.0.dist-info/METADATA,sha256=hB2-2Dm1fOj4fkPULr9PEH3aSLhD7ni4cPDxGAjmgB0,20411
|
|
64
|
+
sourcecode-1.6.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
65
|
+
sourcecode-1.6.0.dist-info/entry_points.txt,sha256=ex3F9rmbXeyDIoFQHtkEqTsKSaJow8F0LrVu8XfIktQ,57
|
|
66
|
+
sourcecode-1.6.0.dist-info/licenses/LICENSE,sha256=7DdHrU9Z_3e7dSvq4ISijZNjnuHo5NIHNiHDouMQ9JU,10491
|
|
67
|
+
sourcecode-1.6.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|