Skip to content

Commit 8abb23f

Browse files
authored
Merge pull request #22 from Anshukumar123975/main
feat(rust): Add AST files for the CTO files and support for concerto-rust
2 parents e306d6c + 16b16a6 commit 8abb23f

File tree

103 files changed

+7604
-126
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

103 files changed

+7604
-126
lines changed

CONTRIBUTION.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Concerto Conformance Contribution Guide
2+
## 1. To add new semantic rules:
3+
a. Add the model file (.cto) within the specification folder under the suitable specification type.
4+
b. Add the scenario in the {specification_type}.feature file using the steps statement mentioned in the steps file.
5+
c. Run the script `npm run convert-ast file_path`
6+
d. If the cto file is syntactically valid a .json file will be created after running the above script just in the same directory as the corresponding .cto file.
7+
e. If the cto file is syntactically invalid then no .json file will be created and the steps file will consider it as an invalid model.
8+
9+
## 2. To modify the semantic rules:
10+
a. To change the scenario you must change the scenario according to the statements in the steps file.
11+
b. If creating a new step then ensure it's working correctly!
12+
13+
#### We'd love for you to contribute to our source code and to make Concerto Conformance Test Suite more robust and accurate!

convertToAST.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import fs from 'fs';
2+
import path from 'path';
3+
import { Parser } from '@accordproject/concerto-cto';
4+
5+
const BASE_DIR = path.resolve('semantic/specifications');
6+
7+
function getAllCTOFiles(dir) {
8+
let files = [];
9+
10+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
11+
const fullPath = path.join(dir, entry.name);
12+
if (entry.isDirectory()) {
13+
files = files.concat(getAllCTOFiles(fullPath));
14+
} else if (entry.isFile() && fullPath.endsWith('.cto')) {
15+
files.push(fullPath);
16+
}
17+
}
18+
19+
return files;
20+
}
21+
22+
function convertAndWriteAST(ctoPath) {
23+
try {
24+
const modelContent = fs.readFileSync(ctoPath, 'utf8');
25+
const ast = Parser.parse(modelContent, ctoPath);
26+
27+
const outFileName = path.basename(ctoPath).replace('.cto', '.json');
28+
const outDir = path.dirname(ctoPath); // same directory as .cto
29+
const outFilePath = path.join(outDir, outFileName);
30+
31+
fs.writeFileSync(outFilePath, JSON.stringify(ast, null, 2), 'utf8');
32+
console.log(`✅ Converted: ${ctoPath}${outFilePath}`);
33+
} catch (error) {
34+
console.error(`❌ Failed to convert: ${ctoPath}`);
35+
console.error(error.message);
36+
}
37+
}
38+
39+
function run() {
40+
const allCTOs = getAllCTOFiles(BASE_DIR);
41+
allCTOs.forEach(convertAndWriteAST);
42+
}
43+
44+
run();

convertToASTpath.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// parseCtoToAst.js
2+
import fs from 'fs';
3+
import path from 'path';
4+
import { Parser } from '@accordproject/concerto-cto';
5+
6+
function convertCTOToAST(ctoPath) {
7+
try {
8+
const absolutePath = path.resolve(ctoPath);
9+
const dir = path.dirname(absolutePath);
10+
const baseName = path.basename(absolutePath, '.cto');
11+
const outFilePath = path.join(dir, `${baseName}.json`);
12+
13+
const modelContent = fs.readFileSync(absolutePath, 'utf8');
14+
const ast = Parser.parse(modelContent, absolutePath);
15+
16+
fs.writeFileSync(outFilePath, JSON.stringify(ast, null, 2), 'utf8');
17+
console.log(`✅ AST written to: ${outFilePath}`);
18+
} catch (err) {
19+
console.error(`❌ Failed to parse: ${ctoPath}`);
20+
console.error(`Error: ${err.message}`);
21+
}
22+
}
23+
24+
const inputPath = process.argv[2];
25+
if (!inputPath) {
26+
console.error('❗ Usage: node parseCtoToAst.js <path/to/file.cto>');
27+
process.exit(1);
28+
}
29+
30+
convertCTOToAST(inputPath);

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
"test:semantic": "cucumber-js \"semantic/features/**/*.feature\" --loader ts-node/esm --import \"semantic/features/support/Javascript/*.ts\" --tags \"not @skip\"",
1010
"test:instances": "cucumber-js validate/features --import validate/validateSteps.js",
1111
"test:csharp": "dotnet test semantic/features/support/C#/Semantic.Support.CSharp/Semantic.Support.CSharp.csproj",
12-
"start": "node cli.js"
12+
"start": "node cli.js",
13+
"convert-ast": "node convertToASTpath.js"
1314
},
1415
"keywords": [],
1516
"author": "",

semantic/features/concepts.feature

Lines changed: 38 additions & 38 deletions
Large diffs are not rendered by default.

semantic/features/enums.feature

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,43 +3,43 @@ Feature: Semantic Validation of Enum Declarations in CTO Models
33
Scenario: Duplicate enum names in the same file should throw an error
44
Given I load the following models:
55
| model_file | alias |
6-
| enums/models/DECLARATION_001/declaration_001_duplicate_enum_names.cto | main |
6+
| enums/models/DECLARATION_001/declaration_001_duplicate_enum_names.json | main |
77
When I validate the models
88
Then an error should be thrown with message "Duplicate"
99

1010
Scenario: Unique enum names in the same file should pass validation
1111
Given I load the following models:
1212
| model_file | alias |
13-
| enums/models/DECLARATION_001/declaration_001_unique_enum_names.cto | main |
13+
| enums/models/DECLARATION_001/declaration_001_unique_enum_names.json | main |
1414
When I validate the models
1515
Then no error should be thrown
1616

1717
Scenario: Local enum name does not conflict with imported enum
1818
Given I load the following models:
1919
| model_file | alias |
20-
| enums/models/DECLARATION_002/importedTypes.cto | imported |
21-
| enums/models/DECLARATION_002/declaration_002_non_conflicting_name.cto | main |
20+
| enums/models/DECLARATION_002/importedTypes.json | imported |
21+
| enums/models/DECLARATION_002/declaration_002_non_conflicting_name.json | main |
2222
When I validate the models
2323
Then no error should be thrown
2424

2525
@skip
2626
Scenario: Enum name conflicts with imported enum should throw an error
2727
Given I load the following models:
2828
| model_file | alias |
29-
| enums/models/DECLARATION_002/importedTypes.cto | imported |
30-
| enums/models/DECLARATION_002/declaration_002_name_conflict_with_import.cto | main |
29+
| enums/models/DECLARATION_002/importedTypes.json | imported |
30+
| enums/models/DECLARATION_002/declaration_002_name_conflict_with_import.json | main |
3131
When I validate the models
3232
Then an error should be thrown with message "already defined in an imported model"
3333

3434
Scenario: Valid enum identifier name should pass validation
3535
Given I load the following models:
3636
| model_file | alias |
37-
| enums/models/MODEL_ELEMENT_002/model_element_002_valid_enum_name.cto | main |
37+
| enums/models/MODEL_ELEMENT_002/model_element_002_valid_enum_name.json | main |
3838
When I validate the models
3939
Then no error should be thrown
4040

4141
Scenario: Invalid enum identifier name should throw an error
4242
Given I load the following models:
4343
| model_file | alias |
44-
| enums/models/MODEL_ELEMENT_002/model_element_002_invalid_enum_name.cto | main |
44+
| enums/models/MODEL_ELEMENT_002/model_element_002_invalid_enum_name.json | main |
4545
Then an error should be thrown with message ""

semantic/features/imports.feature

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,49 +3,49 @@ Feature: Semantic Validation of CTO Model Imports
33
Scenario: Local and imported types have unique names and should pass validation
44
Given I load the following models:
55
| model_file | alias |
6-
| imports/models/DECLARATION_002/importedTypes.cto | imported |
7-
| imports/models/DECLARATION_002/declaration_002_unique_with_imported_type.cto | main |
6+
| imports/models/DECLARATION_002/importedTypes.json | imported |
7+
| imports/models/DECLARATION_002/declaration_002_unique_with_imported_type.json | main |
88
When I validate the models
99
Then no error should be thrown
1010

1111
@skip
1212
Scenario: Conflict with imported type name should throw an error
1313
Given I load the following models:
1414
| model_file | alias |
15-
| imports/models/DECLARATION_002/importedTypes.cto | imported |
16-
| imports/models/DECLARATION_002/declaration_002_conflict_with_imported_type.cto | main |
15+
| imports/models/DECLARATION_002/importedTypes.json | imported |
16+
| imports/models/DECLARATION_002/declaration_002_conflict_with_imported_type.json | main |
1717
When I validate the models
1818
Then an error should be thrown with message "already defined in an imported model"
1919

2020
Scenario: Valid import and reference of existing type should pass validation
2121
Given I load the following models:
2222
| model_file | alias |
23-
| imports/models/DECLARATION_002/importedTypes.cto | imported |
24-
| imports/models/MODEL_FILE_001/model_file_001_existing_import_type.cto | main |
23+
| imports/models/DECLARATION_002/importedTypes.json | imported |
24+
| imports/models/MODEL_FILE_001/model_file_001_existing_import_type.json | main |
2525
When I validate the models
2626
Then no error should be thrown
2727

2828
Scenario: Importing a non-existent type should throw an error
2929
Given I load the following models:
3030
| model_file | alias |
31-
| imports/models/MODEL_FILE_001/model_file_001_import_nonexistent_type.cto | main |
31+
| imports/models/MODEL_FILE_001/model_file_001_import_nonexistent_type.json | main |
3232
When I validate the models
3333
Then an error should be thrown with message "Namespace is not defined"
3434

3535
Scenario: Unique namespace imports should pass validation
3636
Given I load the following models:
3737
| model_file | alias |
38-
| imports/models/DECLARATION_002/importedTypes.cto | import1 |
39-
| imports/models/DECLARATION_002/importedTypes2.cto | import2 |
40-
| imports/models/MODEL_FILE_002/model_file_002_unique_namespace_imports.cto | main |
38+
| imports/models/DECLARATION_002/importedTypes.json | import1 |
39+
| imports/models/DECLARATION_002/importedTypes2.json | import2 |
40+
| imports/models/MODEL_FILE_002/model_file_002_unique_namespace_imports.json | main |
4141
When I validate the models
4242
Then no error should be thrown
4343

4444
@skip
4545
Scenario: Duplicate namespace imports should throw an error
4646
Given I load the following models:
4747
| model_file | alias |
48-
| imports/models/DECLARATION_002/importedTypes.cto | import1 |
49-
| imports/models/MODEL_FILE_002/model_file_002_duplicate_namespace_imports.cto | main |
48+
| imports/models/DECLARATION_002/importedTypes.json | import1 |
49+
| imports/models/MODEL_FILE_002/model_file_002_duplicate_namespace_imports.json | main |
5050
When I validate the models
5151
Then an error should be thrown with message "Import from namespace .* already exists"

semantic/features/maps.feature

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,40 +3,40 @@ Feature: Semantic Validation of CTO Map Specification
33
Scenario: Valid map key type should pass
44
Given I load the following models:
55
| model_file | alias |
6-
| maps/models/MAP_KEY_TYPE_001/map_key_type_001_valid_key_type.cto | main |
6+
| maps/models/MAP_KEY_TYPE_001/map_key_type_001_valid_key_type.json | main |
77
When I validate the models
88
Then no error should be thrown
99

1010
Scenario: Invalid map key type should throw error
1111
Given I load the following models:
1212
| model_file | alias |
13-
| maps/models/MAP_KEY_TYPE_001/map_key_type_001_invalid_key_type.cto | main |
14-
Then an error should be thrown with message "Expected \"DateTime\", \"String\""
13+
| maps/models/MAP_KEY_TYPE_001/map_key_type_001_invalid_key_type.json | main |
14+
Then an error should be thrown with message ""
1515

1616
Scenario: Valid map value type should pass
1717
Given I load the following models:
1818
| model_file | alias |
19-
| maps/models/MAP_VALUE_TYPE_001/map_value_type_001_existing_value_type.cto | main |
19+
| maps/models/MAP_VALUE_TYPE_001/map_value_type_001_existing_value_type.json | main |
2020
When I validate the models
2121
Then no error should be thrown
2222

2323
Scenario: Non-existent map value type should throw error
2424
Given I load the following models:
2525
| model_file | alias |
26-
| maps/models/MAP_VALUE_TYPE_001/map_value_type_001_type_not_exist.cto | main |
26+
| maps/models/MAP_VALUE_TYPE_001/map_value_type_001_type_not_exist.json | main |
2727
When I validate the models
2828
Then an error should be thrown with message "Cannot read properties of null"
2929

3030
Scenario: Duplicate map names should throw error
3131
Given I load the following models:
3232
| model_file | alias |
33-
| maps/models/DECLARATION_001/declaration_001_duplicate_map_name.cto | main |
33+
| maps/models/DECLARATION_001/declaration_001_duplicate_map_name.json | main |
3434
When I validate the models
3535
Then an error should be thrown with message "Duplicate class name"
3636

3737
Scenario: Unique map names should pass
3838
Given I load the following models:
3939
| model_file | alias |
40-
| maps/models/DECLARATION_001/declaration_001_unique_map_name.cto | main |
40+
| maps/models/DECLARATION_001/declaration_001_unique_map_name.json | main |
4141
When I validate the models
4242
Then no error should be thrown

semantic/features/namespaces.feature

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,47 @@ Feature: Semantic Validation of CTO Namespace Imports
44
Scenario: Invalid duplicate namespace imports should throw an error
55
Given I load the following models:
66
| model_file | alias |
7-
| namespaces/models/MODEL_FILE_002/importedTypes.cto | imported |
8-
| namespaces/models/MODEL_FILE_002/model_file_002_duplicate_namespace_imports.cto | main |
7+
| namespaces/models/MODEL_FILE_002/importedTypes.json | imported |
8+
| namespaces/models/MODEL_FILE_002/model_file_002_duplicate_namespace_imports.json | main |
99
When I validate the models
10-
Then an error should be thrown with message "Namespace org.external.types is already defined"
10+
Then an error should be thrown with message "Import namespace is already defined"
1111

1212
Scenario: Valid unique namespace imports should pass
1313
Given I load the following models:
1414
| model_file | alias |
15-
| namespaces/models/MODEL_FILE_002/importedTypes.cto | imported |
16-
| namespaces/models/MODEL_FILE_002/model_file_002_unique_namespace_imports.cto | main |
15+
| namespaces/models/MODEL_FILE_002/importedTypes.json | imported |
16+
| namespaces/models/MODEL_FILE_002/model_file_002_unique_namespace_imports.json | main |
1717
When I validate the models
1818
Then no error should be thrown
1919

20-
Scenario: Invalid self-import should throw MODEL_FILE_004 error
20+
Scenario: Invalid self-import should throw MODEL_FILE_003 error
2121
Given I load the following models:
2222
| model_file | alias |
23-
| namespaces/models/MODEL_FILE_003/model_file_003_self_import.cto | main |
23+
| namespaces/models/MODEL_FILE_003/model_file_003_self_import.json | main |
2424
When I validate the models
2525
Then an error should be thrown with message "Namespace is not defined for type"
2626

2727
Scenario: Valid model without self-import should pass
2828
Given I load the following models:
2929
| model_file | alias |
30-
| namespaces/models/MODEL_FILE_003/model_file_003_valid_import.cto | main |
30+
| namespaces/models/MODEL_FILE_003/model_file_003_valid_import.json | main |
31+
When I validate the models
32+
Then no error should be thrown
33+
34+
@skip
35+
Scenario: Invalid duplicate declared names from different namespace imports should throw an error
36+
Given I load the following models:
37+
| model_file | alias |
38+
| namespaces/models/MODEL_FILE_004/importedTypes.json | imported |
39+
| namespaces/models/MODEL_FILE_004/importedTypestwo.json | imported |
40+
| namespaces/models/MODEL_FILE_004/model_file_004_duplicate_namespace_imports.json | main |
41+
When I validate the models
42+
Then an error should be thrown with message "Can't import same names for different namespaces"
43+
44+
Scenario: Valid unique namespace imports should pass
45+
Given I load the following models:
46+
| model_file | alias |
47+
| namespaces/models/MODEL_FILE_004/importedTypes.json | imported |
48+
| namespaces/models/MODEL_FILE_004/model_file_004_unique_namespace_imports.json | main |
3149
When I validate the models
3250
Then no error should be thrown

0 commit comments

Comments
 (0)