Jolt Lint
jolt_lint is a lint tool specifically designed for the Jolt reactive state management ecosystem, providing code transformation assists and rule checking functionality.
Installation
Add to analysis_options.yaml:
plugins:
jolt_lint: ^3.0.0Requirements
⚠️ Version Requirement: This lint tool only supports Jolt 2.0 and above.
Code Transformation Assists
Convert to Signal
Quickly convert regular variables to Signal. This feature will:
- Wrap variable type as
Signal<T> - Wrap initialization expression as
Signal(...) - Automatically add
.valueaccess at all reference points within the variable's scope
Use Case: When you want to convert a regular variable to a reactive signal.
Example:
// Before conversion
int count = 0;
// After conversion
Signal<int> count = Signal(0);
// All references to count are automatically changed to count.valueConvert from Signal
Convert Signal back to a regular variable. This feature will:
- Unwrap
Signal<T>type toT - Unwrap
Signal(...)initialization expression to original value - Automatically remove all
.valueaccess within the variable's scope
Use Case: When you find a variable doesn't need reactive features and want to simplify code.
Example:
// Before conversion
Signal<int> count = Signal(0);
print(count.value);
// After conversion
int count = 0;
print(count);Widget Wrapping Assists
Multiple quick assist features for wrapping Widgets, helping you quickly integrate Jolt's reactive components.
Wrap with JoltBuilder
Wrap Widget with JoltBuilder, automatically responding to all accessed signal changes.
Use Case: When you need Widget to respond to signal changes.
Example:
// Before conversion
Text('Hello')
// After conversion
JoltBuilder(builder: (context) => Text('Hello'))Wrap with JoltProvider
⚠️ Deprecated:
JoltProvideris deprecated. For dependency injection, use Flutter's built-in solutions likeProvider,Riverpod, or other DI packages.
Wrap Widget with JoltProvider to provide reactive state in the Widget tree.
Use Case: When you need to provide shared reactive state in the Widget tree.
Example:
// Before conversion
MyWidget()
// After conversion (deprecated)
JoltProvider(
create: (context) => null, // Fill in actual creation logic
builder: (context, provider) => MyWidget()
)
// Recommended: Use Provider or Riverpod instead
Provider(
create: (_) => MyStore(),
child: MyWidget(),
)Wrap with JoltSelector
Wrap Widget with JoltSelector to implement fine-grained state selection updates.
Use Case: When you only want to respond to specific state changes, not all signals.
Example:
// Before conversion
Text(counter.value.toString())
// After conversion
JoltSelector(
selector: (prev) => null, // Fill in selector logic
builder: (context, state) => Text(counter.value.toString())
)Wrap with SetupBuilder
Wrap Widget with SetupBuilder to use Jolt's Setup pattern.
Use Case: When you want to use the Setup pattern to organize Widget's reactive logic.
Example:
// Before conversion
MyWidget()
// After conversion
SetupBuilder(setup: (context) { return ()=> MyWidget()})Lint Rules
no_invalid_hook_call
Restricts hook calls to valid hook contexts.
Rule Description:
This rule ensures that useXxx() calls and lifecycle hooks are only used in places where Jolt can preserve hook ordering:
- ✅ Inside
setupbodies - ✅ Inside functions annotated with
@DefineHook - ✅ As arguments passed to other hook calls
- ❌ Inside the function returned from
setup - ❌ As the direct return expression of
setup - ❌ In regular methods, callbacks, or top-level functions without hook context
Example:
class MyWidget extends SetupWidget {
@override
setup(BuildContext context, MyWidget props) {
final count = useSignal(0); // OK
return () {
// useSignal(1); // Invalid: inside returned builder
return Text(count.value.toString());
};
}
}no_setup_this
Prohibits direct or indirect access to instance members (through this or implicit access) in SetupWidget's setup method.
Rule Description:
This rule only applies to SetupWidget, ensuring that instance members can only be accessed through the props parameter in the setup method, maintaining Setup pattern purity and testability.
⚠️ Note: This rule does not apply to SetupMixin. SetupMixin is used in State classes and can normally access this and instance members.
Checks:
- ❌ Explicit use of
this.fieldorthis.method() - ❌ Implicit access to instance members (e.g., directly using
fieldormethod()) - ❌ Assigning
thisto a variable - ❌ Assigning
thisto a setter
Correct Example:
class MyWidget extends SetupWidget {
int count = 0;
@override
Widget setup(BuildContext context, MyWidget props) {
// ✅ Access instance members through props()
return Text(props().count.toString());
}
}Incorrect Example:
class MyWidget extends SetupWidget {
int count = 0;
@override
Widget setup(BuildContext context, MyWidget props) {
// ❌ Cannot directly access this.count
return Text(this.count.toString());
// ❌ Cannot implicitly access count
return Text(count.toString());
}
}SetupMixin Not Restricted by This Rule:
SetupMixin is used in State classes and can normally access this and instance members:
class _MyWidgetState extends State<MyWidget> with SetupMixin<MyWidget> {
int count = 0;
@override
setup(BuildContext context) {
// ✅ SetupMixin can normally use this
return Text(this.count.toString());
// ✅ Can also implicitly access
return Text(count.toString());
}
}Quick Fix Support:
This rule provides automatic fix functionality, quickly converting incorrect code to correct form:
- 🔧 Single Fix: Place cursor on problematic code, press
Ctrl+.(orCmd+.) and select "Replace this with props()" or "Add props() to the member" to automatically fix - 🔧 Batch Fix: The fix menu also provides "Fix all setup this issues" option, which can fix all related issues in the file at once
Fix Example:
// Before fix
Widget setup(BuildContext context, MyWidget props) {
return Text(this.count.toString());
// or
return Text(count.toString());
}
// After fix
Widget setup(BuildContext context, MyWidget props) {
return Text(props().count.toString());
}Usage
After configuration, your IDE (such as VS Code, Android Studio) will automatically provide:
- Code Assists: Place cursor on variable or Widget, press
Ctrl+.(orCmd+.) to view available transformation options - Real-time Checking: Code violating rules such as
no_setup_thisandno_invalid_hook_callwill show diagnostics and fix suggestions when available
Important Notes
- IDE Support: Code assist features require IDE support for Dart analysis server plugins
- Scope Limitations: Code transformation features automatically update all references within the variable's scope
- Type Safety: All transformations maintain type safety and won't break code type checking
- Batch Fix: The
no_setup_thisrule supports batch fixes, allowing you to fix all related issues in the file at once