Skip to content

Commit 9ad5372

Browse files
committed
Merge branch 'master' into chore/antlr4ng
# Conflicts: # CHANGELOG.md # package.json # src/interop/starlasu-v2-metamodel.ts # tests/interop/workspace-transpilation-trace.test.ts # yarn.lock
2 parents af44595 + f774131 commit 9ad5372

10 files changed

+141
-30
lines changed

Diff for: CHANGELOG.md

+7-1
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
5151

5252
## [1.5.0] – Not released
5353

54-
## [1.4.7] – Not yet released
54+
## [1.4.8] – 2024-01-29
55+
56+
### Fixed
57+
- When importing from Ecore, don't treat origins and destinations as children, as well as everything that's not a Node.
58+
59+
## [1.4.7] – 2024-01-18
5560

5661
### Added
5762
- Traversal functions `walkAncestors` and `findAncestorOfType` from Kolasu
63+
- Support for Ecore models with Kolasu's `SimpleOrigin` instances
5864

5965
### Changed
6066
- Aligned AST Transformers with Kolasu, and solved several issues in the previous implementation

Diff for: package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@
116116
"devDependencies": {
117117
"@tsconfig/recommended": "^1.0.3",
118118
"@types/chai": "^4.3.11",
119-
"@types/ecore": "^0.12.3",
119+
"@types/ecore": "^0.12.5",
120120
"@types/jest": "^29.5.10",
121121
"@types/node": "^18.19.2",
122122
"@typescript-eslint/eslint-plugin": "^6.13.2",
@@ -133,7 +133,7 @@
133133
"rimraf": "^3.0.0",
134134
"ts-jest": "^29.1.1",
135135
"ts-node": "^10.9.1",
136-
"typedoc": "^0.25.4",
136+
"typedoc": "^0.25.7",
137137
"typescript": "^5.3.2"
138138
}
139139
}

Diff for: src/interop/ecore.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import {
2323
THE_NODE_ECLASS, THE_NODE_ORIGIN_ECLASS,
2424
THE_POINT_ECLASS,
2525
THE_POSITION_ECLASS, THE_REFERENCE_BY_NAME_ECLASS,
26-
THE_RESULT_ECLASS, THE_TEXT_FILE_DESTINATION_ECLASS
26+
THE_RESULT_ECLASS, THE_SIMPLE_ORIGIN_ECLASS, THE_TEXT_FILE_DESTINATION_ECLASS
2727
} from "./starlasu-v2-metamodel";
2828
import {KOLASU_URI_V1} from "./kolasu-v1-metamodel";
2929
import {EBigDecimal, EBigInteger} from "./ecore-patching";
@@ -303,6 +303,9 @@ export function fromEObject(obj: ECore.EObject | any, parent?: Node): ASTElement
303303
if(isBuiltInClass(eClass, THE_NODE_ORIGIN_ECLASS)) {
304304
return fromEObject(obj.get("node")) as Node;
305305
}
306+
if(isBuiltInClass(eClass, THE_SIMPLE_ORIGIN_ECLASS)) {
307+
return undefined;
308+
}
306309
if(isBuiltInClass(eClass, THE_TEXT_FILE_DESTINATION_ECLASS)) {
307310
return fromEObject(obj.get("position")) as Position;
308311
}

Diff for: src/interop/starlasu-v2-metamodel.ts

+16
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,21 @@ THE_ORIGIN_ECLASS.get("eStructuralFeatures").add(ECore.EReference.create({
6767
eType: THE_POSITION_ECLASS,
6868
containment: true
6969
}));
70+
export const THE_SIMPLE_ORIGIN_ECLASS = Ecore.EClass.create({
71+
name: "SimpleOrigin"
72+
});
73+
THE_SIMPLE_ORIGIN_ECLASS.get("eSuperTypes").add(THE_ORIGIN_ECLASS);
74+
THE_SIMPLE_ORIGIN_ECLASS.get("eStructuralFeatures").add(Ecore.EAttribute.create({
75+
name: "sourceText",
76+
eType: Ecore.EString,
77+
lowerBound: 0
78+
}));
79+
THE_SIMPLE_ORIGIN_ECLASS.get("eStructuralFeatures").add(Ecore.EReference.create({
80+
name: "position",
81+
eType: THE_POSITION_ECLASS,
82+
lowerBound: 0,
83+
containment: true
84+
}));
7085
THE_NODE_ECLASS.get("eStructuralFeatures").add(ECore.EReference.create({
7186
name: "destination",
7287
eType: THE_DESTINATION_INTERFACE,
@@ -286,6 +301,7 @@ THE_AST_EPACKAGE.get('eClassifiers').add(THE_ORIGIN_ECLASS);
286301
THE_AST_EPACKAGE.get('eClassifiers').add(THE_DESTINATION_INTERFACE);
287302
THE_AST_EPACKAGE.get('eClassifiers').add(THE_NODE_ECLASS);
288303
THE_AST_EPACKAGE.get('eClassifiers').add(THE_NODE_ORIGIN_ECLASS);
304+
THE_AST_EPACKAGE.get('eClassifiers').add(THE_SIMPLE_ORIGIN_ECLASS);
289305
THE_AST_EPACKAGE.get('eClassifiers').add(THE_POINT_ECLASS);
290306
THE_AST_EPACKAGE.get('eClassifiers').add(THE_POSITION_ECLASS);
291307
THE_AST_EPACKAGE.get('eClassifiers').add(THE_POSSIBLY_NAMED_INTERFACE);

Diff for: src/interop/strumenta-playground.ts

+13-17
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {ParsingResult} from "../parsing/parsing";
1+
import {ParsingResult} from "../parsing";
22
import {EcoreMetamodelSupport, fromEObject, loadEObject, loadEPackages, Result, toEObject} from "./ecore";
33
import {Node, NodeDefinition} from "../model/model";
44
import ECore from "ecore/dist/ecore";
@@ -7,8 +7,7 @@ import {PARSER_EPACKAGE, PARSER_TRACE_ECLASS} from "./parser-package";
77
import {
88
THE_AST_EPACKAGE,
99
THE_ENTITY_DECLARATION_INTERFACE,
10-
THE_EXPRESSION_INTERFACE,
11-
THE_NODE_ECLASS as THE_NODE_ECLASS_V2,
10+
THE_EXPRESSION_INTERFACE, THE_NODE_ECLASS as THE_NODE_ECLASS_V2,
1211
THE_NODE_ORIGIN_ECLASS,
1312
THE_RESULT_ECLASS as THE_RESULT_ECLASS_V2,
1413
THE_STATEMENT_INTERFACE
@@ -180,6 +179,14 @@ export abstract class TraceNode extends Node {
180179
isStatement(): boolean {
181180
return this.eo.isKindOf(THE_STATEMENT_INTERFACE);
182181
}
182+
183+
protected getChildrenEObjects(role: string | undefined) {
184+
return this.eo.eContents()
185+
.filter((c) => c.isKindOf(THE_NODE_ECLASS_V2) || c.isKindOf(THE_NODE_ECLASS_V1))
186+
.filter((c) => c.eContainingFeature.get("name") != "origin")
187+
.filter((c) => c.eContainingFeature.get("name") != "destination")
188+
.filter((c) => role == null || role == c.eContainingFeature.get("name"));
189+
}
183190
}
184191

185192
export class ParserNode extends TraceNode {
@@ -190,10 +197,7 @@ export class ParserNode extends TraceNode {
190197
}
191198

192199
getChildren(role?: string): ParserNode[] {
193-
return this.eo.eContents()
194-
.filter((c) => c.eContainingFeature.get("name") != "position")
195-
.filter((c) => role == null || role == c.eContainingFeature.get("name"))
196-
.map((c) => new ParserNode(c, this, this.trace));
200+
return this.getChildrenEObjects(role).map((c) => new ParserNode(c, this, this.trace));
197201
}
198202

199203
get children(): Node[] {
@@ -418,10 +422,7 @@ export class SourceNode extends TraceNode {
418422
}
419423

420424
getChildren(role?: string): SourceNode[] {
421-
return this.eo.eContents()
422-
.filter((c) => c.eContainingFeature.get("name") != "position")
423-
.filter((c) => role == null || role == c.eContainingFeature.get("name"))
424-
.map((c) => new SourceNode(c, this.trace, this.file));
425+
return this.getChildrenEObjects(role).map((c) => new SourceNode(c, this.trace, this.file));
425426
}
426427

427428
get children(): Node[] {
@@ -491,12 +492,7 @@ export class TargetNode extends TraceNode {
491492
}
492493

493494
getChildren(role?: string): TargetNode[] {
494-
return this.eo.eContents()
495-
.filter((c) => c.eContainingFeature.get("name") != "position")
496-
.filter((c) => c.eContainingFeature.get("name") != "origin")
497-
.filter((c) => c.eContainingFeature.get("name") != "destination")
498-
.filter((c) => role == null || role == c.eContainingFeature.get("name"))
499-
.map((c) => new TargetNode(c, this.trace, this.file));
495+
return this.getChildrenEObjects(role).map((c) => new TargetNode(c, this.trace, this.file));
500496
}
501497

502498
get children(): Node[] {

Diff for: src/model/model.ts

+14
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,20 @@ export abstract class Origin {
8383

8484
}
8585

86+
export class SimpleOrigin extends Origin {
87+
constructor(public myPosition?: Position, public mySourceText?: string) {
88+
super();
89+
}
90+
91+
get position(): Position | undefined {
92+
return this.myPosition
93+
}
94+
95+
get sourceText(): string | undefined {
96+
return this.mySourceText
97+
}
98+
}
99+
86100
// eslint-disable-next-line @typescript-eslint/no-empty-interface
87101
export interface Destination {}
88102

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
{
2+
"eClass" : "https://strumenta.com/starlasu/transpilation/v2#//WorkspaceTranspilationTrace",
3+
"originalFiles" : [ {
4+
"path" : "CUS300.rpgle",
5+
"code" : " F**********************************************************************\n F* *\n F* PROGRAM ID : CUS200 *\n F* PROGRAM NAME: SAMPLE PROGRAM *\n F* *\n F**********************************************************************\n D DSP S 50 INZ('CUSTOMER')\n D TOTAL S 9P 2 INZ(0)\n D NUM S 9P 2 INZ(1)\n D CNT S 9P 2 INZ(0)\n FCUSTOMER UF E K Disk\n FORDERS IF E K Disk\n FORDSUM IF E K Disk\n C *INZSR BEGSR\n C EVAL DSP='CUSTOMER REPORT'\n C DSPLY DSP\n C ENDSR\n /free\n CNT = 0;\n TOTAL = 0;\n EXSR $clrsum;\n DSPLY '------ Forward ------';\n Setll *Loval CUSTOMER;\n Dou NOT %EOF(CUSTOMER);\n Read CUSTOMER;\n If NOT %EOF(CUSTOMER);\n EXSR $calctotal;\n EXSR $DSPCUS;\n If TOTAL > 0;\n OSCUID = CUID;\n TOTAL *= (TOTAL / CNT +1) * 0.1;\n OSTOT = TOTAL;\n OSCUNM = CUSTNM;\n Write ORDSUM;\n EndIf;\n EndIf;\n EndDO;\n DSPLY '------ Reverse ------';\n Setll *Hival ORDSUM;\n Dou NOT %EOF(ORDSUM);\n Readp ORDSUM;\n If NOT %EOF(ORDSUM);\n DSPLY 'CUSTOMER: ' + OSCUNM + ' $' + OSTOT;\n\n EndIf;\n EndDO;\n\n Begsr $calctotal;\n CNT = 0;\n TOTAL = 0;\n Setll *Loval ORDERS;\n Dou NOT %EOF(ORDERS);\n Read ORDERS;\n If NOT %EOF(ORDERS);\n If CUID = ORCUID;\n TOTAL += ORTOT;\n CNT += 1;\n EndIf;\n EndIf;\n EndDo;\n EndSr;\n\n Begsr $dspcus;\n If TOTAL > 0;\n eval DSP='CUSTOMER: ' + CUSTNM + ' $' + TOTAL;\n DSPLY DSP;\n EndIf;\n EndSr;\n\n Begsr $clrsum;\n CNT = 0;\n DSPLY '------ Delete ------';\n Setll *Loval ORDSUM;\n Dou NOT %EOF(ORDSUM);\n Read ORDSUM;\n If NOT %EOF(ORDSUM);\n delete ORDSUM;\n CNT+=1;\n EndIf;\n EndDO;\n DSPLY 'DELETED: ' + CNT + ' RECORDS';\n EndSr;",
6+
"result" : {
7+
"root" : {
8+
"eClass" : "https://strumenta.com/rpg/model#//CompilationUnit",
9+
"position" : {
10+
"start" : {
11+
"line" : 1
12+
},
13+
"end" : {
14+
"line" : 82,
15+
"column" : 18
16+
}
17+
},
18+
"comments" : [],
19+
"dataDefinitions" : [],
20+
"externalDefinitions" : [],
21+
"fileDescriptions" : [],
22+
"mainStatements" : [],
23+
"subroutines" : [],
24+
"origin" : {
25+
"eClass" : "https://strumenta.com/starlasu/v2#//SimpleOrigin",
26+
"sourceText" : "Footext",
27+
"position" : {
28+
"start" : {
29+
"line" : 1,
30+
"column" : 20
31+
},
32+
"end" : {
33+
"line" : 1,
34+
"column" : 34
35+
}
36+
}
37+
}
38+
}
39+
}
40+
} ],
41+
"generatedFiles" : [
42+
]
43+
}

Diff for: tests/interop/parser-trace.test.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {expect} from "chai";
22
import * as fs from "fs";
33
import {findByPosition, IssueSeverity, IssueType, Point, pos, Position} from "../../src";
4-
import {ParserNode, ParserTraceLoader} from "../../src/interop/strumenta-playground";
4+
import {ParserNode, ParserTraceLoader, TraceNode} from "../../src/interop/strumenta-playground";
55

66
describe('Parser traces – Kolasu metamodel V1', function() {
77

@@ -31,6 +31,10 @@ describe('Parser traces – Kolasu metamodel V1', function() {
3131
expect(trace.issues[0].message).to.eql("Physical line of type FileDescription are currently ignored");
3232
expect(trace.issues[0].severity).to.eql(IssueSeverity.WARNING);
3333
expect(trace.issues[0].position).to.eql(new Position(new Point(18, 0), new Point(18, 42)));
34+
35+
const updateStmt = trace.rootNode.findByPosition(pos(258, 30, 258, 30));
36+
expect(updateStmt).not.to.be.undefined;
37+
expect((updateStmt as TraceNode).getType()).to.eql("com.strumenta.rpgparser.model.UpdateRecordStatement");
3438
});
3539

3640
it("Can load reference RPG parser trace: open-weather",

Diff for: tests/interop/workspace-transpilation-trace.test.ts

+34-5
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import {expect} from "chai";
22
import * as fs from "fs";
3-
import {Point, Position} from "../../src";
3+
import {Point, pos, Position} from "../../src";
44
import { loadEObject, loadEPackages } from "../../src/interop/ecore"
5-
import { TranspilationTraceLoader } from "../../src/interop/strumenta-playground"
5+
import {TraceNode, TranspilationTraceLoader} from "../../src/interop/strumenta-playground"
66
import {THE_AST_EPACKAGE} from "../../src/interop/starlasu-v2-metamodel";
7-
import ECore from "ecore/dist/ecore";
7+
import ECore from "ecore";
88
import {
99
THE_WORKSPACE_TRANSPILATION_TRACE_ECLASS,
1010
TRANSPILATION_EPACKAGE
@@ -90,8 +90,8 @@ describe('Workspace Transpilation traces', function() {
9090
ECore.EPackage.Registry.register(THE_AST_EPACKAGE);
9191
ECore.EPackage.Registry.register(TRANSPILATION_EPACKAGE);
9292
const loader = new TranspilationTraceLoader({
93-
name: "rpg2py",
94-
uri: "file://tests/data/playground/rpg/rpg2py-metamodels.json",
93+
name: "rpg2java",
94+
uri: "file://tests/data/playground/java/rpg2java-metamodels.json",
9595
metamodel: JSON.parse(fs.readFileSync("tests/data/playground/java/rpg2java-metamodels.json").toString())
9696
});
9797
const example = fs.readFileSync("tests/data/playground/java/trace.json").toString();
@@ -117,4 +117,33 @@ describe('Workspace Transpilation traces', function() {
117117
expect(destinationNodes.length).to.equal(1);
118118
expect(destinationNodes[0].file?.path).to.equal("Cus300.java");
119119
});
120+
it("Can load workspace transpilation trace produced by Kolasu with SimpleOrigin instances",
121+
function () {
122+
this.timeout(0);
123+
Ecore.EPackage.Registry.register(THE_AST_EPACKAGE);
124+
Ecore.EPackage.Registry.register(TRANSPILATION_EPACKAGE);
125+
const loader = new TranspilationTraceLoader({
126+
name: "rpg2java",
127+
uri: "file://tests/data/playground/rpg/rpg2java-metamodels.json",
128+
metamodel: JSON.parse(fs.readFileSync("tests/data/playground/java/rpg2java-metamodels.json").toString())
129+
});
130+
const example = fs.readFileSync("tests/data/playground/java/trace-with-simple-origins.json").toString();
131+
const trace = loader.loadWorkspaceTranspilationTrace(example);
132+
133+
expect(trace.originalFiles.length).to.eql(1);
134+
expect(trace.generatedFiles.length).to.eql(0);
135+
expect(trace.transpilationIssues.length).to.eql(0);
136+
137+
const cus300File = trace.originalFiles[0];
138+
expect(cus300File.path).to.eql("CUS300.rpgle")
139+
expect(cus300File.issues.length).to.eql(0)
140+
expect(cus300File.node.getType()).to.eql("com.strumenta.rpgparser.model.CompilationUnit")
141+
expect(cus300File.node.getSimpleType()).to.eql("CompilationUnit")
142+
// The origin is ignored. The position loaded is the explicit position
143+
// The sourceText is not accessible anywhere, as it is irrelevant for the TranspilationTrace
144+
expect(cus300File.node.getPosition()).to.eql(new Position(new Point(1, 0), new Point(82, 18)));
145+
146+
const byPosition = cus300File.node.findByPosition(pos(1, 21, 1, 21)) as TraceNode;
147+
expect(byPosition.getType()).not.to.contain("SimpleOrigin");
148+
});
120149
});

Diff for: tests/processing.test.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ const testCase = new Box(
1313
new Item("6")
1414
]);
1515

16-
const rootP = n => n instanceof Box && n.name == "root";
17-
const item1P = n => n instanceof Item && n.name == "1";
16+
const rootP = (n: any) => n instanceof Box && n.name == "root";
17+
const item1P = (n: any) => n instanceof Item && n.name == "1";
1818

1919
describe('Tree processing', function() {
2020
it("find a node, depth-first",
@@ -36,4 +36,4 @@ describe('Tree processing', function() {
3636
expect(result).not.to.be.undefined;
3737
expect(result.name).to.equal("1");
3838
});
39-
});
39+
});

0 commit comments

Comments
 (0)