Skip to content

Commit

Permalink
Merge pull request #151 from byshy/prefer_single_quotes
Browse files Browse the repository at this point in the history
Add prefer single quotes rule
  • Loading branch information
santitigaga authored Nov 6, 2024
2 parents a2e90be + d096ed1 commit 9d67449
Show file tree
Hide file tree
Showing 6 changed files with 167 additions and 0 deletions.
1 change: 1 addition & 0 deletions example/analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ dart_code_linter:
- no-blank-line-before-single-return
- no-boolean-literal-compare
- no-empty-block
- prefer-single-quotes
- no-equal-then-else
- prefer-async-await
- prefer-correct-type-name:
Expand Down
2 changes: 2 additions & 0 deletions lib/src/analyzers/lint_analyzer/rules/rules_factory.dart
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ import 'rules_list/prefer_last/prefer_last_rule.dart';
import 'rules_list/prefer_match_file_name/prefer_match_file_name_rule.dart';
import 'rules_list/prefer_moving_to_variable/prefer_moving_to_variable_rule.dart';
import 'rules_list/prefer_provide_intl_description/prefer_provide_intl_description_rule.dart';
import 'rules_list/prefer_single_quotes/prefer_single_qoutes.dart';
import 'rules_list/prefer_single_widget_per_file/prefer_single_widget_per_file_rule.dart';
import 'rules_list/prefer_static_class/prefer_static_class_rule.dart';
import 'rules_list/prefer_trailing_comma/prefer_trailing_comma_rule.dart';
Expand Down Expand Up @@ -134,6 +135,7 @@ final _implementedRules = <String, Rule Function(Map<String, Object>)>{
NewlineBeforeReturnRule.ruleId: NewlineBeforeReturnRule.new,
NoBlankLineBeforeSingleReturnRule.ruleId: NoBlankLineBeforeSingleReturnRule.new,
PreferFirstOrNullRule.ruleId: PreferFirstOrNullRule.new,
PreferSingleQuotesRule.ruleId: PreferSingleQuotesRule.new,
NoBooleanLiteralCompareRule.ruleId: NoBooleanLiteralCompareRule.new,
NoEmptyBlockRule.ruleId: NoEmptyBlockRule.new,
NoEqualArgumentsRule.ruleId: NoEqualArgumentsRule.new,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// ignore_for_file: public_member_api_docs

import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';

import '../../../../../utils/node_utils.dart';
import '../../../lint_utils.dart';
import '../../../models/internal_resolved_unit_result.dart';
import '../../../models/issue.dart';
import '../../../models/replacement.dart';
import '../../../models/severity.dart';
import '../../models/dart_rule.dart';
import '../../rule_utils.dart';

part 'visitor.dart';

class PreferSingleQuotesRule extends DartRule {
static const ruleId = 'prefer-single-quotes';
static const _warningMessage = 'Use single quotation marks instead of double quotations.';
static const _replaceComment = "Replace with ''.";

PreferSingleQuotesRule([Map<String, Object> config = const {}])
: super(
id: ruleId,
severity: readSeverity(config, Severity.style),
excludes: readExcludes(config),
includes: readIncludes(config),
);

@override
Iterable<Issue> check(InternalResolvedUnitResult source) {
final visitor = _Visitor();
source.unit.visitChildren(visitor);

return visitor.expressions
.map((expression) => createIssue(
rule: this,
location: nodeLocation(node: expression, source: source),
message: _warningMessage,
replacement: _createReplacement(expression),
))
.toList(growable: false);
}

Replacement _createReplacement(Expression expression) {
if (expression is StringLiteral) {
final originalString = expression.stringValue ?? '';
final singleQuotedString = "'$originalString'";

return Replacement(
comment: _replaceComment,
replacement: singleQuotedString,
);
}

return Replacement(
comment: _replaceComment,
replacement: expression.toSource(),
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
part of 'prefer_single_qoutes.dart';

class _Visitor extends RecursiveAstVisitor<void> {
final _expressions = <Expression>[];

Iterable<Expression> get expressions => _expressions;

@override
void visitSimpleStringLiteral(SimpleStringLiteral node) {
super.visitSimpleStringLiteral(node);

if (node.isSingleQuoted) {
return; // Already using single quotes
}

_expressions.add(node);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// ignore_for_file: unnecessary_cast, unused_local_variable

import 'dart:collection';

void func() {
final String value1 = "some value"; // Lint
final String value2 = 'some value';

final String value3 = "some value \"another text\""; // Lint
final String value4 = 'some value \"another text\"';

final String value5 = """
multi line text
""";
final String value6 = '''
multi line text
''';
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import 'package:dart_code_linter/src/analyzers/lint_analyzer/models/severity.dart';
import 'package:dart_code_linter/src/analyzers/lint_analyzer/rules/rules_list/prefer_single_quotes/prefer_single_qoutes.dart';
import 'package:test/test.dart';

import '../../../../../helpers/rule_test_helper.dart';

const _examplePath = 'prefer_single_quotes/examples/example.dart';

void main() {
group(
'PreferSingleQuotesRule',
() {
test('initialization', () async {
final unit = await RuleTestHelper.resolveFromFile(_examplePath);
final issues = PreferSingleQuotesRule().check(unit);

RuleTestHelper.verifyInitialization(
issues: issues,
ruleId: PreferSingleQuotesRule.ruleId,
severity: Severity.style,
);
});

test('reports about found issues', () async {
final unit = await RuleTestHelper.resolveFromFile(_examplePath);
final issues = PreferSingleQuotesRule().check(unit);

RuleTestHelper.verifyIssues(
issues: issues,
startLines: [
6,
9,
12,
],
startColumns: [
25,
25,
25,
],
messages: [
'Use single quotation marks instead of double quotations.',
'Use single quotation marks instead of double quotations.',
'Use single quotation marks instead of double quotations.',
],
replacementComments: [
"Replace with ''.",
"Replace with ''.",
"Replace with ''.",
],
replacements: [
"'some value'",
'\'some value "another text"\'',
"' multi line text\n"
" '",
],
locationTexts: [
'"some value"',
r'"some value \"another text\""',
'"""\n'
' multi line text\n'
' """',
],
);
});
},
);
}

0 comments on commit 9d67449

Please sign in to comment.