Skip to content

Commit

Permalink
feat: Add low_readability_numeric_literals lint rule and quick fix (#210
Browse files Browse the repository at this point in the history
)
  • Loading branch information
ronnnnn authored Dec 31, 2024
1 parent 8c984c8 commit 764ec8a
Show file tree
Hide file tree
Showing 8 changed files with 219 additions and 5 deletions.
6 changes: 4 additions & 2 deletions melos.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,13 @@ scripts:
description: format (dry-run)

fmt:dart:
run: melos exec -c 1 --fail-fast -- dart format .
# https://github.com/dart-lang/sdk/issues/59815
run: melos exec -c 1 --fail-fast -- dart format --enable-experiment=digit-separators .
description: format dart

fmt:dart:dry:
run: melos exec -c 1 --fail-fast -- dart format --set-exit-if-changed .
# https://github.com/dart-lang/sdk/issues/59815
run: melos exec -c 1 --fail-fast -- dart format --set-exit-if-changed --enable-experiment=digit-separators .
description: format dart (dry-run)

fix:
Expand Down
29 changes: 29 additions & 0 deletions packages/nilts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ Some of lint rules support quick fixes on IDE.
| [defined\_void\_callback\_type](#defined_void_callback_type) | Checks `void Function()` definitions. | Any versions nilts supports | Practice | Experimental | ✅️ |
| [fixed\_text\_scale\_rich\_text](#fixed_text_scale_rich_text) | Checks usage of `textScaler` or `textScaleFactor` in `RichText` constructor. | Any versions nilts supports | Practice | Experimental | ✅️ |
| [flaky\_tests\_with\_set\_up\_all](#flaky_tests_with_set_up_all) | Checks `setUpAll` usages. | Any versions nilts supports | Practice | Experimental | ✅️ |
| [low\_readability\_numeric\_literals](#low_readability_numeric_literals) | Checks numeric literals with 5 or more digits. | >= Flutter 3.27.0 (Dart 3.6.0) | Practice | Experimental | ✅️ |
| [no\_support\_multi\_text\_direction](#no_support_multi_text_direction) | Checks if supports `TextDirection` changes. | Any versions nilts supports | Practice | Experimental | ✅️ |
| [no\_support\_web\_platform\_check](#no_support_web_platform_check) | Checks if `Platform.isXxx` usages. | Any versions nilts supports | Practice | Experimental | ✅️ |
| [shrink\_wrapped\_scroll\_view](#shrink_wrapped_scroll_view) | Checks the content of the scroll view is shrink wrapped. | Any versions nilts supports | Practice | Experimental | ✅️ |
Expand Down Expand Up @@ -412,6 +413,34 @@ See also:

</details>

#### low_readability_numeric_literals

<details>

- Target SDK : >= Flutter 3.27.0 (Dart 3.6.0)
- Rule type : Practice
- Maturity level : Experimental
- Quick fix :

**Consider** using digit separators for numeric literals with 5 or more digits to improve readability.

**BAD:**
```dart
const int value = 123456;
```

**GOOD:**
```dart
const int value = 123_456;
```

See also:

- [Digit Separators in Dart 3.6](https://medium.com/dartlang/announcing-dart-3-6-778dd7a80983)
- [Built-in types | Dart](https://dart.dev/language/built-in-types#numbers)

</details>

#### no_support_multi_text_direction

<details>
Expand Down
3 changes: 3 additions & 0 deletions packages/nilts/lib/nilts.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import 'package:nilts/src/lints/defined_value_getter_type.dart';
import 'package:nilts/src/lints/defined_void_callback_type.dart';
import 'package:nilts/src/lints/fixed_text_scale_rich_text.dart';
import 'package:nilts/src/lints/flaky_tests_with_set_up_all.dart';
import 'package:nilts/src/lints/low_readability_numeric_literals.dart';
import 'package:nilts/src/lints/no_support_multi_text_direction.dart';
import 'package:nilts/src/lints/no_support_web_platform_check.dart';
import 'package:nilts/src/lints/shrink_wrapped_scroll_view.dart';
Expand Down Expand Up @@ -35,6 +36,8 @@ class _NiltsLint extends PluginBase {
else
const FixedTextScaleRichTextLegacy(),
const FlakyTestsWithSetUpAll(),
if (_dartVersion >= const DartVersion(major: 3, minor: 6, patch: 0))
const LowReadabilityNumericLiterals(),
const NoSupportMultiTextDirection(),
const NoSupportWebPlatformCheck(),
const ShrinkWrappedScrollView(),
Expand Down
3 changes: 3 additions & 0 deletions packages/nilts/lib/src/change_priority.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
/// See also:
/// - [IgnoreCode](https://github.com/invertase/dart_custom_lint/blob/1df2851a80ccdc5a2bda4418006560f49c03b8ec/packages/custom_lint_builder/lib/src/ignore.dart#L102)
class ChangePriority {
/// The priority for [_AddDigitSeparators]
static const int addDigitSeparators = 100;

/// The priority for [_AddTextScaleFactor].
static const int addTextScaleFactor = 90;

Expand Down
114 changes: 114 additions & 0 deletions packages/nilts/lib/src/lints/low_readability_numeric_literals.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import 'package:analyzer/error/error.dart' as analyzer;
import 'package:analyzer/error/listener.dart';
import 'package:custom_lint_builder/custom_lint_builder.dart';
import 'package:nilts/src/change_priority.dart';

/// A class for `low_readability_numeric_literals` rule.
///
/// This rule checks numeric literals with 5 or more digits.
///
/// - Target SDK : >= Flutter 3.27.0 (Dart 3.6.0)
/// - Rule type : Practice
/// - Maturity level : Experimental
/// - Quick fix : ✅
///
/// **Consider** using digit separators for numeric literals with 5 or more
/// digits to improve readability.
///
/// **BAD:**
/// ```dart
/// const int value = 123456;
/// ```
///
/// **GOOD:**
/// ```dart
/// const int value = 123_456;
/// ```
///
/// See also:
///
/// - [Digit Separators in Dart 3.6](https://medium.com/dartlang/announcing-dart-3-6-778dd7a80983)
/// - [Built-in types | Dart](https://dart.dev/language/built-in-types#numbers)
class LowReadabilityNumericLiterals extends DartLintRule {
/// Creates a new instance of [LowReadabilityNumericLiterals].
const LowReadabilityNumericLiterals() : super(code: _code);

static const _code = LintCode(
name: 'low_readability_numeric_literals',
problemMessage:
'Numeric literals with 5 or more digits should use digit separators '
'for better readability.',
url: 'https://github.com/ronnnnn/nilts#low_readability_numeric_literals',
);

@override
void run(
CustomLintResolver resolver,
ErrorReporter reporter,
CustomLintContext context,
) {
context.registry.addIntegerLiteral((node) {
final value = node.value;
if (value == null) return;

final literal = node.literal.lexeme;
if (literal.contains('_')) return;

if (value.abs() >= 10000) {
reporter.atNode(node, _code);
}
});
}

@override
List<Fix> getFixes() => [
_AddDigitSeparators(),
];
}

class _AddDigitSeparators extends DartFix {
@override
void run(
CustomLintResolver resolver,
ChangeReporter reporter,
CustomLintContext context,
analyzer.AnalysisError analysisError,
List<analyzer.AnalysisError> others,
) {
context.registry.addIntegerLiteral((node) {
if (!node.sourceRange.intersects(analysisError.sourceRange)) return;

final value = node.value;
if (value == null) return;

final literal = node.literal.lexeme;
if (literal.contains('_')) return;

reporter
.createChangeBuilder(
message: 'Add digit separators',
priority: ChangePriority.addDigitSeparators,
)
.addDartFileEdit((builder) {
final newLiteral = _addSeparators(literal);
builder.addSimpleReplacement(node.sourceRange, newLiteral);
});
});
}

String _addSeparators(String literal) {
final buffer = StringBuffer();
var count = 0;

for (var i = literal.length - 1; i >= 0; i--) {
buffer.write(literal[i]);
count++;
if (count == 3 && i != 0) {
buffer.write('_');
count = 0;
}
}

return buffer.toString().split('').reversed.join();
}
}
4 changes: 2 additions & 2 deletions packages/nilts_test/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ description: A new Flutter module project.
publish_to: 'none'

environment:
sdk: '>=3.0.0 <4.0.0'
flutter: '>=3.10.0'
sdk: '>=3.6.0 <4.0.0'
flutter: '>=3.27.1'

dependencies:
flutter:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// ignore_for_file: avoid_js_rounded_ints
// ignore_for_file: prefer_const_declarations
// ignore_for_file: prefer_final_locals
// ignore_for_file: unused_element
// ignore_for_file: unused_local_variable

const _globalConstant1 = 1234;
// expect_lint: low_readability_numeric_literals
const _globalConstant2 = 12345;

var _globalVariable1 = 1234;
// expect_lint: low_readability_numeric_literals
var _globalVariable2 = 12345;

final _globalFinal1 = 1234;
// expect_lint: low_readability_numeric_literals
final _globalFinal2 = 12345;

void main() {
const constant1 = 1234;
// expect_lint: low_readability_numeric_literals
const constant2 = 12345;
const constant3 = 12_345;
// expect_lint: low_readability_numeric_literals
const constant4 = 1234567890;
const constant5 = 1_234_567_890;
// expect_lint: low_readability_numeric_literals
const constant6 = 123456789012345;
const constant7 = 123_456_789_012_345;

var variable1 = 1234;
// expect_lint: low_readability_numeric_literals
var variable2 = 12345;
var variable3 = 12_345;
// expect_lint: low_readability_numeric_literals
var variable4 = 1234567890;
var variable5 = 1_234_567_890;
// expect_lint: low_readability_numeric_literals
var variable6 = 123456789012345;
var variable7 = 123_456_789_012_345;

final final1 = 1234;
// expect_lint: low_readability_numeric_literals
final final2 = 12345;
final final3 = 12_345;
// expect_lint: low_readability_numeric_literals
final final4 = 1234567890;
final final5 = 1_234_567_890;
// expect_lint: low_readability_numeric_literals
final final6 = 123456789012345;
final final7 = 123_456_789_012_345;

const hex1 = 0x1234;
// expect_lint: low_readability_numeric_literals
const hex2 = 0x12345;
const hex3 = 0x12_345;
// expect_lint: low_readability_numeric_literals
const hex4 = 0x1234567890;
const hex5 = 0x1_234_567_890;
// expect_lint: low_readability_numeric_literals
const hex6 = 0x123456789012345;
const hex7 = 0x123_456_789_012_345;
}
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: nilts_workspace
publish_to: 'none'

environment:
sdk: '>=3.0.0 <4.0.0'
sdk: '>=3.6.0 <4.0.0'

dev_dependencies:
melos: ^6.2.0

0 comments on commit 764ec8a

Please sign in to comment.