@gitwand/core 2.0.1 → 2.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.
- package/README.md +58 -0
- package/dist/__tests__/bench.bench.js +39 -0
- package/dist/__tests__/bench.bench.js.map +1 -1
- package/dist/__tests__/corpus.d.ts.map +1 -1
- package/dist/__tests__/corpus.js +363 -0
- package/dist/__tests__/corpus.js.map +1 -1
- package/dist/__tests__/diff/block-move.test.d.ts +5 -0
- package/dist/__tests__/diff/block-move.test.d.ts.map +1 -0
- package/dist/__tests__/diff/block-move.test.js +132 -0
- package/dist/__tests__/diff/block-move.test.js.map +1 -0
- package/dist/__tests__/diff/histogram.test.d.ts +8 -0
- package/dist/__tests__/diff/histogram.test.d.ts.map +1 -0
- package/dist/__tests__/diff/histogram.test.js +150 -0
- package/dist/__tests__/diff/histogram.test.js.map +1 -0
- package/dist/__tests__/diff/parity.test.d.ts +17 -0
- package/dist/__tests__/diff/parity.test.d.ts.map +1 -0
- package/dist/__tests__/diff/parity.test.js +149 -0
- package/dist/__tests__/diff/parity.test.js.map +1 -0
- package/dist/__tests__/diff.test.js +6 -2
- package/dist/__tests__/diff.test.js.map +1 -1
- package/dist/__tests__/format-profiles/integration.test.d.ts +7 -0
- package/dist/__tests__/format-profiles/integration.test.d.ts.map +1 -0
- package/dist/__tests__/format-profiles/integration.test.js +193 -0
- package/dist/__tests__/format-profiles/integration.test.js.map +1 -0
- package/dist/__tests__/format-profiles/json-patch.test.d.ts +12 -0
- package/dist/__tests__/format-profiles/json-patch.test.d.ts.map +1 -0
- package/dist/__tests__/format-profiles/json-patch.test.js +222 -0
- package/dist/__tests__/format-profiles/json-patch.test.js.map +1 -0
- package/dist/__tests__/format-profiles/registry.test.d.ts +5 -0
- package/dist/__tests__/format-profiles/registry.test.d.ts.map +1 -0
- package/dist/__tests__/format-profiles/registry.test.js +124 -0
- package/dist/__tests__/format-profiles/registry.test.js.map +1 -0
- package/dist/__tests__/patterns/make-score.test.d.ts +9 -0
- package/dist/__tests__/patterns/make-score.test.d.ts.map +1 -0
- package/dist/__tests__/patterns/make-score.test.js +49 -0
- package/dist/__tests__/patterns/make-score.test.js.map +1 -0
- package/dist/__tests__/structural/grandeur-nature.test.d.ts +31 -0
- package/dist/__tests__/structural/grandeur-nature.test.d.ts.map +1 -0
- package/dist/__tests__/structural/grandeur-nature.test.js +264 -0
- package/dist/__tests__/structural/grandeur-nature.test.js.map +1 -0
- package/dist/__tests__/structural/languages.test.d.ts +5 -0
- package/dist/__tests__/structural/languages.test.d.ts.map +1 -0
- package/dist/__tests__/structural/languages.test.js +74 -0
- package/dist/__tests__/structural/languages.test.js.map +1 -0
- package/dist/__tests__/structural/matching.test.d.ts +6 -0
- package/dist/__tests__/structural/matching.test.d.ts.map +1 -0
- package/dist/__tests__/structural/matching.test.js +113 -0
- package/dist/__tests__/structural/matching.test.js.map +1 -0
- package/dist/__tests__/structural/merge.test.d.ts +6 -0
- package/dist/__tests__/structural/merge.test.d.ts.map +1 -0
- package/dist/__tests__/structural/merge.test.js +117 -0
- package/dist/__tests__/structural/merge.test.js.map +1 -0
- package/dist/__tests__/structural/reconstruct.test.d.ts +6 -0
- package/dist/__tests__/structural/reconstruct.test.d.ts.map +1 -0
- package/dist/__tests__/structural/reconstruct.test.js +104 -0
- package/dist/__tests__/structural/reconstruct.test.js.map +1 -0
- package/dist/__tests__/structural/structural-index.test.d.ts +14 -0
- package/dist/__tests__/structural/structural-index.test.d.ts.map +1 -0
- package/dist/__tests__/structural/structural-index.test.js +108 -0
- package/dist/__tests__/structural/structural-index.test.js.map +1 -0
- package/dist/diff/block-move.d.ts +53 -0
- package/dist/diff/block-move.d.ts.map +1 -0
- package/dist/diff/block-move.js +192 -0
- package/dist/diff/block-move.js.map +1 -0
- package/dist/diff/histogram.d.ts +45 -0
- package/dist/diff/histogram.d.ts.map +1 -0
- package/dist/diff/histogram.js +172 -0
- package/dist/diff/histogram.js.map +1 -0
- package/dist/diff/index.d.ts +30 -0
- package/dist/diff/index.d.ts.map +1 -0
- package/dist/diff/index.js +47 -0
- package/dist/diff/index.js.map +1 -0
- package/dist/diff/lcs.d.ts +34 -0
- package/dist/diff/lcs.d.ts.map +1 -0
- package/dist/diff/lcs.js +184 -0
- package/dist/diff/lcs.js.map +1 -0
- package/dist/diff/shared.d.ts +54 -0
- package/dist/diff/shared.d.ts.map +1 -0
- package/dist/diff/shared.js +164 -0
- package/dist/diff/shared.js.map +1 -0
- package/dist/diff.d.ts +6 -65
- package/dist/diff.d.ts.map +1 -1
- package/dist/diff.js +6 -324
- package/dist/diff.js.map +1 -1
- package/dist/format-profiles/index.d.ts +34 -0
- package/dist/format-profiles/index.d.ts.map +1 -0
- package/dist/format-profiles/index.js +86 -0
- package/dist/format-profiles/index.js.map +1 -0
- package/dist/format-profiles/json-patch.d.ts +61 -0
- package/dist/format-profiles/json-patch.d.ts.map +1 -0
- package/dist/format-profiles/json-patch.js +269 -0
- package/dist/format-profiles/json-patch.js.map +1 -0
- package/dist/format-profiles/merge-strategies.d.ts +54 -0
- package/dist/format-profiles/merge-strategies.d.ts.map +1 -0
- package/dist/format-profiles/merge-strategies.js +156 -0
- package/dist/format-profiles/merge-strategies.js.map +1 -0
- package/dist/format-profiles/profiles/composer.d.ts +18 -0
- package/dist/format-profiles/profiles/composer.d.ts.map +1 -0
- package/dist/format-profiles/profiles/composer.js +45 -0
- package/dist/format-profiles/profiles/composer.js.map +1 -0
- package/dist/format-profiles/profiles/helm-values.d.ts +21 -0
- package/dist/format-profiles/profiles/helm-values.d.ts.map +1 -0
- package/dist/format-profiles/profiles/helm-values.js +40 -0
- package/dist/format-profiles/profiles/helm-values.js.map +1 -0
- package/dist/format-profiles/profiles/kubernetes.d.ts +22 -0
- package/dist/format-profiles/profiles/kubernetes.d.ts.map +1 -0
- package/dist/format-profiles/profiles/kubernetes.js +60 -0
- package/dist/format-profiles/profiles/kubernetes.js.map +1 -0
- package/dist/format-profiles/profiles/package-json.d.ts +18 -0
- package/dist/format-profiles/profiles/package-json.d.ts.map +1 -0
- package/dist/format-profiles/profiles/package-json.js +36 -0
- package/dist/format-profiles/profiles/package-json.js.map +1 -0
- package/dist/format-profiles/profiles/tsconfig.d.ts +21 -0
- package/dist/format-profiles/profiles/tsconfig.d.ts.map +1 -0
- package/dist/format-profiles/profiles/tsconfig.js +47 -0
- package/dist/format-profiles/profiles/tsconfig.js.map +1 -0
- package/dist/format-profiles/types.d.ts +67 -0
- package/dist/format-profiles/types.d.ts.map +1 -0
- package/dist/format-profiles/types.js +9 -0
- package/dist/format-profiles/types.js.map +1 -0
- package/dist/index.d.ts +9 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -1
- package/dist/index.js.map +1 -1
- package/dist/patterns/insertion-at-boundary.d.ts.map +1 -1
- package/dist/patterns/insertion-at-boundary.js +15 -33
- package/dist/patterns/insertion-at-boundary.js.map +1 -1
- package/dist/patterns/utils.d.ts +11 -8
- package/dist/patterns/utils.d.ts.map +1 -1
- package/dist/patterns/utils.js +28 -10
- package/dist/patterns/utils.js.map +1 -1
- package/dist/resolver/format-dispatch.d.ts.map +1 -1
- package/dist/resolver/format-dispatch.js +3 -1
- package/dist/resolver/format-dispatch.js.map +1 -1
- package/dist/resolver/index.d.ts +14 -0
- package/dist/resolver/index.d.ts.map +1 -1
- package/dist/resolver/index.js +29 -0
- package/dist/resolver/index.js.map +1 -1
- package/dist/resolver/policy.d.ts.map +1 -1
- package/dist/resolver/policy.js +2 -0
- package/dist/resolver/policy.js.map +1 -1
- package/dist/resolvers/dispatcher.d.ts +22 -2
- package/dist/resolvers/dispatcher.d.ts.map +1 -1
- package/dist/resolvers/dispatcher.js +8 -3
- package/dist/resolvers/dispatcher.js.map +1 -1
- package/dist/resolvers/json.d.ts +11 -2
- package/dist/resolvers/json.d.ts.map +1 -1
- package/dist/resolvers/json.js +55 -7
- package/dist/resolvers/json.js.map +1 -1
- package/dist/resolvers/yaml.d.ts +8 -2
- package/dist/resolvers/yaml.d.ts.map +1 -1
- package/dist/resolvers/yaml.js +156 -2
- package/dist/resolvers/yaml.js.map +1 -1
- package/dist/structural/entities.d.ts +44 -0
- package/dist/structural/entities.d.ts.map +1 -0
- package/dist/structural/entities.js +315 -0
- package/dist/structural/entities.js.map +1 -0
- package/dist/structural/index.d.ts +48 -0
- package/dist/structural/index.d.ts.map +1 -0
- package/dist/structural/index.js +177 -0
- package/dist/structural/index.js.map +1 -0
- package/dist/structural/matching.d.ts +46 -0
- package/dist/structural/matching.d.ts.map +1 -0
- package/dist/structural/matching.js +83 -0
- package/dist/structural/matching.js.map +1 -0
- package/dist/structural/merge.d.ts +45 -0
- package/dist/structural/merge.d.ts.map +1 -0
- package/dist/structural/merge.js +127 -0
- package/dist/structural/merge.js.map +1 -0
- package/dist/structural/parsers/adapters/browser.d.ts +22 -0
- package/dist/structural/parsers/adapters/browser.d.ts.map +1 -0
- package/dist/structural/parsers/adapters/browser.js +27 -0
- package/dist/structural/parsers/adapters/browser.js.map +1 -0
- package/dist/structural/parsers/adapters/node.d.ts +18 -0
- package/dist/structural/parsers/adapters/node.d.ts.map +1 -0
- package/dist/structural/parsers/adapters/node.js +42 -0
- package/dist/structural/parsers/adapters/node.js.map +1 -0
- package/dist/structural/parsers/adapters/tauri.d.ts +26 -0
- package/dist/structural/parsers/adapters/tauri.d.ts.map +1 -0
- package/dist/structural/parsers/adapters/tauri.js +34 -0
- package/dist/structural/parsers/adapters/tauri.js.map +1 -0
- package/dist/structural/parsers/grammars/languages.d.ts +32 -0
- package/dist/structural/parsers/grammars/languages.d.ts.map +1 -0
- package/dist/structural/parsers/grammars/languages.js +73 -0
- package/dist/structural/parsers/grammars/languages.js.map +1 -0
- package/dist/structural/parsers/grammars/ts.d.ts +26 -0
- package/dist/structural/parsers/grammars/ts.d.ts.map +1 -0
- package/dist/structural/parsers/grammars/ts.js +46 -0
- package/dist/structural/parsers/grammars/ts.js.map +1 -0
- package/dist/structural/parsers/loader.d.ts +74 -0
- package/dist/structural/parsers/loader.d.ts.map +1 -0
- package/dist/structural/parsers/loader.js +181 -0
- package/dist/structural/parsers/loader.js.map +1 -0
- package/dist/structural/reconstruct.d.ts +28 -0
- package/dist/structural/reconstruct.d.ts.map +1 -0
- package/dist/structural/reconstruct.js +63 -0
- package/dist/structural/reconstruct.js.map +1 -0
- package/dist/types.d.ts +25 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +16 -2
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Top-level entity extraction from a tree-sitter AST.
|
|
3
|
+
*
|
|
4
|
+
* An "entity" is a top-level declaration in a TypeScript/TSX file:
|
|
5
|
+
* import, export, function, class, interface, type alias, variable declaration,
|
|
6
|
+
* or ambient declaration (declare …).
|
|
7
|
+
*
|
|
8
|
+
* Each entity carries:
|
|
9
|
+
* - `signature` — stable key for 3-way matching (based on name/kind)
|
|
10
|
+
* - `text` — exact source slice (used in the merged output)
|
|
11
|
+
* - byte offsets — for gap-preserving reconstruction
|
|
12
|
+
*/
|
|
13
|
+
// ─── Internal helpers ─────────────────────────────────────────────────────────
|
|
14
|
+
/** Find the first named child with the given field name, or fall back to type search. */
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
16
|
+
function fieldOrType(node, fieldName, typeName) {
|
|
17
|
+
return node.childForFieldName?.(fieldName) ?? findChildByType(node, typeName);
|
|
18
|
+
}
|
|
19
|
+
/** Find the first direct child with the given type. */
|
|
20
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
21
|
+
function findChildByType(node, typeName) {
|
|
22
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
23
|
+
const child = node.child(i);
|
|
24
|
+
if (child.type === typeName)
|
|
25
|
+
return child;
|
|
26
|
+
}
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Derive a stable signature and kind for a top-level tree-sitter node.
|
|
31
|
+
*
|
|
32
|
+
* Signatures are intentionally simple (kind:name) so that a renamed entity
|
|
33
|
+
* is treated as delete+add rather than a mysterious match. Conservative, correct.
|
|
34
|
+
*
|
|
35
|
+
* Covers: TypeScript/TSX/JS/JSX, Python, Go, Rust.
|
|
36
|
+
*/
|
|
37
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
38
|
+
function nodeSignature(node, source) {
|
|
39
|
+
const type = node.type;
|
|
40
|
+
// ╔══════════════════════════════════════════════════════╗
|
|
41
|
+
// ║ TypeScript / JavaScript (shared grammar base) ║
|
|
42
|
+
// ╚══════════════════════════════════════════════════════╝
|
|
43
|
+
// ── import_statement ─────────────────────────────────────
|
|
44
|
+
if (type === "import_statement") {
|
|
45
|
+
const sourceNode = fieldOrType(node, "source", "string");
|
|
46
|
+
const mod = sourceNode
|
|
47
|
+
? source.slice(sourceNode.startIndex, sourceNode.endIndex)
|
|
48
|
+
: String(node.startIndex);
|
|
49
|
+
return { sig: `import:${mod}`, kind: "import" };
|
|
50
|
+
}
|
|
51
|
+
// ── export_statement ─────────────────────────────────────
|
|
52
|
+
if (type === "export_statement") {
|
|
53
|
+
const decl = node.childForFieldName?.("declaration");
|
|
54
|
+
if (decl) {
|
|
55
|
+
const inner = nodeSignature(decl, source);
|
|
56
|
+
return { sig: `export:${inner.sig}`, kind: "export" };
|
|
57
|
+
}
|
|
58
|
+
const preview = source
|
|
59
|
+
.slice(node.startIndex, Math.min(node.startIndex + 60, node.endIndex))
|
|
60
|
+
.replace(/\s+/g, " ")
|
|
61
|
+
.trim();
|
|
62
|
+
return { sig: `export:${preview}`, kind: "export" };
|
|
63
|
+
}
|
|
64
|
+
// ── function_declaration / generator_function_declaration ─
|
|
65
|
+
if (type === "function_declaration" || type === "generator_function_declaration") {
|
|
66
|
+
const name = fieldOrType(node, "name", "identifier");
|
|
67
|
+
const nameText = name ? source.slice(name.startIndex, name.endIndex) : "__anonymous";
|
|
68
|
+
return { sig: `function:${nameText}`, kind: "function" };
|
|
69
|
+
}
|
|
70
|
+
// ── class_declaration / abstract_class_declaration ────────
|
|
71
|
+
if (type === "class_declaration" || type === "abstract_class_declaration") {
|
|
72
|
+
const name = fieldOrType(node, "name", "type_identifier") ?? fieldOrType(node, "name", "identifier");
|
|
73
|
+
const nameText = name ? source.slice(name.startIndex, name.endIndex) : "__anonymous";
|
|
74
|
+
return { sig: `class:${nameText}`, kind: "class" };
|
|
75
|
+
}
|
|
76
|
+
// ── interface_declaration ─────────────────────────────────
|
|
77
|
+
if (type === "interface_declaration") {
|
|
78
|
+
const name = fieldOrType(node, "name", "type_identifier");
|
|
79
|
+
const nameText = name ? source.slice(name.startIndex, name.endIndex) : "__anon";
|
|
80
|
+
return { sig: `interface:${nameText}`, kind: "interface" };
|
|
81
|
+
}
|
|
82
|
+
// ── type_alias_declaration ────────────────────────────────
|
|
83
|
+
if (type === "type_alias_declaration") {
|
|
84
|
+
const name = fieldOrType(node, "name", "type_identifier");
|
|
85
|
+
const nameText = name ? source.slice(name.startIndex, name.endIndex) : "__anon";
|
|
86
|
+
return { sig: `type:${nameText}`, kind: "type" };
|
|
87
|
+
}
|
|
88
|
+
// ── lexical_declaration (const / let) ─────────────────────
|
|
89
|
+
// ── variable_declaration (var) ────────────────────────────
|
|
90
|
+
if (type === "lexical_declaration" || type === "variable_declaration") {
|
|
91
|
+
const names = [];
|
|
92
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
93
|
+
const child = node.child(i);
|
|
94
|
+
if (child.type === "variable_declarator") {
|
|
95
|
+
const nameNode = child.childForFieldName?.("name");
|
|
96
|
+
if (nameNode)
|
|
97
|
+
names.push(source.slice(nameNode.startIndex, nameNode.endIndex));
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return { sig: `var:${names.join(",")}`, kind: "variable" };
|
|
101
|
+
}
|
|
102
|
+
// ── ambient_declaration (declare …) ──────────────────────
|
|
103
|
+
if (type === "ambient_declaration") {
|
|
104
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
105
|
+
const child = node.child(i);
|
|
106
|
+
if (child.type !== "declare") {
|
|
107
|
+
const inner = nodeSignature(child, source);
|
|
108
|
+
return { sig: `declare:${inner.sig}`, kind: "declare" };
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return { sig: `declare:${node.startIndex}`, kind: "declare" };
|
|
112
|
+
}
|
|
113
|
+
// ── expression_statement ──────────────────────────────────
|
|
114
|
+
if (type === "expression_statement") {
|
|
115
|
+
const preview = source
|
|
116
|
+
.slice(node.startIndex, Math.min(node.startIndex + 50, node.endIndex))
|
|
117
|
+
.replace(/\s+/g, " ")
|
|
118
|
+
.trim();
|
|
119
|
+
return { sig: `expr:${preview}`, kind: "expression" };
|
|
120
|
+
}
|
|
121
|
+
// ╔══════════════════════════════════════════════════════╗
|
|
122
|
+
// ║ Python ║
|
|
123
|
+
// ╚══════════════════════════════════════════════════════╝
|
|
124
|
+
// ── function_definition ───────────────────────────────────
|
|
125
|
+
if (type === "function_definition") {
|
|
126
|
+
const name = fieldOrType(node, "name", "identifier");
|
|
127
|
+
const nameText = name ? source.slice(name.startIndex, name.endIndex) : "__anonymous";
|
|
128
|
+
return { sig: `function:${nameText}`, kind: "function" };
|
|
129
|
+
}
|
|
130
|
+
// ── class_definition ──────────────────────────────────────
|
|
131
|
+
if (type === "class_definition") {
|
|
132
|
+
const name = fieldOrType(node, "name", "identifier");
|
|
133
|
+
const nameText = name ? source.slice(name.startIndex, name.endIndex) : "__anonymous";
|
|
134
|
+
return { sig: `class:${nameText}`, kind: "class" };
|
|
135
|
+
}
|
|
136
|
+
// ── decorated_definition (wraps function_definition / class_definition) ──
|
|
137
|
+
if (type === "decorated_definition") {
|
|
138
|
+
// Find the wrapped definition
|
|
139
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
140
|
+
const child = node.child(i);
|
|
141
|
+
if (child.type === "function_definition" || child.type === "class_definition") {
|
|
142
|
+
const inner = nodeSignature(child, source);
|
|
143
|
+
return { sig: `decorated:${inner.sig}`, kind: inner.kind };
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return { sig: `decorated:${node.startIndex}`, kind: "other" };
|
|
147
|
+
}
|
|
148
|
+
// ── import_statement (Python) — already handled above (same name) ──
|
|
149
|
+
// ── import_from_statement (Python) ────────────────────────
|
|
150
|
+
if (type === "import_from_statement") {
|
|
151
|
+
const modNode = node.childForFieldName?.("module_name") ?? findChildByType(node, "dotted_name");
|
|
152
|
+
const mod = modNode ? source.slice(modNode.startIndex, modNode.endIndex) : String(node.startIndex);
|
|
153
|
+
return { sig: `import_from:${mod}`, kind: "import" };
|
|
154
|
+
}
|
|
155
|
+
// ╔══════════════════════════════════════════════════════╗
|
|
156
|
+
// ║ Go ║
|
|
157
|
+
// ╚══════════════════════════════════════════════════════╝
|
|
158
|
+
// ── function_declaration (Go) ─────────────────────────────
|
|
159
|
+
// Note: Go also has function_declaration but the name field is "name" with type "identifier"
|
|
160
|
+
// Already handled above by the JS function_declaration case.
|
|
161
|
+
// ── method_declaration (Go) ───────────────────────────────
|
|
162
|
+
if (type === "method_declaration") {
|
|
163
|
+
const name = fieldOrType(node, "name", "field_identifier") ?? fieldOrType(node, "name", "identifier");
|
|
164
|
+
const nameText = name ? source.slice(name.startIndex, name.endIndex) : "__anonymous";
|
|
165
|
+
const receiver = node.childForFieldName?.("receiver");
|
|
166
|
+
const receiverText = receiver ? source.slice(receiver.startIndex, receiver.endIndex).replace(/\s+/g, " ").trim() : "";
|
|
167
|
+
return { sig: `method:${receiverText}:${nameText}`, kind: "function" };
|
|
168
|
+
}
|
|
169
|
+
// ── type_declaration (Go) ─────────────────────────────────
|
|
170
|
+
if (type === "type_declaration") {
|
|
171
|
+
// Contains type_spec children
|
|
172
|
+
const spec = findChildByType(node, "type_spec");
|
|
173
|
+
if (spec) {
|
|
174
|
+
const name = fieldOrType(spec, "name", "type_identifier");
|
|
175
|
+
const nameText = name ? source.slice(name.startIndex, name.endIndex) : "__anon";
|
|
176
|
+
return { sig: `type:${nameText}`, kind: "type" };
|
|
177
|
+
}
|
|
178
|
+
return { sig: `type:${node.startIndex}`, kind: "type" };
|
|
179
|
+
}
|
|
180
|
+
// ── var_declaration (Go) ───────────────────────────────────
|
|
181
|
+
if (type === "var_declaration") {
|
|
182
|
+
const spec = findChildByType(node, "var_spec");
|
|
183
|
+
if (spec) {
|
|
184
|
+
const name = findChildByType(spec, "identifier");
|
|
185
|
+
const nameText = name ? source.slice(name.startIndex, name.endIndex) : "__anon";
|
|
186
|
+
return { sig: `var:${nameText}`, kind: "variable" };
|
|
187
|
+
}
|
|
188
|
+
return { sig: `var:${node.startIndex}`, kind: "variable" };
|
|
189
|
+
}
|
|
190
|
+
// ── import_declaration (Go) ───────────────────────────────
|
|
191
|
+
if (type === "import_declaration") {
|
|
192
|
+
const preview = source
|
|
193
|
+
.slice(node.startIndex, Math.min(node.startIndex + 60, node.endIndex))
|
|
194
|
+
.replace(/\s+/g, " ")
|
|
195
|
+
.trim();
|
|
196
|
+
return { sig: `import:${preview}`, kind: "import" };
|
|
197
|
+
}
|
|
198
|
+
// ╔══════════════════════════════════════════════════════╗
|
|
199
|
+
// ║ Rust ║
|
|
200
|
+
// ╚══════════════════════════════════════════════════════╝
|
|
201
|
+
// ── function_item (Rust) ──────────────────────────────────
|
|
202
|
+
if (type === "function_item") {
|
|
203
|
+
const name = fieldOrType(node, "name", "identifier");
|
|
204
|
+
const nameText = name ? source.slice(name.startIndex, name.endIndex) : "__anonymous";
|
|
205
|
+
return { sig: `function:${nameText}`, kind: "function" };
|
|
206
|
+
}
|
|
207
|
+
// ── struct_item (Rust) ────────────────────────────────────
|
|
208
|
+
if (type === "struct_item") {
|
|
209
|
+
const name = fieldOrType(node, "name", "type_identifier");
|
|
210
|
+
const nameText = name ? source.slice(name.startIndex, name.endIndex) : "__anon";
|
|
211
|
+
return { sig: `struct:${nameText}`, kind: "class" };
|
|
212
|
+
}
|
|
213
|
+
// ── enum_item (Rust) ──────────────────────────────────────
|
|
214
|
+
if (type === "enum_item") {
|
|
215
|
+
const name = fieldOrType(node, "name", "type_identifier");
|
|
216
|
+
const nameText = name ? source.slice(name.startIndex, name.endIndex) : "__anon";
|
|
217
|
+
return { sig: `enum:${nameText}`, kind: "type" };
|
|
218
|
+
}
|
|
219
|
+
// ── trait_item (Rust) ─────────────────────────────────────
|
|
220
|
+
if (type === "trait_item") {
|
|
221
|
+
const name = fieldOrType(node, "name", "type_identifier");
|
|
222
|
+
const nameText = name ? source.slice(name.startIndex, name.endIndex) : "__anon";
|
|
223
|
+
return { sig: `trait:${nameText}`, kind: "interface" };
|
|
224
|
+
}
|
|
225
|
+
// ── impl_item (Rust) ──────────────────────────────────────
|
|
226
|
+
if (type === "impl_item") {
|
|
227
|
+
// impl Foo or impl Bar for Foo
|
|
228
|
+
const traitNode = node.childForFieldName?.("trait");
|
|
229
|
+
const typeNode = node.childForFieldName?.("type");
|
|
230
|
+
const typeText = typeNode
|
|
231
|
+
? source.slice(typeNode.startIndex, typeNode.endIndex).replace(/\s+/g, " ").trim()
|
|
232
|
+
: String(node.startIndex);
|
|
233
|
+
const traitText = traitNode
|
|
234
|
+
? source.slice(traitNode.startIndex, traitNode.endIndex).replace(/\s+/g, " ").trim()
|
|
235
|
+
: null;
|
|
236
|
+
const sig = traitText ? `impl:${traitText} for ${typeText}` : `impl:${typeText}`;
|
|
237
|
+
return { sig, kind: "class" };
|
|
238
|
+
}
|
|
239
|
+
// ── mod_item (Rust) ───────────────────────────────────────
|
|
240
|
+
if (type === "mod_item") {
|
|
241
|
+
const name = fieldOrType(node, "name", "identifier");
|
|
242
|
+
const nameText = name ? source.slice(name.startIndex, name.endIndex) : "__anon";
|
|
243
|
+
return { sig: `mod:${nameText}`, kind: "declare" };
|
|
244
|
+
}
|
|
245
|
+
// ── use_declaration (Rust) ────────────────────────────────
|
|
246
|
+
if (type === "use_declaration") {
|
|
247
|
+
const preview = source
|
|
248
|
+
.slice(node.startIndex, Math.min(node.startIndex + 60, node.endIndex))
|
|
249
|
+
.replace(/\s+/g, " ")
|
|
250
|
+
.trim();
|
|
251
|
+
return { sig: `use:${preview}`, kind: "import" };
|
|
252
|
+
}
|
|
253
|
+
// ── attribute_item / inner_attribute_item (Rust — top-level attributes) ──
|
|
254
|
+
if (type === "attribute_item" || type === "inner_attribute_item") {
|
|
255
|
+
const preview = source
|
|
256
|
+
.slice(node.startIndex, Math.min(node.startIndex + 40, node.endIndex))
|
|
257
|
+
.replace(/\s+/g, " ")
|
|
258
|
+
.trim();
|
|
259
|
+
return { sig: `attr:${preview}`, kind: "other" };
|
|
260
|
+
}
|
|
261
|
+
// ╔══════════════════════════════════════════════════════╗
|
|
262
|
+
// ║ Fallback ║
|
|
263
|
+
// ╚══════════════════════════════════════════════════════╝
|
|
264
|
+
return { sig: `${type}:${node.startIndex}`, kind: "other" };
|
|
265
|
+
}
|
|
266
|
+
// ─── Public API ───────────────────────────────────────────────────────────────
|
|
267
|
+
/**
|
|
268
|
+
* Extract top-level entities from a parsed tree-sitter tree.
|
|
269
|
+
*
|
|
270
|
+
* Skips unnamed tokens (punctuation, keywords) and ERROR nodes.
|
|
271
|
+
*
|
|
272
|
+
* @param tree - Parsed tree-sitter tree
|
|
273
|
+
* @param source - Source code (as passed to `parser.parse()`)
|
|
274
|
+
*/
|
|
275
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
276
|
+
export function extractEntities(tree, source) {
|
|
277
|
+
const entities = [];
|
|
278
|
+
const root = tree.rootNode;
|
|
279
|
+
for (let i = 0; i < root.childCount; i++) {
|
|
280
|
+
const node = root.child(i);
|
|
281
|
+
// Skip unnamed tokens (semicolons, whitespace nodes) and parse errors
|
|
282
|
+
if (!node.isNamed || node.type === "ERROR")
|
|
283
|
+
continue;
|
|
284
|
+
const { sig, kind } = nodeSignature(node, source);
|
|
285
|
+
entities.push({
|
|
286
|
+
signature: sig,
|
|
287
|
+
kind,
|
|
288
|
+
text: source.slice(node.startIndex, node.endIndex),
|
|
289
|
+
startByte: node.startIndex,
|
|
290
|
+
endByte: node.endIndex,
|
|
291
|
+
startLine: node.startPosition.row,
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
return entities;
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Return `true` if the tree contains at least one ERROR node.
|
|
298
|
+
*
|
|
299
|
+
* A tree with ERROR nodes has parse failures and should not be used
|
|
300
|
+
* for structural merge (we fall back to the hunk-based resolver).
|
|
301
|
+
*/
|
|
302
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
303
|
+
export function hasParseErrors(tree) {
|
|
304
|
+
function walk(node) {
|
|
305
|
+
if (node.type === "ERROR")
|
|
306
|
+
return true;
|
|
307
|
+
for (let i = 0; i < node.childCount; i++) {
|
|
308
|
+
if (walk(node.child(i)))
|
|
309
|
+
return true;
|
|
310
|
+
}
|
|
311
|
+
return false;
|
|
312
|
+
}
|
|
313
|
+
return walk(tree.rootNode);
|
|
314
|
+
}
|
|
315
|
+
//# sourceMappingURL=entities.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entities.js","sourceRoot":"","sources":["../../src/structural/entities.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @gitwand/core v2.3 — Structural (AST-based) merge dispatcher
|
|
3
|
+
*
|
|
4
|
+
* Provides `tryStructuralMergeResolve()`, an async entry point that:
|
|
5
|
+
*
|
|
6
|
+
* 1. Reconstructs the three file versions (base/ours/theirs) from the
|
|
7
|
+
* Git conflict markers in the conflicted content.
|
|
8
|
+
* 2. Parses each version with tree-sitter (via `web-tree-sitter`, optional peer).
|
|
9
|
+
* 3. Extracts top-level entities and matches them across the three versions.
|
|
10
|
+
* 4. Merges entities individually — only auto-resolvable conflicts are handled.
|
|
11
|
+
* 5. Reconstructs the merged file following theirs entity order.
|
|
12
|
+
*
|
|
13
|
+
* Returns `null` (never throws) when:
|
|
14
|
+
* - `web-tree-sitter` is not installed (graceful degradation)
|
|
15
|
+
* - The grammar WASM file is unavailable
|
|
16
|
+
* - Any version has parse errors
|
|
17
|
+
* - Any entity has a real (both-changed-diff) conflict
|
|
18
|
+
*
|
|
19
|
+
* In all these cases the caller falls back to the standard hunk-based resolver.
|
|
20
|
+
*/
|
|
21
|
+
import type { MergeResult } from "../types.js";
|
|
22
|
+
import { type LoaderOptions } from "./parsers/loader.js";
|
|
23
|
+
import { isStructuralLanguage } from "./parsers/grammars/languages.js";
|
|
24
|
+
export type { LoaderOptions as StructuralLoaderOptions };
|
|
25
|
+
export { isStructuralLanguage };
|
|
26
|
+
export type { SupportedLanguage } from "./parsers/grammars/languages.js";
|
|
27
|
+
/**
|
|
28
|
+
* Returns `true` for `.ts` and `.tsx` files.
|
|
29
|
+
* @deprecated Use `isStructuralLanguage` — now covers JS/JSX/Python/Go/Rust too.
|
|
30
|
+
*/
|
|
31
|
+
export declare function isTypeScriptFile(filePath: string): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Attempt structural (AST-based) merge resolution for a TypeScript/TSX file.
|
|
34
|
+
*
|
|
35
|
+
* @param conflictedContent - File content with Git conflict markers
|
|
36
|
+
* @param filePath - File path (grammar selection + type detection)
|
|
37
|
+
* @param opts - Optional loader overrides (WASM paths, custom loaders)
|
|
38
|
+
* @returns Merged content string on success, `null` on any failure
|
|
39
|
+
*/
|
|
40
|
+
export declare function tryStructuralMergeResolve(conflictedContent: string, filePath: string, opts?: LoaderOptions): Promise<string | null>;
|
|
41
|
+
/**
|
|
42
|
+
* Wrap a structurally merged content string in a `MergeResult` object.
|
|
43
|
+
*
|
|
44
|
+
* All hunks are marked as auto-resolved via the "structural-merge" resolver.
|
|
45
|
+
* This keeps the return type compatible with the synchronous `resolve()`.
|
|
46
|
+
*/
|
|
47
|
+
export declare function wrapStructuralResult(conflictedContent: string, mergedContent: string, filePath: string): MergeResult;
|
|
48
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/structural/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH,OAAO,KAAK,EAAE,WAAW,EAA8D,MAAM,aAAa,CAAC;AAE3G,OAAO,EAAgB,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAKvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAIvE,YAAY,EAAE,aAAa,IAAI,uBAAuB,EAAE,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,CAAC;AAChC,YAAY,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAIzE;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAE1D;AAiDD;;;;;;;GAOG;AACH,wBAAsB,yBAAyB,CAC7C,iBAAiB,EAAE,MAAM,EACzB,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE,aAAkB,GACvB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA2CxB;AAID;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,iBAAiB,EAAE,MAAM,EACzB,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,GACf,WAAW,CAyDb"}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @gitwand/core v2.3 — Structural (AST-based) merge dispatcher
|
|
3
|
+
*
|
|
4
|
+
* Provides `tryStructuralMergeResolve()`, an async entry point that:
|
|
5
|
+
*
|
|
6
|
+
* 1. Reconstructs the three file versions (base/ours/theirs) from the
|
|
7
|
+
* Git conflict markers in the conflicted content.
|
|
8
|
+
* 2. Parses each version with tree-sitter (via `web-tree-sitter`, optional peer).
|
|
9
|
+
* 3. Extracts top-level entities and matches them across the three versions.
|
|
10
|
+
* 4. Merges entities individually — only auto-resolvable conflicts are handled.
|
|
11
|
+
* 5. Reconstructs the merged file following theirs entity order.
|
|
12
|
+
*
|
|
13
|
+
* Returns `null` (never throws) when:
|
|
14
|
+
* - `web-tree-sitter` is not installed (graceful degradation)
|
|
15
|
+
* - The grammar WASM file is unavailable
|
|
16
|
+
* - Any version has parse errors
|
|
17
|
+
* - Any entity has a real (both-changed-diff) conflict
|
|
18
|
+
*
|
|
19
|
+
* In all these cases the caller falls back to the standard hunk-based resolver.
|
|
20
|
+
*/
|
|
21
|
+
import { parseConflictMarkers } from "../parser.js";
|
|
22
|
+
import { validateMergedContent } from "../resolver/validation.js";
|
|
23
|
+
import { loadGrammarForFile } from "./parsers/grammars/ts.js";
|
|
24
|
+
import { createParser } from "./parsers/loader.js";
|
|
25
|
+
import { extractEntities, hasParseErrors } from "./entities.js";
|
|
26
|
+
import { matchEntities } from "./matching.js";
|
|
27
|
+
import { mergeEntity, hasEntityConflict } from "./merge.js";
|
|
28
|
+
import { reconstructFile } from "./reconstruct.js";
|
|
29
|
+
import { isStructuralLanguage } from "./parsers/grammars/languages.js";
|
|
30
|
+
export { isStructuralLanguage };
|
|
31
|
+
// ─── Backward-compat alias ────────────────────────────────────────────────────
|
|
32
|
+
/**
|
|
33
|
+
* Returns `true` for `.ts` and `.tsx` files.
|
|
34
|
+
* @deprecated Use `isStructuralLanguage` — now covers JS/JSX/Python/Go/Rust too.
|
|
35
|
+
*/
|
|
36
|
+
export function isTypeScriptFile(filePath) {
|
|
37
|
+
return /\.(ts|tsx)$/i.test(filePath) && !/\.d\.ts$/i.test(filePath);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Reconstruct the three clean file versions from a conflicted file.
|
|
41
|
+
*
|
|
42
|
+
* - `ours` = text segments + ours lines from each conflict hunk
|
|
43
|
+
* - `theirs` = text segments + theirs lines from each conflict hunk
|
|
44
|
+
* - `base` = text segments + base lines (diff3) or ours lines (diff2 fallback)
|
|
45
|
+
*/
|
|
46
|
+
function reconstructVersions(conflictedContent) {
|
|
47
|
+
const { segments } = parseConflictMarkers(conflictedContent);
|
|
48
|
+
const oursLines = [];
|
|
49
|
+
const theirsLines = [];
|
|
50
|
+
const baseLines = [];
|
|
51
|
+
for (const seg of segments) {
|
|
52
|
+
if (seg.type === "text") {
|
|
53
|
+
oursLines.push(...seg.lines);
|
|
54
|
+
theirsLines.push(...seg.lines);
|
|
55
|
+
baseLines.push(...seg.lines);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
const { conflict } = seg;
|
|
59
|
+
oursLines.push(...conflict.oursLines);
|
|
60
|
+
theirsLines.push(...conflict.theirsLines);
|
|
61
|
+
// Use diff3 base if available; fall back to ours (conservative)
|
|
62
|
+
baseLines.push(...(conflict.baseLines.length > 0 ? conflict.baseLines : conflict.oursLines));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
base: baseLines.join("\n"),
|
|
67
|
+
ours: oursLines.join("\n"),
|
|
68
|
+
theirs: theirsLines.join("\n"),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
// ─── Main entry point ─────────────────────────────────────────────────────────
|
|
72
|
+
/**
|
|
73
|
+
* Attempt structural (AST-based) merge resolution for a TypeScript/TSX file.
|
|
74
|
+
*
|
|
75
|
+
* @param conflictedContent - File content with Git conflict markers
|
|
76
|
+
* @param filePath - File path (grammar selection + type detection)
|
|
77
|
+
* @param opts - Optional loader overrides (WASM paths, custom loaders)
|
|
78
|
+
* @returns Merged content string on success, `null` on any failure
|
|
79
|
+
*/
|
|
80
|
+
export async function tryStructuralMergeResolve(conflictedContent, filePath, opts = {}) {
|
|
81
|
+
// Only handle supported languages
|
|
82
|
+
if (!isStructuralLanguage(filePath))
|
|
83
|
+
return null;
|
|
84
|
+
// Load tree-sitter grammar (returns null if optional peer not installed)
|
|
85
|
+
const language = await loadGrammarForFile(filePath, opts);
|
|
86
|
+
if (!language)
|
|
87
|
+
return null;
|
|
88
|
+
// Create parser
|
|
89
|
+
const parser = await createParser(language, opts);
|
|
90
|
+
if (!parser)
|
|
91
|
+
return null;
|
|
92
|
+
// Reconstruct the three file versions
|
|
93
|
+
const { base, ours, theirs } = reconstructVersions(conflictedContent);
|
|
94
|
+
// Parse all three versions
|
|
95
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
96
|
+
const p = parser;
|
|
97
|
+
const [baseTree, oursTree, theirsTree] = [base, ours, theirs].map((src) => p.parse(src));
|
|
98
|
+
// Abort on parse errors in any version
|
|
99
|
+
if (hasParseErrors(baseTree) || hasParseErrors(oursTree) || hasParseErrors(theirsTree)) {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
// Extract top-level entities
|
|
103
|
+
const baseEntities = extractEntities(baseTree, base);
|
|
104
|
+
const oursEntities = extractEntities(oursTree, ours);
|
|
105
|
+
const theirsEntities = extractEntities(theirsTree, theirs);
|
|
106
|
+
// 3-way entity matching
|
|
107
|
+
const matches = matchEntities(baseEntities, oursEntities, theirsEntities);
|
|
108
|
+
// Entity-level merge decisions
|
|
109
|
+
const merges = matches.map(mergeEntity);
|
|
110
|
+
// Abort if any entity has a real conflict
|
|
111
|
+
if (hasEntityConflict(merges))
|
|
112
|
+
return null;
|
|
113
|
+
// Reconstruct the merged file
|
|
114
|
+
const mergedContent = reconstructFile(merges, theirsEntities, oursEntities, theirs);
|
|
115
|
+
return mergedContent;
|
|
116
|
+
}
|
|
117
|
+
// ─── MergeResult wrapper ──────────────────────────────────────────────────────
|
|
118
|
+
/**
|
|
119
|
+
* Wrap a structurally merged content string in a `MergeResult` object.
|
|
120
|
+
*
|
|
121
|
+
* All hunks are marked as auto-resolved via the "structural-merge" resolver.
|
|
122
|
+
* This keeps the return type compatible with the synchronous `resolve()`.
|
|
123
|
+
*/
|
|
124
|
+
export function wrapStructuralResult(conflictedContent, mergedContent, filePath) {
|
|
125
|
+
const { segments } = parseConflictMarkers(conflictedContent);
|
|
126
|
+
const hunks = segments
|
|
127
|
+
.filter((s) => s.type === "conflict")
|
|
128
|
+
.map((s) => ({
|
|
129
|
+
baseLines: s.conflict.baseLines,
|
|
130
|
+
oursLines: s.conflict.oursLines,
|
|
131
|
+
theirsLines: s.conflict.theirsLines,
|
|
132
|
+
startLine: s.conflict.startLine,
|
|
133
|
+
type: "complex",
|
|
134
|
+
confidence: {
|
|
135
|
+
score: 100,
|
|
136
|
+
label: "certain",
|
|
137
|
+
dimensions: {
|
|
138
|
+
typeClassification: 100,
|
|
139
|
+
dataRisk: 0,
|
|
140
|
+
scopeImpact: 0,
|
|
141
|
+
fileFrequency: 0,
|
|
142
|
+
baseAvailability: s.conflict.baseLines.length > 0 ? 100 : 0,
|
|
143
|
+
},
|
|
144
|
+
boosters: ["structural-merge"],
|
|
145
|
+
penalties: [],
|
|
146
|
+
},
|
|
147
|
+
explanation: "Résolu via merge structurel (tree-sitter AST)",
|
|
148
|
+
trace: {
|
|
149
|
+
steps: [],
|
|
150
|
+
selected: "complex",
|
|
151
|
+
summary: "Résolu via analyse structurelle AST — merge par entités TypeScript",
|
|
152
|
+
hasBase: s.conflict.baseLines.length > 0,
|
|
153
|
+
},
|
|
154
|
+
}));
|
|
155
|
+
const resolutions = hunks.map((hunk) => ({
|
|
156
|
+
hunk,
|
|
157
|
+
resolvedLines: null,
|
|
158
|
+
autoResolved: true,
|
|
159
|
+
resolutionReason: "structural-merge: résolu via analyse AST tree-sitter",
|
|
160
|
+
}));
|
|
161
|
+
const byType = hunks.length > 0 ? { complex: hunks.length } : {};
|
|
162
|
+
const validation = validateMergedContent(mergedContent, filePath);
|
|
163
|
+
return {
|
|
164
|
+
filePath,
|
|
165
|
+
mergedContent,
|
|
166
|
+
hunks,
|
|
167
|
+
resolutions,
|
|
168
|
+
stats: {
|
|
169
|
+
totalConflicts: hunks.length,
|
|
170
|
+
autoResolved: hunks.length,
|
|
171
|
+
remaining: 0,
|
|
172
|
+
byType,
|
|
173
|
+
},
|
|
174
|
+
validation,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/structural/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 3-way entity matching for structural merge.
|
|
3
|
+
*
|
|
4
|
+
* Matches top-level entities across the three file versions (base / ours /
|
|
5
|
+
* theirs) using their `signature` as a stable key. Each entity triple is
|
|
6
|
+
* assigned a status that describes what happened to it during the merge.
|
|
7
|
+
*/
|
|
8
|
+
import type { TopLevelEntity } from "./entities.js";
|
|
9
|
+
export type EntityMatchStatus =
|
|
10
|
+
/** Text identical in all three versions */
|
|
11
|
+
"unchanged"
|
|
12
|
+
/** Changed in ours, unchanged in theirs */
|
|
13
|
+
| "ours-only-change"
|
|
14
|
+
/** Changed in theirs, unchanged in ours */
|
|
15
|
+
| "theirs-only-change"
|
|
16
|
+
/** Both sides made the same change (or both deleted) */
|
|
17
|
+
| "both-changed-same"
|
|
18
|
+
/** Both sides changed differently — unresolvable at entity level */
|
|
19
|
+
| "both-changed-diff"
|
|
20
|
+
/** Added only by ours (not in base, not in theirs) */
|
|
21
|
+
| "ours-added"
|
|
22
|
+
/** Added only by theirs (not in base, not in ours) */
|
|
23
|
+
| "theirs-added"
|
|
24
|
+
/** Deleted by ours (was in base and theirs) */
|
|
25
|
+
| "ours-deleted"
|
|
26
|
+
/** Deleted by theirs (was in base and ours) */
|
|
27
|
+
| "theirs-deleted";
|
|
28
|
+
export interface EntityMatch {
|
|
29
|
+
signature: string;
|
|
30
|
+
status: EntityMatchStatus;
|
|
31
|
+
base: TopLevelEntity | null;
|
|
32
|
+
ours: TopLevelEntity | null;
|
|
33
|
+
theirs: TopLevelEntity | null;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Compute 3-way entity matches between base, ours, and theirs.
|
|
37
|
+
*
|
|
38
|
+
* The returned array covers every unique signature found across all three
|
|
39
|
+
* versions. Order follows: base order → ours-only → theirs-only sigs.
|
|
40
|
+
*
|
|
41
|
+
* @param base - Entities extracted from the base (ancestor) version
|
|
42
|
+
* @param ours - Entities extracted from our version (current branch)
|
|
43
|
+
* @param theirs - Entities extracted from their version (incoming branch)
|
|
44
|
+
*/
|
|
45
|
+
export declare function matchEntities(base: TopLevelEntity[], ours: TopLevelEntity[], theirs: TopLevelEntity[]): EntityMatch[];
|
|
46
|
+
//# sourceMappingURL=matching.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matching.d.ts","sourceRoot":"","sources":["../../src/structural/matching.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAIpD,MAAM,MAAM,iBAAiB;AAC3B,2CAA2C;AACzC,WAAW;AACb,2CAA2C;GACzC,kBAAkB;AACpB,2CAA2C;GACzC,oBAAoB;AACtB,wDAAwD;GACtD,mBAAmB;AACrB,oEAAoE;GAClE,mBAAmB;AACrB,sDAAsD;GACpD,YAAY;AACd,sDAAsD;GACpD,cAAc;AAChB,+CAA+C;GAC7C,cAAc;AAChB,+CAA+C;GAC7C,gBAAgB,CAAC;AAErB,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,IAAI,EAAE,cAAc,GAAG,IAAI,CAAC;IAC5B,IAAI,EAAE,cAAc,GAAG,IAAI,CAAC;IAC5B,MAAM,EAAE,cAAc,GAAG,IAAI,CAAC;CAC/B;AA4CD;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,cAAc,EAAE,EACtB,IAAI,EAAE,cAAc,EAAE,EACtB,MAAM,EAAE,cAAc,EAAE,GACvB,WAAW,EAAE,CA8Bf"}
|