Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 28 additions & 7 deletions lib/codegen/fromcto/golang/golangvisitor.js
Original file line number Diff line number Diff line change
Expand Up @@ -170,31 +170,33 @@ class GoLangVisitor {
array = '[]';
}

// we export all fields by capitalizing them
// we strip $ as it is not legal in Go
const name = field.getName().startsWith('$') ? field.getName().substring(1) : field.getName();
const fieldName = ModelUtil.capitalizeFirstLetter(name);

if(ModelUtil.isMap(field)) {
const mapDeclaration = field.getModelFile().getType(field.getType());
let mapKeyType = mapDeclaration.getKey().getType();
let mapValueType = mapDeclaration.getValue().getType();

if (mapDeclaration.getModelFile().getType(mapKeyType).isScalarDeclaration?.()) {
if (mapDeclaration.getModelFile().getType(mapKeyType)?.isScalarDeclaration?.()) {
mapKeyType = mapDeclaration.getModelFile().getType(mapKeyType).getType();
}

const goKeyType = this.toGoType(mapKeyType);

if (mapDeclaration.getModelFile().getType(mapValueType).isScalarDeclaration?.()) {
if (mapDeclaration.getModelFile().getType(mapValueType)?.isScalarDeclaration?.()) {
mapValueType = mapDeclaration.getModelFile().getType(mapValueType).getType();
}

const goValueType = this.toGoType(mapValueType);

parameters.fileWriter.writeLine(1, `${field.getName()} := make(map[${goKeyType}]${goValueType})` + ' `json:"' + field.getName() + '"`');
parameters.fileWriter.writeLine(1, `${fieldName} map[${goKeyType}]${goValueType}` + ' `json:"' + field.getName() + '"`');
return null;
}

// we export all fields by capitalizing them
// we strip $ as it is not legal in Go
const name = field.getName().startsWith('$') ? field.getName().substring(1) : field.getName();
parameters.fileWriter.writeLine(1, ModelUtil.capitalizeFirstLetter(name) + ' ' + array + this.toGoType(field.getType()) + ' `json:"' + field.getName() + '"`' );
parameters.fileWriter.writeLine(1, fieldName + ' ' + array + this.toGoType(field.getType()) + ' `json:"' + field.getName() + '"`' );
return null;
}

Expand Down Expand Up @@ -264,6 +266,25 @@ class GoLangVisitor {
if(field.getType() === 'DateTime') {
return true;
}
if(typeof field.getParent === 'function' && ModelUtil.isMap(field)) {
Comment thread
chaitijain593-prog marked this conversation as resolved.
Resolved
const mapDeclaration = field.getModelFile().getType(field.getType());
if (mapDeclaration) {
let mapKeyType = mapDeclaration.getKey().getType();
let mapValueType = mapDeclaration.getValue().getType();

if (mapDeclaration.getModelFile().getType(mapKeyType)?.isScalarDeclaration?.()) {
mapKeyType = mapDeclaration.getModelFile().getType(mapKeyType).getType();
}

if (mapDeclaration.getModelFile().getType(mapValueType)?.isScalarDeclaration?.()) {
mapValueType = mapDeclaration.getModelFile().getType(mapValueType).getType();
}

if (mapKeyType === 'DateTime' || mapValueType === 'DateTime') {
return true;
}
}
}
}
}
return false;
Expand Down
12 changes: 6 additions & 6 deletions test/codegen/__snapshots__/codegen.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -1059,11 +1059,11 @@ type Company struct {
concerto_1_0_0.Concept
Name string \`json:"name"\`
Headquarters Address \`json:"headquarters"\`
companyProperties := make(map[string]string) \`json:"companyProperties"\`
employeeDirectory := make(map[string]Employee) \`json:"employeeDirectory"\`
employeeTShirtSizes := make(map[string]TShirtSizeType) \`json:"employeeTShirtSizes"\`
employeeProfiles := make(map[string]Concept) \`json:"employeeProfiles"\`
employeeSocialSecurityNumbers := make(map[string]string) \`json:"employeeSocialSecurityNumbers"\`
CompanyProperties map[string]string \`json:"companyProperties"\`
EmployeeDirectory map[string]Employee \`json:"employeeDirectory"\`
EmployeeTShirtSizes map[string]TShirtSizeType \`json:"employeeTShirtSizes"\`
EmployeeProfiles map[string]Concept \`json:"employeeProfiles"\`
EmployeeSocialSecurityNumbers map[string]string \`json:"employeeSocialSecurityNumbers"\`
}
type Department int
const (
Expand Down Expand Up @@ -1097,7 +1097,7 @@ type Person struct {
Ssn string \`json:"ssn"\`
Height float64 \`json:"height"\`
Dob time.Time \`json:"dob"\`
nextOfKin := make(map[string]string) \`json:"nextOfKin"\`
NextOfKin map[string]string \`json:"nextOfKin"\`
}
type Employee struct {
Person
Expand Down
99 changes: 98 additions & 1 deletion test/codegen/fromcto/golang/golangvisitor.js
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,39 @@ describe('GoLangVisitor', function () {

goVisit.visitField(mockField,param);

param.fileWriter.writeLine.withArgs(1, 'dictionary := make(map[string]string) `json:"dictionary"`').calledOnce.should.be.ok;
param.fileWriter.writeLine.withArgs(1, 'Dictionary map[string]string `json:"dictionary"`').calledOnce.should.be.ok;
Comment thread
chaitijain593-prog marked this conversation as resolved.
Resolved
});

it('should handle map field when getType returns null for external or primitive types', () => {
let param = {
fileWriter: mockFileWriter,
};

sandbox.restore();
sandbox.stub(ModelUtil, 'isMap').callsFake(() => {
return true;
});

const mockField = sinon.createStubInstance(Field);
const mockMapDeclaration = sinon.createStubInstance(MapDeclaration);

mockField.getType.returns('Map1');
mockField.getName.returns('properties');
mockField.getModelFile.returns({
getType: sinon.stub().returns(mockMapDeclaration),
});

mockMapDeclaration.getName.returns('Map1');
mockMapDeclaration.getKey.returns({ getType: () => 'String' });
mockMapDeclaration.getValue.returns({ getType: () => 'ExternalType' });
// getType returns null (e.g. cross-namespace or unresolved type)
mockMapDeclaration.getModelFile.returns({
getType: sinon.stub().returns(null),
});

goVisit.visitField(mockField, param);

param.fileWriter.writeLine.withArgs(1, 'Properties map[string]ExternalType `json:"properties"`').calledOnce.should.be.ok;
});

});
Expand Down Expand Up @@ -477,6 +509,71 @@ describe('GoLangVisitor', function () {

goVisit.containsDateTimeField(mockModelFileDefinition).should.deep.equal(false);
});

it('should return true if the model file contains a map field with DateTime value', () => {
const mm = new ModelManager();
const modelFile = mm.addCTOModel(`
namespace org.acme@1.0.0
map TimestampMap {
o String
o DateTime
}
concept EventLog {
o TimestampMap timestamps
}
`);
goVisit.containsDateTimeField(modelFile).should.be.true;
});

it('should return true if the model file contains a map field with a scalar extending DateTime', () => {
const mm = new ModelManager();
const modelFile = mm.addCTOModel(`
namespace org.acme@1.0.0
scalar EventTime extends DateTime
map EventMap {
o String
o EventTime
}
concept LogEntry {
o EventMap events
}
`);
goVisit.containsDateTimeField(modelFile).should.be.true;
});

it('should return false if the model file contains a map field without DateTime', () => {
const mm = new ModelManager();
const modelFile = mm.addCTOModel(`
namespace org.acme@1.0.0
map StringMap {
o String
o String
}
concept LogEntry {
o StringMap items
}
`);
goVisit.containsDateTimeField(modelFile).should.be.false;
});

it('should write import "time" when the only DateTime in the model is in a map field', () => {
const mm = new ModelManager();
const modelFile = mm.addCTOModel(`
namespace org.acme@1.0.0
map TimestampMap {
o String
o DateTime
}
concept EventLog {
o TimestampMap timestamps
}
`);
let param = {
fileWriter: mockFileWriter,
};
goVisit.visitModelFile(modelFile, param);
param.fileWriter.writeLine.withArgs(0, 'import "time"').calledOnce.should.be.ok;
});
});

describe('toGoType', () => {
Expand Down