Skip to content

Commit

Permalink
feat: Remove avoid_sliver_to_box_adapter lint and add `avoid_consec…
Browse files Browse the repository at this point in the history
…utive_sliver_to_box_adapter` lint
  • Loading branch information
naipaka committed Jul 29, 2024
1 parent 63e8ab4 commit 0475751
Show file tree
Hide file tree
Showing 5 changed files with 181 additions and 91 deletions.
4 changes: 2 additions & 2 deletions packages/altive_lints/lib/altive_lints.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import 'package:custom_lint_builder/custom_lint_builder.dart';

import 'src/lints/avoid_consecutive_sliver_to_box_adapter.dart';
import 'src/lints/avoid_hardcoded_japanese.dart';
import 'src/lints/avoid_shrink_wrap_in_list_view.dart';
import 'src/lints/avoid_sliver_to_box_adapter.dart';

PluginBase createPlugin() => _AltivePlugin();

Expand All @@ -11,6 +11,6 @@ class _AltivePlugin extends PluginBase {
List<LintRule> getLintRules(CustomLintConfigs configs) => [
const AvoidHardcodedJapanese(),
const AvoidShrinkWrapInListView(),
const AvoidSliverToBoxAdapter(),
const AvoidConsecutiveSliverToBoxAdapter(),
];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/error/listener.dart';
import 'package:custom_lint_builder/custom_lint_builder.dart';

/// A `avoid_consecutive_sliver_to_box_adapter` rule that
/// identifies and discourages the use of consecutive
/// `SliverToBoxAdapter` widgets within a list.
///
/// Consecutive usage of `SliverToBoxAdapter` can lead to
/// inefficient nesting and performance issues in scrollable areas.
///
/// It suggests using `SliverList.list` or similar consolidated
/// sliver widgets to optimize rendering performance and reduce
/// the complexity of the widget tree.
///
/// ### Example
///
/// #### BAD:
///
/// ```dart
/// CustomScrollView(
/// slivers: <Widget>[
/// SliverToBoxAdapter(child: Text('Item 1')), // Consecutive usage
/// SliverToBoxAdapter(child: Text('Item 2')), // LINT
/// ],
/// );
/// ```
///
/// #### GOOD:
///
/// ```dart
/// CustomScrollView(
/// slivers: <Widget>[
/// SliverList.list(
/// children: [
/// Text('Item 1')
/// Text('Item 2')
/// ],
/// ),
/// ],
/// );
/// ```
class AvoidConsecutiveSliverToBoxAdapter extends DartLintRule {
const AvoidConsecutiveSliverToBoxAdapter() : super(code: _code);

static const _code = LintCode(
name: 'avoid_consecutive_sliver_to_box_adapter',
problemMessage: 'Avoid using consecutive `SliverToBoxAdapter`. '
'Consider using `SliverList.list` instead.',
);

@override
void run(
CustomLintResolver resolver,
ErrorReporter reporter,
CustomLintContext context,
) {
context.registry.addListLiteral((node) {
final iterator = node.elements.iterator;
if (!iterator.moveNext()) {
// if there are no elements, there is nothing to check.
return;
}

var current = iterator.current;
while (iterator.moveNext()) {
final next = iterator.current;
if (_useSliverToBoxAdapter(current) && _useSliverToBoxAdapter(next)) {
reporter.reportErrorForNode(_code, node);
return;
}
current = next;
}
});
}

bool _useSliverToBoxAdapter(CollectionElement element) {
if (element is! Expression) {
return false;
}
return _isSliverToBoxAdapter(element) || _hasSliverToBoxAdapter(element);
}

bool _isSliverToBoxAdapter(Expression expression) {
final typeName =
expression.staticType?.getDisplayString(withNullability: false);
return typeName == 'SliverToBoxAdapter';
}

bool _hasSliverToBoxAdapter(Expression element) {
if (element is! InstanceCreationExpression) {
return false;
}
final constructor = element;
final arguments = constructor.argumentList.arguments;
for (final argument in arguments) {
if (argument is NamedExpression && argument.name.label.name == 'sliver') {
final sliverExpression = argument.expression;
final sliverTypeName = sliverExpression.staticType
?.getDisplayString(withNullability: false);
if (sliverTypeName == 'SliverToBoxAdapter') {
return true;
}
}
}
return false;
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import 'package:flutter/material.dart';

class ConsecutiveSliverToBoxAdapters extends StatelessWidget {
const ConsecutiveSliverToBoxAdapters({super.key});

@override
Widget build(BuildContext context) {
return const CustomScrollView(
// expect_lint: avoid_consecutive_sliver_to_box_adapter
slivers: [
SliverToBoxAdapter(
child: Text('Hello'),
),
SliverToBoxAdapter(
child: Text('World'),
),
],
);
}
}

class ConsecutiveSliverToBoxAdaptersWithSliverPadding extends StatelessWidget {
const ConsecutiveSliverToBoxAdaptersWithSliverPadding({super.key});

@override
Widget build(BuildContext context) {
return const CustomScrollView(
// expect_lint: avoid_consecutive_sliver_to_box_adapter
slivers: [
SliverPadding(
padding: EdgeInsets.zero,
sliver: SliverToBoxAdapter(
child: Text('Hello'),
),
),
SliverPadding(
padding: EdgeInsets.zero,
sliver: SliverToBoxAdapter(
child: Text('World'),
),
),
],
);
}
}

class NonConsecutiveSliverToBoxAdapters extends StatelessWidget {
const NonConsecutiveSliverToBoxAdapters({super.key});

@override
Widget build(BuildContext context) {
return CustomScrollView(
slivers: [
const SliverToBoxAdapter(
child: Text('Hello'),
),
SliverList.builder(
itemCount: 10,
itemBuilder: (context, index) {
return const SliverToBoxAdapter(
child: Text('item'),
);
},
),
const SliverToBoxAdapter(
child: Text('World'),
),
],
);
}
}

This file was deleted.

0 comments on commit 0475751

Please sign in to comment.