diff --git a/lib/codegen/fromcto/csharp/csharpvisitor.js b/lib/codegen/fromcto/csharp/csharpvisitor.js index 10f40d72..ce5e351d 100644 --- a/lib/codegen/fromcto/csharp/csharpvisitor.js +++ b/lib/codegen/fromcto/csharp/csharpvisitor.js @@ -1,3 +1,4 @@ +/* eslint-disable no-unreachable */ /* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -312,11 +313,40 @@ class CSharpVisitor { * @private */ writeField(field, parameters, externalFieldType, isOptional = false) { - // write Map field - if (Object.keys(field).length > 0 && ModelUtil.isMap?.(field)) { - const decl = field.getModelFile().getType(field.getType()); - parameters.fileWriter.writeLine(1, `public Dictionary ${field.getName()} { get; set; }`); + if (ModelUtil.isMap?.(field)) { + const mapDeclaration = field.getModelFile().getType(field.getType()); + const mapKeyType = mapDeclaration.getKey().getType(); + const mapValueType = mapDeclaration.getValue().getType(); + + let keyType; + let valueType; + + // Map Key + if (ModelUtil.isPrimitiveType(mapKeyType)) { + keyType = this.toCSharpType(mapKeyType); + } + else if (ModelUtil.isScalar(mapDeclaration.getKey())) { + const scalarDeclaration = mapDeclaration.getModelFile().getType(mapDeclaration.getKey().getType()); + const keyFQN = ModelUtil.removeNamespaceVersionFromFullyQualifiedName(scalarDeclaration.getFullyQualifiedName()); + const scalarType = keyFQN === 'concerto.scalar.UUID' ? keyFQN : scalarDeclaration.getType(); + keyType = this.toCSharpType(scalarType); + } + + // Map Value + if (ModelUtil.isPrimitiveType(mapValueType)) { + valueType = this.toCSharpType(mapValueType); + } + else if (ModelUtil.isScalar(mapDeclaration.getValue())) { + const scalarDeclaration = mapDeclaration.getModelFile().getType(mapDeclaration.getValue().getType()); + const keyFQN = ModelUtil.removeNamespaceVersionFromFullyQualifiedName(scalarDeclaration.getFullyQualifiedName()); + const scalarType = keyFQN === 'concerto.scalar.UUID' ? keyFQN : scalarDeclaration.getType(); + valueType = this.toCSharpType(scalarType); + } else { + valueType = mapValueType; + } + + parameters.fileWriter.writeLine(1, `public Dictionary<${keyType}, ${valueType}> ${field.getName()} { get; set; }`); return null; } diff --git a/test/codegen/__snapshots__/codegen.js.snap b/test/codegen/__snapshots__/codegen.js.snap index 7bf8e183..4ead9dc6 100644 --- a/test/codegen/__snapshots__/codegen.js.snap +++ b/test/codegen/__snapshots__/codegen.js.snap @@ -382,7 +382,7 @@ public class Company : Concept { public Dictionary employeeDirectory { get; set; } public Dictionary employeeTShirtSizes { get; set; } public Dictionary employeeProfiles { get; set; } - public Dictionary employeeSocialSecurityNumbers { get; set; } + public Dictionary employeeSocialSecurityNumbers { get; set; } } [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))] public enum Department { @@ -428,7 +428,7 @@ public abstract class Person : Participant { public string ssn { get; set; } public float height { get; set; } public System.DateTime dob { get; set; } - public Dictionary nextOfKin { get; set; } + public Dictionary nextOfKin { get; set; } } [AccordProject.Concerto.Type(Namespace = "org.acme.hr", Version = null, Name = "Employee")] [System.Text.Json.Serialization.JsonConverter(typeof(AccordProject.Concerto.ConcertoConverterFactorySystem))] @@ -5932,7 +5932,7 @@ public class Company : Concept { public Dictionary employeeDirectory { get; set; } public Dictionary employeeTShirtSizes { get; set; } public Dictionary employeeProfiles { get; set; } - public Dictionary employeeSocialSecurityNumbers { get; set; } + public Dictionary employeeSocialSecurityNumbers { get; set; } } [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))] public enum Department { @@ -5978,7 +5978,7 @@ public abstract class Person : Participant { public string ssn { get; set; } public float height { get; set; } public System.DateTime dob { get; set; } - public Dictionary nextOfKin { get; set; } + public Dictionary nextOfKin { get; set; } } [AccordProject.Concerto.Type(Namespace = "org.acme.hr", Version = "1.0.0", Name = "Employee")] [System.Text.Json.Serialization.JsonConverter(typeof(AccordProject.Concerto.ConcertoConverterFactorySystem))] diff --git a/test/codegen/fromcto/csharp/csharpvisitor.js b/test/codegen/fromcto/csharp/csharpvisitor.js index 28c5af63..1e9640e6 100644 --- a/test/codegen/fromcto/csharp/csharpvisitor.js +++ b/test/codegen/fromcto/csharp/csharpvisitor.js @@ -1445,7 +1445,7 @@ public class SampleModel : Concept { }; sandbox.restore(); sandbox.stub(ModelUtil, 'isMap').callsFake(() => { - return true; + return false; }); }); @@ -1509,6 +1509,11 @@ public class SampleModel : Concept { mockField.dummy = 'Dummy Value'; mockField.getModelFile.returns({ getType: getType }); + sandbox.restore(); + sandbox.stub(ModelUtil, 'isMap').callsFake(() => { + return true; + }); + const mockMapDeclaration = sinon.createStubInstance(MapDeclaration); const getKeyType = sinon.stub(); const getValueType = sinon.stub(); @@ -1533,11 +1538,22 @@ public class SampleModel : Concept { mockField.dummy = 'Dummy Value'; mockField.getModelFile.returns({ getType: getType }); + sandbox.restore(); + sandbox.stub(ModelUtil, 'isMap').callsFake(() => { + return true; + }); + sandbox.stub(ModelUtil, 'isScalar').callsFake(() => { + return false; + }); let mockMapDeclaration = sinon.createStubInstance(MapDeclaration); + let modelFile = sinon.createStubInstance(ModelFile); const getKeyType = sinon.stub(); const getValueType = sinon.stub(); + mockField.getModelFile.returns(modelFile); + modelFile.getType.returns(mockMapDeclaration); + getType.returns(mockMapDeclaration); getKeyType.returns('String'); getValueType.returns('Concept'); @@ -1558,6 +1574,40 @@ public class SampleModel : Concept { mockField.dummy = 'Dummy Value'; mockField.getModelFile.returns({ getType: getType }); + sandbox.restore(); + sandbox.stub(ModelUtil, 'isMap').callsFake(() => { + return true; + }); + + let mockMapDeclaration = sinon.createStubInstance(MapDeclaration); + const getKeyType = sinon.stub(); + const getValueType = sinon.stub(); + + getType.returns(mockMapDeclaration); + getKeyType.returns('String'); + getValueType.returns('DateTime'); + mockField.getName.returns('Map1'); + mockMapDeclaration.getName.returns('Map1'); + mockMapDeclaration.isMapDeclaration.returns(true); + mockMapDeclaration.getKey.returns({ getType: getKeyType }); + mockMapDeclaration.getValue.returns({ getType: getValueType }); + + csharpVisitor.visitField(mockField, param); + param.fileWriter.writeLine.withArgs(1, 'public Dictionary Map1 { get; set; }').calledOnce.should.be.ok; + }); + + it('should write a line for field name and type thats a map of ', () => { + const mockField = sinon.createStubInstance(Field); + const getType = sinon.stub(); + + mockField.dummy = 'Dummy Value'; + mockField.getModelFile.returns({ getType: getType }); + + sandbox.restore(); + sandbox.stub(ModelUtil, 'isMap').callsFake(() => { + return true; + }); + let mockMapDeclaration = sinon.createStubInstance(MapDeclaration); const getKeyType = sinon.stub(); const getValueType = sinon.stub(); diff --git a/types/lib/codegen/fromcto/golang/golangvisitor.d.ts b/types/lib/codegen/fromcto/golang/golangvisitor.d.ts index 5f350707..f8588223 100644 --- a/types/lib/codegen/fromcto/golang/golangvisitor.d.ts +++ b/types/lib/codegen/fromcto/golang/golangvisitor.d.ts @@ -99,11 +99,4 @@ declare class GoLangVisitor { * @private */ private toGoPackageName; - /** - * Check if field is a Map Declaration - * @param {Field} field - the field being visited - * @return {boolean} true if field is a Map Declaration - * @private - */ - private isMap; }