Allow interpolations on adjacent strings (#2721)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 53e32fa..4ee59cc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,8 @@
not the entire body and doc comment.
- update `unnecessary_getters_setters` to allow otherwise "unnecessary" getters
and setters with annotations.
+- update `missing_whitespace_between_adjacent_strings` to allow String
+ interpolations at the beginning and end of String literals.
# 1.6.1
diff --git a/lib/src/rules/missing_whitespace_between_adjacent_strings.dart b/lib/src/rules/missing_whitespace_between_adjacent_strings.dart
index bce3915..6567826 100644
--- a/lib/src/rules/missing_whitespace_between_adjacent_strings.dart
+++ b/lib/src/rules/missing_whitespace_between_adjacent_strings.dart
@@ -57,7 +57,7 @@
@override
void visitAdjacentStrings(AdjacentStrings node) {
- // skip regexp
+ // Skip strings passed to `RegExp()` or any method named `matches`.
var parent = node.parent;
if (parent is ArgumentList) {
var parentParent = parent.parent;
@@ -73,11 +73,11 @@
for (var i = 0; i < node.strings.length - 1; i++) {
var current = node.strings[i];
var next = node.strings[i + 1];
- if (_visit(current, (l) => _endsWithWhitespace(l.last)) ||
- _visit(next, (l) => _startsWithWhitespace(l.first))) {
+ if (_visit(current, (l) => l.last.endsWithWhitespace) ||
+ _visit(next, (l) => l.first.startsWithWhitespace)) {
continue;
}
- if (!_visit(current, (l) => l.any(_hasWhitespace))) {
+ if (!_visit(current, (l) => l.any((e) => e.hasWhitespace))) {
continue;
}
rule.reportLint(current);
@@ -90,27 +90,39 @@
if (string is SimpleStringLiteral) {
return test([string.value]);
} else if (string is StringInterpolation) {
- return test(string.elements.map((e) {
- if (e is InterpolationString) return e.value;
- return '';
- }));
+ var interpolationSubstitutions = <String>[];
+ for (var e in string.elements) {
+ // Given a [StringInterpolation] like '$text', the elements include
+ // empty [InterpolationString]s on either side of the
+ // [InterpolationExpression]. Don't include them in the evaluation.
+ if (e is InterpolationString && e.value.isNotEmpty) {
+ interpolationSubstitutions.add(e.value);
+ }
+ if (e is InterpolationExpression) {
+ // Treat an interpolation expression as a string with whitespace. This
+ // prevents over-reporting on adjascent Strings which start or end
+ // with interpolations.
+ interpolationSubstitutions.add(' ');
+ }
+ }
+ return test(interpolationSubstitutions);
}
throw ArgumentError('${string.runtimeType}: $string');
}
- bool _hasWhitespace(String value) => _whitespaces.any(value.contains);
- bool _endsWithWhitespace(String value) => _whitespaces.any(value.endsWith);
- bool _startsWithWhitespace(String value) =>
- _whitespaces.any(value.startsWith);
-
static bool _isRegExpInstanceCreation(AstNode? node) {
if (node is InstanceCreationExpression) {
var constructorElement = node.constructorName.staticElement;
- return constructorElement != null &&
- constructorElement.enclosingElement.name == 'RegExp';
+ return constructorElement?.enclosingElement.name == 'RegExp';
}
return false;
}
}
-const _whitespaces = [' ', '\n', '\r', '\t'];
+extension on String {
+ bool get hasWhitespace => whitespaces.any(contains);
+ bool get endsWithWhitespace => whitespaces.any(endsWith);
+ bool get startsWithWhitespace => whitespaces.any(startsWith);
+
+ static const whitespaces = [' ', '\n', '\r', '\t'];
+}
diff --git a/test_data/rules/missing_whitespace_between_adjacent_strings.dart b/test_data/rules/missing_whitespace_between_adjacent_strings.dart
index bd3ac35..061bde4 100644
--- a/test_data/rules/missing_whitespace_between_adjacent_strings.dart
+++ b/test_data/rules/missing_whitespace_between_adjacent_strings.dart
@@ -20,6 +20,11 @@
f(RegExp('(\n)+' '(\n)+' '(\n)+')); // OK
new Unresolved('aaa' 'bbb'); // OK
matches('(\n)+' '(\n)+' '(\n)+'); // OK
+
+ f('Hello' // OK
+ '${1 == 2 ? ', world' : ''}');
+ f('${1 == 2 ? 'Hello ' : ''}' // OK
+ 'world');
}
-void matches(String value){}
+void matches(String value) {}