Skip to content

Commit f7fd30c

Browse files
committed
feat: add case modifiers to the generator settings
Refs: #15
1 parent d1ae077 commit f7fd30c

File tree

7 files changed

+133
-24
lines changed

7 files changed

+133
-24
lines changed

packages/dogs_generator/lib/analyze/structurize.dart

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ import 'package:dogs_generator/dogs_generator.dart';
2323
import 'package:lyell_gen/lyell_gen.dart';
2424
import 'package:source_gen/source_gen.dart';
2525

26+
import '../settings.dart';
27+
2628
class IRStructure {
2729
String type;
2830
StructureConformity conformity;
@@ -104,13 +106,15 @@ TypeChecker enumPropertyChecker = TypeChecker.fromRuntime(EnumProperty);
104106

105107
Future<StructurizeResult> structurizeConstructor(
106108
DartType type,
109+
DogsGeneratorSettings settings,
107110
ConstructorElement constructorElement,
108111
SubjectGenContext<Element> context,
109112
CachedAliasCounter counter) async {
110113
List<AliasImport> imports = [];
111114
List<IRStructureField> fields = [];
112115
var element = type.element! as ClassElement;
113116
var serialName = element.name;
117+
serialName = settings.nameCase.recase(serialName);
114118

115119
// Check for Serializable annotation and override serialName if applicable
116120
if (serializableChecker.hasAnnotationOf(element)) {
@@ -184,6 +188,8 @@ Future<StructurizeResult> structurizeConstructor(
184188
if (fieldType is DynamicType) optional = true;
185189

186190
var propertyName = fieldName;
191+
propertyName = settings.propertyCase.recase(propertyName);
192+
187193
if (propertyNameChecker.hasAnnotationOf(fieldElement)) {
188194
var annotation = propertyNameChecker.annotationsOf(fieldElement).first;
189195
propertyName = annotation.getField("name")!.toStringValue()!;
@@ -233,13 +239,15 @@ Future<StructurizeResult> structurizeConstructor(
233239

234240
Future<StructurizeResult> structurizeBean(
235241
DartType type,
242+
DogsGeneratorSettings settings,
236243
ClassElement classElement,
237244
SubjectGenContext<Element> context,
238245
CachedAliasCounter counter) async {
239246
List<AliasImport> imports = [];
240247
List<IRStructureField> fields = [];
241248
var element = type.element! as ClassElement;
242249
var serialName = element.name;
250+
serialName = settings.nameCase.recase(serialName);
243251

244252
// Check for Serializable annotation and override serialName if applicable
245253
if (serializableChecker.hasAnnotationOf(element)) {
@@ -266,6 +274,8 @@ Future<StructurizeResult> structurizeBean(
266274
if (field.isLate) optional = false;
267275

268276
var propertyName = fieldName;
277+
propertyName = settings.propertyCase.recase(propertyName);
278+
269279
if (propertyNameChecker.hasAnnotationOf(field)) {
270280
var annotation = propertyNameChecker.annotationsOf(field).first;
271281
propertyName = annotation.getField("name")!.toStringValue()!;

packages/dogs_generator/lib/builders/converter_builder.dart

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import 'dart:async';
2+
import 'dart:math';
23

34
import 'package:analyzer/dart/element/element.dart';
45
import 'package:build/build.dart';
56
import 'package:code_builder/code_builder.dart';
67
import 'package:collection/collection.dart';
78
import 'package:dogs_core/dogs_core.dart';
89
import 'package:dogs_generator/dogs_generator.dart';
10+
import 'package:dogs_generator/settings.dart';
911
import 'package:lyell_gen/lyell_gen.dart';
1012
import 'package:source_gen/source_gen.dart';
1113

@@ -23,16 +25,27 @@ class ConverterBuilder extends DogsAdapter<Serializable> {
2325

2426
static Future generateForEnum(
2527
EnumElement element,
28+
DogsGeneratorSettings settings,
2629
SubjectGenContext<Element> genContext,
2730
SubjectCodeContext codeContext) async {
2831
var emitter = DartEmitter();
2932
var converterName = "${element.name}Converter";
3033

34+
String serialName = element.name;
35+
serialName = settings.nameCase.recase(serialName);
36+
37+
var serializableValue = serializableChecker.firstAnnotationOf(element);
38+
if (serializableValue != null) {
39+
var serialNameOverride = serializableValue.getField("serialName")?.toStringValue();
40+
if (serialNameOverride != null) serialName = serialNameOverride;
41+
}
42+
3143
String? fallbackFieldName;
3244
final fieldValueMap =
3345
Map.fromEntries(element.fields.where((e) => e.isEnumConstant).map((e) {
3446
final actual = e.name;
3547
var serializedName = e.name;
48+
serializedName = settings.enumCase.recase(serializedName);
3649

3750
final propertyName = propertyNameChecker.firstAnnotationOf(e);
3851
if (propertyName != null) {
@@ -60,7 +73,7 @@ class ConverterBuilder extends DogsAdapter<Serializable> {
6073

6174
builder.constructors.add(Constructor((builder) => builder
6275
..initializers.add(Code(
63-
"super.structured(serialName: '${codeContext.typeName(element.thisType)}')"))));
76+
"super.structured(serialName: '$serialName')"))));
6477

6578
builder.methods.add(Method((builder) => builder
6679
..name = "values"
@@ -107,6 +120,7 @@ class ConverterBuilder extends DogsAdapter<Serializable> {
107120

108121
static Future generateForClass(
109122
ClassElement element,
123+
DogsGeneratorSettings settings,
110124
SubjectGenContext<Element> genContext,
111125
SubjectCodeContext codeContext) async {
112126
codeContext.additionalImports
@@ -122,12 +136,12 @@ class ConverterBuilder extends DogsAdapter<Serializable> {
122136
if (constructor != null && constructor.parameters.isNotEmpty) {
123137
// Create constructor based serializable
124138
structurized = await structurizeConstructor(
125-
element.thisType, constructor, genContext, codeContext.cachedCounter);
139+
element.thisType, settings, constructor, genContext, codeContext.cachedCounter);
126140
codeContext.additionalImports.addAll(structurized.imports);
127141
} else if (constructor != null) {
128142
// Create bean like property based serializable
129143
structurized = await structurizeBean(
130-
element.thisType, element, genContext, codeContext.cachedCounter);
144+
element.thisType, settings, element, genContext, codeContext.cachedCounter);
131145
codeContext.additionalImports.addAll(structurized.imports);
132146
writeBeanFactory(element, structurized, codeContext);
133147
} else {
@@ -455,12 +469,13 @@ return instance;""")));
455469
codeContext.additionalImports
456470
.add(AliasImport.gen("package:dogs_core/dogs_core.dart"));
457471

472+
var settings = await DogsGeneratorSettings.load(genContext.step);
458473
try {
459474
for (var element in genContext.matches) {
460475
if (element is ClassElement) {
461-
await generateForClass(element, genContext, codeContext);
476+
await generateForClass(element, settings, genContext, codeContext);
462477
} else if (element is EnumElement) {
463-
await generateForEnum(element, genContext, codeContext);
478+
await generateForEnum(element, settings, genContext, codeContext);
464479
}
465480
}
466481
} catch (e, s) {

packages/dogs_generator/lib/builders/library_builder.dart

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import 'package:build/build.dart';
55
import 'package:dogs_core/dogs_core.dart';
66
import 'package:dogs_generator/analyze/built_interop.dart';
77
import 'package:dogs_generator/dogs_generator.dart';
8+
import 'package:dogs_generator/settings.dart';
89
import 'package:lyell_gen/lyell_gen.dart';
910
import 'package:source_gen/source_gen.dart';
1011

@@ -140,6 +141,7 @@ class SerializableLibraryBuilder extends DogsAdapter<SerializableLibrary> {
140141
SubjectCodeContext codeContext) async {
141142
codeContext.additionalImports
142143
.add(AliasImport.gen("package:dogs_core/dogs_core.dart"));
144+
var settings = await DogsGeneratorSettings.load(genContext.step);
143145

144146
var libraries = getSerializableLibraries(genContext);
145147
var resolvedTypeSets = await Future.wait(
@@ -168,10 +170,10 @@ class SerializableLibraryBuilder extends DogsAdapter<SerializableLibrary> {
168170
try {
169171
if (element is ClassElement) {
170172
await ConverterBuilder.generateForClass(
171-
element, genContext, codeContext);
173+
element, settings, genContext, codeContext);
172174
} else if (element is EnumElement) {
173175
await ConverterBuilder.generateForEnum(
174-
element, genContext, codeContext);
176+
element, settings, genContext, codeContext);
175177
}
176178
} catch (ex) {
177179
log.severe(

packages/dogs_generator/lib/builders/reactor_builder.dart

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import 'package:lyell_gen/lyell_gen.dart';
55
import 'package:pubspec/pubspec.dart';
66
import 'package:recase/recase.dart';
77

8+
import '../settings.dart';
9+
810
class DogReactorBuilder extends SubjectReactorBuilder {
911
DogReactorBuilder() : super('dogs', 'dogs.g.dart');
1012

@@ -16,22 +18,8 @@ class DogReactorBuilder extends SubjectReactorBuilder {
1618
Future build(BuildStep buildStep) async {
1719
step = buildStep;
1820
packageName = buildStep.inputId.package;
19-
try {
20-
var pubspecString = await buildStep
21-
.readAsString(AssetId(buildStep.inputId.package, "pubspec.yaml"));
22-
var pubspec = PubSpec.fromYamlString(pubspecString);
23-
var dogsRegion = pubspec.unParsedYaml?["dogs"];
24-
if (dogsRegion != null) {
25-
log.info("Using dogs generator options specified in the pubspec.yaml");
26-
var map = dogsRegion as Map;
27-
isLibrary = map["library"] as bool;
28-
log.info("isLibrary: $isLibrary");
29-
}
30-
} catch (ex) {
31-
log.warning(
32-
"Can't resolve package pubspec.yaml with error: $ex. Using default values.");
33-
}
34-
21+
var settings = await DogsGeneratorSettings.load(buildStep);
22+
isLibrary = settings.isLibrary;
3523
await super.build(buildStep);
3624
}
3725

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import 'package:build/build.dart';
2+
import 'package:pubspec/pubspec.dart';
3+
import 'package:recase/recase.dart';
4+
5+
class DogsGeneratorSettings {
6+
bool isLibrary = false;
7+
CasingType propertyCase = CasingType.keep;
8+
CasingType nameCase = CasingType.keep;
9+
CasingType enumCase = CasingType.keep;
10+
11+
static Future<DogsGeneratorSettings> load(BuildStep buildStep) async {
12+
var settings = DogsGeneratorSettings();
13+
14+
try {
15+
var pubspecString = await buildStep
16+
.readAsString(AssetId(buildStep.inputId.package, "pubspec.yaml"));
17+
var pubspec = PubSpec.fromYamlString(pubspecString);
18+
var dogsRegion = pubspec.unParsedYaml?["dogs"];
19+
if (dogsRegion != null) {
20+
log.info("Using dogs generator options specified in the pubspec.yaml");
21+
var map = dogsRegion as Map;
22+
23+
var isLibraryValue = map["library"];
24+
if (isLibraryValue is bool) {
25+
settings.isLibrary = isLibraryValue;
26+
}
27+
28+
var casingValue = map["property_case"];
29+
if (casingValue is String) {
30+
settings.propertyCase = CasingType.fromString(casingValue);
31+
}
32+
33+
var nameCasingValue = map["name_case"];
34+
if (nameCasingValue is String) {
35+
settings.nameCase = CasingType.fromString(nameCasingValue);
36+
}
37+
38+
var enumCasingValue = map["enum_case"];
39+
if (enumCasingValue is String) {
40+
settings.enumCase = CasingType.fromString(enumCasingValue);
41+
}
42+
}
43+
} catch (ex) {
44+
log.warning(
45+
"Can't resolve package pubspec.yaml with error: $ex. Using default values.");
46+
}
47+
return settings;
48+
}
49+
}
50+
51+
enum CasingType {
52+
keep,
53+
snake,
54+
camel,
55+
pascal,
56+
constant;
57+
58+
static CasingType fromString(String value) {
59+
switch (value.toLowerCase()) {
60+
case "keep":
61+
return CasingType.keep;
62+
case "snake":
63+
return CasingType.snake;
64+
case "camel":
65+
return CasingType.camel;
66+
case "pascal":
67+
return CasingType.pascal;
68+
case "constant":
69+
return CasingType.constant;
70+
default:
71+
return CasingType.keep;
72+
}
73+
}
74+
75+
String recase(String input) {
76+
switch (this) {
77+
case CasingType.keep:
78+
return input;
79+
case CasingType.snake:
80+
return ReCase(input).snakeCase;
81+
case CasingType.camel:
82+
return ReCase(input).camelCase;
83+
case CasingType.pascal:
84+
return ReCase(input).pascalCase;
85+
case CasingType.constant:
86+
return ReCase(input).constantCase;
87+
}
88+
}
89+
}

smoke/test0/lib/special.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ class ConvertableAConverter extends DogConverter<ConvertableA> with OperationMap
5656

5757
@serializable
5858
enum EnumA {
59-
a,b,c;
59+
a,b,c,longNameValue;
6060
}
6161

6262
abstract class CustomBase {

smoke/test0/pubspec.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,8 @@ dev_dependencies:
2323
dogs_generator: any
2424

2525
lints: ^3.0.0
26+
27+
dogs:
28+
property_case: snake
29+
name_case: constant
30+
enum_case: keep

0 commit comments

Comments
 (0)