clast-ai 0.1.2 → 0.2.0

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 (290) hide show
  1. package/.claude-plugin/marketplace.json +14 -0
  2. package/.claude-plugin/plugin.json +11 -9
  3. package/README.md +447 -401
  4. package/bench/ab/onair-concept.json +22 -0
  5. package/bench/ab/onair-deadcode.json +7 -0
  6. package/bench/ab/onair-hard.json +32 -0
  7. package/bench/ab/onair-impact.json +17 -0
  8. package/bench/ab/onair-refactors.json +18 -0
  9. package/bench/ab/onair-survey.json +17 -0
  10. package/bench/ab/onair-tasks.json +20 -0
  11. package/bench/ab/onair.json +52 -0
  12. package/bench/ab/vscode-concept.json +22 -0
  13. package/bench/ab/vscode-hard.json +32 -0
  14. package/bench/ab/vscode-impact.json +17 -0
  15. package/bench/ab/vscode-refactors.json +18 -0
  16. package/bench/ab/vscode-tasks.json +20 -0
  17. package/bench/ab/vscode.json +52 -0
  18. package/bench/ab.mjs +213 -0
  19. package/bench/bench.mjs +98 -0
  20. package/bench/resolution.mjs +75 -0
  21. package/dist/cli.d.ts +2 -0
  22. package/dist/cli.js +257 -0
  23. package/dist/cli.js.map +1 -0
  24. package/dist/config/defaults.d.ts +12 -2
  25. package/dist/config/defaults.js +38 -31
  26. package/dist/config/defaults.js.map +1 -1
  27. package/dist/config/index.d.ts +1 -1
  28. package/dist/config/index.js +26 -14
  29. package/dist/config/index.js.map +1 -1
  30. package/dist/db/index.d.ts +73 -13
  31. package/dist/db/index.js +481 -39
  32. package/dist/db/index.js.map +1 -1
  33. package/dist/engine.d.ts +15 -0
  34. package/dist/engine.js +28 -0
  35. package/dist/engine.js.map +1 -0
  36. package/dist/indexer/imports.d.ts +6 -0
  37. package/dist/indexer/imports.js +254 -0
  38. package/dist/indexer/imports.js.map +1 -0
  39. package/dist/indexer/index.d.ts +63 -0
  40. package/dist/indexer/index.js +360 -0
  41. package/dist/indexer/index.js.map +1 -0
  42. package/dist/indexer/process.d.ts +22 -0
  43. package/dist/indexer/process.js +42 -0
  44. package/dist/indexer/process.js.map +1 -0
  45. package/dist/indexer/scan.d.ts +43 -0
  46. package/dist/indexer/scan.js +223 -0
  47. package/dist/indexer/scan.js.map +1 -0
  48. package/dist/indexer/worker.d.ts +1 -0
  49. package/dist/indexer/worker.js +23 -0
  50. package/dist/indexer/worker.js.map +1 -0
  51. package/dist/llm/comment-generator.d.ts +17 -19
  52. package/dist/llm/comment-generator.js +46 -80
  53. package/dist/llm/comment-generator.js.map +1 -1
  54. package/dist/llm/index.d.ts +0 -1
  55. package/dist/llm/index.js.map +1 -1
  56. package/dist/llm/prompts.d.ts +0 -1
  57. package/dist/llm/prompts.js +16 -16
  58. package/dist/parser/extractor.d.ts +21 -16
  59. package/dist/parser/extractor.js +700 -228
  60. package/dist/parser/extractor.js.map +1 -1
  61. package/dist/parser/index.d.ts +17 -21
  62. package/dist/parser/index.js +115 -171
  63. package/dist/parser/index.js.map +1 -1
  64. package/dist/parser/langs/c.d.ts +3 -0
  65. package/dist/parser/langs/c.js +879 -0
  66. package/dist/parser/langs/c.js.map +1 -0
  67. package/dist/parser/langs/csharp.d.ts +2 -0
  68. package/dist/parser/langs/csharp.js +548 -0
  69. package/dist/parser/langs/csharp.js.map +1 -0
  70. package/dist/parser/langs/dart.d.ts +2 -0
  71. package/dist/parser/langs/dart.js +893 -0
  72. package/dist/parser/langs/dart.js.map +1 -0
  73. package/dist/parser/langs/go.d.ts +2 -0
  74. package/dist/parser/langs/go.js +455 -0
  75. package/dist/parser/langs/go.js.map +1 -0
  76. package/dist/parser/langs/java.d.ts +2 -0
  77. package/dist/parser/langs/java.js +390 -0
  78. package/dist/parser/langs/java.js.map +1 -0
  79. package/dist/parser/langs/php.d.ts +2 -0
  80. package/dist/parser/langs/php.js +486 -0
  81. package/dist/parser/langs/php.js.map +1 -0
  82. package/dist/parser/langs/python.d.ts +2 -0
  83. package/dist/parser/langs/python.js +216 -0
  84. package/dist/parser/langs/python.js.map +1 -0
  85. package/dist/parser/langs/ruby.d.ts +2 -0
  86. package/dist/parser/langs/ruby.js +602 -0
  87. package/dist/parser/langs/ruby.js.map +1 -0
  88. package/dist/parser/langs/rust.d.ts +2 -0
  89. package/dist/parser/langs/rust.js +931 -0
  90. package/dist/parser/langs/rust.js.map +1 -0
  91. package/dist/parser/langs/swift.d.ts +2 -0
  92. package/dist/parser/langs/swift.js +616 -0
  93. package/dist/parser/langs/swift.js.map +1 -0
  94. package/dist/parser/langs/typescript.d.ts +4 -0
  95. package/dist/parser/langs/typescript.js +535 -0
  96. package/dist/parser/langs/typescript.js.map +1 -0
  97. package/dist/parser/registry.d.ts +16 -0
  98. package/dist/parser/registry.js +87 -0
  99. package/dist/parser/registry.js.map +1 -0
  100. package/dist/parser/returns.d.ts +9 -0
  101. package/dist/parser/returns.js +152 -0
  102. package/dist/parser/returns.js.map +1 -0
  103. package/dist/parser/spec.d.ts +165 -0
  104. package/dist/parser/spec.js +188 -0
  105. package/dist/parser/spec.js.map +1 -0
  106. package/dist/query/arity.d.ts +27 -0
  107. package/dist/query/arity.js +187 -0
  108. package/dist/query/arity.js.map +1 -0
  109. package/dist/query/callgraph.d.ts +113 -0
  110. package/dist/query/callgraph.js +332 -0
  111. package/dist/query/callgraph.js.map +1 -0
  112. package/dist/query/format.d.ts +36 -0
  113. package/dist/query/format.js +136 -0
  114. package/dist/query/format.js.map +1 -0
  115. package/dist/query/hierarchy.d.ts +44 -0
  116. package/dist/query/hierarchy.js +441 -0
  117. package/dist/query/hierarchy.js.map +1 -0
  118. package/dist/query/resolve.d.ts +265 -0
  119. package/dist/query/resolve.js +1957 -0
  120. package/dist/query/resolve.js.map +1 -0
  121. package/dist/query/search.d.ts +35 -0
  122. package/dist/query/search.js +379 -0
  123. package/dist/query/search.js.map +1 -0
  124. package/dist/query/words.d.ts +30 -0
  125. package/dist/query/words.js +201 -0
  126. package/dist/query/words.js.map +1 -0
  127. package/dist/server/index.d.ts +1 -3
  128. package/dist/server/index.js +313 -73
  129. package/dist/server/index.js.map +1 -1
  130. package/dist/tools/context.d.ts +35 -0
  131. package/dist/tools/context.js +79 -0
  132. package/dist/tools/context.js.map +1 -0
  133. package/dist/tools/explore.d.ts +51 -0
  134. package/dist/tools/explore.js +779 -0
  135. package/dist/tools/explore.js.map +1 -0
  136. package/dist/tools/impact.d.ts +21 -0
  137. package/dist/tools/impact.js +743 -0
  138. package/dist/tools/impact.js.map +1 -0
  139. package/dist/tools/search.d.ts +59 -0
  140. package/dist/tools/search.js +843 -0
  141. package/dist/tools/search.js.map +1 -0
  142. package/dist/tools/stats.d.ts +26 -0
  143. package/dist/tools/stats.js +604 -0
  144. package/dist/tools/stats.js.map +1 -0
  145. package/dist/types.d.ts +95 -40
  146. package/dist/types.js +9 -1
  147. package/dist/types.js.map +1 -1
  148. package/dist/version.d.ts +2 -0
  149. package/dist/version.js +3 -0
  150. package/dist/version.js.map +1 -0
  151. package/dist/watcher/index.d.ts +18 -16
  152. package/dist/watcher/index.js +94 -77
  153. package/dist/watcher/index.js.map +1 -1
  154. package/package.json +21 -24
  155. package/plugin/server.mjs +50 -0
  156. package/skills/audit/SKILL.md +37 -0
  157. package/skills/deadcode/SKILL.md +33 -0
  158. package/skills/explore/SKILL.md +54 -0
  159. package/skills/impact/SKILL.md +24 -0
  160. package/skills/status/SKILL.md +11 -0
  161. package/src/cli.ts +256 -0
  162. package/src/config/defaults.ts +50 -32
  163. package/src/config/index.ts +23 -14
  164. package/src/db/index.ts +540 -43
  165. package/src/engine.ts +30 -0
  166. package/src/indexer/imports.ts +241 -0
  167. package/src/indexer/index.ts +369 -0
  168. package/src/indexer/process.ts +63 -0
  169. package/src/indexer/scan.ts +226 -0
  170. package/src/indexer/worker.ts +24 -0
  171. package/src/llm/comment-generator.ts +52 -103
  172. package/src/llm/index.ts +80 -80
  173. package/src/llm/prompts.ts +95 -95
  174. package/src/parser/extractor.ts +643 -256
  175. package/src/parser/index.ts +105 -205
  176. package/src/parser/langs/c.ts +860 -0
  177. package/src/parser/langs/csharp.ts +519 -0
  178. package/src/parser/langs/dart.ts +820 -0
  179. package/src/parser/langs/go.ts +437 -0
  180. package/src/parser/langs/java.ts +361 -0
  181. package/src/parser/langs/php.ts +450 -0
  182. package/src/parser/langs/python.ts +206 -0
  183. package/src/parser/langs/ruby.ts +554 -0
  184. package/src/parser/langs/rust.ts +904 -0
  185. package/src/parser/langs/swift.ts +590 -0
  186. package/src/parser/langs/typescript.ts +499 -0
  187. package/src/parser/registry.ts +88 -0
  188. package/src/parser/returns.ts +137 -0
  189. package/src/parser/spec.ts +309 -0
  190. package/src/query/arity.ts +173 -0
  191. package/src/query/callgraph.ts +473 -0
  192. package/src/query/format.ts +136 -0
  193. package/src/query/hierarchy.ts +447 -0
  194. package/src/query/resolve.ts +1972 -0
  195. package/src/query/search.ts +430 -0
  196. package/src/query/words.ts +183 -0
  197. package/src/server/index.ts +390 -79
  198. package/src/tools/context.ts +82 -0
  199. package/src/tools/explore.ts +860 -0
  200. package/src/tools/impact.ts +748 -0
  201. package/src/tools/search.ts +886 -0
  202. package/src/tools/stats.ts +633 -0
  203. package/src/types.ts +113 -45
  204. package/src/version.ts +2 -0
  205. package/src/watcher/index.ts +82 -88
  206. package/tsconfig.json +7 -4
  207. package/.mcp.json +0 -8
  208. package/commands/clast-status.md +0 -9
  209. package/dist/config/defaults.d.ts.map +0 -1
  210. package/dist/config/index.d.ts.map +0 -1
  211. package/dist/db/index.d.ts.map +0 -1
  212. package/dist/db/queries.d.ts +0 -44
  213. package/dist/db/queries.d.ts.map +0 -1
  214. package/dist/db/queries.js +0 -251
  215. package/dist/db/queries.js.map +0 -1
  216. package/dist/db/schema.d.ts +0 -3
  217. package/dist/db/schema.d.ts.map +0 -1
  218. package/dist/db/schema.js +0 -94
  219. package/dist/db/schema.js.map +0 -1
  220. package/dist/db/types.d.ts +0 -44
  221. package/dist/db/types.d.ts.map +0 -1
  222. package/dist/db/types.js +0 -2
  223. package/dist/db/types.js.map +0 -1
  224. package/dist/llm/comment-generator.d.ts.map +0 -1
  225. package/dist/llm/index.d.ts.map +0 -1
  226. package/dist/llm/prompts.d.ts.map +0 -1
  227. package/dist/parser/call-resolver.d.ts +0 -15
  228. package/dist/parser/call-resolver.d.ts.map +0 -1
  229. package/dist/parser/call-resolver.js +0 -16
  230. package/dist/parser/call-resolver.js.map +0 -1
  231. package/dist/parser/extractor.d.ts.map +0 -1
  232. package/dist/parser/index.d.ts.map +0 -1
  233. package/dist/parser/languages.d.ts +0 -11
  234. package/dist/parser/languages.d.ts.map +0 -1
  235. package/dist/parser/languages.js +0 -74
  236. package/dist/parser/languages.js.map +0 -1
  237. package/dist/server/index.d.ts.map +0 -1
  238. package/dist/server/register-tools.d.ts +0 -7
  239. package/dist/server/register-tools.d.ts.map +0 -1
  240. package/dist/server/register-tools.js +0 -17
  241. package/dist/server/register-tools.js.map +0 -1
  242. package/dist/server/tools/clast-call-graph.d.ts +0 -4
  243. package/dist/server/tools/clast-call-graph.d.ts.map +0 -1
  244. package/dist/server/tools/clast-call-graph.js +0 -70
  245. package/dist/server/tools/clast-call-graph.js.map +0 -1
  246. package/dist/server/tools/clast-comment.d.ts +0 -5
  247. package/dist/server/tools/clast-comment.d.ts.map +0 -1
  248. package/dist/server/tools/clast-comment.js +0 -64
  249. package/dist/server/tools/clast-comment.js.map +0 -1
  250. package/dist/server/tools/clast-file-summary.d.ts +0 -4
  251. package/dist/server/tools/clast-file-summary.d.ts.map +0 -1
  252. package/dist/server/tools/clast-file-summary.js +0 -42
  253. package/dist/server/tools/clast-file-summary.js.map +0 -1
  254. package/dist/server/tools/clast-get-context.d.ts +0 -4
  255. package/dist/server/tools/clast-get-context.d.ts.map +0 -1
  256. package/dist/server/tools/clast-get-context.js +0 -80
  257. package/dist/server/tools/clast-get-context.js.map +0 -1
  258. package/dist/server/tools/clast-reindex.d.ts +0 -5
  259. package/dist/server/tools/clast-reindex.d.ts.map +0 -1
  260. package/dist/server/tools/clast-reindex.js +0 -36
  261. package/dist/server/tools/clast-reindex.js.map +0 -1
  262. package/dist/server/tools/clast-search.d.ts +0 -4
  263. package/dist/server/tools/clast-search.d.ts.map +0 -1
  264. package/dist/server/tools/clast-search.js +0 -29
  265. package/dist/server/tools/clast-search.js.map +0 -1
  266. package/dist/server/tools/clast-status.d.ts +0 -5
  267. package/dist/server/tools/clast-status.d.ts.map +0 -1
  268. package/dist/server/tools/clast-status.js +0 -23
  269. package/dist/server/tools/clast-status.js.map +0 -1
  270. package/dist/types.d.ts.map +0 -1
  271. package/dist/watcher/gitignore.d.ts +0 -9
  272. package/dist/watcher/gitignore.d.ts.map +0 -1
  273. package/dist/watcher/gitignore.js +0 -38
  274. package/dist/watcher/gitignore.js.map +0 -1
  275. package/dist/watcher/index.d.ts.map +0 -1
  276. package/skills/clast-explore/SKILL.md +0 -41
  277. package/src/db/queries.ts +0 -332
  278. package/src/db/schema.ts +0 -106
  279. package/src/db/types.ts +0 -47
  280. package/src/parser/call-resolver.ts +0 -17
  281. package/src/parser/languages.ts +0 -86
  282. package/src/server/register-tools.ts +0 -30
  283. package/src/server/tools/clast-call-graph.ts +0 -82
  284. package/src/server/tools/clast-comment.ts +0 -76
  285. package/src/server/tools/clast-file-summary.ts +0 -59
  286. package/src/server/tools/clast-get-context.ts +0 -97
  287. package/src/server/tools/clast-reindex.ts +0 -52
  288. package/src/server/tools/clast-search.ts +0 -38
  289. package/src/server/tools/clast-status.ts +0 -37
  290. package/src/watcher/gitignore.ts +0 -42
@@ -0,0 +1,893 @@
1
+ import { childOfType, field, stripQuotes } from '../spec.js';
2
+ const MAX_SIG_SLICE = 400;
3
+ const MAX_TYPE_TEXT = 120;
4
+ const MAX_INLINE_VALUE = 80;
5
+ const MAX_RECEIVER = 48;
6
+ /** Bodies whose direct children are members of a type. */
7
+ const MEMBER_BODIES = new Set(['class_body', 'extension_body', 'enum_body']);
8
+ /** Tokens / nodes that make up the head of a top-level variable declaration (flat siblings in this grammar). */
9
+ const HEAD_PARTS = new Set([
10
+ 'type_identifier', 'type_arguments', 'nullable_type', '.', 'final_builtin', 'const_builtin', 'inferred_type',
11
+ 'late', 'external', 'static', 'covariant', 'function_type', 'void_type', 'record_type',
12
+ ]);
13
+ /**
14
+ * The grammar is flat: a method is a `method_signature` followed by a sibling
15
+ * `function_body`, a call is an `identifier` followed by sibling `selector`s.
16
+ * No single node covers such a construct, so line ranges and call extents
17
+ * are passed to the framework as a span between two real nodes. The object
18
+ * carries exactly the positional members the extractor reads from a node.
19
+ */
20
+ function span(start, end, line = start) {
21
+ return {
22
+ type: 'span',
23
+ startIndex: start.startIndex,
24
+ endIndex: end.endIndex,
25
+ startPosition: line.startPosition,
26
+ endPosition: line === start ? end.endPosition : line.startPosition,
27
+ previousSibling: start.previousSibling,
28
+ parent: line === start ? start.parent : null,
29
+ childForFieldName: () => null,
30
+ };
31
+ }
32
+ function sliceSig(ctx, start, end) {
33
+ if (end - start > MAX_SIG_SLICE)
34
+ end = start + MAX_SIG_SLICE;
35
+ return ctx.src.slice(start, end).replace(/\s*(=>|[{;=])\s*$/, '');
36
+ }
37
+ function isPublic(name) {
38
+ return name.charCodeAt(0) !== 95; // '_'
39
+ }
40
+ function isUpper(name) {
41
+ const c = name.charCodeAt(0);
42
+ return c >= 65 && c <= 90;
43
+ }
44
+ /** Text of a type that starts at `first`: `Foo`, `prefix.Foo`, `Future<Foo>` (flat siblings). */
45
+ function typeText(first, ctx) {
46
+ let end = first;
47
+ let n = first.nextSibling;
48
+ for (let i = 0; n && i < 6; i++, n = n.nextSibling) {
49
+ if (n.type === '.' || n.type === 'type_identifier' || n.type === 'type_arguments')
50
+ end = n;
51
+ else
52
+ break;
53
+ }
54
+ if (end === first || end.endIndex - first.startIndex > MAX_TYPE_TEXT)
55
+ return first.text;
56
+ return ctx.src.slice(first.startIndex, end.endIndex);
57
+ }
58
+ /** Declared type among the direct children of `node`, before its name. */
59
+ function declaredType(node, ctx) {
60
+ for (const c of node.children) {
61
+ if (!c)
62
+ continue;
63
+ if (c.type === 'type_identifier')
64
+ return typeText(c, ctx);
65
+ if (c.type === 'identifier')
66
+ break;
67
+ }
68
+ return null;
69
+ }
70
+ /** Class of `new Foo()`, `const Foo()`, `new Foo.named()`, `new prefix.Foo()`. */
71
+ function newType(node) {
72
+ let type = null;
73
+ for (const c of node.children) {
74
+ if (!c)
75
+ continue;
76
+ if (c.type === 'type_identifier')
77
+ type = c.text;
78
+ else if (c.type === 'identifier') {
79
+ const name = c.text;
80
+ if (isUpper(name))
81
+ type = name;
82
+ }
83
+ else if (c.type === 'arguments')
84
+ break;
85
+ }
86
+ return type;
87
+ }
88
+ function hasArguments(selector) {
89
+ return !!selector && selector.type === 'selector' && selector.firstChild?.type === 'argument_part';
90
+ }
91
+ /** Member name of a `.name` / `?.name` selector, or null. */
92
+ function memberOf(selector) {
93
+ if (!selector || selector.type !== 'selector')
94
+ return null;
95
+ const inner = selector.firstChild;
96
+ if (!inner || (inner.type !== 'unconditional_assignable_selector' && inner.type !== 'conditional_assignable_selector'))
97
+ return null;
98
+ const id = inner.lastChild;
99
+ return id && id.type === 'identifier' ? id.text : null;
100
+ }
101
+ /**
102
+ * Class constructed by an initialiser that starts at `value`: `Foo()`,
103
+ * `Foo.named()`, `prefix.Foo()`, `new Foo()`, `const Foo()`.
104
+ */
105
+ function constructedType(value) {
106
+ if (!value)
107
+ return null;
108
+ if (value.type === 'new_expression' || value.type === 'const_object_expression') {
109
+ return value.nextSibling?.type === 'selector' ? null : newType(value);
110
+ }
111
+ if (value.type !== 'identifier')
112
+ return null;
113
+ const s1 = value.nextSibling;
114
+ if (hasArguments(s1)) {
115
+ if (s1.nextSibling?.type === 'selector')
116
+ return null;
117
+ const name = value.text;
118
+ return isUpper(name) ? name : null;
119
+ }
120
+ const member = memberOf(s1);
121
+ if (!member)
122
+ return null;
123
+ const s2 = s1.nextSibling;
124
+ if (!hasArguments(s2) || s2.nextSibling?.type === 'selector')
125
+ return null;
126
+ const head = value.text;
127
+ if (isUpper(head))
128
+ return head;
129
+ return isUpper(member) ? member : null;
130
+ }
131
+ /** Names in a flat type list (`extends A`, `implements a.B<T>, C`), qualified names joined with '.'. */
132
+ function typeNames(list, from = 0) {
133
+ const out = [];
134
+ if (!list)
135
+ return out;
136
+ let dotted = false;
137
+ const count = list.childCount;
138
+ for (let i = from; i < count; i++) {
139
+ const c = list.child(i);
140
+ if (!c)
141
+ continue;
142
+ if (c.type === 'type_identifier') {
143
+ if (dotted && out.length)
144
+ out[out.length - 1] += '.' + c.text;
145
+ else
146
+ out.push(c.text);
147
+ dotted = false;
148
+ }
149
+ else if (c.type === '.')
150
+ dotted = true;
151
+ else if (c.type === 'mixins' || c.type === 'interfaces' || c.type === 'class_body')
152
+ break;
153
+ }
154
+ return out;
155
+ }
156
+ function inheritAll(sym, names, kind, ctx) {
157
+ for (const n of names)
158
+ ctx.inherit(sym, n, kind);
159
+ }
160
+ /** Start offset of a declaration: after leading annotations (children in this grammar for classes). */
161
+ function afterAnnotations(node) {
162
+ for (const c of node.children) {
163
+ if (!c)
164
+ continue;
165
+ if (c.type === 'annotation' || c.type === 'comment' || c.type === 'documentation_comment')
166
+ continue;
167
+ return c.startIndex;
168
+ }
169
+ return node.startIndex;
170
+ }
171
+ const classDefinition = (node, ctx) => {
172
+ const nameNode = field(node, 'name');
173
+ if (!nameNode)
174
+ return;
175
+ const name = nameNode.text;
176
+ const body = field(node, 'body');
177
+ const start = afterAnnotations(node);
178
+ const sym = ctx.def(node, {
179
+ name,
180
+ kind: 'class',
181
+ sig: sliceSig(ctx, start, body ? body.startIndex : node.endIndex),
182
+ exported: isPublic(name),
183
+ });
184
+ const superclass = field(node, 'superclass');
185
+ if (superclass) {
186
+ inheritAll(sym, typeNames(superclass), 'extends', ctx);
187
+ inheritAll(sym, typeNames(childOfType(superclass, 'mixins')), 'implements', ctx);
188
+ }
189
+ inheritAll(sym, typeNames(field(node, 'interfaces')), 'implements', ctx);
190
+ };
191
+ /** `mixin Walker on Animal implements Legs { ... }` (no field names in the grammar). */
192
+ const mixinDeclaration = (node, ctx) => {
193
+ let nameNode = null;
194
+ let onAt = -1;
195
+ let body = null;
196
+ let interfaces = null;
197
+ const count = node.childCount;
198
+ for (let i = 0; i < count; i++) {
199
+ const c = node.child(i);
200
+ if (!c)
201
+ continue;
202
+ if (c.type === 'identifier' && !nameNode)
203
+ nameNode = c;
204
+ else if (c.type === 'on')
205
+ onAt = i + 1;
206
+ else if (c.type === 'interfaces')
207
+ interfaces = c;
208
+ else if (c.type === 'class_body')
209
+ body = c;
210
+ }
211
+ if (!nameNode)
212
+ return;
213
+ const name = nameNode.text;
214
+ const sym = ctx.def(node, {
215
+ name,
216
+ kind: 'trait',
217
+ sig: sliceSig(ctx, afterAnnotations(node), body ? body.startIndex : node.endIndex),
218
+ exported: isPublic(name),
219
+ });
220
+ if (onAt > 0)
221
+ inheritAll(sym, typeNames(node, onAt), 'extends', ctx);
222
+ inheritAll(sym, typeNames(interfaces), 'implements', ctx);
223
+ };
224
+ /**
225
+ * `extension StringX on String { ... }` is not a symbol: its members are
226
+ * named after the extended type (`String.blank`), which is how call sites
227
+ * see them (`s.blank`). Extensions on non-nominal types fall back to the
228
+ * extension's own name.
229
+ */
230
+ const extensionDeclaration = (node, ctx) => {
231
+ const on = field(node, 'class');
232
+ if (on && on.type === 'type_identifier') {
233
+ // `on prefix.Foo`: the last segment.
234
+ let last = on;
235
+ for (let n = on.nextSibling; n && (n.type === '.' || n.type === 'type_identifier'); n = n.nextSibling) {
236
+ if (n.type === 'type_identifier')
237
+ last = n;
238
+ }
239
+ ctx.scope(last.text);
240
+ return;
241
+ }
242
+ const name = field(node, 'name');
243
+ if (name)
244
+ ctx.scope(name.text);
245
+ };
246
+ const extensionTypeDeclaration = (node, ctx) => {
247
+ const nameNode = field(node, 'name');
248
+ if (!nameNode)
249
+ return;
250
+ const name = nameNode.text;
251
+ const body = field(node, 'body');
252
+ const sym = ctx.def(node, {
253
+ name,
254
+ kind: 'class',
255
+ sig: sliceSig(ctx, afterAnnotations(node), body ? body.startIndex : node.endIndex),
256
+ exported: isPublic(name),
257
+ });
258
+ inheritAll(sym, typeNames(childOfType(node, 'interfaces')), 'implements', ctx);
259
+ const rep = field(node, 'representation');
260
+ const repName = field(rep, 'name');
261
+ const repType = field(rep, 'type');
262
+ if (repName && repType && repType.type === 'type_identifier')
263
+ ctx.typeHint(repName.text, typeText(repType, ctx));
264
+ };
265
+ const enumDeclaration = (node, ctx) => {
266
+ const nameNode = field(node, 'name');
267
+ if (!nameNode)
268
+ return;
269
+ const name = nameNode.text;
270
+ const body = field(node, 'body');
271
+ const sym = ctx.def(node, {
272
+ name,
273
+ kind: 'enum',
274
+ sig: sliceSig(ctx, afterAnnotations(node), body ? body.startIndex : node.endIndex),
275
+ exported: isPublic(name),
276
+ });
277
+ inheritAll(sym, typeNames(childOfType(node, 'mixins')), 'implements', ctx);
278
+ inheritAll(sym, typeNames(childOfType(node, 'interfaces')), 'implements', ctx);
279
+ };
280
+ const enumConstant = (node, ctx) => {
281
+ const nameNode = field(node, 'name');
282
+ if (!nameNode)
283
+ return;
284
+ const name = nameNode.text;
285
+ ctx.def(node, {
286
+ name,
287
+ kind: 'constant',
288
+ sig: sliceSig(ctx, afterAnnotations(node), Math.min(node.endIndex, node.startIndex + 120)),
289
+ exported: isPublic(name),
290
+ });
291
+ };
292
+ /** `typedef Callback = void Function(int);` and the old `typedef int Compare(Object a, Object b);`. */
293
+ const typeAlias = (node, ctx) => {
294
+ let nameNode = null;
295
+ for (const c of node.children) {
296
+ if (!c)
297
+ continue;
298
+ if (c.type === 'type_identifier')
299
+ nameNode = c;
300
+ else if (c.type === '=' || c.type === 'formal_parameter_list' || c.type === 'type_parameters')
301
+ break;
302
+ }
303
+ if (!nameNode)
304
+ return;
305
+ const name = nameNode.text;
306
+ ctx.def(node, { name, kind: 'type', sig: sliceSig(ctx, node.startIndex, node.endIndex), exported: isPublic(name) });
307
+ };
308
+ /** Name and kind of a `*_signature` node; `member` says whether it sits in a class-like body. */
309
+ function describe(sig, member, ctx) {
310
+ switch (sig.type) {
311
+ case 'function_signature': {
312
+ const name = field(sig, 'name');
313
+ if (!name)
314
+ return null;
315
+ return {
316
+ name: name.text,
317
+ kind: member ? 'method' : 'function',
318
+ params: childOfType(sig, 'formal_parameter_list'),
319
+ getterType: null,
320
+ hintParams: true,
321
+ };
322
+ }
323
+ case 'getter_signature': {
324
+ const name = field(sig, 'name');
325
+ if (!name)
326
+ return null;
327
+ return { name: name.text, kind: 'property', params: null, getterType: declaredType(sig, ctx), hintParams: false };
328
+ }
329
+ case 'setter_signature': {
330
+ const name = field(sig, 'name');
331
+ if (!name)
332
+ return null;
333
+ return { name: name.text, kind: 'property', params: null, getterType: null, hintParams: false };
334
+ }
335
+ case 'operator_signature': {
336
+ let op = null;
337
+ for (const c of sig.children) {
338
+ if (c && c.type === 'operator') {
339
+ op = c.nextSibling;
340
+ break;
341
+ }
342
+ }
343
+ if (!op || op.endIndex - op.startIndex > 8)
344
+ return null;
345
+ return {
346
+ name: op.text,
347
+ kind: 'method',
348
+ params: childOfType(sig, 'formal_parameter_list'),
349
+ getterType: null,
350
+ hintParams: true,
351
+ };
352
+ }
353
+ case 'constructor_signature':
354
+ case 'constant_constructor_signature':
355
+ case 'factory_constructor_signature':
356
+ case 'redirecting_factory_constructor_signature': {
357
+ // `Foo(...)` -> Foo, `Foo.named(...)` -> named.
358
+ let name = null;
359
+ let params = null;
360
+ for (const c of sig.children) {
361
+ if (!c)
362
+ continue;
363
+ if (c.type === 'identifier')
364
+ name = c;
365
+ else if (c.type === 'formal_parameter_list') {
366
+ params = c;
367
+ break;
368
+ }
369
+ }
370
+ if (!name)
371
+ return null;
372
+ return { name: name.text, kind: 'method', params, getterType: null, hintParams: true };
373
+ }
374
+ default:
375
+ return null;
376
+ }
377
+ }
378
+ function hintParameter(p, ctx) {
379
+ const name = field(p, 'name');
380
+ if (!name)
381
+ return;
382
+ const type = declaredType(p, ctx);
383
+ if (type)
384
+ ctx.typeHint(name.text, type);
385
+ }
386
+ function hintParameters(list, ctx) {
387
+ if (!list)
388
+ return;
389
+ for (const c of list.namedChildren) {
390
+ if (!c)
391
+ continue;
392
+ if (c.type === 'formal_parameter')
393
+ hintParameter(c, ctx);
394
+ else if (c.type === 'optional_formal_parameters')
395
+ hintParameters(c, ctx);
396
+ }
397
+ }
398
+ /** Inner `*_signature` of a `method_signature` / `declaration` (after `static`, `external`, ...). */
399
+ function innerSignature(node) {
400
+ for (const c of node.namedChildren) {
401
+ if (c && c.type.endsWith('_signature'))
402
+ return c;
403
+ }
404
+ return null;
405
+ }
406
+ /** First of the flat siblings that belong to a top-level declaration ending at `node` (`external`, `final`, type...). */
407
+ function headStart(node) {
408
+ let first = node;
409
+ let prev = node.previousSibling;
410
+ for (let i = 0; prev && i < 12 && HEAD_PARTS.has(prev.type); i++) {
411
+ first = prev;
412
+ prev = prev.previousSibling;
413
+ }
414
+ return first;
415
+ }
416
+ function defineCallable(node, range, info, sigEnd, ctx) {
417
+ // A getter of an extension has no class symbol to carry its type; the hint would land on the file.
418
+ const fieldLike = range.parent?.type === 'program' || ctx.parentKind() !== null;
419
+ ctx.def(node, {
420
+ name: info.name,
421
+ kind: info.kind,
422
+ range,
423
+ sig: sliceSig(ctx, range.startIndex, sigEnd),
424
+ exported: isPublic(info.name),
425
+ });
426
+ // Parameters precede the body in the tree; their hints belong to the symbol just opened.
427
+ if (info.hintParams)
428
+ hintParameters(info.params, ctx);
429
+ if (info.getterType && fieldLike)
430
+ ctx.typeHint(info.name, info.getterType);
431
+ }
432
+ /**
433
+ * Functions, methods, getters, setters and constructors WITH a body. The
434
+ * symbol is opened on the body node (the signature is its previous sibling)
435
+ * so calls inside are attributed to it; the range spans signature + body.
436
+ */
437
+ const functionBody = (node, ctx) => {
438
+ const outer = node.previousSibling;
439
+ if (!outer)
440
+ return;
441
+ const sig = outer.type === 'method_signature' ? innerSignature(outer) : outer;
442
+ if (!sig)
443
+ return;
444
+ const container = outer.parent;
445
+ const info = describe(sig, !!container && MEMBER_BODIES.has(container.type), ctx);
446
+ if (!info)
447
+ return;
448
+ const first = container && container.type === 'program' ? headStart(outer) : outer;
449
+ // Constructor initialisers (`: super(x), a = b`) are not part of the signature.
450
+ const init = outer.type === 'method_signature' ? childOfType(outer, 'initializers', 'redirection') : null;
451
+ defineCallable(node, span(first, node), info, init ? init.startIndex : node.startIndex, ctx);
452
+ };
453
+ /** Class members without a body: abstract / external methods, getters, constructors with `;`. */
454
+ const declaration = (node, ctx) => {
455
+ const sig = innerSignature(node);
456
+ if (!sig)
457
+ return; // fields: see `declarator`
458
+ const container = node.parent;
459
+ const info = describe(sig, !!container && MEMBER_BODIES.has(container.type), ctx);
460
+ if (!info)
461
+ return;
462
+ const init = childOfType(node, 'initializers', 'redirection');
463
+ defineCallable(node, node, info, init ? init.startIndex : node.endIndex, ctx);
464
+ };
465
+ /** Top-level `external int f();` and other body-less top-level signatures. */
466
+ const bareSignature = (node, ctx) => {
467
+ const parent = node.parent;
468
+ if (!parent || parent.type !== 'program')
469
+ return;
470
+ if (node.nextSibling?.type === 'function_body')
471
+ return;
472
+ const info = describe(node, false, ctx);
473
+ if (!info)
474
+ return;
475
+ const first = headStart(node);
476
+ defineCallable(node, first === node ? node : span(first, node), info, node.endIndex, ctx);
477
+ };
478
+ /**
479
+ * Fields (`final Client _client;`, `static const int max = 10;`) and
480
+ * top-level variables: one symbol per declarator.
481
+ */
482
+ const declarator = (node, ctx) => {
483
+ const list = node.parent;
484
+ if (!list || (list.type !== 'initialized_identifier_list' && list.type !== 'static_final_declaration_list'))
485
+ return;
486
+ const owner = list.parent;
487
+ if (!owner)
488
+ return;
489
+ const nameNode = node.firstChild;
490
+ if (!nameNode || nameNode.type !== 'identifier')
491
+ return;
492
+ let member;
493
+ let first;
494
+ if (owner.type === 'declaration') {
495
+ const body = owner.parent;
496
+ if (!body || !MEMBER_BODIES.has(body.type))
497
+ return;
498
+ member = true;
499
+ first = owner.firstChild ?? list;
500
+ }
501
+ else if (owner.type === 'program') {
502
+ member = false;
503
+ first = headStart(list);
504
+ }
505
+ else {
506
+ return;
507
+ }
508
+ // Modifiers and declared type: the siblings from `first` up to the list.
509
+ let isConst = false;
510
+ let isStatic = false;
511
+ let type = null;
512
+ let n = first;
513
+ for (let i = 0; n && n.startIndex < list.startIndex && i < 16; i++, n = n.nextSibling) {
514
+ if (n.type === 'const_builtin')
515
+ isConst = true;
516
+ else if (n.type === 'static')
517
+ isStatic = true;
518
+ else if (n.type === 'type_identifier' && !type)
519
+ type = typeText(n, ctx);
520
+ }
521
+ const name = nameNode.text;
522
+ const eq = nameNode.nextSibling;
523
+ const value = eq && eq.type === '=' ? eq.nextSibling : null;
524
+ const long = !!value && (node.endIndex - value.startIndex > MAX_INLINE_VALUE || node.endPosition.row !== value.startPosition.row);
525
+ const head = ctx.src.slice(first.startIndex, Math.min(list.startIndex, first.startIndex + MAX_SIG_SLICE));
526
+ const sig = head + sliceSig(ctx, node.startIndex, long ? value.startIndex : node.endIndex);
527
+ const kind = member ? (isStatic && isConst ? 'constant' : 'field') : isConst ? 'constant' : 'variable';
528
+ ctx.def(node, {
529
+ name,
530
+ kind,
531
+ range: member ? owner : span(first, list),
532
+ sig,
533
+ exported: isPublic(name),
534
+ });
535
+ // The symbol is not a container, so the hint lands on the enclosing class (or the file).
536
+ const hint = type ?? constructedType(value);
537
+ if (hint)
538
+ ctx.typeHint(name, hint);
539
+ };
540
+ /** Typed locals: `final Foo x = ...`, `Foo x;`, `var x = Foo()`, `final x = Foo.named()`. */
541
+ const localVariable = (node, ctx) => {
542
+ if (!ctx.inCallable())
543
+ return;
544
+ const name = field(node, 'name');
545
+ if (!name)
546
+ return;
547
+ const type = declaredType(node, ctx) ?? constructedType(field(node, 'value'));
548
+ if (type)
549
+ ctx.typeHint(name.text, type);
550
+ };
551
+ /** `for (final Item it in items)`. */
552
+ const forLoopParts = (node, ctx) => {
553
+ const name = field(node, 'name');
554
+ if (!name || !ctx.inCallable())
555
+ return;
556
+ const type = declaredType(node, ctx);
557
+ if (type)
558
+ ctx.typeHint(name.text, type);
559
+ };
560
+ /** `on FooException catch (e)`. */
561
+ const catchClause = (node, ctx) => {
562
+ const type = node.previousSibling;
563
+ if (!type || type.type !== 'type_identifier' || !ctx.inCallable())
564
+ return;
565
+ const id = childOfType(node, 'catch_parameters')?.namedChild(0);
566
+ if (id && id.type === 'identifier')
567
+ ctx.typeHint(id.text, type.text);
568
+ };
569
+ /** Typed closure parameters: `(Foo f) { f.go(); }`. Parameters of declarations are hinted with their symbol. */
570
+ const formalParameter = (node, ctx) => {
571
+ let list = node.parent;
572
+ if (list && list.type === 'optional_formal_parameters')
573
+ list = list.parent;
574
+ if (!list || list.parent?.type !== 'function_expression')
575
+ return;
576
+ if (ctx.inCallable())
577
+ hintParameter(node, ctx);
578
+ };
579
+ function emit(calls, start, ctx) {
580
+ // Outermost first: the framework links a chained call to the call producing its receiver
581
+ // when the inner call is recorded after the outer one.
582
+ for (let i = calls.length - 1; i >= 0; i--) {
583
+ const c = calls[i];
584
+ const receiver = c.recv === undefined ? null : c.recv === null || c.recv.length > MAX_RECEIVER ? '?' : c.recv;
585
+ ctx.call(c.name, span(start, c.at, c.at), receiver, receiver === '?' ? c.rtype : null);
586
+ }
587
+ }
588
+ function stepMember(st, id) {
589
+ if (!id || id.type !== 'identifier') {
590
+ // Index access: whatever follows has a computed receiver.
591
+ st.recv = null;
592
+ st.name = null;
593
+ st.rtype = null;
594
+ return;
595
+ }
596
+ if (st.name === null)
597
+ st.recv = null;
598
+ else {
599
+ st.recv = st.recv === undefined ? st.name : st.recv === null ? null : st.recv + '.' + st.name;
600
+ st.rtype = null;
601
+ }
602
+ st.name = id.text;
603
+ }
604
+ function stepCall(st, at, out) {
605
+ if (st.name !== null)
606
+ out.push({ name: st.name, recv: st.recv, rtype: st.rtype, at });
607
+ st.recv = null;
608
+ st.name = null;
609
+ st.rtype = null;
610
+ }
611
+ /**
612
+ * A run of selectors after a primary expression: `x.a(1).b`, `Foo()`,
613
+ * `this.repo.find()`, `super.m()`, `Foo.named()`. Handled once, from the
614
+ * first selector of the run.
615
+ */
616
+ const selector = (node, ctx) => {
617
+ const primary = node.previousSibling;
618
+ if (!primary || primary.type === 'selector')
619
+ return;
620
+ const st = { recv: undefined, name: null, rtype: null };
621
+ let start = primary;
622
+ switch (primary.type) {
623
+ case 'identifier':
624
+ case 'this':
625
+ case 'super':
626
+ st.name = primary.text;
627
+ break;
628
+ case 'unconditional_assignable_selector': {
629
+ // `super.m()`: the first member access is not wrapped in a selector.
630
+ const sup = primary.previousSibling;
631
+ const id = primary.lastChild;
632
+ if (id && id.type === 'identifier')
633
+ st.name = id.text;
634
+ st.recv = sup && sup.type === 'super' ? 'super' : null;
635
+ if (sup)
636
+ start = sup;
637
+ break;
638
+ }
639
+ case 'new_expression':
640
+ case 'const_object_expression':
641
+ st.recv = null;
642
+ st.rtype = newType(primary);
643
+ break;
644
+ default:
645
+ st.recv = null;
646
+ }
647
+ const out = [];
648
+ for (let s = node; s && s.type === 'selector'; s = s.nextSibling) {
649
+ const inner = s.firstChild;
650
+ if (!inner)
651
+ continue;
652
+ switch (inner.type) {
653
+ case 'unconditional_assignable_selector':
654
+ case 'conditional_assignable_selector':
655
+ stepMember(st, inner.lastChild);
656
+ break;
657
+ case 'argument_part':
658
+ stepCall(st, s, out);
659
+ break;
660
+ case '!':
661
+ break;
662
+ default:
663
+ st.recv = null;
664
+ st.name = null;
665
+ st.rtype = null;
666
+ }
667
+ }
668
+ if (out.length)
669
+ emit(out, start, ctx);
670
+ };
671
+ /** `target..add(1)..child.remove(2)`: each section is a member access on the cascade target. */
672
+ const cascadeSection = (node, ctx) => {
673
+ let target = node.previousSibling;
674
+ while (target && target.type === 'cascade_section')
675
+ target = target.previousSibling;
676
+ const st = { recv: null, name: null, rtype: null };
677
+ if (target) {
678
+ if (target.type === 'identifier' || target.type === 'this') {
679
+ st.recv = target.text;
680
+ }
681
+ else if (hasArguments(target)) {
682
+ // `Foo()..init()`: the target is a freshly constructed Foo.
683
+ const callee = target.previousSibling;
684
+ if (callee && callee.type === 'identifier' && callee.previousSibling?.type !== 'selector') {
685
+ const name = callee.text;
686
+ if (isUpper(name))
687
+ st.rtype = name;
688
+ }
689
+ }
690
+ else if (target.type === 'new_expression' || target.type === 'const_object_expression') {
691
+ st.rtype = newType(target);
692
+ }
693
+ }
694
+ const out = [];
695
+ let seen = false;
696
+ for (const c of node.children) {
697
+ if (!c)
698
+ continue;
699
+ if (c.type === 'cascade_selector') {
700
+ const id = c.firstChild;
701
+ if (!id || id.type !== 'identifier')
702
+ return;
703
+ st.name = id.text;
704
+ seen = true;
705
+ }
706
+ else if (!seen) {
707
+ continue;
708
+ }
709
+ else if (c.type === 'unconditional_assignable_selector' || c.type === 'conditional_assignable_selector') {
710
+ stepMember(st, c.lastChild);
711
+ }
712
+ else if (c.type === 'argument_part') {
713
+ stepCall(st, c, out);
714
+ }
715
+ else if (c.type !== '!') {
716
+ break; // assignment: `..name = value`
717
+ }
718
+ }
719
+ if (out.length)
720
+ emit(out, node, ctx);
721
+ };
722
+ /** `new Foo()`, `const Foo()`, `new Foo.named()`, `new prefix.Foo()`. */
723
+ const newExpression = (node, ctx) => {
724
+ let type = null;
725
+ let named = null;
726
+ for (const c of node.children) {
727
+ if (!c)
728
+ continue;
729
+ if (c.type === 'type_identifier')
730
+ type = c;
731
+ else if (c.type === 'identifier')
732
+ named = c;
733
+ else if (c.type === 'arguments')
734
+ break;
735
+ }
736
+ if (!type)
737
+ return;
738
+ if (!named)
739
+ ctx.call(type.text, node);
740
+ else {
741
+ const name = named.text;
742
+ if (isUpper(name))
743
+ ctx.call(name, node);
744
+ else
745
+ ctx.call(name, node, type.text);
746
+ }
747
+ };
748
+ function enclosingClass(node) {
749
+ let cur = node.parent;
750
+ for (let i = 0; cur && i < 6; i++, cur = cur.parent) {
751
+ if (cur.type === 'class_definition' || cur.type === 'enum_declaration' || cur.type === 'mixin_declaration')
752
+ return cur;
753
+ }
754
+ return null;
755
+ }
756
+ /** `: super(x)`, `: super.named(x)` in a constructor's initialiser list, and `: this(x)` / `: this.named(x)`. */
757
+ const constructorCall = (node, ctx) => {
758
+ const head = node.firstChild?.type === ':' ? node.child(1) : node.firstChild;
759
+ if (!head || (head.type !== 'super' && head.type !== 'this'))
760
+ return;
761
+ let named = null;
762
+ let hasArgs = false;
763
+ for (const c of node.children) {
764
+ if (!c)
765
+ continue;
766
+ if (c.type === 'identifier')
767
+ named = c;
768
+ else if (c.type === 'arguments') {
769
+ hasArgs = true;
770
+ break;
771
+ }
772
+ }
773
+ if (!hasArgs)
774
+ return;
775
+ const cls = enclosingClass(node);
776
+ if (!cls)
777
+ return;
778
+ let target;
779
+ if (head.type === 'this')
780
+ target = field(cls, 'name')?.text ?? null;
781
+ else
782
+ target = typeNames(field(cls, 'superclass'))[0] ?? null;
783
+ if (!target)
784
+ return;
785
+ target = target.slice(target.lastIndexOf('.') + 1);
786
+ if (named)
787
+ ctx.call(named.text, node, target);
788
+ else
789
+ ctx.call(target, node);
790
+ };
791
+ /** `factory Foo.make() = Bar;` constructs a Bar. */
792
+ const redirectingFactory = (node, ctx) => {
793
+ let seenEq = false;
794
+ let type = null;
795
+ let named = null;
796
+ for (const c of node.children) {
797
+ if (!c)
798
+ continue;
799
+ if (c.type === '=')
800
+ seenEq = true;
801
+ else if (!seenEq)
802
+ continue;
803
+ else if (c.type === 'type_identifier')
804
+ type = c;
805
+ else if (c.type === 'identifier')
806
+ named = c;
807
+ }
808
+ if (!type)
809
+ return;
810
+ if (named)
811
+ ctx.call(named.text, node, type.text);
812
+ else
813
+ ctx.call(type.text, node);
814
+ };
815
+ function uriOf(node) {
816
+ let uri = childOfType(node, 'uri');
817
+ if (!uri)
818
+ uri = childOfType(childOfType(node, 'configurable_uri'), 'uri');
819
+ if (!uri || uri.endIndex - uri.startIndex > 300)
820
+ return null;
821
+ return stripQuotes(uri.text);
822
+ }
823
+ /**
824
+ * `import 'x.dart' as p show A, B;` and `export 'x.dart' show A;`. Names
825
+ * bound: the prefix (a namespace) and the shown names; an import without
826
+ * either makes every public name of the library visible ('*').
827
+ */
828
+ const importOrExport = (node, ctx) => {
829
+ const source = uriOf(node);
830
+ if (!source)
831
+ return;
832
+ const names = [];
833
+ let shown = false;
834
+ for (const c of node.children) {
835
+ if (!c)
836
+ continue;
837
+ if (c.type === 'identifier')
838
+ names.push(c.text);
839
+ else if (c.type === 'combinator' && c.firstChild?.type === 'show') {
840
+ shown = true;
841
+ for (const id of c.namedChildren) {
842
+ if (id && id.type === 'identifier')
843
+ names.push(id.text);
844
+ }
845
+ }
846
+ }
847
+ if (!names.length && !shown)
848
+ names.push('*');
849
+ ctx.imp(source, node, names);
850
+ };
851
+ const partDirective = (node, ctx) => {
852
+ ctx.imp(uriOf(node), node);
853
+ };
854
+ export const dart = {
855
+ id: 'dart',
856
+ grammar: 'dart',
857
+ extensions: ['.dart'],
858
+ identifiers: ['identifier', 'type_identifier'],
859
+ comments: ['comment', 'documentation_comment'],
860
+ // Annotations are siblings of the member they annotate.
861
+ docSkip: ['annotation'],
862
+ visit: {
863
+ class_definition: classDefinition,
864
+ mixin_declaration: mixinDeclaration,
865
+ extension_declaration: extensionDeclaration,
866
+ extension_type_declaration: extensionTypeDeclaration,
867
+ enum_declaration: enumDeclaration,
868
+ enum_constant: enumConstant,
869
+ type_alias: typeAlias,
870
+ function_body: functionBody,
871
+ declaration,
872
+ function_signature: bareSignature,
873
+ getter_signature: bareSignature,
874
+ setter_signature: bareSignature,
875
+ initialized_identifier: declarator,
876
+ static_final_declaration: declarator,
877
+ initialized_variable_definition: localVariable,
878
+ for_loop_parts: forLoopParts,
879
+ catch_clause: catchClause,
880
+ formal_parameter: formalParameter,
881
+ selector,
882
+ cascade_section: cascadeSection,
883
+ new_expression: newExpression,
884
+ const_object_expression: newExpression,
885
+ initializer_list_entry: constructorCall,
886
+ redirection: constructorCall,
887
+ redirecting_factory_constructor_signature: redirectingFactory,
888
+ import_specification: importOrExport,
889
+ library_export: importOrExport,
890
+ part_directive: partDirective,
891
+ },
892
+ };
893
+ //# sourceMappingURL=dart.js.map