Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: rewrite csharp generator tests #807

Merged
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ exports[`Should be able to render auto-implemented properties in CSharp and shou
Array [
"public class Root
{
public string[] Emails { get; set; }
public string StringProp { get; set; }
public dynamic[]? Emails { get; set; }
public string? StringProp { get; set; }
public double? NumberProp { get; set; }
}",
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ exports[`Should be able to render collections in C# as IEnumerable and should lo
Array [
"public class Root
{
private IEnumerable<string> email;
private IEnumerable<dynamic> email;

public IEnumerable<string> Email
public IEnumerable<dynamic> Email
{
get { return email; }
set { email = value; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Array [
"public class Root
{
private bool requiredBoolean;
private bool? notRequiredBoolean;
private bool notRequiredBoolean;
private string requiredString;
private string notRequiredString;

Expand All @@ -15,7 +15,7 @@ Array [
set { requiredBoolean = value; }
}

public bool? NotRequiredBoolean
public bool NotRequiredBoolean
{
get { return notRequiredBoolean; }
set { notRequiredBoolean = value; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,11 @@ internal class RootConverter : JsonConverter<Root>

string propertyName = reader.GetString();
if (propertyName == \\"email\\")
{
var value = JsonSerializer.Deserialize<string>(ref reader, options);
instance.Email = value;
continue;
}




{
var value = JsonSerializer.Deserialize<string>(ref reader, options);
instance.email = value;
continue;
}
}

throw new JsonException();
Expand All @@ -69,17 +65,13 @@ internal class RootConverter : JsonConverter<Root>

writer.WriteStartObject();

if(value.Email != null) {
if(value.email != null) {
// write property name and let the serializer serialize the value itself
writer.WritePropertyName(\\"email\\");
JsonSerializer.Serialize(writer, value.Email, options);
JsonSerializer.Serialize(writer, value.email, options);
}






writer.WriteEndObject();
}

Expand Down
69 changes: 51 additions & 18 deletions examples/generate-go-enums/__snapshots__/index.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,70 @@

exports[`Should be able to render Go Enums and should log expected output to console 1`] = `
Array [
"// Cities represents an enum of string.
type Cities string

const (
CitiesLondon Cities = \\"London\\"
CitiesRome = \\"Rome\\"
CitiesBrussels = \\"Brussels\\"
)",
"// Root represents a Root model.
type Root struct {
Cities *Cities
Options *Options
}",
]
`;

exports[`Should be able to render Go Enums and should log expected output to console 2`] = `
Array [
"// ClickOptions represents an enum of string.
type ClickOptions string
"// Cities represents an enum of Cities.
type Cities uint

const (
ClickOptionsClickAndPlay ClickOptions = \\"click_and_play\\"
ClickOptionsClickPay = \\"click&pay\\"
)",
CitiesLondon Cities = iota
CitiesRome
CitiesBrussels
)

// Value returns the value of the enum.
func (op Cities) Value() any {
if op >= Cities(len(CitiesValues)) {
return nil
}
return CitiesValues[op]
}

var CitiesValues = []any{\\"London\\",\\"Rome\\",\\"Brussels\\"}
var ValuesToCities = map[any]Cities{
CitiesValues[CitiesLondon]: CitiesLondon,
CitiesValues[CitiesRome]: CitiesRome,
CitiesValues[CitiesBrussels]: CitiesBrussels,
}
",
]
`;

exports[`Should be able to render Go Enums and should log expected output to console 3`] = `
Array [
"// Options represents an enum of int.
type Options int
"// Options represents an enum of Options.
type Options uint

const (
OptionsFirstOption Options = iota
OptionsSecondOption
)",
OptionsNumber_123 Options = iota
OptionsNumber_213
OptionsTrue
OptionsRun
)

// Value returns the value of the enum.
func (op Options) Value() any {
if op >= Options(len(OptionsValues)) {
return nil
}
return OptionsValues[op]
}

var OptionsValues = []any{123,213,true,\\"Run\\"}
var ValuesToOptions = map[any]Options{
OptionsValues[OptionsNumber_123]: OptionsNumber_123,
OptionsValues[OptionsNumber_213]: OptionsNumber_213,
OptionsValues[OptionsTrue]: OptionsTrue,
OptionsValues[OptionsRun]: OptionsRun,
}
",
]
`;
6 changes: 3 additions & 3 deletions examples/generate-go-enums/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ describe('Should be able to render Go Enums', () => {
});
test('and should log expected output to console', async () => {
await generate();
//Generate is called 2x, so even though we expect 4 model (root and three different enums type), we double it
expect(spy.mock.calls.length).toEqual(8);
//Generate is called 2x, so even though we expect 3 model (root and three different enums type), we double it
expect(spy.mock.calls.length).toEqual(6);
expect(spy.mock.calls[0]).toMatchSnapshot();
expect(spy.mock.calls[1]).toMatchSnapshot();
expect(spy.mock.calls[2]).toMatchSnapshot();
expect(spy.mock.calls[3]).toMatchSnapshot();
});
});
9 changes: 2 additions & 7 deletions examples/generate-go-enums/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,10 @@ const jsonSchemaDraft7 = {
type: 'string',
enum: ['London', 'Rome', 'Brussels'],
},
click_options: {
$id: 'click_options',
type: 'string',
enum: ['click_and_play', 'click&pay'],
},
options: {
$id: 'options',
type: 'integer',
enum: ['first_option', 'second_option'],
type: ['integer', 'boolean', 'string'],
enum: [123, 213, true, 'Run'],
},
}
};
Expand Down
2 changes: 1 addition & 1 deletion src/generators/csharp/CSharpConstrainer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const CSharpDefaultTypeMapping: TypeMapping<CSharpOptions> = {
return 'dynamic';
},
Float (): string {
return 'float';
return 'double';
},
Integer (): string {
return 'int';
Expand Down
4 changes: 2 additions & 2 deletions src/generators/csharp/CSharpPreset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ export interface CsharpClassPreset<O> extends ClassPreset<ClassRenderer, O> {
export type ClassPresetType<O> = CsharpClassPreset<O>;
export type EnumPresetType<O> = EnumPreset<EnumRenderer, O>;

export type CSharpPreset<O = CSharpOptions> = Preset<{
export type CSharpPreset<O = any> = Preset<{
class: CsharpClassPreset<O>;
enum: EnumPreset<EnumRenderer, O>
}>;

export const CSHARP_DEFAULT_PRESET: CSharpPreset = {
export const CSHARP_DEFAULT_PRESET: CSharpPreset<CSharpOptions> = {
class: CSHARP_DEFAULT_CLASS_PRESET,
enum: CSHARP_DEFAULT_ENUM_PRESET,
};
10 changes: 6 additions & 4 deletions src/generators/csharp/constrainer/EnumConstrainer.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/no-non-null-assertion */
import { ConstrainedEnumModel, EnumModel } from '../../../models';
import { NO_NUMBER_START_CHAR, NO_DUPLICATE_ENUM_KEYS, NO_EMPTY_VALUE, NO_RESERVED_KEYWORDS} from '../../../helpers/Constraints';
import { EnumKeyConstraint, EnumValueConstraint, FormatHelpers } from '../../../helpers';
Expand Down Expand Up @@ -36,20 +35,23 @@ export function defaultEnumKeyConstraints(customConstraints?: Partial<ModelEnumK
constrainedEnumKey = constraints.NO_NUMBER_START_CHAR(constrainedEnumKey);
constrainedEnumKey = constraints.NO_EMPTY_VALUE(constrainedEnumKey);
constrainedEnumKey = constraints.NO_RESERVED_KEYWORDS(constrainedEnumKey);
//If the enum key has been manipulated, lets make sure it don't clash with existing keys
if (constrainedEnumKey !== enumKey) {
constrainedEnumKey = constraints.NO_DUPLICATE_KEYS(constrainedEnumModel, enumModel, constrainedEnumKey, constraints.NAMING_FORMATTER);
}
constrainedEnumKey = constraints.NAMING_FORMATTER(constrainedEnumKey);
constrainedEnumKey = constraints.NO_DUPLICATE_KEYS(constrainedEnumModel, enumModel, constrainedEnumKey, constraints.NAMING_FORMATTER!);
return constrainedEnumKey;
};
}

export function defaultEnumValueConstraints(): EnumValueConstraint {
return ({enumValue}) => {
let normalizedEnumValue;
switch (typeof enumValue.value) {
switch (typeof enumValue) {
case 'boolean':
case 'bigint':
case 'number': {
normalizedEnumValue = enumValue.value;
normalizedEnumValue = enumValue;
break;
}
case 'object': {
Expand Down
7 changes: 5 additions & 2 deletions src/generators/csharp/constrainer/PropertyKeyConstrainer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export const DefaultPropertyKeyConstraints: PropertyKeyConstraintOptions = {
NO_NUMBER_START_CHAR,
NO_DUPLICATE_PROPERTIES,
NO_EMPTY_VALUE,
NAMING_FORMATTER: FormatHelpers.toPascalCase,
NAMING_FORMATTER: FormatHelpers.toCamelCase,
NO_RESERVED_KEYWORDS: (value: string) => {
return NO_RESERVED_KEYWORDS(value, isReservedCSharpKeyword);
}
Expand All @@ -37,8 +37,11 @@ export function defaultPropertyKeyConstraints(customConstraints?: Partial<Proper
constrainedPropertyKey = constraints.NO_NUMBER_START_CHAR(constrainedPropertyKey);
constrainedPropertyKey = constraints.NO_EMPTY_VALUE(constrainedPropertyKey);
constrainedPropertyKey = constraints.NO_RESERVED_KEYWORDS(constrainedPropertyKey);
//If the property name has been manipulated, lets make sure it don't clash with existing properties
if (constrainedPropertyKey !== objectPropertyModel.propertyName) {
constrainedPropertyKey = constraints.NO_DUPLICATE_PROPERTIES(constrainedObjectModel, objectModel, constrainedPropertyKey, constraints.NAMING_FORMATTER);
}
constrainedPropertyKey = constraints.NAMING_FORMATTER(constrainedPropertyKey);
constrainedPropertyKey = constraints.NO_DUPLICATE_PROPERTIES(constrainedObjectModel, objectModel, constrainedPropertyKey, constraints.NAMING_FORMATTER);
return constrainedPropertyKey;
};
}
4 changes: 3 additions & 1 deletion src/generators/csharp/presets/CommonPreset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,9 @@ export const CSHARP_COMMON_PRESET: CSharpPreset<CSharpCommonPresetOptions> = {
options = options || {};
const blocks: string[] = [];

if (options.equal === undefined || options.equal === true) { blocks.push(renderEqual({ renderer, model })); }
if (options.equal === undefined || options.equal === true) {
blocks.push(renderEqual({ renderer, model }));
}
if (options.hash === undefined || options.hash === true) {
renderer.addDependency('using System;');
blocks.push(renderHashCode({ renderer, model }));
Expand Down
3 changes: 2 additions & 1 deletion src/generators/csharp/presets/JsonSerializerPreset.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { CSharpRenderer } from '../CSharpRenderer';
import { CSharpPreset } from '../CSharpPreset';
import { ConstrainedDictionaryModel, ConstrainedEnumModel, ConstrainedObjectModel, ConstrainedObjectPropertyModel, ConstrainedReferenceModel } from '../../../models';
import { CSharpOptions } from '../CSharpGenerator';

function renderSerializeProperty(modelInstanceVariable: string, model: ConstrainedObjectPropertyModel) {
let value = modelInstanceVariable;
Expand Down Expand Up @@ -156,7 +157,7 @@ ${renderer.indent(deserializeProperties, 4)}
*
* @implements {CSharpPreset}
*/
export const CSHARP_JSON_SERIALIZER_PRESET: CSharpPreset = {
export const CSHARP_JSON_SERIALIZER_PRESET: CSharpPreset<CSharpOptions> = {
class: {
self({ renderer, model, content}) {
renderer.addDependency('using System.Text.Json;');
Expand Down
12 changes: 6 additions & 6 deletions src/generators/csharp/renderers/ClassRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,19 +57,19 @@ ${this.indent(this.renderBlock(content, 2))}
}

runAccessorPreset(property: ConstrainedObjectPropertyModel): Promise<string> {
return this.runPreset('accessor', { property });
return this.runPreset('accessor', { property, options: this.options, renderer: this });
}

runPropertyPreset(property: ConstrainedObjectPropertyModel): Promise<string> {
return this.runPreset('property', { property });
return this.runPreset('property', { property, options: this.options, renderer: this });
}

runGetterPreset(property: ConstrainedObjectPropertyModel): Promise<string> {
return this.runPreset('getter', { property });
return this.runPreset('getter', { property, options: this.options, renderer: this });
}

runSetterPreset(property: ConstrainedObjectPropertyModel): Promise<string> {
return this.runPreset('setter', { property });
return this.runPreset('setter', { property, options: this.options, renderer: this });
}
}

Expand All @@ -78,10 +78,10 @@ export const CSHARP_DEFAULT_CLASS_PRESET: CsharpClassPreset<CSharpOptions> = {
return renderer.defaultSelf();
},
async property({ renderer, property, options }) {
if (options.autoImplementedProperties) {
if (options?.autoImplementedProperties) {
const getter = await renderer.runGetterPreset(property);
const setter = await renderer.runSetterPreset(property);
return `public ${property.property.type} ${pascalCase(property.propertyName)} { ${getter} ${setter} }`;
return `public ${property.property.type}${property.required === false && '?'} ${pascalCase(property.propertyName)} { ${getter} ${setter} }`;
}
return `private ${property.property.type} ${property.propertyName};`;
},
Expand Down
10 changes: 5 additions & 5 deletions src/generators/go/GoConstrainer.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { TypeMapping } from '../../helpers';
import { Constraints, TypeMapping } from '../../helpers';
import { defaultEnumKeyConstraints, defaultEnumValueConstraints } from './constrainer/EnumConstrainer';
import { defaultModelNameConstraints } from './constrainer/ModelNameConstrainer';
import { defaultPropertyKeyConstraints } from './constrainer/PropertyKeyConstrainer';
Expand All @@ -9,7 +9,7 @@ export const GoDefaultTypeMapping: TypeMapping<GoOptions> = {
return constrainedModel.name;
},
Reference ({constrainedModel}): string {
return constrainedModel.name;
return `${constrainedModel.name}`;
},
Any (): string {
return 'interface{}';
Expand All @@ -27,7 +27,7 @@ export const GoDefaultTypeMapping: TypeMapping<GoOptions> = {
return 'bool';
},
Tuple (): string {
//Because Java have no notion of tuples (and no custom implementation), we have to render it as a list of any value.
//Because Go have no notion of tuples (and no custom implementation), we have to render it as a list of any value.
return '[]interface{}';
},
Array ({constrainedModel}): string {
Expand All @@ -37,15 +37,15 @@ export const GoDefaultTypeMapping: TypeMapping<GoOptions> = {
return constrainedModel.name;
},
Union (): string {
//Because Java have no notion of unions (and no custom implementation), we have to render it as any value.
//Because Go have no notion of unions (and no custom implementation), we have to render it as any value.
return 'interface{}';
},
Dictionary ({constrainedModel}): string {
return `map[${constrainedModel.key.type}]${constrainedModel.value.type}`;
}
};

export const GoDefaultConstraints = {
export const GoDefaultConstraints: Constraints = {
enumKey: defaultEnumKeyConstraints(),
enumValue: defaultEnumValueConstraints(),
modelName: defaultModelNameConstraints(),
Expand Down
Loading