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.
Files changed (174) hide show
  1. cg_code_graph-0.10.1.dist-info/METADATA +678 -0
  2. cg_code_graph-0.10.1.dist-info/RECORD +174 -0
  3. cg_code_graph-0.10.1.dist-info/WHEEL +5 -0
  4. cg_code_graph-0.10.1.dist-info/entry_points.txt +3 -0
  5. cg_code_graph-0.10.1.dist-info/licenses/LICENSE +21 -0
  6. cg_code_graph-0.10.1.dist-info/top_level.txt +1 -0
  7. codegraph/__init__.py +2 -0
  8. codegraph/aitools.py +129 -0
  9. codegraph/apps.py +76 -0
  10. codegraph/blindspots.py +428 -0
  11. codegraph/bridges.py +1701 -0
  12. codegraph/cli.py +725 -0
  13. codegraph/concepts.py +362 -0
  14. codegraph/config.py +559 -0
  15. codegraph/core/__init__.py +0 -0
  16. codegraph/core/cache.py +375 -0
  17. codegraph/core/detect.py +80 -0
  18. codegraph/core/extractors.py +187 -0
  19. codegraph/core/fsutil.py +61 -0
  20. codegraph/core/generated.py +575 -0
  21. codegraph/core/model.py +174 -0
  22. codegraph/core/paths.py +175 -0
  23. codegraph/core/plugin.py +160 -0
  24. codegraph/core/store.py +80 -0
  25. codegraph/core/syntax_errors.py +132 -0
  26. codegraph/coverage.py +928 -0
  27. codegraph/doctor.py +453 -0
  28. codegraph/external.py +613 -0
  29. codegraph/indexer.py +336 -0
  30. codegraph/link.py +434 -0
  31. codegraph/lint_async.py +524 -0
  32. codegraph/mcp_server.py +1303 -0
  33. codegraph/parity.py +473 -0
  34. codegraph/parity_structure.py +307 -0
  35. codegraph/payload.py +321 -0
  36. codegraph/plans.py +1285 -0
  37. codegraph/platform_scan.py +643 -0
  38. codegraph/platforms.py +1369 -0
  39. codegraph/plugins/__init__.py +0 -0
  40. codegraph/plugins/cfamily/__init__.py +0 -0
  41. codegraph/plugins/cfamily/plugin.py +930 -0
  42. codegraph/plugins/cfamily/syntax.py +881 -0
  43. codegraph/plugins/dart/__init__.py +0 -0
  44. codegraph/plugins/dart/bridges.py +345 -0
  45. codegraph/plugins/dart/extractor/bin/extract.dart +717 -0
  46. codegraph/plugins/dart/extractor/pubspec.lock +149 -0
  47. codegraph/plugins/dart/extractor/pubspec.yaml +7 -0
  48. codegraph/plugins/dart/http.py +904 -0
  49. codegraph/plugins/dart/models.py +308 -0
  50. codegraph/plugins/dart/plugin.py +625 -0
  51. codegraph/plugins/dart/program.py +907 -0
  52. codegraph/plugins/django/__init__.py +0 -0
  53. codegraph/plugins/django/extras.py +378 -0
  54. codegraph/plugins/django/models.py +508 -0
  55. codegraph/plugins/django/plugin.py +728 -0
  56. codegraph/plugins/django/schemas.py +339 -0
  57. codegraph/plugins/django/shapes.py +216 -0
  58. codegraph/plugins/django/urls.py +603 -0
  59. codegraph/plugins/express/__init__.py +0 -0
  60. codegraph/plugins/express/plugin.py +428 -0
  61. codegraph/plugins/flutter/__init__.py +0 -0
  62. codegraph/plugins/flutter/plugin.py +538 -0
  63. codegraph/plugins/kotlin/__init__.py +0 -0
  64. codegraph/plugins/kotlin/exact.py +457 -0
  65. codegraph/plugins/kotlin/plugin.py +1961 -0
  66. codegraph/plugins/kotlin/reparse.py +234 -0
  67. codegraph/plugins/laravel/__init__.py +0 -0
  68. codegraph/plugins/laravel/broadcast.py +351 -0
  69. codegraph/plugins/laravel/plugin.py +863 -0
  70. codegraph/plugins/laravel/tests.py +262 -0
  71. codegraph/plugins/laravel/values.py +728 -0
  72. codegraph/plugins/native/__init__.py +0 -0
  73. codegraph/plugins/native/gates.py +286 -0
  74. codegraph/plugins/native/runner.py +183 -0
  75. codegraph/plugins/native/scipread.py +194 -0
  76. codegraph/plugins/native/ts.py +54 -0
  77. codegraph/plugins/nest/__init__.py +0 -0
  78. codegraph/plugins/nest/plugin.py +654 -0
  79. codegraph/plugins/nextjs/__init__.py +0 -0
  80. codegraph/plugins/nextjs/plugin.py +336 -0
  81. codegraph/plugins/nuxt/__init__.py +0 -0
  82. codegraph/plugins/nuxt/plugin.py +308 -0
  83. codegraph/plugins/php/__init__.py +0 -0
  84. codegraph/plugins/php/extractor/composer.json +5 -0
  85. codegraph/plugins/php/extractor/composer.lock +76 -0
  86. codegraph/plugins/php/extractor/extract.php +743 -0
  87. codegraph/plugins/php/gating.py +573 -0
  88. codegraph/plugins/php/plugin.py +668 -0
  89. codegraph/plugins/php/strings.py +197 -0
  90. codegraph/plugins/python/__init__.py +0 -0
  91. codegraph/plugins/python/aitools.py +664 -0
  92. codegraph/plugins/python/external.py +245 -0
  93. codegraph/plugins/python/fields.py +107 -0
  94. codegraph/plugins/python/plugin.py +1733 -0
  95. codegraph/plugins/python/refs.py +485 -0
  96. codegraph/plugins/python/roots.py +412 -0
  97. codegraph/plugins/python/socketio.py +210 -0
  98. codegraph/plugins/python/subproc.py +864 -0
  99. codegraph/plugins/python/tests.py +1040 -0
  100. codegraph/plugins/python/values.py +179 -0
  101. codegraph/plugins/pyweb/__init__.py +0 -0
  102. codegraph/plugins/pyweb/plugin.py +1334 -0
  103. codegraph/plugins/pyweb/values.py +68 -0
  104. codegraph/plugins/rust/__init__.py +0 -0
  105. codegraph/plugins/rust/cargo.py +226 -0
  106. codegraph/plugins/rust/plugin.py +980 -0
  107. codegraph/plugins/rust/syntax.py +678 -0
  108. codegraph/plugins/scip/__init__.py +0 -0
  109. codegraph/plugins/scip/importer.py +129 -0
  110. codegraph/plugins/scip/scip.proto +962 -0
  111. codegraph/plugins/scip/scip_pb2.py +97 -0
  112. codegraph/plugins/stubs/__init__.py +0 -0
  113. codegraph/plugins/stubs/plugins.py +38 -0
  114. codegraph/plugins/swift/__init__.py +0 -0
  115. codegraph/plugins/swift/baseurl.py +109 -0
  116. codegraph/plugins/swift/exact.py +415 -0
  117. codegraph/plugins/swift/indexstore.py +209 -0
  118. codegraph/plugins/swift/packages.py +174 -0
  119. codegraph/plugins/swift/plugin.py +2890 -0
  120. codegraph/plugins/ts/__init__.py +0 -0
  121. codegraph/plugins/ts/baseurl.py +185 -0
  122. codegraph/plugins/ts/extractor/extract.mjs +2652 -0
  123. codegraph/plugins/ts/extractor/fw.mjs +685 -0
  124. codegraph/plugins/ts/extractor/package-lock.json +205 -0
  125. codegraph/plugins/ts/extractor/package.json +9 -0
  126. codegraph/plugins/ts/plugin.py +480 -0
  127. codegraph/plugins/tsweb/__init__.py +0 -0
  128. codegraph/plugins/tsweb/common.py +290 -0
  129. codegraph/plugins/tsweb/data.py +276 -0
  130. codegraph/presets/__init__.py +146 -0
  131. codegraph/presets/c_cpp.yaml +9 -0
  132. codegraph/presets/common.yaml +66 -0
  133. codegraph/presets/dart.yaml +9 -0
  134. codegraph/presets/django-ninja.yaml +15 -0
  135. codegraph/presets/django.yaml +25 -0
  136. codegraph/presets/djangorestframework.yaml +17 -0
  137. codegraph/presets/express.yaml +17 -0
  138. codegraph/presets/kotlin.yaml +11 -0
  139. codegraph/presets/laravel.yaml +40 -0
  140. codegraph/presets/nest.yaml +11 -0
  141. codegraph/presets/nextjs.yaml +15 -0
  142. codegraph/presets/nuxt.yaml +9 -0
  143. codegraph/presets/php.yaml +5 -0
  144. codegraph/presets/python.yaml +10 -0
  145. codegraph/presets/rust.yaml +5 -0
  146. codegraph/presets/swift.yaml +10 -0
  147. codegraph/presets/typescript.yaml +13 -0
  148. codegraph/process_runs.py +328 -0
  149. codegraph/protocols/__init__.py +299 -0
  150. codegraph/protocols/builtin.py +67 -0
  151. codegraph/protocols/matchers.py +144 -0
  152. codegraph/protocols/view.py +334 -0
  153. codegraph/query.py +2089 -0
  154. codegraph/realtime.py +260 -0
  155. codegraph/roundtrip.py +346 -0
  156. codegraph/routes.py +442 -0
  157. codegraph/starters.py +218 -0
  158. codegraph/tests_index.py +117 -0
  159. codegraph/viz/__init__.py +0 -0
  160. codegraph/viz/graph.py +369 -0
  161. codegraph/viz/server.py +198 -0
  162. codegraph/viz/static/app.css +148 -0
  163. codegraph/viz/static/app.js +1082 -0
  164. codegraph/viz/static/index.html +81 -0
  165. codegraph/viz/static/layered.js +237 -0
  166. codegraph/viz/static/vendor/VERSIONS.txt +4 -0
  167. codegraph/viz/static/vendor/cose-base.js +3214 -0
  168. codegraph/viz/static/vendor/cytoscape-fcose.js +1549 -0
  169. codegraph/viz/static/vendor/cytoscape.min.js +31 -0
  170. codegraph/viz/static/vendor/layout-base.js +5230 -0
  171. codegraph/viz/tools/package-lock.json +303 -0
  172. codegraph/viz/tools/package.json +7 -0
  173. codegraph/viz/tools/shoot.mjs +165 -0
  174. codegraph/xcode.py +251 -0
@@ -0,0 +1,174 @@
1
+ """SwiftPM modules (#90): the targets of every local `Package.swift`, the folder each one compiles and the targets
2
+ it depends on (its own `dependencies:`, `.product(name:package:)` of local packages, transitively). A file in a
3
+ package target sees only its own module and those dependencies, never app, extension, preview or test code; a file
4
+ outside every package target (an Xcode app, extension or preview folder) sees everything it links."""
5
+ from __future__ import annotations
6
+
7
+ import re
8
+ from pathlib import Path
9
+
10
+ TARGET = re.compile(r"\.(target|executableTarget|testTarget|macro|plugin|systemLibrary|binaryTarget)\s*\(\s*name\s*:\s*\"([^\"]+)\"")
11
+ PRODUCT = re.compile(r"\.(?:library|executable|plugin)\s*\(\s*name\s*:\s*\"([^\"]+)\"[^)]*?targets\s*:\s*\[([^\]]*)\]", re.S)
12
+ DEP_PRODUCT = re.compile(r"\.product\s*\(\s*name\s*:\s*\"([^\"]+)\"")
13
+ DEP_NAMED = re.compile(r"\.(?:target|byName)\s*\(\s*name\s*:\s*\"([^\"]+)\"")
14
+ DEP_STRING = re.compile(r"(?<![:\w])\s*\"([^\"]+)\"")
15
+
16
+
17
+ def _call_body(txt: str, start: int) -> tuple[str, int]:
18
+ """The text of the parenthesised call opening at or after `start`, up to its closing parenthesis (parentheses
19
+ inside string literals do not count), and the offset of that parenthesis."""
20
+ i = txt.find("(", start)
21
+ depth, j = 0, i
22
+ while 0 <= j < len(txt):
23
+ c = txt[j]
24
+ if c == "(":
25
+ depth += 1
26
+ elif c == ")":
27
+ depth -= 1
28
+ if depth == 0:
29
+ return txt[i + 1:j], j
30
+ elif c == '"':
31
+ k = txt.find('"', j + 1)
32
+ if k < 0:
33
+ break
34
+ j = k
35
+ j += 1
36
+ return txt[i + 1:], len(txt)
37
+
38
+
39
+ def _array(body: str, key: str) -> str | None:
40
+ m = re.search(rf"\b{key}\s*:\s*\[", body)
41
+ if not m:
42
+ return None
43
+ depth, i = 0, m.end() - 1
44
+ for j in range(i, len(body)):
45
+ if body[j] == "[":
46
+ depth += 1
47
+ elif body[j] == "]":
48
+ depth -= 1
49
+ if depth == 0:
50
+ return body[i + 1:j]
51
+ return body[i + 1:]
52
+
53
+
54
+ class SwiftPM:
55
+ def __init__(self, root: Path, files: list[str] | None = None):
56
+ """`files`: the project's Swift files as the index walks them (skip presets applied); the manifests are the
57
+ `Package.swift` among them (default: the root and up to three folders down)."""
58
+ self.root = root
59
+ self._files = files
60
+ self.targets: dict[str, dict] = {} # "<package dir>:<name>" -> {name, path, deps (raw), kind}
61
+ self.products: dict[str, set[str]] = {} # product name -> target keys
62
+ self.manifests: list[str] = []
63
+ for pk in sorted(self._manifests()):
64
+ self._parse(pk)
65
+ by_name: dict[str, list[str]] = {}
66
+ for k, t in self.targets.items():
67
+ by_name.setdefault(t["name"], []).append(k)
68
+ self.visible: dict[str, set[str]] = {}
69
+ direct = {}
70
+ for k, t in self.targets.items():
71
+ pkg = k.rsplit(":", 1)[0]
72
+ out = set()
73
+ for kind, name in t["deps"]:
74
+ same = f"{pkg}:{name}"
75
+ if kind != "product" and same in self.targets:
76
+ out.add(same)
77
+ elif name in self.products:
78
+ out |= self.products[name]
79
+ elif kind != "product":
80
+ out |= set(by_name.get(name, ()))
81
+ direct[k] = out
82
+ for k in self.targets:
83
+ seen, todo = {k}, [k]
84
+ while todo:
85
+ for d in direct.get(todo.pop(), ()):
86
+ if d not in seen:
87
+ seen.add(d)
88
+ todo.append(d)
89
+ self.visible[k] = seen
90
+ every = set(self.targets)
91
+ for k, t in self.targets.items():
92
+ if t.get("deps_unknown"):
93
+ self.visible[k] = every
94
+ # longest target folder first
95
+ self._paths = sorted(((t["path"], k) for k, t in self.targets.items() if t["path"] is not None),
96
+ key=lambda x: -len(x[0]))
97
+ self._cache: dict[str, str | None] = {}
98
+
99
+ def _manifests(self):
100
+ if self._files is not None:
101
+ return [self.root / f for f in self._files if f.rsplit("/", 1)[-1] == "Package.swift" and f.count("/") <= 3]
102
+ out = []
103
+ for depth in range(0, 4):
104
+ for p in self.root.glob("/".join(["*"] * depth + ["Package.swift"])):
105
+ # (the index passes its file list, skip presets applied; this walk is for direct use)
106
+ if not any(x.startswith(".") for x in p.relative_to(self.root).parts[:-1]):
107
+ out.append(p)
108
+ return out
109
+
110
+ def _parse(self, pk: Path):
111
+ try:
112
+ txt = pk.read_text(encoding="utf-8", errors="replace")
113
+ except OSError:
114
+ return
115
+ txt = re.sub(r"//[^\n]*|/\*.*?\*/", " ", txt, flags=re.S)
116
+ d = pk.parent.relative_to(self.root).as_posix()
117
+ d = "" if d == "." else d
118
+ self.manifests.append(pk.relative_to(self.root).as_posix())
119
+ end = -1
120
+ for m in TARGET.finditer(txt):
121
+ if m.start() < end:
122
+ continue # `.target(name: "Csqlite3")` in another target's `dependencies:`
123
+ kind, name = m.groups()
124
+ body, end = _call_body(txt, m.start())
125
+ deps = []
126
+ arr = _array(body, "dependencies")
127
+ # dependencies the manifest computes (`dependencies: shared`, `[...] + extra`): unknown, so the target
128
+ # may name any package target (never app code)
129
+ unknown = bool(re.search(r"\bdependencies\s*:", body)) and (arr is None or bool(re.sub(
130
+ r"\.\w+\s*\((?:[^()]|\((?:[^()]|\([^()]*\))*\))*\)|\"[^\"]*\"|[\s,]", "", arr)) or bool(re.search(
131
+ r"\bdependencies\s*:\s*\[" + re.escape(arr) + r"\]\s*\+", body)))
132
+ if arr:
133
+ for x in DEP_PRODUCT.finditer(arr):
134
+ deps.append(("product", x.group(1)))
135
+ for x in DEP_NAMED.finditer(arr):
136
+ deps.append(("target", x.group(1)))
137
+ plain = re.sub(r"\.\w+\s*\((?:[^()]|\([^()]*\))*\)", " ", arr) # drop .product(...) / .target(...)
138
+ for x in DEP_STRING.finditer(plain):
139
+ deps.append(("name", x.group(1)))
140
+ pm = re.search(r"\bpath\s*:\s*\"([^\"]*)\"", body)
141
+ if kind in ("binaryTarget", "plugin") and not pm:
142
+ path = None
143
+ else:
144
+ sub = pm.group(1) if pm else (f"Tests/{name}" if kind == "testTarget" else
145
+ f"Plugins/{name}" if kind == "plugin" else f"Sources/{name}")
146
+ path = "/".join(x for x in (d, sub.strip("/")) if x)
147
+ self.targets[f"{d}:{name}"] = {"name": name, "path": path, "deps": deps, "kind": kind,
148
+ "deps_unknown": unknown}
149
+ for m in PRODUCT.finditer(txt):
150
+ names = re.findall(r"\"([^\"]+)\"", m.group(2))
151
+ self.products.setdefault(m.group(1), set()).update(f"{d}:{n}" for n in names)
152
+
153
+ def module_of(self, rel: str) -> str | None:
154
+ """The package target compiling the file, or None (app / extension / preview code, or no package)."""
155
+ if rel in self._cache:
156
+ return self._cache[rel]
157
+ hit = None
158
+ for p, k in self._paths:
159
+ if rel == p or rel.startswith(p + "/"):
160
+ hit = k
161
+ break
162
+ self._cache[rel] = hit
163
+ return hit
164
+
165
+ def sees(self, caller_rel: str, callee_rel: str) -> bool:
166
+ """May code in `caller_rel` name a declaration of `callee_rel`?"""
167
+ m = self.module_of(caller_rel)
168
+ if m is None:
169
+ return True
170
+ dm = self.module_of(callee_rel)
171
+ return dm is not None and dm in self.visible.get(m, {m})
172
+
173
+ def __bool__(self):
174
+ return bool(self.targets)