Skip to content

Commit a695a63

Browse files
committed
Refactor NodeDefinition -> Concept (deprecating old names but keeping them)
1 parent fc2b5c1 commit a695a63

File tree

7 files changed

+99
-72
lines changed

7 files changed

+99
-72
lines changed

CHANGELOG.md

+7-2
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,17 @@
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-
## [Unreleased]
5+
## [1.6.31] [Unreleased]
6+
7+
### Added
8+
- Concept (was _NodeDefinition_) has a reference to the extended concept.
69

710
### Changed
811
- `Position`'s method `isEmpty` is deprecated in favour of `isFlat` to ensure consistency across the [StarLasu](https://github.com/Strumenta/StarLasu) libraries collection.
9-
- `Issue`'s messages are capitalized.
12+
- `Issue`'s messages are capitalized, as in recent versions of Kolasu.
1013
- Parsing `Issue`s' position uses the token's length.
14+
- Start renaming `NodeDefinition` to `Concept` but retain the old names as deprecated types/functions/methods.
15+
- Update Lionweb to version `0.6.12`.
1116

1217
## [1.6.30] – 2024-09-30
1318

package.json

+1-1
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.30",
6+
"version": "1.6.31",
77
"license": "Apache-2.0",
88
"keywords": [
99
"antlr",

src/interop/ecore.ts

+10-10
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@
55
import {
66
ensureNodeDefinition,
77
ensurePackage,
8-
getNodeDefinition,
8+
getConcept,
99
Node,
10-
NODE_TYPES, NodeDefinition,
10+
NODE_TYPES,
1111
PackageDescription,
1212
Feature,
1313
registerNodeDefinition,
14-
registerNodeAttribute
14+
registerNodeAttribute, Concept
1515
} from "../model/model";
1616
import ECore from "ecore/dist/ecore";
1717
import {Point, Position} from "../model/position";
@@ -101,15 +101,15 @@ function registerEClass(nodeType: string, packageDef: PackageDescription, ePacka
101101
});
102102
constructor[ECLASS_SYMBOL] = eClass;
103103
const proto = Object.getPrototypeOf(constructor);
104-
const parentNodeDef = getNodeDefinition(proto);
104+
const parentNodeDef = getConcept(proto);
105105
if(parentNodeDef && parentNodeDef.package && parentNodeDef.name) {
106106
const {packageDef, ePackage} = registerEPackage(parentNodeDef.package, {});
107107
const superclass = registerEClass(parentNodeDef.name, packageDef, ePackage);
108108
eClass.get("eSuperTypes").add(superclass);
109109
} else {
110110
eClass.get("eSuperTypes").add(THE_NODE_ECLASS);
111111
}
112-
const nodeDef = getNodeDefinition(constructor);
112+
const nodeDef = getConcept(constructor);
113113
if (nodeDef) {
114114
for (const prop in nodeDef.features) {
115115
const property = nodeDef.features[prop];
@@ -841,17 +841,17 @@ export class ECoreNode extends NodeAdapter implements PossiblyNamed {
841841
return this.getAttributeValue("name");
842842
}
843843

844-
private _nodeDefinition?: NodeDefinition;
844+
private _concept?: Concept;
845845

846-
get nodeDefinition() {
847-
if (!this._nodeDefinition) {
848-
this._nodeDefinition = {
846+
get concept() {
847+
if (!this._concept) {
848+
this._concept = {
849849
package: this.eo.eClass.eContainer.get("name") as string,
850850
name: this.eo.eClass.get("name") as string,
851851
features: this.getFeatures()
852852
};
853853
}
854-
return this._nodeDefinition;
854+
return this._concept;
855855
}
856856

857857
get(...path: string[]): NodeAdapter | undefined {

src/interop/lionweb.ts

+15-15
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*/
55
import {
66
Classifier,
7-
Concept,
7+
Concept as LWConcept,
88
Containment, Datatype, DefaultPrimitiveTypeDeserializer, deserializeSerializationChunk,
99
Feature as LWFeature,
1010
Id,
@@ -19,17 +19,17 @@ import {
1919
NodeAdapter,
2020
Issue,
2121
Node,
22-
NodeDefinition,
22+
Concept,
2323
Position,
2424
Feature,
2525
Point,
2626
TraceNode,
27-
getNodeDefinition
27+
getConcept
2828
} from "..";
2929
import {STARLASU_LANGUAGE} from "./lionweb-starlasu-language";
3030
export {STARLASU_LANGUAGE} from "./lionweb-starlasu-language";
3131

32-
export const ASTNode = STARLASU_LANGUAGE.entities.find(e => e.name == "ASTNode")! as Concept;
32+
export const ASTNode = STARLASU_LANGUAGE.entities.find(e => e.name == "ASTNode")! as LWConcept;
3333
export const PositionFeature = ASTNode.features.find(f => f.name == "position")! as Property;
3434
export const PositionType = PositionFeature.type!;
3535
export const PointType = STARLASU_LANGUAGE.entities.find(e => e.name == "Point")! as Datatype;
@@ -55,7 +55,7 @@ export class LanguageMapping {
5555

5656
register(nodeType: any, classifier: Classifier) {
5757
if (!classifier) {
58-
throw new Error(`Can't register ${getNodeDefinition(nodeType)?.name}: not a classifier: ${classifier}`);
58+
throw new Error(`Can't register ${getConcept(nodeType)?.name}: not a classifier: ${classifier}`);
5959
}
6060
this.nodeTypes.set(nodeType, classifier);
6161
this.classifiers.set(classifier, nodeType);
@@ -83,7 +83,7 @@ function importFeature(feature: LWFeature): Feature | undefined {
8383
return def;
8484
}
8585

86-
function importConcept(concept: NodeDefinition | undefined, classifier: Classifier) {
86+
function importConcept(concept: Concept | undefined, classifier: Classifier) {
8787
concept = {
8888
name: classifier.name,
8989
features: {},
@@ -100,7 +100,7 @@ function importConcept(concept: NodeDefinition | undefined, classifier: Classifi
100100

101101
export class TylasuInstantiationFacade implements InstantiationFacade<TylasuWrapper> {
102102

103-
protected readonly concepts = new Map<Classifier, NodeDefinition>();
103+
protected readonly concepts = new Map<Classifier, Concept>();
104104

105105
constructor(public languageMappings: LanguageMapping[] = [STARLASU_LANGUAGE_MAPPING]) {}
106106

@@ -166,7 +166,7 @@ STARLASU_LANGUAGE_MAPPING.register(Node, AST_NODE_CLASSIFIER);
166166

167167
function allFeatures(classifier: Classifier) {
168168
const features = [...classifier.features];
169-
if (classifier instanceof Concept) {
169+
if (classifier instanceof LWConcept) {
170170
const superConcept = classifier.extends;
171171
if (superConcept) {
172172
features.push(...allFeatures(superConcept));
@@ -187,12 +187,12 @@ export class LionwebNode extends NodeAdapter {
187187

188188
parent: LionwebNode;
189189

190-
get nodeDefinition() {
191-
return this._nodeDefinition;
190+
get concept() {
191+
return this._concept;
192192
}
193193

194194
constructor(
195-
protected readonly _nodeDefinition: NodeDefinition,
195+
protected readonly _concept: Concept,
196196
protected readonly classifier: Classifier,
197197
protected lwnode: LWNodeInterface
198198
) {
@@ -216,8 +216,8 @@ export class LionwebNode extends NodeAdapter {
216216

217217
getAttributes(): { [p: string]: any } {
218218
const attributes = {};
219-
for (const p in this.nodeDefinition.features) {
220-
if (!this.nodeDefinition.features[p].child) {
219+
for (const p in this.concept.features) {
220+
if (!this.concept.features[p].child) {
221221
attributes[p] = this.getAttributeValue(p);
222222
}
223223
}
@@ -252,15 +252,15 @@ export class LionwebNode extends NodeAdapter {
252252
}
253253

254254
isOfKnownType(name: string): boolean {
255-
return this.classifier instanceof Concept && conceptImplements(this.classifier, name);
255+
return this.classifier instanceof LWConcept && conceptImplements(this.classifier, name);
256256
}
257257

258258
equals(other: NodeAdapter | undefined): boolean {
259259
return other instanceof LionwebNode && other.lwnode == this.lwnode;
260260
}
261261
}
262262

263-
function conceptImplements(concept: Concept, interfaceName: string) {
263+
function conceptImplements(concept: LWConcept, interfaceName: string) {
264264
const directlyImplements = !!concept.implements.find(intf => intf.name == interfaceName);
265265
return directlyImplements || !!(concept.extends && conceptImplements(concept.extends, interfaceName));
266266
}

src/model/model.ts

+50-28
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import {Position, Source} from "./position";
22
import "reflect-metadata";
33
import {PossiblyNamed, ReferenceByName} from "./naming";
44

5-
export const NODE_DEFINITION_SYMBOL = Symbol("nodeDefinition");
5+
export const CONCEPT_SYMBOL = Symbol("concept");
66

77
export type PackageDescription = {
88
name: string,
@@ -12,14 +12,19 @@ export const NODE_TYPES: { [name: string]: PackageDescription } = {
1212
"": { name: "", nodes: {} }
1313
};
1414

15-
export type NodeDefinition = {
15+
export type Concept = {
1616
package?: string,
1717
name?: string,
1818
features: { [name: string | symbol]: Feature },
1919
resolved?: boolean;
20-
inheritsFrom?: NodeDefinition
20+
inheritsFrom?: Concept
2121
};
2222

23+
/**
24+
* @deprecated use Concept instead.
25+
*/
26+
export type NodeDefinition = Concept;
27+
2328
export type Feature = {
2429
name: string | symbol,
2530
child?: boolean,
@@ -35,45 +40,52 @@ export type Feature = {
3540
*/
3641
export type PropertyDefinition = Feature;
3742

43+
/**
44+
* @deprecated in favor of getConcept
45+
*/
3846
export function getNodeDefinition(node: Node | (abstract new (...args: any[]) => Node)): NodeDefinition {
47+
return getConcept(node);
48+
}
49+
50+
export function getConcept(node: Node | (abstract new (...args: any[]) => Node)): Concept {
3951
const target = typeof node === "function" ? node : node.constructor;
40-
let definition: NodeDefinition;
41-
if(Object.prototype.hasOwnProperty.call(target, NODE_DEFINITION_SYMBOL)) {
42-
definition = target[NODE_DEFINITION_SYMBOL] as NodeDefinition;
52+
let concept: Concept;
53+
if(Object.prototype.hasOwnProperty.call(target, CONCEPT_SYMBOL)) {
54+
concept = target[CONCEPT_SYMBOL] as Concept;
4355
} else {
44-
const inheritedFeatures = {...(target[NODE_DEFINITION_SYMBOL]?.features || {})};
56+
const inheritedFeatures = {...(target[CONCEPT_SYMBOL]?.features || {})};
4557
for (const p in inheritedFeatures) {
4658
inheritedFeatures[p] = { inherited: true, ...inheritedFeatures[p] };
4759
}
48-
target[NODE_DEFINITION_SYMBOL] = definition = {
60+
target[CONCEPT_SYMBOL] = concept = {
4961
features: inheritedFeatures,
5062
resolved: false
5163
};
5264
}
53-
if(definition && definition.features && !definition.resolved) {
65+
if(concept && concept.features && !concept.resolved) {
5466
try {
5567
let metadataHolder;
5668
try {
5769
metadataHolder = new (node as any)();
5870
} catch {
5971
metadataHolder = node;
6072
}
61-
for(const p in definition.features) {
62-
if (!definition.features[p].type) {
73+
for(const p in concept.features) {
74+
if (!concept.features[p].type) {
6375
const type = Reflect.getMetadata("design:type", metadataHolder, p);
64-
definition.features[p].type = type;
76+
concept.features[p].type = type;
6577
if(type === Array) {
66-
definition.features[p].arrayType =
78+
concept.features[p].arrayType =
6779
Reflect.getMetadata("design:arrayElementType", metadataHolder, p);
6880
}
6981
}
7082
}
71-
definition.resolved = true;
83+
concept.resolved = true;
7284
} catch {
7385
//Ignore
7486
}
7587
}
76-
return definition;
88+
return concept;
7789
}
7890

7991
export abstract class Origin {
@@ -166,8 +178,13 @@ export abstract class Node extends Origin implements Destination {
166178
return Object.getOwnPropertyNames(props).filter(p => props[p].child);
167179
}
168180

181+
get concept(): Concept {
182+
return getConcept(this);
183+
}
184+
185+
/** @deprecated use concept */
169186
get nodeDefinition(): NodeDefinition {
170-
return getNodeDefinition(this);
187+
return this.concept;
171188
}
172189

173190
get features(): FeatureDescription[] {
@@ -461,8 +478,8 @@ export function setNodeRedefinitionStrategy(strategy: typeof errorOnRedefinition
461478
}
462479

463480
export function registerNodeDefinition<T extends Node>(
464-
target: abstract new (...args: any[]) => T, pkg?: string, name?: string): NodeDefinition {
465-
let def: NodeDefinition;
481+
target: abstract new (...args: any[]) => T, pkg?: string, name?: string): Concept {
482+
let def: Concept;
466483
if(pkg !== undefined) {
467484
if (!name) {
468485
throw new Error("Package name without node name");
@@ -473,8 +490,8 @@ export function registerNodeDefinition<T extends Node>(
473490
nodeRedefinitionStrategy(name, target, existingTarget);
474491
}
475492
}
476-
const existingDef = target[NODE_DEFINITION_SYMBOL] as NodeDefinition;
477-
if(Object.prototype.hasOwnProperty.call(target, NODE_DEFINITION_SYMBOL)) {
493+
const existingDef = target[CONCEPT_SYMBOL] as Concept;
494+
if(Object.prototype.hasOwnProperty.call(target, CONCEPT_SYMBOL)) {
478495
if((existingDef.package !== undefined && existingDef.package != pkg) ||
479496
(existingDef.name !== undefined && existingDef.name != name)) {
480497
throw new Error(`Type ${pkg}.${name} (${target}) is already defined as ${JSON.stringify(existingDef)}`);
@@ -499,22 +516,27 @@ export function registerNodeDefinition<T extends Node>(
499516
if(pkg !== undefined && name !== undefined) {
500517
NODE_TYPES[pkg].nodes[name] = target;
501518
}
502-
target[NODE_DEFINITION_SYMBOL] = def;
519+
target[CONCEPT_SYMBOL] = def;
503520
return def;
504521
}
505522

506-
export function ensureNodeDefinition(node: Node | { new (...args: any[]): Node }): NodeDefinition {
507-
let definition = getNodeDefinition(node);
508-
if (!definition) {
523+
export function ensureConcept(node: Node | { new (...args: any[]): Node }): Concept {
524+
let concept = getConcept(node);
525+
if (!concept) {
509526
if(typeof node === 'function') {
510-
definition = registerNodeDefinition(node);
527+
concept = registerNodeDefinition(node);
511528
} else if(typeof node.constructor === 'function') {
512-
definition = registerNodeDefinition(node.constructor as any);
529+
concept = registerNodeDefinition(node.constructor as any);
513530
} else {
514531
throw new Error("Not a valid node: " + node);
515532
}
516533
}
517-
return definition;
534+
return concept;
535+
}
536+
537+
/** @deprecated use ensureConcept */
538+
export function ensureNodeDefinition(node: Node | { new (...args: any[]): Node }): Concept {
539+
return ensureConcept(node);
518540
}
519541

520542
export function registerNodeAttribute<T extends Node>(
@@ -523,7 +545,7 @@ export function registerNodeAttribute<T extends Node>(
523545
if (methodName == "parent" || methodName == "children" || methodName == "origin") {
524546
methodName = Symbol(methodName);
525547
}
526-
const definition = ensureNodeDefinition(type);
548+
const definition = ensureConcept(type);
527549
if (!definition.features[methodName]) {
528550
definition.features[methodName] = {
529551
name: methodName

0 commit comments

Comments
 (0)