cg-code-graph 0.10.1__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.
- cg_code_graph-0.10.1.dist-info/METADATA +678 -0
- cg_code_graph-0.10.1.dist-info/RECORD +174 -0
- cg_code_graph-0.10.1.dist-info/WHEEL +5 -0
- cg_code_graph-0.10.1.dist-info/entry_points.txt +3 -0
- cg_code_graph-0.10.1.dist-info/licenses/LICENSE +21 -0
- cg_code_graph-0.10.1.dist-info/top_level.txt +1 -0
- codegraph/__init__.py +2 -0
- codegraph/aitools.py +129 -0
- codegraph/apps.py +76 -0
- codegraph/blindspots.py +428 -0
- codegraph/bridges.py +1701 -0
- codegraph/cli.py +725 -0
- codegraph/concepts.py +362 -0
- codegraph/config.py +559 -0
- codegraph/core/__init__.py +0 -0
- codegraph/core/cache.py +375 -0
- codegraph/core/detect.py +80 -0
- codegraph/core/extractors.py +187 -0
- codegraph/core/fsutil.py +61 -0
- codegraph/core/generated.py +575 -0
- codegraph/core/model.py +174 -0
- codegraph/core/paths.py +175 -0
- codegraph/core/plugin.py +160 -0
- codegraph/core/store.py +80 -0
- codegraph/core/syntax_errors.py +132 -0
- codegraph/coverage.py +928 -0
- codegraph/doctor.py +453 -0
- codegraph/external.py +613 -0
- codegraph/indexer.py +336 -0
- codegraph/link.py +434 -0
- codegraph/lint_async.py +524 -0
- codegraph/mcp_server.py +1303 -0
- codegraph/parity.py +473 -0
- codegraph/parity_structure.py +307 -0
- codegraph/payload.py +321 -0
- codegraph/plans.py +1285 -0
- codegraph/platform_scan.py +643 -0
- codegraph/platforms.py +1369 -0
- codegraph/plugins/__init__.py +0 -0
- codegraph/plugins/cfamily/__init__.py +0 -0
- codegraph/plugins/cfamily/plugin.py +930 -0
- codegraph/plugins/cfamily/syntax.py +881 -0
- codegraph/plugins/dart/__init__.py +0 -0
- codegraph/plugins/dart/bridges.py +345 -0
- codegraph/plugins/dart/extractor/bin/extract.dart +717 -0
- codegraph/plugins/dart/extractor/pubspec.lock +149 -0
- codegraph/plugins/dart/extractor/pubspec.yaml +7 -0
- codegraph/plugins/dart/http.py +904 -0
- codegraph/plugins/dart/models.py +308 -0
- codegraph/plugins/dart/plugin.py +625 -0
- codegraph/plugins/dart/program.py +907 -0
- codegraph/plugins/django/__init__.py +0 -0
- codegraph/plugins/django/extras.py +378 -0
- codegraph/plugins/django/models.py +508 -0
- codegraph/plugins/django/plugin.py +728 -0
- codegraph/plugins/django/schemas.py +339 -0
- codegraph/plugins/django/shapes.py +216 -0
- codegraph/plugins/django/urls.py +603 -0
- codegraph/plugins/express/__init__.py +0 -0
- codegraph/plugins/express/plugin.py +428 -0
- codegraph/plugins/flutter/__init__.py +0 -0
- codegraph/plugins/flutter/plugin.py +538 -0
- codegraph/plugins/kotlin/__init__.py +0 -0
- codegraph/plugins/kotlin/exact.py +457 -0
- codegraph/plugins/kotlin/plugin.py +1961 -0
- codegraph/plugins/kotlin/reparse.py +234 -0
- codegraph/plugins/laravel/__init__.py +0 -0
- codegraph/plugins/laravel/broadcast.py +351 -0
- codegraph/plugins/laravel/plugin.py +863 -0
- codegraph/plugins/laravel/tests.py +262 -0
- codegraph/plugins/laravel/values.py +728 -0
- codegraph/plugins/native/__init__.py +0 -0
- codegraph/plugins/native/gates.py +286 -0
- codegraph/plugins/native/runner.py +183 -0
- codegraph/plugins/native/scipread.py +194 -0
- codegraph/plugins/native/ts.py +54 -0
- codegraph/plugins/nest/__init__.py +0 -0
- codegraph/plugins/nest/plugin.py +654 -0
- codegraph/plugins/nextjs/__init__.py +0 -0
- codegraph/plugins/nextjs/plugin.py +336 -0
- codegraph/plugins/nuxt/__init__.py +0 -0
- codegraph/plugins/nuxt/plugin.py +308 -0
- codegraph/plugins/php/__init__.py +0 -0
- codegraph/plugins/php/extractor/composer.json +5 -0
- codegraph/plugins/php/extractor/composer.lock +76 -0
- codegraph/plugins/php/extractor/extract.php +743 -0
- codegraph/plugins/php/gating.py +573 -0
- codegraph/plugins/php/plugin.py +668 -0
- codegraph/plugins/php/strings.py +197 -0
- codegraph/plugins/python/__init__.py +0 -0
- codegraph/plugins/python/aitools.py +664 -0
- codegraph/plugins/python/external.py +245 -0
- codegraph/plugins/python/fields.py +107 -0
- codegraph/plugins/python/plugin.py +1733 -0
- codegraph/plugins/python/refs.py +485 -0
- codegraph/plugins/python/roots.py +412 -0
- codegraph/plugins/python/socketio.py +210 -0
- codegraph/plugins/python/subproc.py +864 -0
- codegraph/plugins/python/tests.py +1040 -0
- codegraph/plugins/python/values.py +179 -0
- codegraph/plugins/pyweb/__init__.py +0 -0
- codegraph/plugins/pyweb/plugin.py +1334 -0
- codegraph/plugins/pyweb/values.py +68 -0
- codegraph/plugins/rust/__init__.py +0 -0
- codegraph/plugins/rust/cargo.py +226 -0
- codegraph/plugins/rust/plugin.py +980 -0
- codegraph/plugins/rust/syntax.py +678 -0
- codegraph/plugins/scip/__init__.py +0 -0
- codegraph/plugins/scip/importer.py +129 -0
- codegraph/plugins/scip/scip.proto +962 -0
- codegraph/plugins/scip/scip_pb2.py +97 -0
- codegraph/plugins/stubs/__init__.py +0 -0
- codegraph/plugins/stubs/plugins.py +38 -0
- codegraph/plugins/swift/__init__.py +0 -0
- codegraph/plugins/swift/baseurl.py +109 -0
- codegraph/plugins/swift/exact.py +415 -0
- codegraph/plugins/swift/indexstore.py +209 -0
- codegraph/plugins/swift/packages.py +174 -0
- codegraph/plugins/swift/plugin.py +2890 -0
- codegraph/plugins/ts/__init__.py +0 -0
- codegraph/plugins/ts/baseurl.py +185 -0
- codegraph/plugins/ts/extractor/extract.mjs +2652 -0
- codegraph/plugins/ts/extractor/fw.mjs +685 -0
- codegraph/plugins/ts/extractor/package-lock.json +205 -0
- codegraph/plugins/ts/extractor/package.json +9 -0
- codegraph/plugins/ts/plugin.py +480 -0
- codegraph/plugins/tsweb/__init__.py +0 -0
- codegraph/plugins/tsweb/common.py +290 -0
- codegraph/plugins/tsweb/data.py +276 -0
- codegraph/presets/__init__.py +146 -0
- codegraph/presets/c_cpp.yaml +9 -0
- codegraph/presets/common.yaml +66 -0
- codegraph/presets/dart.yaml +9 -0
- codegraph/presets/django-ninja.yaml +15 -0
- codegraph/presets/django.yaml +25 -0
- codegraph/presets/djangorestframework.yaml +17 -0
- codegraph/presets/express.yaml +17 -0
- codegraph/presets/kotlin.yaml +11 -0
- codegraph/presets/laravel.yaml +40 -0
- codegraph/presets/nest.yaml +11 -0
- codegraph/presets/nextjs.yaml +15 -0
- codegraph/presets/nuxt.yaml +9 -0
- codegraph/presets/php.yaml +5 -0
- codegraph/presets/python.yaml +10 -0
- codegraph/presets/rust.yaml +5 -0
- codegraph/presets/swift.yaml +10 -0
- codegraph/presets/typescript.yaml +13 -0
- codegraph/process_runs.py +328 -0
- codegraph/protocols/__init__.py +299 -0
- codegraph/protocols/builtin.py +67 -0
- codegraph/protocols/matchers.py +144 -0
- codegraph/protocols/view.py +334 -0
- codegraph/query.py +2089 -0
- codegraph/realtime.py +260 -0
- codegraph/roundtrip.py +346 -0
- codegraph/routes.py +442 -0
- codegraph/starters.py +218 -0
- codegraph/tests_index.py +117 -0
- codegraph/viz/__init__.py +0 -0
- codegraph/viz/graph.py +369 -0
- codegraph/viz/server.py +198 -0
- codegraph/viz/static/app.css +148 -0
- codegraph/viz/static/app.js +1082 -0
- codegraph/viz/static/index.html +81 -0
- codegraph/viz/static/layered.js +237 -0
- codegraph/viz/static/vendor/VERSIONS.txt +4 -0
- codegraph/viz/static/vendor/cose-base.js +3214 -0
- codegraph/viz/static/vendor/cytoscape-fcose.js +1549 -0
- codegraph/viz/static/vendor/cytoscape.min.js +31 -0
- codegraph/viz/static/vendor/layout-base.js +5230 -0
- codegraph/viz/tools/package-lock.json +303 -0
- codegraph/viz/tools/package.json +7 -0
- codegraph/viz/tools/shoot.mjs +165 -0
- codegraph/xcode.py +251 -0
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
"""Static evaluation of PHP string expressions into name patterns.
|
|
2
|
+
|
|
3
|
+
Used for broadcast channel names (`"orders.{$this->order->id}"`, helper methods that build names, values passed
|
|
4
|
+
in at `new Event(...)` sites) and for URLs in HTTP tests. The result is a small set of patterns in which every
|
|
5
|
+
part that is unknown statically is a `{placeholder}`.
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import itertools
|
|
10
|
+
import re
|
|
11
|
+
|
|
12
|
+
MAX_ALTS = 8
|
|
13
|
+
PH_RE = re.compile(r"\{[^{}]*\}")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _short(d) -> str:
|
|
17
|
+
"""Placeholder name for a dynamic expression: `$x` -> x, `$a->b->id` -> id, `$o->getKey()` -> key."""
|
|
18
|
+
if not d:
|
|
19
|
+
return "?"
|
|
20
|
+
k = d.get("k")
|
|
21
|
+
if k == "var":
|
|
22
|
+
return d.get("n") or "?"
|
|
23
|
+
if k in ("prop", "sprop"):
|
|
24
|
+
return d.get("n") or "?"
|
|
25
|
+
if k in ("mcall", "scall"):
|
|
26
|
+
m = d.get("m") or "?"
|
|
27
|
+
return m[3].lower() + m[4:] if m.startswith("get") and len(m) > 3 else m
|
|
28
|
+
if k == "dim" and (d.get("key") or {}).get("k") == "str":
|
|
29
|
+
return d["key"]["v"]
|
|
30
|
+
if k == "func":
|
|
31
|
+
a = d.get("args") or []
|
|
32
|
+
return _short(a[0]) if a else (d.get("n") or "?")
|
|
33
|
+
return "?"
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class StrEval:
|
|
37
|
+
def __init__(self, prog):
|
|
38
|
+
self.prog = prog
|
|
39
|
+
|
|
40
|
+
def eval(self, d, fn, bind=None, depth=0) -> list[str]:
|
|
41
|
+
out = self._ev(d, fn, bind or {}, depth)
|
|
42
|
+
seen, res = set(), []
|
|
43
|
+
for s in out:
|
|
44
|
+
if s not in seen:
|
|
45
|
+
seen.add(s)
|
|
46
|
+
res.append(s)
|
|
47
|
+
return res[:MAX_ALTS]
|
|
48
|
+
|
|
49
|
+
def _prod(self, lists) -> list[str]:
|
|
50
|
+
out = []
|
|
51
|
+
for combo in itertools.product(*lists):
|
|
52
|
+
out.append("".join(combo))
|
|
53
|
+
if len(out) >= MAX_ALTS:
|
|
54
|
+
break
|
|
55
|
+
return out
|
|
56
|
+
|
|
57
|
+
def _ev(self, d, fn, bind, depth) -> list[str]:
|
|
58
|
+
if not d or depth > 10:
|
|
59
|
+
return ["{?}"]
|
|
60
|
+
k = d.get("k")
|
|
61
|
+
if k == "str":
|
|
62
|
+
return [d.get("v") or ""]
|
|
63
|
+
if k == "int":
|
|
64
|
+
return [str(d.get("v"))]
|
|
65
|
+
if k == "interp":
|
|
66
|
+
return self._prod([self._ev(p, fn, bind, depth + 1) for p in d.get("parts") or []])
|
|
67
|
+
if k == "concat":
|
|
68
|
+
return self._prod([self._ev(d.get("l"), fn, bind, depth + 1), self._ev(d.get("r"), fn, bind, depth + 1)])
|
|
69
|
+
if k == "alt":
|
|
70
|
+
out = []
|
|
71
|
+
for o in d.get("opts") or []:
|
|
72
|
+
out += self._ev(o, fn, bind, depth + 1)
|
|
73
|
+
return out[:MAX_ALTS]
|
|
74
|
+
if k == "var":
|
|
75
|
+
n = d.get("n")
|
|
76
|
+
if n in bind:
|
|
77
|
+
bd, bfn, bb = bind[n]
|
|
78
|
+
return self._ev(bd, bfn, bb, depth + 1)
|
|
79
|
+
assigns = [f for f in fn.facts if f.get("t") == "assign" and f.get("var") == n]
|
|
80
|
+
if 0 < len(assigns) <= 3:
|
|
81
|
+
out = []
|
|
82
|
+
for a in assigns:
|
|
83
|
+
out += self._ev(a["expr"], fn, {}, depth + 1)
|
|
84
|
+
return out[:MAX_ALTS]
|
|
85
|
+
return ["{" + (n or "?") + "}"]
|
|
86
|
+
if k == "prop":
|
|
87
|
+
if (d.get("of") or {}).get("k") == "this":
|
|
88
|
+
return ["{this." + (d.get("n") or "?") + "}"]
|
|
89
|
+
return ["{" + _short(d) + "}"]
|
|
90
|
+
if k == "const":
|
|
91
|
+
v = self.class_const(d.get("class"), d.get("n"))
|
|
92
|
+
return [str(v)] if isinstance(v, (str, int)) else ["{" + (d.get("n") or "?") + "}"]
|
|
93
|
+
if k in ("mcall", "scall", "func"):
|
|
94
|
+
r = self._call(d, fn, bind, depth)
|
|
95
|
+
if r is not None:
|
|
96
|
+
return r
|
|
97
|
+
return ["{" + _short(d) + "}"]
|
|
98
|
+
if k == "dim":
|
|
99
|
+
return ["{" + _short(d) + "}"]
|
|
100
|
+
return ["{?}"]
|
|
101
|
+
|
|
102
|
+
def class_const(self, cls, name):
|
|
103
|
+
if not cls or not name:
|
|
104
|
+
return None
|
|
105
|
+
for a in self.prog.ancestors(cls):
|
|
106
|
+
c = self.prog.cls(a)
|
|
107
|
+
if c:
|
|
108
|
+
for k in c.consts:
|
|
109
|
+
if k.get("name") == name:
|
|
110
|
+
return k.get("value")
|
|
111
|
+
return None
|
|
112
|
+
|
|
113
|
+
def _call(self, d, fn, bind, depth):
|
|
114
|
+
k = d.get("k")
|
|
115
|
+
args = d.get("args") or []
|
|
116
|
+
if k == "func":
|
|
117
|
+
n = (d.get("n") or "").lower().lstrip("\\")
|
|
118
|
+
if n in ("sprintf", "vsprintf") and args and args[0].get("k") == "str":
|
|
119
|
+
return self._sprintf(args[0]["v"], args[1:], fn, bind, depth)
|
|
120
|
+
if n in ("strtolower", "strtoupper", "trim", "strval", "str", "e") and args:
|
|
121
|
+
return self._ev(args[0], fn, bind, depth + 1)
|
|
122
|
+
if n == "implode" and len(args) == 2 and args[1].get("k") == "arr" and args[0].get("k") == "str":
|
|
123
|
+
lists = []
|
|
124
|
+
for j, it in enumerate(args[1].get("items") or []):
|
|
125
|
+
if j:
|
|
126
|
+
lists.append([args[0]["v"]])
|
|
127
|
+
lists.append(self._ev(it.get("v"), fn, bind, depth + 1))
|
|
128
|
+
return self._prod(lists) if lists else [""]
|
|
129
|
+
target = self.prog.functions.get(n)
|
|
130
|
+
elif k == "scall":
|
|
131
|
+
c = d.get("class")
|
|
132
|
+
target = self.prog.find_method(c, d.get("m")) if c and self.prog.cls(c) else None
|
|
133
|
+
else:
|
|
134
|
+
target = None
|
|
135
|
+
of = d.get("of") or {}
|
|
136
|
+
if of.get("k") == "this" and fn.cls:
|
|
137
|
+
target = self.prog.find_method(fn.cls, d.get("m"))
|
|
138
|
+
if not target or target.abstract:
|
|
139
|
+
return None
|
|
140
|
+
rets = [f for f in target.facts if f.get("t") == "return" and not f.get("ctx")]
|
|
141
|
+
if not rets:
|
|
142
|
+
return None
|
|
143
|
+
nb = {}
|
|
144
|
+
for i, p in enumerate(target.params):
|
|
145
|
+
a = next((x for x in args if x.get("named") == p["name"]), None)
|
|
146
|
+
if a is None and i < len(args) and not args[i].get("named"):
|
|
147
|
+
a = args[i]
|
|
148
|
+
if a is not None:
|
|
149
|
+
nb[p["name"]] = (a, fn, bind)
|
|
150
|
+
out = []
|
|
151
|
+
for r in rets[:4]:
|
|
152
|
+
out += self._ev(r["expr"], target, nb, depth + 1)
|
|
153
|
+
return out[:MAX_ALTS]
|
|
154
|
+
|
|
155
|
+
def _sprintf(self, fmt, args, fn, bind, depth):
|
|
156
|
+
pieces = re.split(r"(%(?:\d+\$)?[-+ 0']*\d*(?:\.\d+)?[sdfuxX])", fmt)
|
|
157
|
+
lists, i = [], 0
|
|
158
|
+
for p in pieces:
|
|
159
|
+
m = re.fullmatch(r"%(?:(\d+)\$)?[-+ 0']*\d*(?:\.\d+)?[sdfuxX]", p)
|
|
160
|
+
if m:
|
|
161
|
+
idx = int(m.group(1)) - 1 if m.group(1) else i
|
|
162
|
+
i += 1
|
|
163
|
+
lists.append(self._ev(args[idx], fn, bind, depth + 1) if idx < len(args) else ["{?}"])
|
|
164
|
+
else:
|
|
165
|
+
lists.append([p.replace("%%", "%")])
|
|
166
|
+
return self._prod(lists)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def pattern_regex(p: str) -> str:
|
|
170
|
+
out = []
|
|
171
|
+
for part in re.split(r"(\{[^{}]*\})", p):
|
|
172
|
+
if not part:
|
|
173
|
+
continue
|
|
174
|
+
out.append("[^.]+" if part.startswith("{") and part.endswith("}") else re.escape(part))
|
|
175
|
+
return "".join(out)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def concrete(p: str) -> str:
|
|
179
|
+
return PH_RE.sub("X", p)
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def fully_dynamic(p: str) -> bool:
|
|
183
|
+
return not PH_RE.sub("", p).strip(". -_:/")
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def same_shape(a: str, b: str) -> bool:
|
|
187
|
+
return PH_RE.sub("{}", a) == PH_RE.sub("{}", b)
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def channel_match(name: str, declared: str) -> bool:
|
|
191
|
+
"""A published / subscribed channel name (placeholders = runtime values) fits a declared channel pattern."""
|
|
192
|
+
if fully_dynamic(name):
|
|
193
|
+
return False
|
|
194
|
+
if re.fullmatch(pattern_regex(declared), concrete(name)):
|
|
195
|
+
return True
|
|
196
|
+
# a placeholder on the publishing side may itself stand for a dotted value (`{channel}`): try the reverse fit
|
|
197
|
+
return bool(re.fullmatch(pattern_regex(name), concrete(declared)))
|
|
File without changes
|