Skip to content
This repository has been archived by the owner on Jun 6, 2024. It is now read-only.

Commit

Permalink
feat: Add icon & Remove icon
Browse files Browse the repository at this point in the history
  • Loading branch information
K9i-0 committed May 3, 2023
1 parent 68edebc commit ef357d6
Show file tree
Hide file tree
Showing 6 changed files with 253 additions and 77 deletions.
2 changes: 1 addition & 1 deletion packages/material_button_assist/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class MainApp extends StatelessWidget {
onPressed: () {},
child: const Text('Hello World!'),
),
FilledButton.tonal(
FilledButton(
onPressed: () {},
child: const Text('Hello World!'),
),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
library material_button_assist;

import 'package:custom_lint_builder/custom_lint_builder.dart';
import 'package:material_button_assist/src/assists/add_icon.dart';
import 'package:material_button_assist/src/assists/convert_to_other_button.dart';
import 'package:material_button_assist/src/assists/utils.dart';
import 'package:material_button_assist/src/assists/remove_icon.dart';

PluginBase createPlugin() => _MaterialButtonAssist();

Expand All @@ -14,5 +17,7 @@ class _MaterialButtonAssist extends PluginBase {
...MaterialButtonType.values
.map((buttonType) => ConvertToOtherButton(targetType: buttonType))
.toList(),
AddIcon(),
RemoveIcon(),
];
}
73 changes: 73 additions & 0 deletions packages/material_button_assist/lib/src/assists/add_icon.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/source/source_range.dart';
import 'package:custom_lint_builder/custom_lint_builder.dart';
import 'package:material_button_assist/src/assists/utils.dart';

class AddIcon extends DartAssist {
@override
void run(
CustomLintResolver resolver,
ChangeReporter reporter,
CustomLintContext context,
SourceRange target,
) {
context.registry.addInstanceCreationExpression((node) {
// Select from "new" to the opening bracket
if (!target.intersects(node.constructorName.sourceRange)) return;

final createdType = node.constructorName.type.type;
if (createdType == null || !allButtonType.isExactlyType(createdType)) {
return;
}

final simpleIdentifier = node.constructorName.name;
final supportedIdentifier = getSupportedIdentifier(simpleIdentifier);

if (supportedIdentifier == SupportedIdentifier.icon ||
supportedIdentifier == SupportedIdentifier.tonalIcon) return;

final changeBuilder = reporter.createChangeBuilder(
message: 'Add icon',
priority: addOrRemoveIconPriority,
);

changeBuilder.addDartFileEdit((builder) {
if (supportedIdentifier == SupportedIdentifier.tonal) {
builder.addSimpleReplacement(
node.constructorName.sourceRange,
'FilledButton.tonalIcon',
);
} else {
builder.addSimpleInsertion(
node.constructorName.sourceRange.end,
'.icon',
);
}

var existIcon = false;

node.argumentList.arguments.forEach((argument) {
if (argument is NamedExpression) {
if (argument.name.label.name == 'child') {
builder.addSimpleReplacement(
argument.name.sourceRange,
'label:',
);
}

if (argument.name.label.name == 'icon') {
existIcon = true;
}
}
});

if (!existIcon) {
builder.addSimpleInsertion(
node.argumentList.arguments.last.sourceRange.end,
', icon: Icon(Icons.abc)',
);
}
});
});
}
}
Original file line number Diff line number Diff line change
@@ -1,81 +1,6 @@
import 'package:analyzer/source/source_range.dart';
import 'package:custom_lint_builder/custom_lint_builder.dart';

const convertToOtherButtonPriority = 26;

enum MaterialButtonType {
elevated(
buttonName: 'ElevatedButton',
constructorName: 'ElevatedButton',
priority: convertToOtherButtonPriority,
typeChecker: TypeChecker.fromName(
'ElevatedButton',
packageName: 'flutter',
),
),
filled(
buttonName: 'FilledButton',
constructorName: 'FilledButton',
priority: convertToOtherButtonPriority,
typeChecker: TypeChecker.fromName(
'FilledButton',
packageName: 'flutter',
),
),
filledTonal(
buttonName: 'FilledTonalButton',
constructorName: 'FilledButton.tonal',
priority: convertToOtherButtonPriority,
typeChecker: TypeChecker.fromName(
'FilledButton',
packageName: 'flutter',
),
),
outlined(
buttonName: 'OutlinedButton',
constructorName: 'OutlinedButton',
priority: convertToOtherButtonPriority,
typeChecker: TypeChecker.fromName(
'OutlinedButton',
packageName: 'flutter',
),
),
text(
buttonName: 'TextButton',
constructorName: 'TextButton',
priority: convertToOtherButtonPriority,
typeChecker: TypeChecker.fromName(
'TextButton',
packageName: 'flutter',
),
);

const MaterialButtonType({
required this.buttonName,
required this.constructorName,
required this.priority,
required this.typeChecker,
});
final String buttonName;
final String constructorName;
final int priority;
final TypeChecker typeChecker;
}

TypeChecker getBaseType({
required MaterialButtonType? exclude,
}) {
return TypeChecker.any(
MaterialButtonType.values
.where((e) => e != exclude)
.map((e) => e.typeChecker),
);
}

final filledButtonType = TypeChecker.any([
MaterialButtonType.filled.typeChecker,
MaterialButtonType.filledTonal.typeChecker,
]);
import 'package:material_button_assist/src/assists/utils.dart';

class ConvertToOtherButton extends DartAssist {
ConvertToOtherButton({
Expand Down
70 changes: 70 additions & 0 deletions packages/material_button_assist/lib/src/assists/remove_icon.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/source/source_range.dart';
import 'package:custom_lint_builder/custom_lint_builder.dart';
import 'package:material_button_assist/src/assists/utils.dart';

class RemoveIcon extends DartAssist {
@override
void run(
CustomLintResolver resolver,
ChangeReporter reporter,
CustomLintContext context,
SourceRange target,
) {
context.registry.addInstanceCreationExpression((node) {
// Select from "new" to the opening bracket
if (!target.intersects(node.constructorName.sourceRange)) return;

final createdType = node.constructorName.type.type;
if (createdType == null || !allButtonType.isExactlyType(createdType)) {
return;
}

final simpleIdentifier = node.constructorName.name;
final supportedIdentifier = getSupportedIdentifier(simpleIdentifier);

if (supportedIdentifier == null ||
supportedIdentifier == SupportedIdentifier.tonal) return;

final changeBuilder = reporter.createChangeBuilder(
message: 'Remove icon',
priority: addOrRemoveIconPriority,
);

changeBuilder.addDartFileEdit((builder) {
if (supportedIdentifier == SupportedIdentifier.tonalIcon) {
builder.addSimpleReplacement(
node.constructorName.sourceRange,
'FilledButton.tonal',
);
} else {
builder.addSimpleReplacement(
node.constructorName.sourceRange,
node.constructorName.type.name.name,
);
}

node.argumentList.arguments.forEach((argument) {
if (argument is NamedExpression) {
if (argument.name.label.name == 'label') {
builder.addSimpleReplacement(
argument.name.sourceRange,
'child:',
);
}

if (argument.name.label.name == 'icon') {
builder.addDeletion(
SourceRange(
argument.sourceRange.offset,
argument.sourceRange.length +
(argument.endToken.next?.lexeme == ',' ? 1 : 0),
),
);
}
}
});
});
});
}
}
103 changes: 103 additions & 0 deletions packages/material_button_assist/lib/src/assists/utils.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:custom_lint_builder/custom_lint_builder.dart';

const convertToOtherButtonPriority = 27;
const addOrRemoveIconPriority = 27;

enum MaterialButtonType {
elevated(
buttonName: 'ElevatedButton',
constructorName: 'ElevatedButton',
priority: convertToOtherButtonPriority,
typeChecker: TypeChecker.fromName(
'ElevatedButton',
packageName: 'flutter',
),
),
filled(
buttonName: 'FilledButton',
constructorName: 'FilledButton',
priority: convertToOtherButtonPriority,
typeChecker: TypeChecker.fromName(
'FilledButton',
packageName: 'flutter',
),
),
filledTonal(
buttonName: 'FilledTonalButton',
constructorName: 'FilledButton.tonal',
priority: convertToOtherButtonPriority,
typeChecker: TypeChecker.fromName(
'FilledButton',
packageName: 'flutter',
),
),
outlined(
buttonName: 'OutlinedButton',
constructorName: 'OutlinedButton',
priority: convertToOtherButtonPriority,
typeChecker: TypeChecker.fromName(
'OutlinedButton',
packageName: 'flutter',
),
),
text(
buttonName: 'TextButton',
constructorName: 'TextButton',
priority: convertToOtherButtonPriority,
typeChecker: TypeChecker.fromName(
'TextButton',
packageName: 'flutter',
),
);

const MaterialButtonType({
required this.buttonName,
required this.constructorName,
required this.priority,
required this.typeChecker,
});
final String buttonName;
final String constructorName;
final int priority;
final TypeChecker typeChecker;
}

TypeChecker getBaseType({
required MaterialButtonType? exclude,
}) {
return TypeChecker.any(
MaterialButtonType.values
.where((e) => e != exclude)
.map((e) => e.typeChecker),
);
}

final allButtonType = TypeChecker.any(
MaterialButtonType.values.map((e) => e.typeChecker),
);

final filledButtonType = TypeChecker.any([
MaterialButtonType.filled.typeChecker,
MaterialButtonType.filledTonal.typeChecker,
]);

enum SupportedIdentifier {
icon,
tonal,
tonalIcon,
}

SupportedIdentifier? getSupportedIdentifier(
SimpleIdentifier? simpleIdentifier) {
switch (simpleIdentifier?.name) {
case 'icon':
return SupportedIdentifier.icon;
case 'tonal':
return SupportedIdentifier.tonal;
case 'tonalIcon':
return SupportedIdentifier.tonalIcon;
}

return null;
}

0 comments on commit ef357d6

Please sign in to comment.