Closed hasimyerlikaya closed 5 months ago
import 'package:code_builder/code_builder.dart';
class CustomEmitter extends DartEmitter { CustomEmitter() : super(Allocator.simplePrefixing(), true, false);
@override StringSink visitExpression(Expression expression, [StringSink? output]) { var sink = output ?? StringBuffer(); if (expression is CodeExpression) { expression.code.accept(this, sink); } else if (expression is LiteralExpression) { final value = expression.literal.toString(); if (value.startsWith("'") && value.endsWith("'")) { sink.write('"' + value.substring(1, value.length - 1) + '"'); } else { sink.write(value); } } else { super.visitExpression(expression, sink); } return sink; }
@override StringSink visitRecordLiteral(RecordLiteral literal, [StringSink? output]) { var sink = output ?? StringBuffer(); sink.write('('); var needsComma = false; for (var field in literal.fields) { if (needsComma) { sink.write(', '); } field.accept(this, sink); needsComma = true; } if (needsComma) { sink.write(','); // Add trailing comma for named fields } sink.write(')'); return sink; } }
void main() { var emitter = CustomEmitter(); var spec = Code(''' import 'package:lang_generator/lang_generator.dart';
@AppLangConfig(jsonExport: true) @AppLangImporter( path: "lib/app_lang_source.en_US.json", locale: "en_US", ) class AppLangSource { var incomeTransaction = ( fields: ( amount: (tr_TR: "Fiyat", en_US: "Amount"), paymentDate: (tr_TR: "Ödeme Tarihi", en_US: "Payment Date"), ), actions: ( update: (tr_TR: "Düzenle", en_US: "Edit"), detail: (tr_TR: "Detay", en_US: "Detail"), addTag: (tr_TR: "Etiket Ekle", en_US: "Add Tag"), ), validations: ( amount: ( notNull: (tr_TR: "Tutar girmelisiniz", en_US: "You must enter an amount"), lessThen: (tr_TR: "Tutar 100'den küçük olmalı", en_US: "Amount must be less than 100"), ), ), );
var expenseTransaction = ( fields: ( amount: (tr_TR: "Fiyat", en_US: "Amount"), paymentDate: (tr_TR: "Ödeme Tarihi", en_US: "Payment Date"), ), ); } '''); print(spec.accept(emitter)); }
The CustomEmitter class inherits from DartEmitter: ----- The visitExpression method overrides the default behavior to ensure double quotes are retained. The visitRecordLiteral method is customized to add a trailing comma after each named field.
@AkashKeote Thank you so much. It seems you are using different version of code_builder. But you gave me the idea and I did it.
code_builder: ^4.10.0
import 'package:code_builder/code_builder.dart';
import 'package:code_builder/src/specs/expression.dart';
// region [p]
class CustomEmitter extends DartEmitter {
CustomEmitter()
: super(
allocator: Allocator.simplePrefixing(),
orderDirectives: true,
useNullSafetySyntax: false,
);
@override
StringSink visitLiteralExpression(LiteralExpression expression, [StringSink? output]) {
output ??= StringBuffer();
final escaped = expression.literal.replaceAll('\\\'', '\'').replaceAll('\\n', '\n');
if (escaped.startsWith("'") && escaped.endsWith("'")) {
return output..write('"${escaped.substring(1, escaped.length - 1)}"');
}
return output..write(escaped);
}
@override
StringSink visitLiteralRecordExpression(LiteralRecordExpression expression, [StringSink? output]) {
final out = output ??= StringBuffer();
out.write('(');
_visitAll<Object?>(expression.positionalFieldValues, out, (value) {
_acceptLiteral(value, out);
});
if (expression.namedFieldValues.isNotEmpty) {
if (expression.positionalFieldValues.isNotEmpty) {
out.write(', ');
}
} else if (expression.positionalFieldValues.length == 1) {
out.write(',');
}
_visitAll<MapEntry<String, Object?>>(expression.namedFieldValues.entries, out, (entry) {
out.write('${entry.key}: ');
_acceptLiteral(entry.value, out);
});
if (expression.namedFieldValues.isNotEmpty) {
out.write(',');
}
return out..write(')');
}
/// Helper method improving on [StringSink.writeAll].
///
/// For every `Spec` in [elements], executing [visit].
///
/// If [elements] is at least 2 elements, inserts [separator] delimiting them.
StringSink _visitAll<T>(
Iterable<T> elements,
StringSink output,
void Function(T) visit, [
String separator = ', ',
]) {
// Basically, this whole method is an improvement on
// output.writeAll(specs.map((s) => s.accept(visitor));
//
// ... which would allocate more StringBuffer(s) for a one-time use.
if (elements.isEmpty) {
return output;
}
final iterator = elements.iterator..moveNext();
visit(iterator.current);
while (iterator.moveNext()) {
output.write(separator);
visit(iterator.current);
}
return output;
}
void _acceptLiteral(Object? literalOrSpec, StringSink output) {
if (literalOrSpec is Spec) {
literalOrSpec.accept(this, output);
return;
}
literal(literalOrSpec).accept(this, output);
}
}
// endregion
need your help how to contribute on the gssoc as my exam is over now and i am in 2nd year dont have much idea about pull request and fork button not here
@AkashKeote
Fork Button on the home page of the repo. You can make changes and then you can create pull request on your forked repo.
thanku so much sir this will help me a lot
@AkashKeote You are welcome. You helped me a lot, too. Thank you. 👍
Hi,
I'm using the code_builder package to create some classes and I'm mainly using variables of type Records. There is no comma at the end of the named fields, so the format is corrupted when I save the file.
The trailing comma feature has been added to Emitter for some data types, but I think not for Records.
Is it possible to add a comma at the end of named fields, or can you add it?
Another problem is that even though I create the text with double quotes, it is converted to single quotes in the generated text. I need to prevent this too.
Do you have a suggestion?
Thank you.
Source:
Generated: