Skip to content

Commit f9a1f1c

Browse files
committed
New rule: no_condition_parens_rule (sass#15)
1 parent 4f1ae0c commit f9a1f1c

File tree

3 files changed

+122
-4
lines changed

3 files changed

+122
-4
lines changed

lib/src/engine.dart

+6-4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import 'linter.dart';
99
import 'rule.dart';
1010
import 'rules/no_debug.dart';
1111
import 'rules/no_empty_style.dart';
12+
import 'rules/no_condition_parens.dart';
1213
import 'rules/no_loud_comment.dart';
1314
import 'rules/non_numeric_dimension.dart';
1415
import 'rules/quote_map_keys.dart';
@@ -21,6 +22,7 @@ import 'rules/use_falsey_null.dart';
2122
final allRules = <Rule>[
2223
new NoDebugRule(),
2324
new NoEmptyStyleRule(),
25+
new NoConditionParensRule(),
2426
new NoLoudCommentRule(),
2527
new NonNumericDimensionRule(),
2628
new QuoteMapKeysRule(),
@@ -86,7 +88,7 @@ class Engine {
8688
}
8789

8890
Iterable<String> _scssFilesInDir(String path) => new Directory(path)
89-
.listSync(recursive: true)
90-
.where((entity) => entity is File)
91-
.map((entity) => entity.path)
92-
.where((path) => path.endsWith('.scss'));
91+
.listSync(recursive: true)
92+
.where((entity) => entity is File)
93+
.map((entity) => entity.path)
94+
.where((path) => path.endsWith('.scss'));
+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Copyright 2018 Google Inc. Use of this source code is governed by an
2+
// MIT-style license that can be found in the LICENSE file or at
3+
// https://opensource.org/licenses/MIT.
4+
5+
// The sass package's API is not necessarily stable. It is being imported with
6+
// the Sass team's explicit knowledge and approval. See
7+
// https://github.com/sass/dart-sass/issues/236.
8+
import 'package:sass/src/ast/sass.dart';
9+
10+
import '../lint.dart';
11+
import '../rule.dart';
12+
13+
/// A lint rule that reports unnecessary parentheses in conditionals.
14+
///
15+
/// Sometimes users who are familiar with other languages forget that Sass
16+
/// doesn't need parentheses around its conditionals (as in, `@if (...) {`, or
17+
/// `@else if (...) {`, or `@while (...) {`). This rule suggests removing these
18+
/// parentheses.
19+
class NoConditionParensRule extends Rule {
20+
NoConditionParensRule() : super('no_condition_parens_rule');
21+
22+
@override
23+
List<Lint> visitIfRule(IfRule node) {
24+
var lint = <Lint>[];
25+
for (var clause in node.clauses) {
26+
if (clause.expression is ParenthesizedExpression) {
27+
lint.add(Lint(
28+
rule: this,
29+
span: clause.expression.span,
30+
message:
31+
'Parentheses around ${clause.expression.span.text} are unnecessary'));
32+
}
33+
}
34+
return lint..addAll(super.visitIfRule(node));
35+
}
36+
37+
@override
38+
List<Lint> visitWhileRule(WhileRule node) {
39+
var lint = <Lint>[];
40+
if (node.condition is ParenthesizedExpression) {
41+
lint.add(Lint(
42+
rule: this,
43+
span: node.condition.span,
44+
message:
45+
'Parentheses around ${node.condition.span.text} are unnecessary'));
46+
}
47+
return lint..addAll(super.visitWhileRule(node));
48+
}
49+
}
+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// Copyright 2018 Google Inc. Use of this source code is governed by an
2+
// MIT-style license that can be found in the LICENSE file or at
3+
// https://opensource.org/licenses/MIT.
4+
5+
import 'package:sass_linter/src/rules/no_condition_parens.dart';
6+
import 'package:sass_linter/src/lint.dart';
7+
import 'package:sass_linter/src/linter.dart';
8+
import 'package:test/test.dart';
9+
10+
final url = 'a.scss';
11+
final rule = new NoConditionParensRule();
12+
13+
void main() {
14+
test('does not report lint when there are no parens', () {
15+
var lints = getLints(r'@if 1 != 7 { @debug("quack"); }');
16+
17+
expect(lints, isEmpty);
18+
});
19+
20+
test('reports lint when there is a paren in @if', () {
21+
var lints = getLints(r'@if (1 != 7) { @debug("quack"); }');
22+
23+
expect(lints, hasLength(1));
24+
25+
var lint = lints.single;
26+
expect(lint.rule, rule);
27+
expect(lint.message, contains('Parentheses'));
28+
expect(lint.message, contains('(1 != 7)'));
29+
expect(lint.message, contains('unnecessary'));
30+
expect(lint.url, new Uri.file(url));
31+
expect(lint.line, 0);
32+
expect(lint.column, 4);
33+
});
34+
35+
test('reports lint when there is a paren in @else if', () {
36+
var lints = getLints(r'@if 1 {} @else if (2 != 3) { @debug("quack"); }');
37+
38+
expect(lints, hasLength(1));
39+
40+
var lint = lints.single;
41+
expect(lint.rule, rule);
42+
expect(lint.message, contains('Parentheses'));
43+
expect(lint.message, contains('(2 != 3)'));
44+
expect(lint.message, contains('unnecessary'));
45+
expect(lint.url, new Uri.file(url));
46+
expect(lint.line, 0);
47+
expect(lint.column, 18);
48+
});
49+
50+
test('reports lint when there is a paren in @while', () {
51+
var lints = getLints(r'@while (2 == 3) { @debug("quack"); }');
52+
53+
expect(lints, hasLength(1));
54+
55+
var lint = lints.single;
56+
expect(lint.rule, rule);
57+
expect(lint.message, contains('Parentheses'));
58+
expect(lint.message, contains('(2 == 3)'));
59+
expect(lint.message, contains('unnecessary'));
60+
expect(lint.url, new Uri.file(url));
61+
expect(lint.line, 0);
62+
expect(lint.column, 18);
63+
});
64+
}
65+
66+
List<Lint> getLints(String source) =>
67+
new Linter(source, [rule], url: url).run();

0 commit comments

Comments
 (0)