Add lint rule for calling init() after creation.

This commit is contained in:
Dain Nilsson 2024-03-07 17:03:17 +01:00
parent 3ee27bea96
commit c66f96016b
No known key found for this signature in database
GPG Key ID: F04367096FBA95E8
3 changed files with 54 additions and 44 deletions

View File

@ -13,18 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import 'dart:async';
import 'package:flutter/material.dart';
import 'app_input_decoration.dart';
/// TextField without autocorrect and suggestions
// ignore: must_be_immutable
class AppTextField extends TextField {
bool _initialized = false;
AppTextField({
const AppTextField({
// default settings to turn off autocorrect
super.autocorrect = false,
super.enableSuggestions = false,
@ -89,22 +84,14 @@ class AppTextField extends TextField {
super.canRequestFocus,
super.spellCheckConfiguration,
super.magnifierConfiguration,
}) : super(decoration: decoration) {
// TODO: Replace this with a custom lint check, if possible
Timer.run(() {
assert(_initialized, 'AppTextField not initialized!');
});
}
}) : super(decoration: decoration);
Widget init() {
_initialized = true;
return Builder(
builder: (context) => DefaultSelectionStyle(
selectionColor: decoration?.errorText != null
? Theme.of(context).colorScheme.error
: null,
child: this,
),
);
}
Widget init() => Builder(
builder: (context) => DefaultSelectionStyle(
selectionColor: decoration?.errorText != null
? Theme.of(context).colorScheme.error
: null,
child: this,
),
);
}

View File

@ -14,17 +14,13 @@
* limitations under the License.
*/
import 'dart:async';
import 'package:flutter/material.dart';
import 'app_input_decoration.dart';
/// TextFormField without autocorrect and suggestions
// ignore: must_be_immutable
class AppTextFormField extends TextFormField {
final AppInputDecoration? decoration;
bool _initialized = false;
AppTextFormField({
// default settings to turn off autocorrect
super.autocorrect = false,
@ -94,22 +90,14 @@ class AppTextFormField extends TextFormField {
super.clipBehavior,
super.scribbleEnabled,
super.canRequestFocus,
}) : super(decoration: decoration) {
// TODO: Replace this with a custom lint check, if possible
Timer.run(() {
assert(_initialized, 'AppTextFormField not initialized!');
});
}
}) : super(decoration: decoration);
Widget init() {
_initialized = true;
return Builder(
builder: (context) => DefaultSelectionStyle(
selectionColor: decoration?.errorText != null
? Theme.of(context).colorScheme.error
: null,
child: this,
),
);
}
Widget init() => Builder(
builder: (context) => DefaultSelectionStyle(
selectionColor: decoration?.errorText != null
? Theme.of(context).colorScheme.error
: null,
child: this,
),
);
}

View File

@ -14,6 +14,7 @@
* limitations under the License.
*/
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/error/listener.dart';
import 'package:custom_lint_builder/custom_lint_builder.dart';
@ -30,6 +31,8 @@ class _AppLinter extends PluginBase {
discouraged: 'TextFormField',
recommended: 'AppTextFormField',
),
const CallInitAfterCreation(className: 'AppTextField'),
const CallInitAfterCreation(className: 'AppTextFormField'),
];
}
@ -59,3 +62,35 @@ class UseRecommendedWidget extends DartLintRule {
});
}
}
class CallInitAfterCreation extends DartLintRule {
final String className;
const CallInitAfterCreation({required this.className})
: super(
code: const LintCode(
name: 'call_init_after_creation',
problemMessage: 'Call init() after creation',
));
@override
void run(
CustomLintResolver resolver,
ErrorReporter reporter,
CustomLintContext context,
) {
context.registry.addInstanceCreationExpression((node) {
if (node.constructorName.toString() == className) {
final dot = node.endToken.next;
final next = dot?.next;
if (dot?.type == TokenType.PERIOD) {
if (next?.type == TokenType.IDENTIFIER &&
next?.toString() == 'init') {
return;
}
}
reporter.reportErrorForNode(code, node.constructorName);
}
});
}
}