0 purchases
data class plugin
Data Class Plugin #
Data Class Plugin code generator powered by Tachyon.
Table of contents #
How it works
Installation
Generate the code you want
DataClass Annotation
Union Annotation
Enum Annotation
Enums
Configuration
Configuration file
Available options
Configuration examples
Notes
Examples
Development
Known Issues
How it works #
Data Class Plugin uses Tachyon as it's build engine to provide fast code generation. Also this plugin uses the analyzer system and analyzer plugin
to get access on the source code, parse it and provide code actions based on that.
These code actions are similar to the ones provide by the language - e.g. wrap with try/catch - so you don't need to rely on snippets or manually typing any boilerplate code.
Installation #
In your project's pubspec.yaml add
dependencies:
data_class_plugin: any
dev_dependencies:
tachyon: any
copied to clipboard
Create tachyon_config.yaml on the project's root folder
file_generation_paths: # which files/paths to include for build
- "file/path/to/watch"
- "another/one"
generated_file_line_length: 80 # default line length
plugins:
- data_class_plugin # register data_class_plugin
copied to clipboard
Update your analysis_options.yaml (to enable code action)
Minimal analysis_options.yaml
include: package:lints/recommended.yaml
# You need to register the plugin under analyzer > plugins
analyzer:
plugins:
- data_class_plugin
copied to clipboard
Restart the analysis server
VSCode
Open the Command Palette
Windows/Linux: Ctrl + Shift + P
MacOS: ⌘ + Shift + P
Type and select "Dart: Restart Analysis Server"
IntelliJ
Open Find Action
Windows/Linux: Ctrl + Shift + A
MacOS: ⌘ + Shift + A
Type and select "Restart Dart Analysis Server"
Generate the code you want! #
DataClass Annotation #
Create a simple class, annotate it with @DataClass() and provide abstract getter fields for your model.
import 'package:data_class_plugin/data_class_plugin.dart';
@DataClass()
class User {
String get id;
String get username;
}
copied to clipboard
Generated code:
class _$UserImpl extends User {
_$UserImpl({
required this.id,
required this.username,
}) : super.ctor();
@override
final String id;
@override
final String username;
@override
bool operator ==(Object? other) {
return identical(this, other) ||
other is User &&
runtimeType == other.runtimeType &&
id == other.id &&
username == other.username;
}
@override
int get hashCode {
return Object.hashAll(<Object?>[
runtimeType,
id,
username,
]);
}
@override
String toString() {
String toStringOutput = 'User{<optimized out>}';
assert(() {
toStringOutput = 'User@<$hexIdentity>{id: $id, username: $username}';
return true;
}());
return toStringOutput;
}
@override
Type get runtimeType => User;
}
copied to clipboard
Run code actions on your IDE
VSCode
Windows/Linux: Ctrl + .
MacOS: ⌘ + .
Intellij
Windows/Linux: Alt + Enter
MacOS: ⌘ + Enter
Select Generate data/union classes
This will generate all the boilerplate code on the source file.
Hint: Fields declared with final (e.g. final String id;) will be automatically coverters to abstract getters.
Now to generate the part file code (part directive inserted by the code action) you need to run tachyon.
Executing tachyon:
dart run tachyon build
See more options about tachyon by executing: dart run tachyon --help
Note: As you can see on the screenshot @DataClass annotations provides a variety of options to choose from. While this is ok, in many cases you might prefer to set these options on path match or project level.
Check Configuration section to find more option about data_class_plugin_options.yaml
Union Annotation #
Adding this annotation to a class enables it to create union types.
This configuration can be overriden in data_class_plugin_options.yaml, see Configuration.
Enum Annotation #
Create an enumeration with the last field closed by semicolon and annotate it with the @Enum() annotation.
@Enum()
enum Category {
science,
sports;
}
copied to clipboard
Select Generate enum
This configuration can be overriden in data_class_plugin_options.yaml, see Configuration.
Enums #
Even if you don't use the @Enum() annotation, you can still generate methods in enums.
Create an enumeration with the last field closed by semicolon
enum Category {
science,
sports;
}
copied to clipboard
Place the cursor anywhere inside the Category enum
Run code actions on your IDE
A list with the following actions will be displayed
Generate constructor
Generate 'fromJson'
Generate 'toJson'
Generate 'toString'
Enums can have an optional single field of primitive type to be used in the fromJson or toJson transforms,
if not provided then the .name is used as the default json value.
enum Category {
science(0),
sports(1);
final int value;
}
copied to clipboard
Json Converters #
The plugin exposes a json converter registrant that be used through out the app to register your custom converters. This eliminates the need to annotate every single field with a custom converter like (json_serializable).
By default the plugin provides 3 converters for the following classes: Duration, DateTime, Uri.
In case you want to override the default implementation of these converters you can do it by registering your custom converter with jsonConverterRegistrant.register(const MyCustomConverter()). For more info on how to create and register a converter, see this example
In case you want to provide a custom implementation for a single field that might contain complex logic for parsing/conversion you can use a JsonConverter implementation and annotate the specific field with the implementer class.
See example on ClassWithLatLngConverterAnnotation class.
If implementing a JsonConverter is too complex for your case you can use the JsonKey fromJson/toJson functions.
Configuration #
You can customize the generated code produced by Data Class Plugin.
Configuration file
To create a custom configuration you need to add a file named data_class_plugin_options.yaml in the root folder of your project.
Available options
auto_delete_code_from_annotation
To automatically remove code which can be generated by an action in the source file
if the annotation value and the code are in matching.
Based on this example :
@DataClass(toJson: false)
class User {
Map<String, dynamic> toJson() {
// ...
}
}
copied to clipboard
When auto_delete_code_from_annotation is true => toJson will be removed because is set as false in the @DataClass.
When auto_delete_code_from_annotation is false => toJson will be kept as it is even when toJson is set as false in the @DataClass. This allows to create custom fromJson/toJson implementations.
json
Set the default naming convention for json keys.
You can also override the default naming convention for the specified directories.
Supported naming conventions: camelCase, snake_case, kebab-case & PascalCase.
data_class
Set the default values for the provided methods of the @DataClass annotation,
by specifying the directories where they will be enabled or disabled.
union
Set the default values for the provided methods of the @Union annotation,
by specifying the directories where they will be enabled or disabled.
enum
Set the default values for the provided methods of the @Enum annotation,
by specifying the directories where they will be enabled or disabled.
Configuration supported values
# To automatically remove code generated from an annotation or code that can be generated by an annotation action. (commonly fromJson / toJson)
auto_delete_code_from_annotation: true | false
json:
# Default naming convention for json keys
key_name_convention: camel_case (default) | snake_case | kebab_case | pascal_case
# Maps naming conventions to globs
# You can provide a map of all the conventions you need and then a list with all the globs
# key_name_conventions glob match takes precedence over key_name_convention
key_name_conventions:
<camel_case | snake_case | kebab_case | pascal_case>:
- "a/glob/here"
- "another/glob/here"
# Allows to configure "toJson" code generation
# If no config is provided, null values will be dropped by default
to_json:
options_config:
drop_null_values:
default: boolean # default value is there is no match in enabled or disabled lists
enabled: # list of globs
- "a/glob/here"
- "another/glob/here"
disabled: # list of globs
- "a/glob/here"
- "another/glob/here"
data_class:
options_config:
# For each of the provided methods you can provide a configuration
# The configuration can be an enabled or disabled field that contains a list of globs
# Default values for each options
# copy_with (true), hash_and_equals (true), to_string (true), from_json (false),to_json (false), unmodifiable_collections (true)
<copy_with | hash_and_equals | to_string | from_json | to_json | unmodifiable_collections>:
default: boolean # default value is there is no match in enabled or disabled lists
enabled: # list of globs
- "a/glob/here"
- "another/glob/here"
disabled: # list of globs
- "a/glob/here"
- "another/glob/here"
union:
options_config:
# For each of the provided methods you can provide a configuration
# The configuration can be an enabled or disabled field that contains a list of globs
# Default values for each options
# copy_with (false), hash_and_equals (true), to_string (true) from_json(false), to_json (false), unmodifiable_collections (true), when (true)
<copy_with | hash_and_equals | to_string | from_json | to_json | unmodifiable_collections | when>:
default: boolean # default value is there is no match in enabled or disabled lists
enabled: # list of globs
- "a/glob/here"
- "another/glob/here"
disabled: # list of globs
- "a/glob/here"
- "another/glob/here"
enum:
options_config:
# For each of the provided methods you can provide a configuration
# The configuration can be an enabled or disabled field that contains a list of globs
# Default values for each options
# to_string (false), from_json(false), to_json (false)
<to_string | from_json | to_json>:
default: boolean # default value is there is no match in enabled or disabled lists
enabled: # list of globs
- "a/glob/here"
- "another/glob/here"
disabled: # list of globs
- "a/glob/here"
- "another/glob/here"
copied to clipboard
Notes #
If the generated method doesn't exist it will be placed in the end of the class/enum body (before }), otherwise it will be re-generated to be up-to-date with current snapshot of the code (fields, annotations configuration).
The constructor is always generated at the start of the body (after {) for classes.
class MyClass {
// constructor will be generated here
final int a;
}
copied to clipboard
The constructor is always generated after the semicolon (;) in the values declaration for enums.
enum MyEnum {
a,
b,
c;
// constructor will be generated here
}
copied to clipboard
Examples #
You can find a variety of examples in the examples folder and the source code from the Live Demo, as it was presented in the Flutter Greek Community, here.
Development #
In order to see your changes in the plugin you need to modify tools/analyzer_plugin/pubspec.yaml and add the following section:
dependency_overrides:
data_class_plugin:
path: /absolute/path/to/root_project
copied to clipboard
And restart the analysis server (in case that fails run pub_get.sh).
Known Issues #
When using IntelliJ/Android Studio the $toString parameter of the @DataClass annotation is not visible in the Suggestions list.
However, you can still use it by typing it.
For personal and professional use. You cannot resell or redistribute these repositories in their original state.
There are no reviews.