From e4968a6c32e5b880eb6c317cbf27e59c2243f74b Mon Sep 17 00:00:00 2001 From: Jaskeerat Singh Saluja <58400083+salujajaskeerat@users.noreply.github.com> Date: Wed, 4 Sep 2024 14:23:20 +0530 Subject: [PATCH] feat(csharp,java): support aliasing imports (#115) * feat(i114): updated the property type-resolution Signed-off-by: Jaskeerat Singh Saluja * feat(csharp-alias-import): minor bug fixed - Earlier non-imported types gave error. Signed-off-by: Jaskeerat Singh Saluja * feat(i114): test cases added and minor bug fixed Signed-off-by: Jaskeerat Singh Saluja * feat(i114): Java visitor updated for aliased import Signed-off-by: Jaskeerat Singh Saluja * feat(alias-import):updating changes Signed-off-by: Jaskeerat Singh Saluja * feat(alias-import): Test cases for java-visitor added Signed-off-by: Jaskeerat Singh Saluja * feat(import-alias): concerto-core version updated and minor changes Signed-off-by: Jaskeerat Singh Saluja * feat(alias-import):Minor bug fixed Signed-off-by: Jaskeerat Singh Saluja * feat(alias-import): Pr suggestions Signed-off-by: Jaskeerat Singh Saluja --------- Signed-off-by: Jaskeerat Singh Saluja Signed-off-by: Jaskeerat Singh Saluja <58400083+salujajaskeerat@users.noreply.github.com> Co-authored-by: Jaskeerat Singh Saluja --- lib/codegen/fromcto/csharp/csharpvisitor.js | 4 ++ lib/codegen/fromcto/java/javavisitor.js | 11 +++- package-lock.json | 48 ++++++++++++++-- package.json | 3 +- test/codegen/codegen.js | 1 + test/codegen/fromcto/csharp/csharpvisitor.js | 59 ++++++++++++++++++++ test/codegen/fromcto/java/javavisitor.js | 24 +++++++- 7 files changed, 139 insertions(+), 11 deletions(-) diff --git a/lib/codegen/fromcto/csharp/csharpvisitor.js b/lib/codegen/fromcto/csharp/csharpvisitor.js index fefab2c1..e7ac7a7b 100644 --- a/lib/codegen/fromcto/csharp/csharpvisitor.js +++ b/lib/codegen/fromcto/csharp/csharpvisitor.js @@ -383,6 +383,10 @@ class CSharpVisitor { } } else if (!field.isPrimitive()) { let fqn = this.getDotNetNamespaceOfType(field.getFullyQualifiedTypeName(), field.getParent(), parameters); + const modelFile = field.getModelFile(); + if (modelFile?.isImportedType(fieldType)) { + fieldType = modelFile.getImportedType(fieldType); + } fieldType = `${fqn}${fieldType}`; } diff --git a/lib/codegen/fromcto/java/javavisitor.js b/lib/codegen/fromcto/java/javavisitor.js index a3f296cf..7a6b838d 100644 --- a/lib/codegen/fromcto/java/javavisitor.js +++ b/lib/codegen/fromcto/java/javavisitor.js @@ -267,9 +267,14 @@ class JavaVisitor { if(field.isArray()) { array = '[]'; } - - const fieldType = this.toJavaType(field.getType()) + array; - + let fieldType = field.getType(); + if (!ModelUtil.isPrimitiveType(fieldType)) { + const modelFile = field.getModelFile(); + if (modelFile?.isImportedType(fieldType)) { + fieldType = modelFile.getImportedType(fieldType); + } + } + fieldType = this.toJavaType(fieldType) + array; const fieldName = field.getName(); const getterName = 'get' + this.capitalizeFirstLetter(fieldName); const setterName = 'set' + this.capitalizeFirstLetter(fieldName); diff --git a/package-lock.json b/package-lock.json index b9cfbeac..4639ab10 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "3.23.3", "license": "Apache-2.0", "dependencies": { - "@accordproject/concerto-core": "3.18.1", + "@accordproject/concerto-core": "3.19.0", "@accordproject/concerto-util": "3.18.1", "@accordproject/concerto-vocabulary": "3.18.1", "@openapi-contrib/openapi-schema-to-json-schema": "5.1.0", @@ -61,13 +61,15 @@ } }, "node_modules/@accordproject/concerto-core": { - "version": "3.18.1", - "resolved": "https://registry.npmjs.org/@accordproject/concerto-core/-/concerto-core-3.18.1.tgz", - "integrity": "sha512-XtTiQCPj+Bdkcei8EXzi8Zp+Himlim4mkfdMs+AxfIltaH2jhzwVyu6VfMCwTcCggmHU04QC+JBjnJ5ImusUrg==", + "version": "3.19.0", + "resolved": "https://registry.npmjs.org/@accordproject/concerto-core/-/concerto-core-3.19.0.tgz", + "integrity": "sha512-zgAV8s5e+I4wGJjYeQkYl/5c3/Ew8ZbQWunbICu2obtoW4xmvPJ7gWBRg2n3lrsCYuEde7eMT8tRZ8Kcgwuh7w==", + "license": "Apache-2.0", "dependencies": { - "@accordproject/concerto-cto": "3.18.1", + "@accordproject/concerto-cto": "3.19.0", "@accordproject/concerto-metamodel": "3.10.0", - "@accordproject/concerto-util": "3.18.1", + "@accordproject/concerto-util": "3.19.0", + "dayjs": "1.11.10", "debug": "4.3.4", "lorem-ipsum": "2.0.8", @@ -82,7 +84,41 @@ "npm": ">=8" } }, + "node_modules/@accordproject/concerto-core/node_modules/@accordproject/concerto-cto": { + "version": "3.19.0", + "resolved": "https://registry.npmjs.org/@accordproject/concerto-cto/-/concerto-cto-3.19.0.tgz", + "integrity": "sha512-eA8O2IcEmnOdGTu2bWeSFQMSSHQr7vJ/Gzhv0cWxnh41wxKhmfoBK/BmEZgyJi6dI7HufKkat+p2B76MIwCqOA==", + "license": "Apache-2.0", + "dependencies": { + "@accordproject/concerto-metamodel": "3.10.0", + "@accordproject/concerto-util": "3.19.0", + "path-browserify": "1.0.1" + }, + "engines": { + "node": ">=16", + "npm": ">=8" + } + }, + "node_modules/@accordproject/concerto-core/node_modules/@accordproject/concerto-util": { + "version": "3.19.0", + "resolved": "https://registry.npmjs.org/@accordproject/concerto-util/-/concerto-util-3.19.0.tgz", + "integrity": "sha512-zadhEhKoVDuRcmUZGH5xbgV2Am1zv8jMPJaedWadiSyqw2qif95MZvKg7DEIdSohQvcfJ5z53iPJqsdmfauJAA==", + "license": "Apache-2.0", + "dependencies": { + "@supercharge/promise-pool": "1.7.0", + "axios": "1.6.8", + "colors": "1.4.0", + "debug": "4.3.4", + "json-colorizer": "2.2.2", + "slash": "3.0.0" + }, + "engines": { + "node": ">=16", + "npm": ">=8" + } + }, "node_modules/@accordproject/concerto-cto": { + "version": "3.18.1", "resolved": "https://registry.npmjs.org/@accordproject/concerto-cto/-/concerto-cto-3.18.1.tgz", "integrity": "sha512-TqX5C5ZeOjlr3b9ErGVwO3TzkPtKxi+rho5KxcWNVxyWwucUSM5sRLY1+lJOgvX12L1sNlnmsMu/549V//NoSw==", diff --git a/package.json b/package.json index a850791d..aae42367 100644 --- a/package.json +++ b/package.json @@ -70,7 +70,8 @@ "webpack-cli": "4.9.1" }, "dependencies": { - "@accordproject/concerto-core": "3.18.1", + + "@accordproject/concerto-core": "3.19.0", "@accordproject/concerto-util": "3.18.1", "@accordproject/concerto-vocabulary": "3.18.1", "@openapi-contrib/openapi-schema-to-json-schema": "5.1.0", diff --git a/test/codegen/codegen.js b/test/codegen/codegen.js index b80204d2..2aaf4c9e 100644 --- a/test/codegen/codegen.js +++ b/test/codegen/codegen.js @@ -31,6 +31,7 @@ describe('codegen', function () { before(function() { process.env.ENABLE_MAP_TYPE = 'true'; // TODO Remove on release of MapType + process.env.IMPORT_ALIASING = 'true'; }); beforeEach(function() { diff --git a/test/codegen/fromcto/csharp/csharpvisitor.js b/test/codegen/fromcto/csharp/csharpvisitor.js index 1e9640e6..01c475e5 100644 --- a/test/codegen/fromcto/csharp/csharpvisitor.js +++ b/test/codegen/fromcto/csharp/csharpvisitor.js @@ -785,6 +785,65 @@ public class SampleModel : Concept { file1.should.match(/public System.Guid otherThingId/); file1.should.match(/public string someOtherThingId/); }); + + it('should handle imported field which is aliased in a concept', () => { + const modelManager = new ModelManager({ importAliasing: true }); + modelManager.addCTOModel(` + namespace org.example.basic + concept file{ + o String name + } + `); + modelManager.addCTOModel(` + namespace org.example.complex + import org.example.basic.{file as f} + + concept folder { + o String name + o f[] files + } + `); + csharpVisitor.visit(modelManager, { fileWriter }); + const files = fileWriter.getFilesInMemory(); + const file1 = files.get('org.example.basic.cs'); + file1.should.match(/namespace org.example.basic;/); + file1.should.match(/class file : Concept/); + file1.should.match(/public string name { get; set; }/); + + const file2 = files.get('org.example.complex.cs'); + file2.should.match(/namespace org.example.complex;/); + file2.should.match(/using org.example.basic;/); + file2.should.match(/class folder : Concept/); + file2.should.match(/org.example.basic.file\[\] files/); + }); + + it('should handle imported field which extended in concept', () => { + const modelManager = new ModelManager({ importAliasing: true }); + modelManager.addCTOModel(` + namespace org.example.basic + concept file{ + o String name + } + `); + modelManager.addCTOModel(` + namespace org.example.complex + import org.example.basic.{file as f} + + concept bigFile extends f{ + } + `); + csharpVisitor.visit(modelManager, { fileWriter }); + const files = fileWriter.getFilesInMemory(); + const file1 = files.get('org.example.basic.cs'); + file1.should.match(/namespace org.example.basic;/); + file1.should.match(/class file : Concept/); + file1.should.match(/public string name { get; set; }/); + + const file2 = files.get('org.example.complex.cs'); + file2.should.match(/namespace org.example.complex;/); + file2.should.match(/using org.example.basic;/); + file2.should.match(/public class bigFile : org.example.basic.file/); + }); }); describe('visit', () => { diff --git a/test/codegen/fromcto/java/javavisitor.js b/test/codegen/fromcto/java/javavisitor.js index 7ed6f004..375ab986 100644 --- a/test/codegen/fromcto/java/javavisitor.js +++ b/test/codegen/fromcto/java/javavisitor.js @@ -467,9 +467,10 @@ describe('JavaVisitor', function () { const mockField = sinon.createStubInstance(Field); const getType = sinon.stub(); + const isImportedType = sinon.stub(); mockField.ast = { type: { name: 'Dummy Value'} }; - mockField.getModelFile.returns({ getType: getType }); + mockField.getModelFile.returns({ getType: getType, isImportedType: isImportedType }); const mockMapDeclaration = sinon.createStubInstance(MapDeclaration); const getKeyType = sinon.stub(); @@ -481,6 +482,7 @@ describe('JavaVisitor', function () { getType.returns(mockMapDeclaration); getKeyType.returns('String'); getValueType.returns('String'); + isImportedType.returns(false); mockField.getName.returns('Map1'); mockMapDeclaration.getName.returns('Map1'); mockMapDeclaration.isMapDeclaration.returns(true); @@ -582,6 +584,26 @@ describe('JavaVisitor', function () { param.fileWriter.writeLine.getCall(1).args.should.deep.equal([2, 'return this.Bob;']); param.fileWriter.writeLine.getCall(2).args.should.deep.equal([1, '}']); }); + + it('should write a line getting a field of type aliased import', () => { + // Document aliased as Doc + let mockField = sinon.createStubInstance(Field); + let mockModelFile = sinon.createStubInstance(ModelFile); + + mockField.isField.returns(true); + mockField.isArray.returns(false); + mockField.getName.returns('Bob'); + mockField.getType.returns('Doc'); + mockField.getModelFile.returns(mockModelFile); + mockModelFile.isImportedType.returns(true); + mockModelFile.getImportedType.returns('Document'); + + javaVisit.visitField(mockField, Object.assign({}, param, { mode: 'getter' })); + param.fileWriter.writeLine.callCount.should.deep.equal(3); + param.fileWriter.writeLine.getCall(0).args.should.deep.equal([1, 'public Document getBob() {']); + param.fileWriter.writeLine.getCall(1).args.should.deep.equal([2, 'return this.Bob;']); + param.fileWriter.writeLine.getCall(2).args.should.deep.equal([1, '}']); + }); }); describe('visitEnumValueDeclaration', () => {