@typemf/generator 0.7.0 → 0.8.1
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/dist/cli.js +67 -17
- package/dist/index.d.ts +29 -32
- package/dist/index.js +69 -17
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
- package/templates/typescript/eclass.njk +21 -46
- package/templates/typescript/efactory.njk +4 -4
- package/templates/typescript/epackage.njk +24 -55
- package/templates/typescript/epackageref.njk +6 -38
- package/templates/typescript/etypeguards.njk +3 -17
package/dist/cli.js
CHANGED
|
@@ -743,7 +743,7 @@ var FileExtension = class {
|
|
|
743
743
|
// src/generate.ts
|
|
744
744
|
function generate(pkg, templateSet, options = {}) {
|
|
745
745
|
assignFreshIds(pkg);
|
|
746
|
-
const problems = templateSet.validate?.(pkg) ?? [];
|
|
746
|
+
const problems = templateSet.validate?.(pkg, options) ?? [];
|
|
747
747
|
if (problems.length > 0) {
|
|
748
748
|
throw new Error(
|
|
749
749
|
`Cannot generate from this package - ${templateSet.name} found ${problems.length} unresolved problem(s):
|
|
@@ -818,13 +818,19 @@ var TypeImportMapping = class _TypeImportMapping {
|
|
|
818
818
|
};
|
|
819
819
|
|
|
820
820
|
// src/generation-context.ts
|
|
821
|
-
var generationContext = {
|
|
821
|
+
var generationContext = {
|
|
822
|
+
pkg: void 0,
|
|
823
|
+
typeImports: new TypeImportMapping(),
|
|
824
|
+
generateEcore: false
|
|
825
|
+
};
|
|
826
|
+
var GENERATE_ECORE_OPTION = "generate-ecore";
|
|
822
827
|
var TYPE_IMPORTS_OPTION = "type-imports";
|
|
823
828
|
function beginGeneration(pkg, options) {
|
|
824
829
|
generationContext.pkg = pkg;
|
|
825
830
|
const entries = options[TYPE_IMPORTS_OPTION];
|
|
826
831
|
const valid = typeof entries === "object" && entries !== null && !Array.isArray(entries);
|
|
827
832
|
generationContext.typeImports = new TypeImportMapping(valid ? entries : {});
|
|
833
|
+
generationContext.generateEcore = options[GENERATE_ECORE_OPTION] === true;
|
|
828
834
|
}
|
|
829
835
|
function isExternal(classifier) {
|
|
830
836
|
const owner = classifier.getEPackage();
|
|
@@ -924,7 +930,8 @@ function locationOfPath(path) {
|
|
|
924
930
|
|
|
925
931
|
// src/typescript-filters.ts
|
|
926
932
|
import {
|
|
927
|
-
detailValue as detailValue2
|
|
933
|
+
detailValue as detailValue2,
|
|
934
|
+
isEDataType as isDataTypeObject
|
|
928
935
|
} from "@typemf/core";
|
|
929
936
|
var TYPEMF_GENERATOR_ANNOTATION_SOURCE = "https://typemf.dev/generator";
|
|
930
937
|
var ECLIPSE_GENMODEL_ANNOTATION_SOURCE = "http://www.eclipse.org/emf/2002/GenModel";
|
|
@@ -940,18 +947,34 @@ function layeredAnnotationDetail(element, key, fallbackSource) {
|
|
|
940
947
|
function documentationOf(element) {
|
|
941
948
|
return layeredAnnotationDetail(element, "documentation", ECLIPSE_ECORE_ANNOTATION_SOURCE);
|
|
942
949
|
}
|
|
950
|
+
var DOC_COMMENT_WIDTH = 100;
|
|
943
951
|
function docComment(element, indent = "") {
|
|
944
|
-
const doc = documentationOf(element);
|
|
952
|
+
const doc = documentationOf(element)?.trim();
|
|
945
953
|
if (!doc) return "";
|
|
946
|
-
const
|
|
947
|
-
if (
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
const body = lines.map((line) => `${indent} * ${line}`).join("\n");
|
|
954
|
+
const single = `${indent}/** ${doc} */`;
|
|
955
|
+
if (!doc.includes("\n") && single.length <= DOC_COMMENT_WIDTH) return single;
|
|
956
|
+
const width = DOC_COMMENT_WIDTH - `${indent} * `.length;
|
|
957
|
+
const lines = doc.split("\n").flatMap((line) => wrapLine(line, width));
|
|
958
|
+
const body = lines.map((line) => line === "" ? `${indent} *` : `${indent} * ${line}`).join("\n");
|
|
951
959
|
return `${indent}/**
|
|
952
960
|
${body}
|
|
953
961
|
${indent} */`;
|
|
954
962
|
}
|
|
963
|
+
function wrapLine(line, width) {
|
|
964
|
+
if (line.length <= width) return [line];
|
|
965
|
+
const lines = [];
|
|
966
|
+
let current = "";
|
|
967
|
+
for (const word of line.split(" ")) {
|
|
968
|
+
if (current !== "" && current.length + 1 + word.length > width) {
|
|
969
|
+
lines.push(current);
|
|
970
|
+
current = word;
|
|
971
|
+
} else {
|
|
972
|
+
current = current === "" ? word : `${current} ${word}`;
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
lines.push(current);
|
|
976
|
+
return lines;
|
|
977
|
+
}
|
|
955
978
|
function operationBody(operation) {
|
|
956
979
|
return layeredAnnotationDetail(operation, "body", ECLIPSE_GENMODEL_ANNOTATION_SOURCE);
|
|
957
980
|
}
|
|
@@ -1086,10 +1109,24 @@ function isPrimitiveValueType(classifier) {
|
|
|
1086
1109
|
return classifier !== void 0 && isEDataType(classifier) && PRIMITIVE_VALUE_DATATYPE_NAMES.has(classifier.getName());
|
|
1087
1110
|
}
|
|
1088
1111
|
function primitiveDefaultValue(feature) {
|
|
1089
|
-
const
|
|
1090
|
-
|
|
1091
|
-
const
|
|
1092
|
-
|
|
1112
|
+
const declared = "getDefaultValueLiteral" in feature ? feature.getDefaultValueLiteral()?.trim() : void 0;
|
|
1113
|
+
const literal = declared === "" ? void 0 : declared;
|
|
1114
|
+
const typeName = feature.getEType()?.getName();
|
|
1115
|
+
const invalid = () => new Error(`Invalid defaultValueLiteral '${literal}' for feature '${feature.getName()}'.`);
|
|
1116
|
+
if (typeName === "EBoolean") {
|
|
1117
|
+
if (literal === void 0) return "false";
|
|
1118
|
+
if (!/^(true|false)$/i.test(literal)) throw invalid();
|
|
1119
|
+
return literal.toLowerCase();
|
|
1120
|
+
}
|
|
1121
|
+
if (typeName === "ELong") {
|
|
1122
|
+
if (literal === void 0) return "0n";
|
|
1123
|
+
if (!/^[+-]?\d+$/.test(literal)) throw invalid();
|
|
1124
|
+
return `${BigInt(literal)}n`;
|
|
1125
|
+
}
|
|
1126
|
+
if (literal === void 0) return "0";
|
|
1127
|
+
const value = Number(literal);
|
|
1128
|
+
if (Number.isNaN(value)) throw invalid();
|
|
1129
|
+
return String(value);
|
|
1093
1130
|
}
|
|
1094
1131
|
function tsOptionalScalarType(type) {
|
|
1095
1132
|
const scalar = tsScalarType(type);
|
|
@@ -1314,13 +1351,13 @@ function superTypeChain(eClass) {
|
|
|
1314
1351
|
return chain;
|
|
1315
1352
|
}
|
|
1316
1353
|
function isClassifierDerived(eClass) {
|
|
1317
|
-
return superTypeChain(eClass).some((c) => c.getName() === "EClassifier");
|
|
1354
|
+
return generationContext.generateEcore && superTypeChain(eClass).some((c) => c.getName() === "EClassifier");
|
|
1318
1355
|
}
|
|
1319
1356
|
function isStructuralFeatureDerived(eClass) {
|
|
1320
|
-
return superTypeChain(eClass).some((c) => c.getName() === "EStructuralFeature");
|
|
1357
|
+
return generationContext.generateEcore && superTypeChain(eClass).some((c) => c.getName() === "EStructuralFeature");
|
|
1321
1358
|
}
|
|
1322
1359
|
function isOperationDerived(eClass) {
|
|
1323
|
-
return superTypeChain(eClass).some((c) => c.getName() === "EOperation");
|
|
1360
|
+
return generationContext.generateEcore && superTypeChain(eClass).some((c) => c.getName() === "EOperation");
|
|
1324
1361
|
}
|
|
1325
1362
|
function isBookkeepingOperation(op, eClass) {
|
|
1326
1363
|
if (op.getName() === "getClassifierID" && op.getEParameters().isEmpty() && isClassifierDerived(eClass)) return true;
|
|
@@ -1475,6 +1512,16 @@ function jsString(value) {
|
|
|
1475
1512
|
}
|
|
1476
1513
|
return JSON.stringify(value);
|
|
1477
1514
|
}
|
|
1515
|
+
function hasStoredManyValuedFeature(features) {
|
|
1516
|
+
return [...features].some((feature) => feature.isMany() && featureGetter(feature) === void 0);
|
|
1517
|
+
}
|
|
1518
|
+
function runtimeAnnotations(element) {
|
|
1519
|
+
return element.getEAnnotations().toArray().filter((annotation) => {
|
|
1520
|
+
const source = annotation.getSource() ?? "";
|
|
1521
|
+
if (source === ECLIPSE_GENMODEL_ANNOTATION_SOURCE) return false;
|
|
1522
|
+
return !source.startsWith(TYPEMF_GENERATOR_ANNOTATION_SOURCE) || isDataTypeObject(element);
|
|
1523
|
+
});
|
|
1524
|
+
}
|
|
1478
1525
|
function detailsEntries(annotation) {
|
|
1479
1526
|
return [...annotation.getDetails()].map((entry) => ({ key: entry.getKey() ?? "", value: entry.getValue() ?? "" }));
|
|
1480
1527
|
}
|
|
@@ -1500,7 +1547,8 @@ function useImport(name, location, opts) {
|
|
|
1500
1547
|
var typescriptTemplateSet = {
|
|
1501
1548
|
name: "typescript",
|
|
1502
1549
|
baseFolder: join(packageRoot, "templates", "typescript"),
|
|
1503
|
-
validate(pkg) {
|
|
1550
|
+
validate(pkg, options) {
|
|
1551
|
+
beginGeneration(pkg, options);
|
|
1504
1552
|
return [
|
|
1505
1553
|
...findUnnamedElements(pkg),
|
|
1506
1554
|
...findUnresolvedCollisions(pkg).map(
|
|
@@ -1545,6 +1593,8 @@ var typescriptTemplateSet = {
|
|
|
1545
1593
|
env.addGlobal("findEClassByName", findEClassByName);
|
|
1546
1594
|
env.addGlobal("jsString", jsString);
|
|
1547
1595
|
env.addGlobal("detailsEntries", detailsEntries);
|
|
1596
|
+
env.addGlobal("runtimeAnnotations", runtimeAnnotations);
|
|
1597
|
+
env.addGlobal("hasStoredManyValuedFeature", hasStoredManyValuedFeature);
|
|
1548
1598
|
env.addGlobal("beanGetterName", beanGetterName);
|
|
1549
1599
|
env.addGlobal("isPrimitiveValueType", isPrimitiveValueType);
|
|
1550
1600
|
env.addGlobal("primitiveDefaultValue", primitiveDefaultValue);
|
package/dist/index.d.ts
CHANGED
|
@@ -155,7 +155,7 @@ interface TemplateSet {
|
|
|
155
155
|
* colliding in a way it doesn't know how to resolve automatically.
|
|
156
156
|
* Runs once, after ID assignment, before configureEnvironment/main.njk.
|
|
157
157
|
*/
|
|
158
|
-
validate?(pkg: EPackage): string[];
|
|
158
|
+
validate?(pkg: EPackage, options: Record<string, unknown>): string[];
|
|
159
159
|
/**
|
|
160
160
|
* Optional hook to register set-specific filters/globals (e.g. a
|
|
161
161
|
* `tsType` filter mapping EDataType names to TypeScript type names) on
|
|
@@ -274,12 +274,9 @@ declare function layeredAnnotationDetail(element: EModelElement, key: string, fa
|
|
|
274
274
|
*/
|
|
275
275
|
declare function documentationOf(element: EModelElement): string | undefined;
|
|
276
276
|
/**
|
|
277
|
-
* Renders a JSDoc block from documentationOf(), or '' if there is none.
|
|
278
|
-
*
|
|
279
|
-
*
|
|
280
|
-
* next one, so the template's own newline is what separates them - a
|
|
281
|
-
* trailing newline here as well used to leave a blank line between every
|
|
282
|
-
* doc comment and the declaration it documents.
|
|
277
|
+
* Renders a JSDoc block from documentationOf(), or '' if there is none. Lines longer than
|
|
278
|
+
* {@link DOC_COMMENT_WIDTH} are wrapped at spaces; shorter lines are kept as written. Has no
|
|
279
|
+
* trailing newline, since every template puts the declaration on the next line itself.
|
|
283
280
|
*/
|
|
284
281
|
declare function docComment(element: EModelElement, indent?: string): string;
|
|
285
282
|
/**
|
|
@@ -436,10 +433,11 @@ declare function resolveDataTypeTs(dataType: EDataType): ResolvedDataTypeText;
|
|
|
436
433
|
declare function registerBodyImports(element: EModelElement): string;
|
|
437
434
|
declare function isPrimitiveValueType(classifier: EClassifier | undefined): boolean;
|
|
438
435
|
/**
|
|
439
|
-
* The
|
|
440
|
-
*
|
|
441
|
-
*
|
|
442
|
-
*
|
|
436
|
+
* The initial value of a stored field of a primitive data type, as TypeScript source: the
|
|
437
|
+
* feature's `defaultValueLiteral` if it has one, else `false` for EBoolean, `0n` for ELong and
|
|
438
|
+
* `0` for the other numeric types.
|
|
439
|
+
*
|
|
440
|
+
* @throws Error if the `defaultValueLiteral` is not a valid value of the type.
|
|
443
441
|
*/
|
|
444
442
|
declare function primitiveDefaultValue(feature: ETypedElement): string;
|
|
445
443
|
/**
|
|
@@ -572,31 +570,20 @@ declare function superType(eClass: EClass): EClass | undefined;
|
|
|
572
570
|
/** eClass itself, then each ancestor in turn (via superType()), nearest first. */
|
|
573
571
|
declare function superTypeChain(eClass: EClass): EClass[];
|
|
574
572
|
/**
|
|
575
|
-
* Whether
|
|
576
|
-
*
|
|
577
|
-
*
|
|
578
|
-
*
|
|
579
|
-
* bootstrap code constructing the metamodel's own classifier shells
|
|
580
|
-
* (which ARE real EClassifier-derived instances, e.g. EClassImpl,
|
|
581
|
-
* EDataTypeImpl) genuinely needs to set it. Confirmed as a real,
|
|
582
|
-
* necessary gap by actually running self-hosted bootstrap code, not
|
|
583
|
-
* assumed - see NOTES.md.
|
|
573
|
+
* Whether `eClass` is EClassifier or a subclass of it, when generating Ecore itself: such a class
|
|
574
|
+
* gets a stored classifier ID (`getClassifierID`/`setClassifierID`), which is bookkeeping, not a
|
|
575
|
+
* modeled feature. Always false for any other package, so a user class that happens to be named
|
|
576
|
+
* EClassifier is generated like any other class.
|
|
584
577
|
*/
|
|
585
578
|
declare function isClassifierDerived(eClass: EClass): boolean;
|
|
586
|
-
/**
|
|
579
|
+
/** Like {@link isClassifierDerived}, for EStructuralFeature (feature ID and container class). */
|
|
587
580
|
declare function isStructuralFeatureDerived(eClass: EClass): boolean;
|
|
588
|
-
/**
|
|
581
|
+
/** Like {@link isClassifierDerived}, for EOperation (operation ID). */
|
|
589
582
|
declare function isOperationDerived(eClass: EClass): boolean;
|
|
590
583
|
/**
|
|
591
|
-
* Whether
|
|
592
|
-
*
|
|
593
|
-
*
|
|
594
|
-
* genuinely declares both "EClassifier.getClassifierID(): EInt" and
|
|
595
|
-
* "EStructuralFeature.getFeatureID(): EInt" as real, zero-arg operations
|
|
596
|
-
* - colliding, by name, with exactly the bookkeeping getters added for
|
|
597
|
-
* the self-hosting bootstrap fix. Confirmed directly against the real
|
|
598
|
-
* file before excluding these operations from the generic,
|
|
599
|
-
* throwing-stub-generating operation loop, not assumed - see NOTES.md.
|
|
584
|
+
* Whether `op` is one of Ecore's own operations that the bookkeeping methods implement
|
|
585
|
+
* (`getClassifierID`, `getFeatureID`, `getOperationID`, `getContainerClass`; see
|
|
586
|
+
* {@link isClassifierDerived}), so the operation loop must not generate it again.
|
|
600
587
|
*/
|
|
601
588
|
declare function isBookkeepingOperation(op: EOperation, eClass: EClass): boolean;
|
|
602
589
|
/**
|
|
@@ -717,6 +704,16 @@ declare function jsString(value: string | undefined): string;
|
|
|
717
704
|
* properties). Converting to a plain array here avoids relying on
|
|
718
705
|
* behavior that was never actually verified.
|
|
719
706
|
*/
|
|
707
|
+
/** Whether one of `features` is many-valued and stored in a list (has no custom getter). */
|
|
708
|
+
declare function hasStoredManyValuedFeature(features: Iterable<EStructuralFeature>): boolean;
|
|
709
|
+
/**
|
|
710
|
+
* `element`'s annotations that belong in the runtime metamodel. EMF's GenModel annotations are
|
|
711
|
+
* left out, and so are the generator's own (sources starting with https://typemf.dev/generator),
|
|
712
|
+
* which only steer code generation - except on a data type, where they say which TypeScript type
|
|
713
|
+
* the data type maps to and what to import, which generating another package that uses the data
|
|
714
|
+
* type reads from this runtime metamodel.
|
|
715
|
+
*/
|
|
716
|
+
declare function runtimeAnnotations(element: EModelElement): EAnnotation[];
|
|
720
717
|
declare function detailsEntries(annotation: EAnnotation): {
|
|
721
718
|
key: string;
|
|
722
719
|
value: string;
|
|
@@ -738,4 +735,4 @@ declare function singleValuedFeatures(features: Iterable<EStructuralFeature>): E
|
|
|
738
735
|
|
|
739
736
|
declare const typescriptTemplateSet: TemplateSet;
|
|
740
737
|
|
|
741
|
-
export { ECLIPSE_ECORE_ANNOTATION_SOURCE, ECLIPSE_GENMODEL_ANNOTATION_SOURCE, FEATURE_ANNOTATION_SOURCE, type GeneratedFile, type GeneratorConfig, type MemberCollision, type OverloadBranch, type OverloadDispatch, type ResolvedDataTypeText, type RunGenerationResult, TYPEMF_GENERATOR_ANNOTATION_SOURCE, type TemplateSet, argList, assignFreshIds, beanGetterName, buildEcoreMetaSchema, concreteEClassesOf, convertDynamicEcoreToTyped, customBodyNeedsOwnField, detailsEntries, docComment, documentationOf, eClassesOf, factoryClassName, featureGetter, featureSetter, findEClassByName, findFeatureAnnotationProblems, findUnnamedElements, findUnresolvedCollisions, generate, genericArgumentClassifiers, groupOperationsByName, isBookkeepingOperation, isClassifierDerived, isEClass, isEDataType, isEEnum, isEReference, isOperationDerived, isOptional, isPrimitiveValueType, isReadOnlyFeature, isStructuralFeatureDerived, jsString, layeredAnnotationDetail, loadConfig, loadEcorePackage, mergedParamList, mergedReturnType, metaclassAccessorCollision, metaclassAccessorCollisionTypeNames, needsImplOnlySetter, operationBody, optionalParamList, overloadDispatch, packageClassName, paramList, primitiveDefaultValue, referencedApiTypes, referencedOperationTypes, registerBodyImports, resolveDataTypeTs, resolveTemplateSet, runGeneration, singleValuedFeatures, superType, superTypeChain, switchClassName, trivialDerivedFormula, tsFeatureType, tsOperationReturnType, tsOptionalScalarType, tsScalarType, typeGuardsClassName, typescriptTemplateSet, ucfirst };
|
|
738
|
+
export { ECLIPSE_ECORE_ANNOTATION_SOURCE, ECLIPSE_GENMODEL_ANNOTATION_SOURCE, FEATURE_ANNOTATION_SOURCE, type GeneratedFile, type GeneratorConfig, type MemberCollision, type OverloadBranch, type OverloadDispatch, type ResolvedDataTypeText, type RunGenerationResult, TYPEMF_GENERATOR_ANNOTATION_SOURCE, type TemplateSet, argList, assignFreshIds, beanGetterName, buildEcoreMetaSchema, concreteEClassesOf, convertDynamicEcoreToTyped, customBodyNeedsOwnField, detailsEntries, docComment, documentationOf, eClassesOf, factoryClassName, featureGetter, featureSetter, findEClassByName, findFeatureAnnotationProblems, findUnnamedElements, findUnresolvedCollisions, generate, genericArgumentClassifiers, groupOperationsByName, hasStoredManyValuedFeature, isBookkeepingOperation, isClassifierDerived, isEClass, isEDataType, isEEnum, isEReference, isOperationDerived, isOptional, isPrimitiveValueType, isReadOnlyFeature, isStructuralFeatureDerived, jsString, layeredAnnotationDetail, loadConfig, loadEcorePackage, mergedParamList, mergedReturnType, metaclassAccessorCollision, metaclassAccessorCollisionTypeNames, needsImplOnlySetter, operationBody, optionalParamList, overloadDispatch, packageClassName, paramList, primitiveDefaultValue, referencedApiTypes, referencedOperationTypes, registerBodyImports, resolveDataTypeTs, resolveTemplateSet, runGeneration, runtimeAnnotations, singleValuedFeatures, superType, superTypeChain, switchClassName, trivialDerivedFormula, tsFeatureType, tsOperationReturnType, tsOptionalScalarType, tsScalarType, typeGuardsClassName, typescriptTemplateSet, ucfirst };
|
package/dist/index.js
CHANGED
|
@@ -734,7 +734,7 @@ var FileExtension = class {
|
|
|
734
734
|
// src/generate.ts
|
|
735
735
|
function generate(pkg, templateSet, options = {}) {
|
|
736
736
|
assignFreshIds(pkg);
|
|
737
|
-
const problems = templateSet.validate?.(pkg) ?? [];
|
|
737
|
+
const problems = templateSet.validate?.(pkg, options) ?? [];
|
|
738
738
|
if (problems.length > 0) {
|
|
739
739
|
throw new Error(
|
|
740
740
|
`Cannot generate from this package - ${templateSet.name} found ${problems.length} unresolved problem(s):
|
|
@@ -813,13 +813,19 @@ var TypeImportMapping = class _TypeImportMapping {
|
|
|
813
813
|
};
|
|
814
814
|
|
|
815
815
|
// src/generation-context.ts
|
|
816
|
-
var generationContext = {
|
|
816
|
+
var generationContext = {
|
|
817
|
+
pkg: void 0,
|
|
818
|
+
typeImports: new TypeImportMapping(),
|
|
819
|
+
generateEcore: false
|
|
820
|
+
};
|
|
821
|
+
var GENERATE_ECORE_OPTION = "generate-ecore";
|
|
817
822
|
var TYPE_IMPORTS_OPTION = "type-imports";
|
|
818
823
|
function beginGeneration(pkg, options) {
|
|
819
824
|
generationContext.pkg = pkg;
|
|
820
825
|
const entries = options[TYPE_IMPORTS_OPTION];
|
|
821
826
|
const valid = typeof entries === "object" && entries !== null && !Array.isArray(entries);
|
|
822
827
|
generationContext.typeImports = new TypeImportMapping(valid ? entries : {});
|
|
828
|
+
generationContext.generateEcore = options[GENERATE_ECORE_OPTION] === true;
|
|
823
829
|
}
|
|
824
830
|
function isExternal(classifier) {
|
|
825
831
|
const owner = classifier.getEPackage();
|
|
@@ -919,7 +925,8 @@ function locationOfPath(path) {
|
|
|
919
925
|
|
|
920
926
|
// src/typescript-filters.ts
|
|
921
927
|
import {
|
|
922
|
-
detailValue as detailValue2
|
|
928
|
+
detailValue as detailValue2,
|
|
929
|
+
isEDataType as isDataTypeObject
|
|
923
930
|
} from "@typemf/core";
|
|
924
931
|
var TYPEMF_GENERATOR_ANNOTATION_SOURCE = "https://typemf.dev/generator";
|
|
925
932
|
var ECLIPSE_GENMODEL_ANNOTATION_SOURCE = "http://www.eclipse.org/emf/2002/GenModel";
|
|
@@ -935,18 +942,34 @@ function layeredAnnotationDetail(element, key, fallbackSource) {
|
|
|
935
942
|
function documentationOf(element) {
|
|
936
943
|
return layeredAnnotationDetail(element, "documentation", ECLIPSE_ECORE_ANNOTATION_SOURCE);
|
|
937
944
|
}
|
|
945
|
+
var DOC_COMMENT_WIDTH = 100;
|
|
938
946
|
function docComment(element, indent = "") {
|
|
939
|
-
const doc = documentationOf(element);
|
|
947
|
+
const doc = documentationOf(element)?.trim();
|
|
940
948
|
if (!doc) return "";
|
|
941
|
-
const
|
|
942
|
-
if (
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
const body = lines.map((line) => `${indent} * ${line}`).join("\n");
|
|
949
|
+
const single = `${indent}/** ${doc} */`;
|
|
950
|
+
if (!doc.includes("\n") && single.length <= DOC_COMMENT_WIDTH) return single;
|
|
951
|
+
const width = DOC_COMMENT_WIDTH - `${indent} * `.length;
|
|
952
|
+
const lines = doc.split("\n").flatMap((line) => wrapLine(line, width));
|
|
953
|
+
const body = lines.map((line) => line === "" ? `${indent} *` : `${indent} * ${line}`).join("\n");
|
|
946
954
|
return `${indent}/**
|
|
947
955
|
${body}
|
|
948
956
|
${indent} */`;
|
|
949
957
|
}
|
|
958
|
+
function wrapLine(line, width) {
|
|
959
|
+
if (line.length <= width) return [line];
|
|
960
|
+
const lines = [];
|
|
961
|
+
let current = "";
|
|
962
|
+
for (const word of line.split(" ")) {
|
|
963
|
+
if (current !== "" && current.length + 1 + word.length > width) {
|
|
964
|
+
lines.push(current);
|
|
965
|
+
current = word;
|
|
966
|
+
} else {
|
|
967
|
+
current = current === "" ? word : `${current} ${word}`;
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
lines.push(current);
|
|
971
|
+
return lines;
|
|
972
|
+
}
|
|
950
973
|
function operationBody(operation) {
|
|
951
974
|
return layeredAnnotationDetail(operation, "body", ECLIPSE_GENMODEL_ANNOTATION_SOURCE);
|
|
952
975
|
}
|
|
@@ -1095,10 +1118,24 @@ function isPrimitiveValueType(classifier) {
|
|
|
1095
1118
|
return classifier !== void 0 && isEDataType(classifier) && PRIMITIVE_VALUE_DATATYPE_NAMES.has(classifier.getName());
|
|
1096
1119
|
}
|
|
1097
1120
|
function primitiveDefaultValue(feature) {
|
|
1098
|
-
const
|
|
1099
|
-
|
|
1100
|
-
const
|
|
1101
|
-
|
|
1121
|
+
const declared = "getDefaultValueLiteral" in feature ? feature.getDefaultValueLiteral()?.trim() : void 0;
|
|
1122
|
+
const literal = declared === "" ? void 0 : declared;
|
|
1123
|
+
const typeName = feature.getEType()?.getName();
|
|
1124
|
+
const invalid = () => new Error(`Invalid defaultValueLiteral '${literal}' for feature '${feature.getName()}'.`);
|
|
1125
|
+
if (typeName === "EBoolean") {
|
|
1126
|
+
if (literal === void 0) return "false";
|
|
1127
|
+
if (!/^(true|false)$/i.test(literal)) throw invalid();
|
|
1128
|
+
return literal.toLowerCase();
|
|
1129
|
+
}
|
|
1130
|
+
if (typeName === "ELong") {
|
|
1131
|
+
if (literal === void 0) return "0n";
|
|
1132
|
+
if (!/^[+-]?\d+$/.test(literal)) throw invalid();
|
|
1133
|
+
return `${BigInt(literal)}n`;
|
|
1134
|
+
}
|
|
1135
|
+
if (literal === void 0) return "0";
|
|
1136
|
+
const value = Number(literal);
|
|
1137
|
+
if (Number.isNaN(value)) throw invalid();
|
|
1138
|
+
return String(value);
|
|
1102
1139
|
}
|
|
1103
1140
|
function tsOptionalScalarType(type) {
|
|
1104
1141
|
const scalar = tsScalarType(type);
|
|
@@ -1323,13 +1360,13 @@ function superTypeChain(eClass) {
|
|
|
1323
1360
|
return chain;
|
|
1324
1361
|
}
|
|
1325
1362
|
function isClassifierDerived(eClass) {
|
|
1326
|
-
return superTypeChain(eClass).some((c) => c.getName() === "EClassifier");
|
|
1363
|
+
return generationContext.generateEcore && superTypeChain(eClass).some((c) => c.getName() === "EClassifier");
|
|
1327
1364
|
}
|
|
1328
1365
|
function isStructuralFeatureDerived(eClass) {
|
|
1329
|
-
return superTypeChain(eClass).some((c) => c.getName() === "EStructuralFeature");
|
|
1366
|
+
return generationContext.generateEcore && superTypeChain(eClass).some((c) => c.getName() === "EStructuralFeature");
|
|
1330
1367
|
}
|
|
1331
1368
|
function isOperationDerived(eClass) {
|
|
1332
|
-
return superTypeChain(eClass).some((c) => c.getName() === "EOperation");
|
|
1369
|
+
return generationContext.generateEcore && superTypeChain(eClass).some((c) => c.getName() === "EOperation");
|
|
1333
1370
|
}
|
|
1334
1371
|
function isBookkeepingOperation(op, eClass) {
|
|
1335
1372
|
if (op.getName() === "getClassifierID" && op.getEParameters().isEmpty() && isClassifierDerived(eClass)) return true;
|
|
@@ -1484,6 +1521,16 @@ function jsString(value) {
|
|
|
1484
1521
|
}
|
|
1485
1522
|
return JSON.stringify(value);
|
|
1486
1523
|
}
|
|
1524
|
+
function hasStoredManyValuedFeature(features) {
|
|
1525
|
+
return [...features].some((feature) => feature.isMany() && featureGetter(feature) === void 0);
|
|
1526
|
+
}
|
|
1527
|
+
function runtimeAnnotations(element) {
|
|
1528
|
+
return element.getEAnnotations().toArray().filter((annotation) => {
|
|
1529
|
+
const source = annotation.getSource() ?? "";
|
|
1530
|
+
if (source === ECLIPSE_GENMODEL_ANNOTATION_SOURCE) return false;
|
|
1531
|
+
return !source.startsWith(TYPEMF_GENERATOR_ANNOTATION_SOURCE) || isDataTypeObject(element);
|
|
1532
|
+
});
|
|
1533
|
+
}
|
|
1487
1534
|
function detailsEntries(annotation) {
|
|
1488
1535
|
return [...annotation.getDetails()].map((entry) => ({ key: entry.getKey() ?? "", value: entry.getValue() ?? "" }));
|
|
1489
1536
|
}
|
|
@@ -1509,7 +1556,8 @@ function useImport(name, location, opts) {
|
|
|
1509
1556
|
var typescriptTemplateSet = {
|
|
1510
1557
|
name: "typescript",
|
|
1511
1558
|
baseFolder: join(packageRoot, "templates", "typescript"),
|
|
1512
|
-
validate(pkg) {
|
|
1559
|
+
validate(pkg, options) {
|
|
1560
|
+
beginGeneration(pkg, options);
|
|
1513
1561
|
return [
|
|
1514
1562
|
...findUnnamedElements(pkg),
|
|
1515
1563
|
...findUnresolvedCollisions(pkg).map(
|
|
@@ -1554,6 +1602,8 @@ var typescriptTemplateSet = {
|
|
|
1554
1602
|
env.addGlobal("findEClassByName", findEClassByName);
|
|
1555
1603
|
env.addGlobal("jsString", jsString);
|
|
1556
1604
|
env.addGlobal("detailsEntries", detailsEntries);
|
|
1605
|
+
env.addGlobal("runtimeAnnotations", runtimeAnnotations);
|
|
1606
|
+
env.addGlobal("hasStoredManyValuedFeature", hasStoredManyValuedFeature);
|
|
1557
1607
|
env.addGlobal("beanGetterName", beanGetterName);
|
|
1558
1608
|
env.addGlobal("isPrimitiveValueType", isPrimitiveValueType);
|
|
1559
1609
|
env.addGlobal("primitiveDefaultValue", primitiveDefaultValue);
|
|
@@ -1631,6 +1681,7 @@ export {
|
|
|
1631
1681
|
generate,
|
|
1632
1682
|
genericArgumentClassifiers,
|
|
1633
1683
|
groupOperationsByName,
|
|
1684
|
+
hasStoredManyValuedFeature,
|
|
1634
1685
|
isBookkeepingOperation,
|
|
1635
1686
|
isClassifierDerived,
|
|
1636
1687
|
isEClass2 as isEClass,
|
|
@@ -1663,6 +1714,7 @@ export {
|
|
|
1663
1714
|
resolveDataTypeTs,
|
|
1664
1715
|
resolveTemplateSet,
|
|
1665
1716
|
runGeneration,
|
|
1717
|
+
runtimeAnnotations,
|
|
1666
1718
|
singleValuedFeatures,
|
|
1667
1719
|
superType,
|
|
1668
1720
|
superTypeChain,
|