Skip to content

Commit

Permalink
fix(class): throw error when class is extending itself (#767)
Browse files Browse the repository at this point in the history
* fix(parser): throw error when concept is extending itself in CTO

Signed-off-by: Stefan Blaginov <[email protected]>
Signed-off-by: Stefan Blaginov <[email protected]>

* fix(parser): throw error when concept is extending itself in JSON metamodel form

Signed-off-by: Stefan Blaginov <[email protected]>
Signed-off-by: Stefan Blaginov <[email protected]>

* fix(parser): throw error when concept is extending itself in the AST

Signed-off-by: Stefan Blaginov <[email protected]>
Signed-off-by: Stefan Blaginov <[email protected]>

* refactor(validation): alphabetical rearrangement

Signed-off-by: Stefan Blaginov <[email protected]>
Signed-off-by: Stefan Blaginov <[email protected]>

* test(self-extending): remove redundant tests (codepath covered in concerto-cto)

Signed-off-by: Stefan Blaginov <[email protected]>
Signed-off-by: Stefan Blaginov <[email protected]>

* test(fix): remove unneeded import

Signed-off-by: Stefan Blaginov <[email protected]>
Signed-off-by: Stefan Blaginov <[email protected]>

---------

Signed-off-by: Stefan Blaginov <[email protected]>
Signed-off-by: Stefan Blaginov <[email protected]>
Co-authored-by: Stefan Blaginov <[email protected]>
  • Loading branch information
Stefan Blaginov and Stefan Blaginov authored Nov 28, 2023
1 parent fc35a40 commit 886a91b
Show file tree
Hide file tree
Showing 12 changed files with 116 additions and 0 deletions.
13 changes: 13 additions & 0 deletions packages/concerto-core/lib/introspect/classdeclaration.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,19 @@ class ClassDeclaration extends Declaration {

// if we have a super type make sure it exists
if (this.superType !== null) {
// and make sure that the class isn't extending itself
// (an exemption is made for the core classes)
if (
this.superType === this.name &&
![
'Asset', 'Concept', 'Event', 'Participant', 'Transaction',
].includes(this.superType)
) {
let formatter = Globalize('en').messageFormatter('classdeclaration-validate-selfextending');
throw new IllegalModelException(formatter({
'class': this.name,
}), this.modelFile, this.ast.location);
}
this._resolveSuperType();
}

Expand Down
1 change: 1 addition & 0 deletions packages/concerto-core/messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"classdeclaration-validate-identifiernotstring": "Class \"{class}\" is identified by field \"{idField}\", but the type of the field is not \"String\".",
"classdeclaration-validate-duplicatefieldname": "Class \"{class}\" has more than one field named \"{fieldName}\".",
"classdeclaration-validate-missingidentifier" : "Class \"{class}\" is not declared as \"abstract\". It must define an identifying field.",
"classdeclaration-validate-selfextending": "Class \"{class}\" cannot extend itself.",

"modelfile-constructor-unrecmodelelem": "Unrecognised model element \"{type}\".",
"modelfile-resolvetype-undecltype": "Undeclared type \"{type}\" in \"{context}\".",
Expand Down
15 changes: 15 additions & 0 deletions packages/concerto-cto/lib/parser.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions packages/concerto-cto/lib/parser.pegjs
Original file line number Diff line number Diff line change
Expand Up @@ -966,6 +966,9 @@ AssetDeclaration
...buildRange(location())
};
if (classExtension) {
if (classExtension.name === id.name) {
throw new Error(`The asset "${id.name}" cannot extend itself.`);
}
result.superType = classExtension;
}
if (idField) {
Expand All @@ -989,6 +992,9 @@ ParticipantDeclaration
...buildRange(location())
};
if (classExtension) {
if (classExtension.name === id.name) {
throw new Error(`The participant "${id.name}" cannot extend itself.`);
}
result.superType = classExtension;
}
if (idField) {
Expand All @@ -1012,6 +1018,9 @@ TransactionDeclaration
...buildRange(location())
};
if (classExtension) {
if (classExtension.name === id.name) {
throw new Error(`The transaction "${id.name}" cannot extend itself.`);
}
result.superType = classExtension;
}
if (idField) {
Expand All @@ -1035,6 +1044,9 @@ EventDeclaration
...buildRange(location())
};
if (classExtension) {
if (classExtension.name === id.name) {
throw new Error(`The event "${id.name}" cannot extend itself.`);
}
result.superType = classExtension;
}
if (idField) {
Expand All @@ -1058,6 +1070,9 @@ ConceptDeclaration
...buildRange(location())
};
if (classExtension) {
if (classExtension.name === id.name) {
throw new Error(`The concept "${id.name}" cannot extend itself.`);
}
result.superType = classExtension;
}
if (idField) {
Expand Down
3 changes: 3 additions & 0 deletions packages/concerto-cto/lib/printer.js
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,9 @@ function declFromMetaModel(mm) {
}
}
if (mm.superType) {
if (mm.superType.name === mm.name) {
throw new Error(`The declaration "${mm.name}" cannot extend itself.`);
}
result += `extends ${mm.superType.name} `;
}
result += '{';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
namespace [email protected]

asset Self_Extending extends Self_Extending {
o String foo optional
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
namespace [email protected]

concept Self_Extending extends Self_Extending {
o String foo optional
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
namespace [email protected]

event Self_Extending extends Self_Extending {
o String foo optional
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
namespace [email protected]

participant Self_Extending extends Self_Extending {
o String foo optional
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
namespace [email protected]

transaction Self_Extending extends Self_Extending {
o String foo optional
}
18 changes: 18 additions & 0 deletions packages/concerto-cto/test/parserMain.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,24 @@ describe('parser', () => {
});
});

describe('self-extending', () => {
const declarationTypes = [
'asset',
'participant',
'transaction',
'event',
'concept',
];
declarationTypes.forEach(declarationType => {
it(`Should not parse a self-extending ${declarationType}`, () => {
let content = fs.readFileSync(`./test/cto/bad/self-extending-${declarationType}.bad.cto`, 'utf8');
(() => {
Parser.parse(content);
}).should.throw(new RegExp(`The ${declarationType} ".+" cannot extend itself.`));
});
});
});

describe('identifiers', () => {

const acceptedIdentifiers = [
Expand Down
26 changes: 26 additions & 0 deletions packages/concerto-cto/test/printer.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,30 @@ describe('parser', () => {
declarations: [],
})).should.throw(Error, 'Unrecognized import');
});

it('Should throw error for a self-extending declaration', () => {
(() => Printer.toCTO({
'$class': '[email protected]',
'namespace': '[email protected]',
'declarations': [
{
'$class': '[email protected]',
'name': 'Self_Extending',
'isAbstract': false,
'properties': [
{
'$class': '[email protected]',
'name': 'foo',
'isArray': false,
'isOptional': true
}
],
'superType': {
'$class': '[email protected]',
'name': 'Self_Extending'
}
}
]
})).should.throw(Error, 'The declaration "Self_Extending" cannot extend itself.');
});
});

0 comments on commit 886a91b

Please sign in to comment.