@mrclrchtr/supi-code-intelligence 4.1.0 → 4.3.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 (47) hide show
  1. package/README.md +4 -2
  2. package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/package.json +1 -1
  3. package/node_modules/@mrclrchtr/supi-code-runtime/package.json +2 -2
  4. package/node_modules/@mrclrchtr/supi-core/package.json +1 -1
  5. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/package.json +1 -1
  6. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/package.json +2 -2
  7. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/package.json +1 -1
  8. package/node_modules/@mrclrchtr/supi-lsp/package.json +3 -3
  9. package/node_modules/@mrclrchtr/supi-lsp/src/utils.ts +2 -2
  10. package/node_modules/@mrclrchtr/supi-tree-sitter/README.md +5 -5
  11. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/package.json +1 -1
  12. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/package.json +2 -2
  13. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/package.json +1 -1
  14. package/node_modules/@mrclrchtr/supi-tree-sitter/package.json +3 -3
  15. package/node_modules/@mrclrchtr/supi-tree-sitter/src/language.ts +2 -1
  16. package/node_modules/@mrclrchtr/supi-tree-sitter/src/operation-support.ts +19 -0
  17. package/node_modules/@mrclrchtr/supi-tree-sitter/src/syntax-node.ts +1 -0
  18. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/outline-c-family.ts +230 -0
  19. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/outline-html-sql.ts +186 -0
  20. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/outline-jvm.ts +311 -0
  21. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/outline-polyglot.ts +218 -0
  22. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/outline-scripting.ts +307 -0
  23. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/outline.ts +9 -5
  24. package/node_modules/@mrclrchtr/supi-tree-sitter/src/types.ts +6 -2
  25. package/package.json +5 -5
  26. package/src/analysis/search/pattern.ts +2 -2
  27. package/src/analysis/target/symbol.ts +5 -2
  28. package/src/extension.ts +5 -1
  29. package/src/session/orientation/collect.ts +134 -180
  30. package/src/session/orientation/context-sections.ts +14 -48
  31. package/src/session/orientation-types.ts +14 -4
  32. package/src/session/orientation-workflow.ts +20 -48
  33. package/src/substrate/lsp/lifecycle.ts +55 -3
  34. package/src/substrate/lsp/state.ts +6 -0
  35. package/src/tool/graph/execute.ts +1 -1
  36. package/src/tool/graph/markdown.ts +222 -0
  37. package/src/tool/orientation/markdown.ts +66 -11
  38. package/src/tool/register.ts +10 -0
  39. package/src/ui/footer.ts +33 -8
  40. package/src/ui/markdown/overview-data.ts +3 -15
  41. package/src/ui/markdown/overview.ts +4 -10
  42. package/src/ui/markdown/types.ts +0 -1
  43. package/src/tool/graph/calls-md.ts +0 -41
  44. package/src/tool/graph/implementations-md.ts +0 -57
  45. package/src/tool/graph/markdown-base.ts +0 -88
  46. package/src/tool/graph/provider-location-md.ts +0 -9
  47. package/src/tool/graph/references-md.ts +0 -41
package/README.md CHANGED
@@ -41,6 +41,8 @@ The extension detects project languages and starts matching language servers. In
41
41
  | Kotlin | `kotlin-lsp` |
42
42
  | R | `R` with `languageserver` |
43
43
 
44
+ Semantic and structural support intentionally differ where the syntax differs: Ruby LSP handles ERB templates, and gopls handles `go.mod`, while AST search excludes both rather than parsing them with the wrong Tree-sitter grammar. Ruby gemspecs and KornShell files use the existing Ruby and Bash structural grammars.
45
+
44
46
  Check runtime status with:
45
47
 
46
48
  ```text
@@ -64,7 +66,7 @@ The extension registers exactly eight `code_*` tools:
64
66
 
65
67
  `code_impact`, `code_context`, `code_brief`, `code_references`, `code_calls`, and `code_implementations` are not compatibility aliases.
66
68
 
67
- A lightweight architecture overview may be injected once near session start when a project model is available.
69
+ A complete manifest-derived architecture overview is injected once near session start when a project model is available; discovered modules, descriptions, entrypoints, and relationships are not truncated.
68
70
 
69
71
  ## Exact-one target selectors
70
72
 
@@ -157,7 +159,7 @@ code_find({ query: "@scope/package", mode: "ast", kind: "import", scope: ["src"]
157
159
 
158
160
  Use PI's `grep` tool for literal or regex source search when it is active. `code_find` does not redirect removed text/regex calls to another tool.
159
161
 
160
- AST `kind` accepts exactly `definition`, `import`, `export`, `call`, `type`, `interface`, `class`, `method`, and `enum`. AST `call` finds written call-site names, not symbol identity. Use `code_graph` references on a resolved target for symbol-identity relationships.
162
+ AST `kind` accepts exactly `definition`, `import`, `export`, `call`, `type`, `interface`, `class`, `method`, and `enum`. Outline-backed kinds support every vendored grammar family; HTML definitions are elements with non-empty `id` attributes, while SQL definitions are supported `CREATE` declarations and shallow table/type members. Imports and exports remain JavaScript/TypeScript-only. AST `call` finds written call-site names, not symbol identity. Use `code_graph` references on a resolved target for symbol-identity relationships.
161
163
 
162
164
  #### AST Scan universe
163
165
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrclrchtr/supi-core",
3
- "version": "4.1.0",
3
+ "version": "4.3.0",
4
4
  "description": "SuPi core — shared infrastructure for SuPi extensions (XML context tags, config system)",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrclrchtr/supi-code-runtime",
3
- "version": "4.1.0",
3
+ "version": "4.3.0",
4
4
  "description": "SuPi code-runtime — shared workspace context, capability contracts, and canonical types for the code-understanding stack",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -29,7 +29,7 @@
29
29
  "!__tests__"
30
30
  ],
31
31
  "dependencies": {
32
- "@mrclrchtr/supi-core": "4.1.0"
32
+ "@mrclrchtr/supi-core": "4.3.0"
33
33
  },
34
34
  "bundledDependencies": [
35
35
  "@mrclrchtr/supi-core"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrclrchtr/supi-core",
3
- "version": "4.1.0",
3
+ "version": "4.3.0",
4
4
  "description": "SuPi core — shared infrastructure for SuPi extensions (XML context tags, config system)",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrclrchtr/supi-core",
3
- "version": "4.1.0",
3
+ "version": "4.3.0",
4
4
  "description": "SuPi core — shared infrastructure for SuPi extensions (XML context tags, config system)",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrclrchtr/supi-code-runtime",
3
- "version": "4.1.0",
3
+ "version": "4.3.0",
4
4
  "description": "SuPi code-runtime — shared workspace context, capability contracts, and canonical types for the code-understanding stack",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -29,7 +29,7 @@
29
29
  "!__tests__"
30
30
  ],
31
31
  "dependencies": {
32
- "@mrclrchtr/supi-core": "4.1.0"
32
+ "@mrclrchtr/supi-core": "4.3.0"
33
33
  },
34
34
  "bundledDependencies": [
35
35
  "@mrclrchtr/supi-core"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrclrchtr/supi-core",
3
- "version": "4.1.0",
3
+ "version": "4.3.0",
4
4
  "description": "SuPi core — shared infrastructure for SuPi extensions (XML context tags, config system)",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrclrchtr/supi-lsp",
3
- "version": "4.1.0",
3
+ "version": "4.3.0",
4
4
  "description": "SuPi LSP runtime — Language Server Protocol integration library for pi",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -37,8 +37,8 @@
37
37
  "vscode-jsonrpc": "^9.0.0",
38
38
  "vscode-languageserver-protocol": "^3.17.5",
39
39
  "vscode-languageserver-types": "^3.17.5",
40
- "@mrclrchtr/supi-code-runtime": "4.1.0",
41
- "@mrclrchtr/supi-core": "4.1.0"
40
+ "@mrclrchtr/supi-code-runtime": "4.3.0",
41
+ "@mrclrchtr/supi-core": "4.3.0"
42
42
  },
43
43
  "bundledDependencies": [
44
44
  "@mrclrchtr/supi-code-runtime",
@@ -24,7 +24,7 @@ const EXT_TO_LANGUAGE: Record<string, string> = {
24
24
  pyi: "python",
25
25
  rs: "rust",
26
26
  go: "go",
27
- mod: "go",
27
+ mod: "go.mod",
28
28
  c: "c",
29
29
  h: "c",
30
30
  cpp: "cpp",
@@ -52,7 +52,7 @@ const EXT_TO_LANGUAGE: Record<string, string> = {
52
52
  sql: "sql",
53
53
  r: "r",
54
54
  rb: "ruby",
55
- erb: "ruby",
55
+ erb: "erb",
56
56
  gemspec: "ruby",
57
57
  java: "java",
58
58
  kt: "kotlin",
@@ -40,17 +40,17 @@ Coordinates in the library APIs use **1-based** line and character columns. Char
40
40
  - JavaScript / TypeScript (`.js`, `.jsx`, `.ts`, `.tsx`, `.mjs`, `.cjs`, `.mts`, `.cts`)
41
41
  - Python (`.py`, `.pyi`)
42
42
  - Rust (`.rs`)
43
- - Go (`.go`, `.mod`)
43
+ - Go (`.go`)
44
44
  - C / C++ (`.c`, `.h`, `.cpp`, `.hpp`, `.cc`, `.cxx`, `.hxx`, `.c++`, `.h++`)
45
45
  - Java (`.java`)
46
46
  - Kotlin (`.kt`, `.kts`)
47
- - Ruby (`.rb`)
48
- - Bash / shell (`.sh`, `.bash`, `.zsh`)
47
+ - Ruby (`.rb`, `.gemspec`)
48
+ - Bash / shell (`.sh`, `.bash`, `.zsh`, `.ksh`)
49
49
  - HTML (`.html`, `.htm`, `.xhtml`)
50
50
  - R (`.r`)
51
51
  - SQL (`.sql`)
52
52
 
53
- Parser support is broader than extractor support. Outline, import, and export collection currently support JavaScript/TypeScript-family grammars. Call-site collection supports every listed family except HTML and SQL. Consumers performing a bulk structural scan should use `getStructuralSearchSupportedExtensions(operation)` rather than treating every parseable extension as eligible.
53
+ Outline collection supports every listed family. HTML outlines contain elements with non-empty `id` attributes; SQL outlines contain `CREATE` declarations and shallow table/type members. Import and export collection remains JavaScript/TypeScript-only, and call-site collection supports every listed family except HTML and SQL. Go module manifests and ERB templates are intentionally excluded because the Go and Ruby grammars do not parse those mixed or separate syntaxes; `supi-lsp` still handles them semantically. Consumers performing a bulk structural scan should use `getStructuralSearchSupportedExtensions(operation)` rather than treating parser support as operation support.
54
54
 
55
55
  ## Architecture
56
56
 
@@ -107,4 +107,4 @@ if (state.kind === "ready") {
107
107
  - `src/operation-support.ts` — authoritative operation-specific extension support
108
108
  - `src/session/service-registry.ts` — shared session-scoped structural service registry
109
109
  - `src/provider/tree-sitter-provider.ts` — `StructuralProvider` adapter consumed by `@mrclrchtr/supi-code-intelligence`
110
- - `src/tool/outline.ts`, `src/tool/imports.ts`, `src/tool/exports.ts`, `src/tool/node-at.ts`, `src/tool/callees.ts`, `src/tool/call-sites.ts` — structural analyses exposed through the library surface
110
+ - `src/tool/outline.ts`, `src/tool/outline-*.ts`, `src/tool/imports.ts`, `src/tool/exports.ts`, `src/tool/node-at.ts`, `src/tool/callees.ts`, `src/tool/call-sites.ts` — structural analyses exposed through the library surface
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrclrchtr/supi-core",
3
- "version": "4.1.0",
3
+ "version": "4.3.0",
4
4
  "description": "SuPi core — shared infrastructure for SuPi extensions (XML context tags, config system)",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrclrchtr/supi-code-runtime",
3
- "version": "4.1.0",
3
+ "version": "4.3.0",
4
4
  "description": "SuPi code-runtime — shared workspace context, capability contracts, and canonical types for the code-understanding stack",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -29,7 +29,7 @@
29
29
  "!__tests__"
30
30
  ],
31
31
  "dependencies": {
32
- "@mrclrchtr/supi-core": "4.1.0"
32
+ "@mrclrchtr/supi-core": "4.3.0"
33
33
  },
34
34
  "bundledDependencies": [
35
35
  "@mrclrchtr/supi-core"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrclrchtr/supi-core",
3
- "version": "4.1.0",
3
+ "version": "4.3.0",
4
4
  "description": "SuPi core — shared infrastructure for SuPi extensions (XML context tags, config system)",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrclrchtr/supi-tree-sitter",
3
- "version": "4.1.0",
3
+ "version": "4.3.0",
4
4
  "description": "SuPi Tree-sitter library — structural AST analysis for pi",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -34,8 +34,8 @@
34
34
  ],
35
35
  "dependencies": {
36
36
  "web-tree-sitter": "^0.26.8",
37
- "@mrclrchtr/supi-code-runtime": "4.1.0",
38
- "@mrclrchtr/supi-core": "4.1.0"
37
+ "@mrclrchtr/supi-code-runtime": "4.3.0",
38
+ "@mrclrchtr/supi-core": "4.3.0"
39
39
  },
40
40
  "bundledDependencies": [
41
41
  "@mrclrchtr/supi-code-runtime",
@@ -25,7 +25,6 @@ const EXTENSION_GRAMMAR: Record<string, GrammarId> = {
25
25
  ".pyi": "python",
26
26
  ".rs": "rust",
27
27
  ".go": "go",
28
- ".mod": "go",
29
28
  ".c": "c",
30
29
  ".h": "c",
31
30
  ".cpp": "cpp",
@@ -39,9 +38,11 @@ const EXTENSION_GRAMMAR: Record<string, GrammarId> = {
39
38
  ".kt": "kotlin",
40
39
  ".kts": "kotlin",
41
40
  ".rb": "ruby",
41
+ ".gemspec": "ruby",
42
42
  ".sh": "bash",
43
43
  ".bash": "bash",
44
44
  ".zsh": "bash",
45
+ ".ksh": "bash",
45
46
  ".html": "html",
46
47
  ".htm": "html",
47
48
  ".xhtml": "html",
@@ -2,6 +2,24 @@ import { getSupportedExtensionGrammarEntries, isJsTsGrammar } from "./language.t
2
2
  import { supportsCallSitesGrammar } from "./tool/call-sites.ts";
3
3
  import type { GrammarId, SupportedExtension } from "./types.ts";
4
4
 
5
+ const OUTLINE_GRAMMARS: ReadonlySet<GrammarId> = new Set([
6
+ "javascript",
7
+ "typescript",
8
+ "tsx",
9
+ "python",
10
+ "rust",
11
+ "go",
12
+ "c",
13
+ "cpp",
14
+ "java",
15
+ "kotlin",
16
+ "ruby",
17
+ "bash",
18
+ "html",
19
+ "r",
20
+ "sql",
21
+ ]);
22
+
5
23
  /** Structural collection operations whose language support defines an AST Scan universe. */
6
24
  const STRUCTURAL_SEARCH_OPERATIONS = ["outline", "imports", "exports", "call-sites"] as const;
7
25
 
@@ -31,6 +49,7 @@ export function supportsGrammarOperation(
31
49
  case "call-sites":
32
50
  return supportsCallSitesGrammar(grammar);
33
51
  case "outline":
52
+ return OUTLINE_GRAMMARS.has(grammar);
34
53
  case "imports":
35
54
  case "exports":
36
55
  return isJsTsGrammar(grammar);
@@ -10,4 +10,5 @@ export interface SyntaxNodeLike {
10
10
  startPosition: { row: number; column: number };
11
11
  endPosition: { row: number; column: number };
12
12
  childForFieldName(name: string): SyntaxNodeLike | null;
13
+ childrenForFieldName(name: string): SyntaxNodeLike[];
13
14
  }
@@ -0,0 +1,230 @@
1
+ import { nodeToRange } from "../coordinates.ts";
2
+ import type { SyntaxNodeLike } from "../syntax-node.ts";
3
+ import type { OutlineItem } from "../types.ts";
4
+
5
+ /** Extract C and C++ declarations from their grammar-specific node shapes. */
6
+ export function extractCFamilyOutlineItems(
7
+ node: SyntaxNodeLike,
8
+ source: string,
9
+ ): OutlineItem[] | undefined {
10
+ switch (node.type) {
11
+ case "class_specifier":
12
+ return one(typeContainer(node, "class", source));
13
+ case "struct_specifier":
14
+ return one(typeContainer(node, "struct", source));
15
+ case "union_specifier":
16
+ return one(typeContainer(node, "union", source));
17
+ case "enum_specifier":
18
+ return one(enumContainer(node, source));
19
+ case "type_definition":
20
+ return typeDefinitions(node, source);
21
+ case "alias_declaration":
22
+ return one(named(node, "type", source));
23
+ case "concept_definition":
24
+ return one(named(node, "concept", source));
25
+ case "namespace_definition": {
26
+ const item = namespaceItem(node, source);
27
+ return item ? [item] : collectDeclarations(node.childForFieldName("body"), source);
28
+ }
29
+ case "function_definition":
30
+ return one(declaratorItem(node, "function", source));
31
+ case "declaration":
32
+ return declarationItems(node, "variable", "function", source);
33
+ default:
34
+ return undefined;
35
+ }
36
+ }
37
+
38
+ function one(item: OutlineItem | null): OutlineItem[] {
39
+ return item ? [item] : [];
40
+ }
41
+
42
+ function named(node: SyntaxNodeLike, kind: string, source: string): OutlineItem | null {
43
+ const name = node.childForFieldName("name");
44
+ return name ? { name: name.text, kind, range: nodeToRange(node, source) } : null;
45
+ }
46
+
47
+ function typeContainer(
48
+ node: SyntaxNodeLike,
49
+ kind: "class" | "struct" | "union",
50
+ source: string,
51
+ ): OutlineItem | null {
52
+ const name = node.childForFieldName("name");
53
+ if (!name) return null;
54
+ return {
55
+ name: name.text,
56
+ kind,
57
+ range: nodeToRange(node, source),
58
+ children: collectTypeMembers(node.childForFieldName("body"), source),
59
+ };
60
+ }
61
+
62
+ function enumContainer(node: SyntaxNodeLike, source: string): OutlineItem | null {
63
+ const name = node.childForFieldName("name");
64
+ if (!name) return null;
65
+ return {
66
+ name: name.text,
67
+ kind: "enum",
68
+ range: nodeToRange(node, source),
69
+ children: enumMembers(node, source),
70
+ };
71
+ }
72
+
73
+ function enumMembers(node: SyntaxNodeLike, source: string): OutlineItem[] {
74
+ const body = node.childForFieldName("body");
75
+ return (
76
+ body?.children.flatMap((child) =>
77
+ child.type === "enumerator" ? one(named(child, "enum-member", source)) : [],
78
+ ) ?? []
79
+ );
80
+ }
81
+
82
+ function typeDefinitions(node: SyntaxNodeLike, source: string): OutlineItem[] {
83
+ const type = node.childForFieldName("type");
84
+ const kind = cTypeKind(type?.type);
85
+ const aliases = declaratorNodes(node).flatMap((declarator) => declaratorNames(declarator));
86
+ if (aliases.length === 0) return [];
87
+ const range = nodeToRange(node, source);
88
+ const children =
89
+ kind === "enum" && type
90
+ ? enumMembers(type, source)
91
+ : type
92
+ ? collectTypeMembers(type.childForFieldName("body"), source)
93
+ : undefined;
94
+ return aliases.map((name) => ({ name, kind, range, ...(children ? { children } : {}) }));
95
+ }
96
+
97
+ function cTypeKind(type: string | undefined): string {
98
+ switch (type) {
99
+ case "class_specifier":
100
+ return "class";
101
+ case "struct_specifier":
102
+ return "struct";
103
+ case "union_specifier":
104
+ return "union";
105
+ case "enum_specifier":
106
+ return "enum";
107
+ default:
108
+ return "type";
109
+ }
110
+ }
111
+
112
+ function namespaceItem(node: SyntaxNodeLike, source: string): OutlineItem | null {
113
+ const name = node.childForFieldName("name");
114
+ if (!name) return null;
115
+ return {
116
+ name: name.text,
117
+ kind: "namespace",
118
+ range: nodeToRange(node, source),
119
+ children: collectDeclarations(node.childForFieldName("body"), source),
120
+ };
121
+ }
122
+
123
+ function collectDeclarations(
124
+ parent: SyntaxNodeLike | null | undefined,
125
+ source: string,
126
+ ): OutlineItem[] {
127
+ if (!parent) return [];
128
+ return parent.children.flatMap((child) => {
129
+ const items = extractCFamilyOutlineItems(child, source);
130
+ return items ?? collectDeclarations(child, source);
131
+ });
132
+ }
133
+
134
+ function collectTypeMembers(
135
+ body: SyntaxNodeLike | null | undefined,
136
+ source: string,
137
+ ): OutlineItem[] {
138
+ if (!body) return [];
139
+ return body.children.flatMap((child) => typeMemberItems(child, source));
140
+ }
141
+
142
+ function typeMemberItems(node: SyntaxNodeLike, source: string): OutlineItem[] {
143
+ switch (node.type) {
144
+ case "field_declaration":
145
+ case "declaration":
146
+ return declarationItems(node, "field", "method", source);
147
+ case "function_definition":
148
+ return one(declaratorItem(node, "method", source));
149
+ case "class_specifier":
150
+ return one(typeContainer(node, "class", source));
151
+ case "struct_specifier":
152
+ return one(typeContainer(node, "struct", source));
153
+ case "union_specifier":
154
+ return one(typeContainer(node, "union", source));
155
+ case "enum_specifier":
156
+ return one(enumContainer(node, source));
157
+ case "type_definition":
158
+ return typeDefinitions(node, source);
159
+ case "alias_declaration":
160
+ return one(named(node, "type", source));
161
+ case "friend_declaration":
162
+ return [];
163
+ default:
164
+ return node.children.flatMap((child) => typeMemberItems(child, source));
165
+ }
166
+ }
167
+
168
+ function declarationItems(
169
+ node: SyntaxNodeLike,
170
+ valueKind: string,
171
+ functionKind: string,
172
+ source: string,
173
+ ): OutlineItem[] {
174
+ const range = nodeToRange(node, source);
175
+ return declaratorNodes(node).flatMap((declarator) =>
176
+ declaratorNames(declarator).map((name) => ({
177
+ name,
178
+ kind: isFunctionDeclarator(declarator) ? functionKind : valueKind,
179
+ range,
180
+ })),
181
+ );
182
+ }
183
+
184
+ function declaratorItem(node: SyntaxNodeLike, kind: string, source: string): OutlineItem | null {
185
+ const declarator = node.childForFieldName("declarator");
186
+ const name = declarator ? declaratorNames(declarator)[0] : undefined;
187
+ return name ? { name, kind, range: nodeToRange(node, source) } : null;
188
+ }
189
+
190
+ function declaratorNodes(node: SyntaxNodeLike): SyntaxNodeLike[] {
191
+ const declarators = node.childrenForFieldName("declarator");
192
+ if (declarators.length > 0) return declarators;
193
+ const declarator = node.childForFieldName("declarator");
194
+ return declarator ? [declarator] : [];
195
+ }
196
+
197
+ function declaratorNames(node: SyntaxNodeLike): string[] {
198
+ if (DECLARATOR_NAME_TYPES.has(node.type)) return [node.text];
199
+ if (node.type === "structured_binding_declarator") {
200
+ return node.children.filter((child) => child.type === "identifier").map((child) => child.text);
201
+ }
202
+ const nested = node.childrenForFieldName("declarator");
203
+ if (nested.length > 0) return nested.flatMap(declaratorNames);
204
+ const declarator = node.childForFieldName("declarator");
205
+ return declarator ? declaratorNames(declarator) : [];
206
+ }
207
+
208
+ function isFunctionDeclarator(node: SyntaxNodeLike): boolean {
209
+ if (node.type === "function_declarator") {
210
+ const subject = node.childForFieldName("declarator");
211
+ return subject?.type !== "parenthesized_declarator" || !containsPointer(subject);
212
+ }
213
+ const declarator = node.childForFieldName("declarator");
214
+ return declarator ? isFunctionDeclarator(declarator) : false;
215
+ }
216
+
217
+ function containsPointer(node: SyntaxNodeLike): boolean {
218
+ if (node.type === "pointer_declarator" || node.type === "reference_declarator") return true;
219
+ return node.children.some(containsPointer);
220
+ }
221
+
222
+ const DECLARATOR_NAME_TYPES = new Set([
223
+ "identifier",
224
+ "field_identifier",
225
+ "type_identifier",
226
+ "qualified_identifier",
227
+ "template_function",
228
+ "operator_name",
229
+ "destructor_name",
230
+ ]);