aja-codeintel 0.1.2__tar.gz → 0.1.3__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.
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/PKG-INFO +1 -1
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/aja_codeintel.egg-info/PKG-INFO +1 -1
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/aja_codeintel.egg-info/SOURCES.txt +1 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/commands/project/__init__.py +3 -1
- aja_codeintel-0.1.3/codeintel_cli/commands/project/types_cmd.py +351 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/pyproject.toml +1 -1
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/LICENSE +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/README.md +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/aja_codeintel.egg-info/dependency_links.txt +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/aja_codeintel.egg-info/entry_points.txt +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/aja_codeintel.egg-info/requires.txt +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/aja_codeintel.egg-info/top_level.txt +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/__init__.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/__main__.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/cli.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/commands/__init__.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/commands/graph/__init__.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/commands/graph/deps_cmd.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/commands/graph/related_cmd.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/commands/graph/relsymbols_cmd.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/commands/graph/reverse_related_cmd.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/commands/nav/__init__.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/commands/nav/copy_cmd.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/commands/nav/open_cmd.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/commands/nav/where_cmd.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/commands/project/context_cmd.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/commands/project/endpoints_cmd.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/commands/project/folder_cmd.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/commands/project/imports_cmd.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/commands/project/models_cmd.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/commands/project/modeltree_cmd.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/commands/project/new.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/commands/project/resolve_cmd.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/commands/project/scan_cmd.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/commands/project/servicemap_cmd.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/commands/project/tree_cmd.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/commands/project/version_cmd.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/context/java_context.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/context/java_rel.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/context/java_service.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/context/python_context.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/context/python_rel.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/context/python_service.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/core/fuzzy.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/core/opener.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/core/project.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/core/resolve_folder.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/core/resolve_model_target.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/core/resolve_target.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/core/timing.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/core/where.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/db/__init__.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/db/cache.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/db/operations.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/db/schema.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/endpoints/__init__.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/endpoints/java_spring.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/endpoints/models.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/endpoints/python_web.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/endpoints/scan.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/errors.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/graph/__init__.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/graph/builder.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/graph/query.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/graph/traverse.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/lang/__init__.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/lang/java/__init__.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/lang/java/engine.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/lang/java/models.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/lang/java/resolve.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/lang/python/__init__.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/lang/python/engine.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/lang/python/models.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/lang/router.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/parser/imports.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/parser/resolve.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/parser/symbols.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/scanner/__init__.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/scanner/scanner.py +0 -0
- {aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/setup.cfg +0 -0
|
@@ -33,6 +33,7 @@ codeintel_cli/commands/project/resolve_cmd.py
|
|
|
33
33
|
codeintel_cli/commands/project/scan_cmd.py
|
|
34
34
|
codeintel_cli/commands/project/servicemap_cmd.py
|
|
35
35
|
codeintel_cli/commands/project/tree_cmd.py
|
|
36
|
+
codeintel_cli/commands/project/types_cmd.py
|
|
36
37
|
codeintel_cli/commands/project/version_cmd.py
|
|
37
38
|
codeintel_cli/context/java_context.py
|
|
38
39
|
codeintel_cli/context/java_rel.py
|
|
@@ -12,6 +12,7 @@ from .modeltree_cmd import register_modeltree
|
|
|
12
12
|
from .models_cmd import register_models
|
|
13
13
|
from .servicemap_cmd import register_servicemap
|
|
14
14
|
from .endpoints_cmd import register_endpoints
|
|
15
|
+
from .types_cmd import register_types_command
|
|
15
16
|
|
|
16
17
|
def register_project_commands(app: typer.Typer) -> None:
|
|
17
18
|
register_scan(app)
|
|
@@ -24,4 +25,5 @@ def register_project_commands(app: typer.Typer) -> None:
|
|
|
24
25
|
register_modeltree(app)
|
|
25
26
|
register_models(app)
|
|
26
27
|
register_servicemap(app)
|
|
27
|
-
register_endpoints(app)
|
|
28
|
+
register_endpoints(app)
|
|
29
|
+
register_types_command(app)
|
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Iterable, Optional, Tuple, Any
|
|
5
|
+
import re
|
|
6
|
+
import typer
|
|
7
|
+
|
|
8
|
+
IGNORE_DIRS = {
|
|
9
|
+
".git", ".idea", ".vscode", ".mvn",
|
|
10
|
+
"__pycache__", ".pytest_cache", ".ruff_cache", ".tox",
|
|
11
|
+
".venv", "venv", "env",
|
|
12
|
+
"node_modules", "dist", "build", "out", "target", ".gradle",
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
PY_MARKERS = {"dto", "schema", "schemas", "model", "models", "types"}
|
|
16
|
+
|
|
17
|
+
REQ_KEYS = ("request", "create", "update", "input", "payload", "command")
|
|
18
|
+
RES_KEYS = ("response", "result", "output", "view")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
# ----------------- file walking -----------------
|
|
22
|
+
def _walk_files(root: Path) -> Iterable[Path]:
|
|
23
|
+
stack = [root]
|
|
24
|
+
while stack:
|
|
25
|
+
cur = stack.pop()
|
|
26
|
+
try:
|
|
27
|
+
for child in cur.iterdir():
|
|
28
|
+
if child.is_dir():
|
|
29
|
+
if child.name not in IGNORE_DIRS:
|
|
30
|
+
stack.append(child)
|
|
31
|
+
else:
|
|
32
|
+
yield child
|
|
33
|
+
except (PermissionError, FileNotFoundError):
|
|
34
|
+
continue
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _is_java_dto(p: Path) -> bool:
|
|
38
|
+
if p.suffix != ".java":
|
|
39
|
+
return False
|
|
40
|
+
parts = [x.lower() for x in p.parts]
|
|
41
|
+
# include auth/dto and dto/request dto/response etc.
|
|
42
|
+
return "dto" in parts
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _is_python_dto_like(p: Path) -> bool:
|
|
46
|
+
if p.suffix != ".py":
|
|
47
|
+
return False
|
|
48
|
+
parts = {part.lower() for part in p.parts}
|
|
49
|
+
return any(m in parts for m in PY_MARKERS)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _rel(p: Path, root: Path) -> str:
|
|
53
|
+
try:
|
|
54
|
+
return str(p.relative_to(root))
|
|
55
|
+
except ValueError:
|
|
56
|
+
return str(p)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def _read_text_limited(p: Path, max_kb: int = 256) -> str:
|
|
60
|
+
try:
|
|
61
|
+
raw = p.read_bytes()
|
|
62
|
+
except Exception:
|
|
63
|
+
return ""
|
|
64
|
+
raw = raw[: max_kb * 1024]
|
|
65
|
+
return raw.decode("utf-8", errors="replace")
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
# ----------------- classification -----------------
|
|
69
|
+
def _classify_java(rel_path: str, type_name: str) -> str:
|
|
70
|
+
r = rel_path.lower().replace("\\", "/")
|
|
71
|
+
n = type_name.lower()
|
|
72
|
+
|
|
73
|
+
# folder-based classification is most reliable in your repo
|
|
74
|
+
if "/dto/request/" in r or r.endswith("/request") or "/request/" in r:
|
|
75
|
+
return "request"
|
|
76
|
+
if "/dto/response/" in r or r.endswith("/response") or "/response/" in r:
|
|
77
|
+
return "response"
|
|
78
|
+
|
|
79
|
+
# name heuristics as fallback
|
|
80
|
+
if any(k in n for k in REQ_KEYS):
|
|
81
|
+
return "request"
|
|
82
|
+
if any(k in n for k in RES_KEYS) or "response" in n:
|
|
83
|
+
return "response"
|
|
84
|
+
return "other"
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
# ----------------- java parsing -----------------
|
|
88
|
+
_record_re = re.compile(
|
|
89
|
+
r"\brecord\s+([A-Za-z_][A-Za-z0-9_]*)\s*\((.*?)\)\s*\{",
|
|
90
|
+
re.S,
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
_class_re = re.compile(
|
|
94
|
+
r"\b(class|record)\s+([A-Za-z_][A-Za-z0-9_]*)\b"
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
_field_re = re.compile(
|
|
98
|
+
# optional annotations lines handled separately; this matches actual field line
|
|
99
|
+
r"^\s*(public|protected|private)?\s*(static\s+)?(final\s+)?([A-Za-z_][\w\<\>\[\]\., ?]+)\s+([A-Za-z_]\w*)\s*(=.*)?;",
|
|
100
|
+
re.M,
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
_annotation_token_re = re.compile(r"^@\w+(\(.*\))?$")
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def _strip_java_annotations_from_type(type_tokens: list[str]) -> list[str]:
|
|
107
|
+
# remove leading annotation tokens like @NotBlank, @Email, @Size(...)
|
|
108
|
+
out = []
|
|
109
|
+
for t in type_tokens:
|
|
110
|
+
if _annotation_token_re.match(t.strip()):
|
|
111
|
+
continue
|
|
112
|
+
out.append(t)
|
|
113
|
+
return out
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def _parse_java_record(src: str) -> Optional[Tuple[str, list[str]]]:
|
|
117
|
+
m = _record_re.search(src)
|
|
118
|
+
if not m:
|
|
119
|
+
return None
|
|
120
|
+
name = m.group(1)
|
|
121
|
+
params = m.group(2).strip()
|
|
122
|
+
if not params:
|
|
123
|
+
return (name, [])
|
|
124
|
+
|
|
125
|
+
# split by commas (naive but ok for typical DTO params)
|
|
126
|
+
parts = []
|
|
127
|
+
buf = []
|
|
128
|
+
depth_angle = 0
|
|
129
|
+
depth_paren = 0
|
|
130
|
+
for ch in params:
|
|
131
|
+
if ch == "<":
|
|
132
|
+
depth_angle += 1
|
|
133
|
+
elif ch == ">":
|
|
134
|
+
depth_angle = max(0, depth_angle - 1)
|
|
135
|
+
elif ch == "(":
|
|
136
|
+
depth_paren += 1
|
|
137
|
+
elif ch == ")":
|
|
138
|
+
depth_paren = max(0, depth_paren - 1)
|
|
139
|
+
|
|
140
|
+
if ch == "," and depth_angle == 0 and depth_paren == 0:
|
|
141
|
+
parts.append("".join(buf).strip())
|
|
142
|
+
buf = []
|
|
143
|
+
else:
|
|
144
|
+
buf.append(ch)
|
|
145
|
+
if buf:
|
|
146
|
+
parts.append("".join(buf).strip())
|
|
147
|
+
|
|
148
|
+
fields: list[str] = []
|
|
149
|
+
for part in parts:
|
|
150
|
+
tokens = part.split()
|
|
151
|
+
if len(tokens) >= 2:
|
|
152
|
+
fname = tokens[-1].strip()
|
|
153
|
+
ftype_tokens = _strip_java_annotations_from_type(tokens[:-1])
|
|
154
|
+
ftype = " ".join(ftype_tokens).strip() or "?"
|
|
155
|
+
fields.append(f"{fname}:{ftype}")
|
|
156
|
+
else:
|
|
157
|
+
fields.append(part)
|
|
158
|
+
|
|
159
|
+
return (name, fields)
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def _parse_java_class_fields(src: str) -> Optional[Tuple[str, list[str]]]:
|
|
163
|
+
# Find first class name (good enough for DTO files)
|
|
164
|
+
cm = _class_re.search(src)
|
|
165
|
+
if not cm:
|
|
166
|
+
return None
|
|
167
|
+
kind = cm.group(1)
|
|
168
|
+
name = cm.group(2)
|
|
169
|
+
if kind == "record":
|
|
170
|
+
# record handled elsewhere
|
|
171
|
+
return None
|
|
172
|
+
|
|
173
|
+
fields: list[str] = []
|
|
174
|
+
for m in _field_re.finditer(src):
|
|
175
|
+
is_static = m.group(2) is not None
|
|
176
|
+
if is_static:
|
|
177
|
+
continue
|
|
178
|
+
|
|
179
|
+
ftype = (m.group(4) or "").strip()
|
|
180
|
+
fname = (m.group(5) or "").strip()
|
|
181
|
+
|
|
182
|
+
# cleanup type
|
|
183
|
+
ftype = re.sub(r"\s+", " ", ftype)
|
|
184
|
+
ftype = ftype.replace(" ?", "?") # tiny cleanup
|
|
185
|
+
|
|
186
|
+
if fname and ftype:
|
|
187
|
+
fields.append(f"{fname}:{ftype}")
|
|
188
|
+
|
|
189
|
+
# de-duplicate while preserving order
|
|
190
|
+
seen = set()
|
|
191
|
+
uniq = []
|
|
192
|
+
for f in fields:
|
|
193
|
+
if f not in seen:
|
|
194
|
+
seen.add(f)
|
|
195
|
+
uniq.append(f)
|
|
196
|
+
|
|
197
|
+
return (name, uniq)
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
# ----------------- python parsing (optional, kept) -----------------
|
|
201
|
+
def _parse_python_dataclasses(src: str) -> list[Tuple[str, list[str]]]:
|
|
202
|
+
out: list[Tuple[str, list[str]]] = []
|
|
203
|
+
lines = src.splitlines()
|
|
204
|
+
|
|
205
|
+
i = 0
|
|
206
|
+
while i < len(lines):
|
|
207
|
+
if lines[i].strip().startswith("@dataclass"):
|
|
208
|
+
j = i + 1
|
|
209
|
+
while j < len(lines) and "class " not in lines[j]:
|
|
210
|
+
j += 1
|
|
211
|
+
if j >= len(lines):
|
|
212
|
+
break
|
|
213
|
+
cm = re.match(r"\s*class\s+([A-Za-z_][A-Za-z0-9_]*)\s*[:\(]", lines[j])
|
|
214
|
+
if not cm:
|
|
215
|
+
i = j + 1
|
|
216
|
+
continue
|
|
217
|
+
|
|
218
|
+
name = cm.group(1)
|
|
219
|
+
|
|
220
|
+
k = j + 1
|
|
221
|
+
fields: list[str] = []
|
|
222
|
+
while k < len(lines):
|
|
223
|
+
raw = lines[k]
|
|
224
|
+
if raw.strip() == "":
|
|
225
|
+
k += 1
|
|
226
|
+
continue
|
|
227
|
+
if not raw.startswith(" ") and not raw.startswith("\t"):
|
|
228
|
+
break
|
|
229
|
+
|
|
230
|
+
s = raw.strip()
|
|
231
|
+
fm = re.match(r"([A-Za-z_][A-Za-z0-9_]*)\s*:\s*([^=]+?)(\s*=\s*(.+))?$", s)
|
|
232
|
+
if fm:
|
|
233
|
+
fname = fm.group(1).strip()
|
|
234
|
+
ftype = fm.group(2).strip()
|
|
235
|
+
default = fm.group(4).strip() if fm.group(4) else None
|
|
236
|
+
fields.append(f"{fname}:{ftype}" + (f"={default}" if default else ""))
|
|
237
|
+
k += 1
|
|
238
|
+
|
|
239
|
+
out.append((name, fields))
|
|
240
|
+
i = k
|
|
241
|
+
else:
|
|
242
|
+
i += 1
|
|
243
|
+
|
|
244
|
+
return out
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
# ----------------- printing -----------------
|
|
248
|
+
def _print_section(title: str) -> None:
|
|
249
|
+
typer.echo("")
|
|
250
|
+
typer.echo(title)
|
|
251
|
+
typer.echo("-" * len(title))
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
def _fmt_item(name: str, fields: list[str], show_path: bool, rel: str) -> str:
|
|
255
|
+
f = ", ".join(fields) if fields else "(no fields found)"
|
|
256
|
+
return f"• {name}: {f}" + (f" ({rel})" if show_path else "")
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
def register_types_command(app: typer.Typer) -> None:
|
|
260
|
+
@app.command("types")
|
|
261
|
+
def types_cmd(
|
|
262
|
+
path: str = typer.Argument(".", help="Project root/folder to scan"),
|
|
263
|
+
contains: str = typer.Option("", "-c", "--contains", help="Filter by path substring"),
|
|
264
|
+
max_files: int = typer.Option(500, "-n", "--max-files", help="Max files per language"),
|
|
265
|
+
max_kb: int = typer.Option(256, "--max-kb", help="Max KB to read per file"),
|
|
266
|
+
show_path: bool = typer.Option(False, "--show-path", help="Show source file path"),
|
|
267
|
+
) -> None:
|
|
268
|
+
root = Path(path).resolve()
|
|
269
|
+
if not root.exists():
|
|
270
|
+
raise typer.BadParameter(f"Path not found: {root}")
|
|
271
|
+
|
|
272
|
+
filt = contains.strip().lower()
|
|
273
|
+
|
|
274
|
+
java_files: list[Path] = []
|
|
275
|
+
py_files: list[Path] = []
|
|
276
|
+
|
|
277
|
+
for f in _walk_files(root):
|
|
278
|
+
rel = _rel(f, root)
|
|
279
|
+
if filt and filt not in rel.lower():
|
|
280
|
+
continue
|
|
281
|
+
if _is_java_dto(f):
|
|
282
|
+
java_files.append(f)
|
|
283
|
+
elif _is_python_dto_like(f):
|
|
284
|
+
py_files.append(f)
|
|
285
|
+
|
|
286
|
+
java_files.sort(key=lambda p: _rel(p, root).lower())
|
|
287
|
+
py_files.sort(key=lambda p: _rel(p, root).lower())
|
|
288
|
+
|
|
289
|
+
typer.echo(f"ROOT: {root}")
|
|
290
|
+
typer.echo(f"Filter: {contains!r}" if contains else "Filter: (none)")
|
|
291
|
+
|
|
292
|
+
# ---- JAVA ----
|
|
293
|
+
java_items: list[dict[str, Any]] = []
|
|
294
|
+
for f in java_files[:max_files]:
|
|
295
|
+
src = _read_text_limited(f, max_kb=max_kb)
|
|
296
|
+
rel = _rel(f, root)
|
|
297
|
+
|
|
298
|
+
parsed = _parse_java_record(src)
|
|
299
|
+
if parsed:
|
|
300
|
+
name, fields = parsed
|
|
301
|
+
kind = _classify_java(rel, name)
|
|
302
|
+
java_items.append({"kind": kind, "name": name, "fields": fields, "path": rel})
|
|
303
|
+
continue
|
|
304
|
+
|
|
305
|
+
parsed2 = _parse_java_class_fields(src)
|
|
306
|
+
if parsed2:
|
|
307
|
+
name, fields = parsed2
|
|
308
|
+
kind = _classify_java(rel, name)
|
|
309
|
+
java_items.append({"kind": kind, "name": name, "fields": fields, "path": rel})
|
|
310
|
+
|
|
311
|
+
# ---- PYTHON ----
|
|
312
|
+
py_items: list[dict[str, Any]] = []
|
|
313
|
+
for f in py_files[:max_files]:
|
|
314
|
+
rel = _rel(f, root)
|
|
315
|
+
if rel.endswith("__init__.py"):
|
|
316
|
+
continue
|
|
317
|
+
src = _read_text_limited(f, max_kb=max_kb)
|
|
318
|
+
for name, fields in _parse_python_dataclasses(src):
|
|
319
|
+
py_items.append({"name": name, "fields": fields, "path": rel})
|
|
320
|
+
|
|
321
|
+
# Print only the sections that exist (clean UX)
|
|
322
|
+
if java_items:
|
|
323
|
+
req = [x for x in java_items if x["kind"] == "request"]
|
|
324
|
+
res = [x for x in java_items if x["kind"] == "response"]
|
|
325
|
+
other = [x for x in java_items if x["kind"] == "other"]
|
|
326
|
+
|
|
327
|
+
_print_section(f"JAVA DTO SUMMARY ({len(java_items)})")
|
|
328
|
+
|
|
329
|
+
if req:
|
|
330
|
+
_print_section(f"WHAT WE SEND (REQUEST) ({len(req)})")
|
|
331
|
+
for x in req:
|
|
332
|
+
typer.echo(_fmt_item(x["name"], x["fields"], show_path, x["path"]))
|
|
333
|
+
|
|
334
|
+
if res:
|
|
335
|
+
_print_section(f"WHAT WE RECEIVE (RESPONSE) ({len(res)})")
|
|
336
|
+
for x in res:
|
|
337
|
+
typer.echo(_fmt_item(x["name"], x["fields"], show_path, x["path"]))
|
|
338
|
+
|
|
339
|
+
if other:
|
|
340
|
+
_print_section(f"OTHER JAVA DTO ({len(other)})")
|
|
341
|
+
for x in other:
|
|
342
|
+
typer.echo(_fmt_item(x["name"], x["fields"], show_path, x["path"]))
|
|
343
|
+
|
|
344
|
+
if py_items:
|
|
345
|
+
_print_section(f"PYTHON DTO/MODEL SUMMARY ({len(py_items)})")
|
|
346
|
+
for x in py_items:
|
|
347
|
+
typer.echo(_fmt_item(x["name"], x["fields"], show_path, x["path"]))
|
|
348
|
+
|
|
349
|
+
if not java_items and not py_items:
|
|
350
|
+
typer.echo("")
|
|
351
|
+
typer.echo("(no DTO-like types found)")
|
|
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
|
{aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/commands/graph/reverse_related_cmd.py
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
|
{aja_codeintel-0.1.2 → aja_codeintel-0.1.3}/codeintel_cli/commands/project/servicemap_cmd.py
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
|