Merge pull request #2024 from dart-lang/avoid-returning-null-for-future-highlight
Improve the highlight range for avoid_returning_null_for_future
diff --git a/example/all.yaml b/example/all.yaml
index 97cb311..423bc3c 100644
--- a/example/all.yaml
+++ b/example/all.yaml
@@ -67,6 +67,7 @@
- invariant_booleans
- iterable_contains_unrelated_type
- join_return_with_assignment
+ - leading_newlines_in_multiline_strings
- library_names
- library_prefixes
- lines_longer_than_80_chars
diff --git a/lib/src/rules.dart b/lib/src/rules.dart
index d277fd0..286ec02 100644
--- a/lib/src/rules.dart
+++ b/lib/src/rules.dart
@@ -68,6 +68,7 @@
import 'rules/invariant_booleans.dart';
import 'rules/iterable_contains_unrelated_type.dart';
import 'rules/join_return_with_assignment.dart';
+import 'rules/leading_newlines_in_multiline_strings.dart';
import 'rules/library_names.dart';
import 'rules/library_prefixes.dart';
import 'rules/lines_longer_than_80_chars.dart';
@@ -238,6 +239,7 @@
..register(InvariantBooleans())
..register(IterableContainsUnrelatedType())
..register(JoinReturnWithAssignment())
+ ..register(LeadingNewlinesInMultilineStrings())
..register(LibraryNames())
..register(LibraryPrefixes())
..register(LinesLongerThan80Chars())
diff --git a/lib/src/rules/leading_newlines_in_multiline_strings.dart b/lib/src/rules/leading_newlines_in_multiline_strings.dart
new file mode 100644
index 0000000..70765f9
--- /dev/null
+++ b/lib/src/rules/leading_newlines_in_multiline_strings.dart
@@ -0,0 +1,90 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
+
+import '../analyzer.dart';
+
+const _desc = r'Start multiline strings with a newline.';
+
+const _details = r"""
+Multiline strings are easier to read when they start with a newline (a newline
+starting a multiline string is ignored).
+
+**BAD:**
+```
+var s1 = '''{
+ "a": 1,
+ "b": 2
+}''';
+```
+
+**GOOD:**
+```
+var s1 = '''
+{
+ "a": 1,
+ "b": 2
+}''';
+
+var s2 = '''This onliner multiline string is ok. It usually allows to escape both ' and " in the string.''';
+```
+
+""";
+
+class LeadingNewlinesInMultilineStrings extends LintRule
+ implements NodeLintRule {
+ LeadingNewlinesInMultilineStrings()
+ : super(
+ name: 'leading_newlines_in_multiline_strings',
+ description: _desc,
+ details: _details,
+ group: Group.style);
+
+ @override
+ void registerNodeProcessors(NodeLintRegistry registry,
+ [LinterContext context]) {
+ final visitor = _Visitor(this);
+ registry.addCompilationUnit(this, visitor);
+ registry.addSimpleStringLiteral(this, visitor);
+ registry.addStringInterpolation(this, visitor);
+ }
+}
+
+class _Visitor extends SimpleAstVisitor<void> {
+ _Visitor(this.rule);
+
+ final LintRule rule;
+
+ LineInfo lineInfo;
+
+ @override
+ void visitCompilationUnit(CompilationUnit node) {
+ lineInfo = node.lineInfo;
+ }
+
+ @override
+ void visitSimpleStringLiteral(SimpleStringLiteral node) {
+ _visitSingleStringLiteral(node, node.literal.lexeme);
+ }
+
+ @override
+ void visitStringInterpolation(StringInterpolation node) {
+ _visitSingleStringLiteral(
+ node, (node.elements.first as InterpolationString).contents.lexeme);
+ }
+
+ void _visitSingleStringLiteral(SingleStringLiteral node, String lexeme) {
+ if (node.isMultiline &&
+ lineInfo.getLocation(node.offset).lineNumber !=
+ lineInfo.getLocation(node.end).lineNumber) {
+ bool startWithNewLine(int index) =>
+ lexeme.startsWith('\n', index) || lexeme.startsWith('\r', index);
+ if (!startWithNewLine(node.isRaw ? 4 : 3)) {
+ rule.reportLint(node);
+ }
+ }
+ }
+}
diff --git a/test/rules/leading_newlines_in_multiline_strings.dart b/test/rules/leading_newlines_in_multiline_strings.dart
new file mode 100644
index 0000000..b9ca997
--- /dev/null
+++ b/test/rules/leading_newlines_in_multiline_strings.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// test w/ `pub run test -N leading_newlines_in_multiline_strings`
+
+f(o) {
+ f(''''''); // OK
+ f('''this is a multiline string'''); // OK
+ f('''$o'''); // OK
+ f("""uses double quotes"""); // OK
+ // OK
+ f('''
+this is a multiline string''');
+ // LINT [+1]
+ f('''this
+ is a multiline string''');
+
+ f('''this is a multiline string $f'''); // OK
+ // OK
+ f('''
+this is a multiline string $f''');
+ // LINT [+1]
+ f('''this
+ is a multiline string$f''');
+}