Skip to content

Commit 1b57835

Browse files
committed
Correctly compute the parent of TraceNodes referred to by ReferenceByName instances.
1 parent c5e25fb commit 1b57835

File tree

3 files changed

+53
-6
lines changed

3 files changed

+53
-6
lines changed

src/interop/starlasu-v2-metamodel.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ THE_REFERENCE_BY_NAME_ECLASS.get("eStructuralFeatures").add(ECore.EAttribute.cre
131131
}));
132132
THE_REFERENCE_BY_NAME_ECLASS.get("eStructuralFeatures").add(ECore.EReference.create({
133133
name: "referenced",
134-
containment: true
134+
containment: false
135135
}));
136136
THE_REFERENCE_BY_NAME_ECLASS.get("eStructuralFeatures").at(1).set("eGenericType", ECore.EGenericType.create({
137137
eTypeParameter: THE_REFERENCE_BY_NAME_ECLASS.get("eTypeParameters").at(0)

src/trace/trace-node.ts

+44-2
Original file line numberDiff line numberDiff line change
@@ -184,15 +184,38 @@ export class TraceNode extends Node implements PossiblyNamed {
184184
const innerRef = this.nodeAdapter.getReference(name);
185185
if (innerRef) {
186186
const reference = new ReferenceByName<TraceNode>(innerRef.name);
187-
if (innerRef?.referred) {
188-
reference.referred = this.make(innerRef.referred);
187+
const refTarget = innerRef?.referred;
188+
if (refTarget instanceof NodeAdapter) {
189+
const referred = this.make(innerRef.referred);
190+
reference.referred = referred.withParent(this.computeParentForReference(refTarget));
189191
}
190192
return reference;
191193
} else {
192194
return undefined;
193195
}
194196
}
195197

198+
private computeParentForReference(refTarget: NodeAdapter) {
199+
let node: TraceNode | undefined = undefined;
200+
let tempParent: TraceNode | undefined = undefined;
201+
while (refTarget.parent) {
202+
const parent = this.make(refTarget.parent);
203+
if (node) {
204+
node.parent = parent;
205+
} else {
206+
tempParent = parent;
207+
}
208+
node = parent;
209+
refTarget = refTarget.parent;
210+
}
211+
if (tempParent) {
212+
const newParent = this.getRoot().get(tempParent.getPathFromRoot());
213+
if (newParent instanceof Node) {
214+
return newParent;
215+
}
216+
}
217+
}
218+
196219
private makeChild(child: Node | undefined | NodeAdapter, name: string | symbol) {
197220
if (child instanceof NodeAdapter) {
198221
return this.make(child).withParent(this);
@@ -259,4 +282,23 @@ export class TraceNode extends Node implements PossiblyNamed {
259282
isStatement(): boolean {
260283
return this.nodeAdapter.isStatement();
261284
}
285+
286+
get(path: (string | number)[]) {
287+
// eslint-disable-next-line @typescript-eslint/no-this-alias
288+
let node: Node | Node[] | undefined = this;
289+
for (const elem of path) {
290+
if (typeof elem == "string") {
291+
if (node instanceof Node) {
292+
node = node.getChild(elem);
293+
} else {
294+
throw new Error("Invalid path at " + elem + ", expected node, got " + node);
295+
}
296+
} else if (Array.isArray(node)) {
297+
node = node[elem];
298+
} else {
299+
throw new Error("Invalid path at " + elem + ", expected children, got " + node);
300+
}
301+
}
302+
return node;
303+
}
262304
}

tests/interop/workspace-transpilation-trace.test.ts

+8-3
Original file line numberDiff line numberDiff line change
@@ -115,12 +115,17 @@ describe('Workspace Transpilation traces', function() {
115115
filter((node: TraceNode) => node.getType() == "com.strumenta.rpgparser.model.ReferenceExpr"),
116116
first()).first as TraceNode;
117117
expect(refExpr).not.to.be.undefined;
118+
expect(refExpr.getPathFromRoot()).to.eql(["mainStatements", 0, "expression", "target"]);
118119
const reference = refExpr.getReference("dataDefinition");
119120
expect(reference).to.be.instanceof(ReferenceByName);
120121
expect(reference?.name).to.equal("CNT");
121-
expect(reference?.referred).to.be.instanceof(TraceNode);
122-
expect(reference?.referred?.getType()).to.equal("com.strumenta.rpgparser.model.StandaloneField");
123-
expect(reference?.referred?.name).to.equal("CNT");
122+
const refTarget = reference?.referred;
123+
expect(refTarget).to.be.instanceof(TraceNode);
124+
expect(refTarget?.getType()).to.equal("com.strumenta.rpgparser.model.StandaloneField");
125+
expect(refTarget?.name).to.equal("CNT");
126+
expect(refTarget?.getRole()).to.equal("dataDefinitions");
127+
expect(refTarget?.getPathFromRoot()).to.eql(["dataDefinitions", 3]);
128+
expect(refTarget?.getRoot()).to.equal(sourceRoot);
124129

125130
// TODO broken expect(cus300File.node.getChildren("dataDefinition").length).to.eql(4)
126131
expect(sourceRoot.getChildren("mainStatements").length).to.eql(9)

0 commit comments

Comments
 (0)