Code Generation in Flutter (Part 1): antlr4dart vs generators

Wissam Sbenaty
4 min readApr 22, 2023

--

Flutter is a popular mobile app development framework that allows developers to build high-performance, cross-platform mobile applications using a single code base. One of the key features of Flutter is its ability to generate code automatically, which can save developers a lot of time and effort.

Two popular code generation techniques in Flutter are using the ANTLR library or basic code generation. In this article, we will explore the differences between these two approaches and the benefits and drawbacks of each.

ANTLR Library in Flutter

The ANTLR library can be found on pub.dev at https://pub.dev/packages/antlr4dart. ANTLR (ANother Tool for Language Recognition) is a powerful parser generator that can be used to analyze, transform, and generate code. ANTLR is a popular choice for generating code in Flutter, as it can be used to parse complex data structures and generate code based on those structures.

Using ANTLR in Flutter involves defining a grammar that describes the structure of the data you want to parse, and then using the ANTLR library to generate code based on that grammar. The generated code can then be used in your Flutter application to parse and manipulate data.

ANTLR has several advantages over basic code generation in Flutter:

  1. ANTLR is highly customizable and can be used to generate code for complex data structures.
  2. ANTLR-generated code is often more efficient than code generated using other methods.
  3. ANTLR can be used to generate code in multiple programming languages, making it a versatile tool for developers.
  4. ANTLR can parse any type of text file such as .json or .txt files.
  5. ANTLR generating function can be used in runtime with backend json responses

However, there are also some drawbacks to using ANTLR in Flutter:

  1. ANTLR has a steep learning curve and can be difficult to use for developers who are new to the tool.
  2. ANTLR-generated code can be difficult to debug, as it is often highly optimized and may not be easily readable.
  3. ANTLR-generated code can be difficult to maintain, as changes to the grammar may require significant changes to the generated code.
void main(List<String> args) async {
MyGrammarLexer.checkVersion();
MyGrammarParser.checkVersion();
String filePath='examples/example1.json';
final input = await InputStream.fromPath(filePath);
final lexer = MyGrammarLexer(input);
final tokens = CommonTokenStream(lexer);
final parser = MyGrammarParser(tokens);
parser.addErrorListener(DiagnosticErrorListener());
parser.buildParseTree = true;
final tree = parser.json();
ParseTreeWalker.DEFAULT.walk(TreeShapeListener(), tree);
}
Parsing a json file using antlr4flutter

Basic Code Generation in Flutter

Basic code generation refers to the practice of manually generating code based on a data structure or set of requirements. This approach is often used in simple applications or for generating boilerplate code, The generated code is written in Dart and can be used in your Flutter application to manipulate data.

its really simple to use, most of these kinds of libraries use annotations to recognize which class needs to use a generator, what kind of generator are you using, and to specify some parameters then all you have to do after adding a new class or editing an existing class is to run this command line

flutter pub run build_runner watch

For example, the freezed library (https://pub.dev/packages/freezed) uses basic code generation to create immutable classes and unions for data models. The generated code includes things like data classes and union classes, which can be used to manage the state of your application.

part 'order_model.freezed.dart';
part 'order_model.g.dart';

@freezed
class OrderModel with _$OrderModel{

factory OrderModel({
required int id,
required double totalCost,
required OrderStatus orderStatus,
@JsonKey(name: 'number') required String orderNumber,

String? imagePath,
@JsonKey(name: 'createdOn',fromJson:DateTime.parse,) required DateTime orderDate,
})=_OrderModel;

factory OrderModel.fromJson( Map<String,dynamic> data)=>_$OrderModelFromJson(data);


}

The result of this example is generating 2 new dart classes: order_model.freezed.dart which is responsible for creating immutable instances of OrderModel and order_model.g.dart which is responsible for providing FromJson and ToJson all prepared for you!

Basic code generation has several advantages over ANTLR-generated code:

  1. Basic code generation is often easier to understand and maintain than ANTLR-generated code.
  2. Basic code generation can be used for simple applications or to generate boilerplate code.
  3. Basic code generation only uses correctly-written Dart files.

However, there are also some drawbacks to using basic code generation in Flutter:

  1. Basic code generation can be time-consuming for complex data structures or requirements.
  2. Basic code generation can be error-prone, as it is often done manually and may require significant testing to ensure it is working correctly.
  3. Basic code generation may not be as efficient as ANTLR-generated code, especially for complex data structures.
  4. Basic code generation only use in compilation time, which may limit your ability to generate using some dynamic values in the runtime

One key difference between ANTLR library and basic code generation is that ANTLR can parse any type of text files such as .json or .txt files in application runtime, whereas basic code generation only uses correctly-written Dart files in compilation time as I mentioned above, so this huge difference could lead to making your choice very easily.

Conclusion

In summary, both ANTLR library and basic code generation are valid approaches for generating code in Flutter. ANTLR is a powerful tool that can be used to parse complex data structures and generate highly optimized code, while basic code generation is a simpler approach that can be used for simple applications or to generate boilerplate code.

Which approach you choose will depend on your specific needs and requirements. If you need to parse complex data structures or generate highly optimized code, ANTLR is likely the better choice. If you are working on a simple application or need to generate boilerplate code, basic code generation may be the simpler approach.

--

--