Skip to content

Commit 9715d9a

Browse files
committed
Renamed "property" to either "feature" or "attribute" according to Kolasu terminology
Correctly record references in node metadata for ECore nodes
1 parent 9d7ae9d commit 9715d9a

File tree

14 files changed

+80
-66
lines changed

14 files changed

+80
-66
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@
22
All notable changes to this project from version 1.2.0 upwards are documented in this file.
33
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
44

5+
## [1.6.16] – 2024-03-21
6+
7+
### Changed
8+
- Renamed "property" to either "feature" or "attribute" according to Kolasu terminology
9+
10+
### Fixed
11+
- Correctly record references in node metadata for ECore nodes
12+
513
## [1.6.15] – 2024-03-21
614

715
### Added

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"description": "AST building blocks for TypeScript/JavaScript, part of the *lasu family, with optional integrations with ANTLR4 and Ecore.",
44
"author": "Strumenta s.r.l.",
55
"publisher": "strumenta",
6-
"version": "1.6.15",
6+
"version": "1.6.16",
77
"license": "Apache-2.0",
88
"keywords": [
99
"antlr",

src/interop/ecore.ts

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,8 @@ function registerEClass(nodeType: string, packageDef: PackageDescription, ePacka
111111
}
112112
const nodeDef = getNodeDefinition(constructor);
113113
if (nodeDef) {
114-
for (const prop in nodeDef.properties) {
115-
const property = nodeDef.properties[prop];
114+
for (const prop in nodeDef.features) {
115+
const property = nodeDef.features[prop];
116116
if(property.inherited) {
117117
continue;
118118
}
@@ -376,8 +376,8 @@ Node.prototype[TO_EOBJECT_SYMBOL] = function(): ECore.EObject {
376376
throw new Error("Unknown class " + def.name + " in package " + def.package);
377377
}
378378
const eObject = eClass.create();
379-
for (const name in def.properties) {
380-
const p = def.properties[name];
379+
for (const name in def.features) {
380+
const p = def.features[name];
381381
const feature = eClass.get("eAllStructuralFeatures").find(f => f.get("name") == name);
382382
if (!feature) {
383383
throw new Error(`Unknown feature: ${name} of ${eClass.get("name")}`);
@@ -850,7 +850,7 @@ export class ECoreNode extends NodeAdapter implements PossiblyNamed {
850850
this._nodeDefinition = {
851851
package: this.eo.eClass.eContainer.get("name") as string,
852852
name: this.eo.eClass.get("name") as string,
853-
properties: this.getProperties()
853+
features: this.getFeatures()
854854
};
855855
}
856856
return this._nodeDefinition;
@@ -946,7 +946,7 @@ export class ECoreNode extends NodeAdapter implements PossiblyNamed {
946946
return this.eo.eContainingFeature?.get("name");
947947
}
948948

949-
getProperties(): { [name: string | symbol]: PropertyDefinition } {
949+
getFeatures(): { [name: string | symbol]: PropertyDefinition } {
950950
const result: { [name: string | symbol]: PropertyDefinition } = {};
951951
const eClass = this.eo.eClass;
952952
const features = eClass.get("eAllStructuralFeatures");
@@ -956,11 +956,13 @@ export class ECoreNode extends NodeAdapter implements PossiblyNamed {
956956
if (isReference && !isNodeType(ft.get("eType") || ft.get("eGenericType")?.get("eClassifier"))) {
957957
// skip
958958
} else {
959+
const isChild = isReference &&
960+
ft.get('containment') &&
961+
ft.get("eGenericType")?.get("eClassifier") != THE_REFERENCE_BY_NAME_ECLASS;
959962
result[name] = {
960963
name,
961-
child: isReference &&
962-
ft.get('containment') &&
963-
ft.get("eGenericType")?.get("eClassifier") != THE_REFERENCE_BY_NAME_ECLASS,
964+
child: isChild,
965+
reference: isReference && !isChild,
964966
multiple: isReference ? ft.get('many') : undefined,
965967
};
966968
}

src/interop/indexing.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export class OnlyReferencedIdProvider implements IdProvider {
4040

4141
constructor(private root: Node, private idProvider: IdProvider = new SequentialIdProvider()) {
4242
for (const node of root.walk()) {
43-
node.properties
43+
node.features
4444
.filter(p => p.value instanceof ReferenceByName)
4545
.map(p => (p.value as ReferenceByName<any>).referred as Node)
4646
.forEach(node => this.referencedElements.push(node));

src/interop/lionweb.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ export class LionwebNode extends NodeAdapter {
141141
});
142142
this._nodeDefinition = {
143143
name: classifier.name,
144-
properties: properties,
144+
features: properties,
145145
resolved: true
146146
};
147147
}
@@ -164,8 +164,8 @@ export class LionwebNode extends NodeAdapter {
164164

165165
getAttributes(): { [p: string]: any } {
166166
const attributes = {};
167-
for (const p in this.nodeDefinition.properties) {
168-
if (!this.nodeDefinition.properties[p].child) {
167+
for (const p in this.nodeDefinition.features) {
168+
if (!this.nodeDefinition.features[p].child) {
169169
attributes[p] = this.getAttributeValue(p);
170170
}
171171
}

src/model/model.ts

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export const NODE_TYPES: { [name: string]: PackageDescription } = {
1515
export type NodeDefinition = {
1616
package?: string,
1717
name?: string,
18-
properties: { [name: string | symbol]: PropertyDefinition },
18+
features: { [name: string | symbol]: PropertyDefinition },
1919
resolved?: boolean;
2020
};
2121

@@ -35,29 +35,29 @@ export function getNodeDefinition(node: Node | (new (...args: any[]) => Node)):
3535
if(Object.prototype.hasOwnProperty.call(target, NODE_DEFINITION_SYMBOL)) {
3636
definition = target[NODE_DEFINITION_SYMBOL] as NodeDefinition;
3737
} else {
38-
const inheritedProperties = {...(target[NODE_DEFINITION_SYMBOL]?.properties || {})};
39-
for (const p in inheritedProperties) {
40-
inheritedProperties[p] = { inherited: true, ...inheritedProperties[p] };
38+
const inheritedFeatures = {...(target[NODE_DEFINITION_SYMBOL]?.features || {})};
39+
for (const p in inheritedFeatures) {
40+
inheritedFeatures[p] = { inherited: true, ...inheritedFeatures[p] };
4141
}
4242
target[NODE_DEFINITION_SYMBOL] = definition = {
43-
properties: inheritedProperties,
43+
features: inheritedFeatures,
4444
resolved: false
4545
};
4646
}
47-
if(definition && definition.properties && !definition.resolved) {
47+
if(definition && definition.features && !definition.resolved) {
4848
try {
4949
let metadataHolder;
5050
try {
5151
metadataHolder = new (node as any)();
5252
} catch (_) {
5353
metadataHolder = node;
5454
}
55-
for(const p in definition.properties) {
56-
if (!definition.properties[p].type) {
55+
for(const p in definition.features) {
56+
if (!definition.features[p].type) {
5757
const type = Reflect.getMetadata("design:type", metadataHolder, p);
58-
definition.properties[p].type = type;
58+
definition.features[p].type = type;
5959
if(type === Array) {
60-
definition.properties[p].arrayType =
60+
definition.features[p].arrayType =
6161
Reflect.getMetadata("design:arrayElementType", metadataHolder, p);
6262
}
6363
}
@@ -152,16 +152,16 @@ export abstract class Node extends Origin implements Destination {
152152
}
153153

154154
getChildNames(): string[] {
155-
const props = this.nodeDefinition?.properties || {};
155+
const props = this.nodeDefinition?.features || {};
156156
return Object.getOwnPropertyNames(props).filter(p => props[p].child);
157157
}
158158

159159
get nodeDefinition(): NodeDefinition {
160160
return getNodeDefinition(this);
161161
}
162162

163-
get properties(): PropertyDescription[] {
164-
const props = this.nodeDefinition?.properties || {};
163+
get features(): FeatureDescription[] {
164+
const props = this.nodeDefinition?.features || {};
165165
return Object.getOwnPropertyNames(props).map(p => {
166166
const value = props[p].child ?
167167
(props[p].multiple ? this.getChildren(p) : this.getChild(p)) :
@@ -171,7 +171,7 @@ export abstract class Node extends Origin implements Destination {
171171
}
172172

173173
containment(name: string | symbol): PropertyDefinition | undefined {
174-
const props = this.nodeDefinition?.properties || {};
174+
const props = this.nodeDefinition?.features || {};
175175
return props[name]?.child ? props[name] : undefined;
176176
}
177177

@@ -241,7 +241,7 @@ export abstract class Node extends Origin implements Destination {
241241
}
242242

243243
getAllChildren() {
244-
const props = this.nodeDefinition?.properties || {};
244+
const props = this.nodeDefinition?.features || {};
245245
const result: Node[] = [];
246246
for (const p in props) {
247247
const prop = props[p];
@@ -273,7 +273,7 @@ export abstract class Node extends Origin implements Destination {
273273
}
274274

275275
getAttributeValue(name: string | symbol): any {
276-
const props = this.nodeDefinition?.properties || {};
276+
const props = this.nodeDefinition?.features || {};
277277
const prop = props[name];
278278
if(prop) {
279279
if (prop.child) {
@@ -291,7 +291,7 @@ export abstract class Node extends Origin implements Destination {
291291
}
292292

293293
setAttributeValue(name: string | symbol, value: any) {
294-
const props = this.nodeDefinition?.properties || {};
294+
const props = this.nodeDefinition?.features || {};
295295
const prop = props[name];
296296
if(prop) {
297297
if (prop.child) {
@@ -339,7 +339,7 @@ export abstract class Node extends Origin implements Destination {
339339
}
340340
}
341341

342-
export interface PropertyDescription {
342+
export interface FeatureDescription {
343343
name: string;
344344
value: any;
345345
}
@@ -414,11 +414,11 @@ export function registerNodeDefinition<T extends Node>(
414414
def = {
415415
package: pkg,
416416
name: name,
417-
properties: {}
417+
features: {}
418418
};
419419
if(existingDef) {
420-
for(const prop in existingDef.properties) {
421-
def.properties[prop] = { inherited: true, ...existingDef.properties[prop]};
420+
for(const prop in existingDef.features) {
421+
def.features[prop] = { inherited: true, ...existingDef.features[prop]};
422422
}
423423
}
424424
}
@@ -450,12 +450,12 @@ export function registerNodeAttribute<T extends Node>(
450450
methodName = Symbol(methodName);
451451
}
452452
const definition = ensureNodeDefinition(type);
453-
if (!definition.properties[methodName]) {
454-
definition.properties[methodName] = {
453+
if (!definition.features[methodName]) {
454+
definition.features[methodName] = {
455455
name: methodName
456456
};
457457
}
458-
return definition.properties[methodName];
458+
return definition.features[methodName];
459459
}
460460

461461
export function registerNodeChild<T extends Node>(

src/testing/testing.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ export function assertASTsAreEqual(
1212
if (considerPosition) {
1313
expect(actual.position, `${context}.position`).to.eql(expected.position);
1414
}
15-
expected.properties.forEach(expectedProperty => {
16-
const actualPropValue = actual.properties.find(p => p.name == expectedProperty.name)!.value;
15+
expected.features.forEach(expectedProperty => {
16+
const actualPropValue = actual.features.find(p => p.name == expectedProperty.name)!.value;
1717
const expectedPropValue = expectedProperty.value;
1818

1919
if (actualPropValue instanceof Node && expectedPropValue instanceof Node) {

src/trace/trace-node.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export abstract class NodeAdapter extends Node {
2323

2424
getRole(): string | symbol | undefined {
2525
if (this.parent) { // Inefficient default implementation, searching in the parent's children
26-
const props = this.parent.nodeDefinition?.properties || {};
26+
const props = this.parent.nodeDefinition?.features || {};
2727
for (const p in props) {
2828
const prop = props[p];
2929
if (prop.child) {

src/transformation/transformation.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export class PropertyRef<Obj, Value> {
2323
}
2424

2525
if (nodeDefinition) {
26-
const property = Object.keys(nodeDefinition.properties).find(p => p == name);
26+
const property = Object.keys(nodeDefinition.features).find(p => p == name);
2727
if (!property) {
2828
throw new Error(`${name} is not a feature of ${nodeDefinition}`)
2929
}
@@ -286,7 +286,7 @@ export class ASTTransformer {
286286
if (prefix) {
287287
prefix += "#";
288288
}
289-
const properties = nodeDefinition ? Object.keys(nodeDefinition.properties) : Object.keys(node);
289+
const properties = nodeDefinition ? Object.keys(nodeDefinition.features) : Object.keys(node);
290290
properties.forEach(propertyName => {
291291
const childNodeFactory = factory.getChildNodeFactory(prefix, propertyName);
292292
if (childNodeFactory) {

src/traversing/structurally.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ Node.prototype.walkDescendants = function(walker: typeof walk = walk) {
9393
* @return all direct children of this node.
9494
*/
9595
export function* walkChildren(node: Node): Generator<Node> {
96-
for (const property of node.properties) {
96+
for (const property of node.features) {
9797
const value = property.value;
9898
if (value instanceof Node) {
9999
yield value;

0 commit comments

Comments
 (0)