Skip to content

Commit

Permalink
New rule: no_condition_parens_rule (sass#15)
Browse files Browse the repository at this point in the history
  • Loading branch information
mik01aj committed Nov 9, 2018
1 parent 4f1ae0c commit f9a1f1c
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 4 deletions.
10 changes: 6 additions & 4 deletions lib/src/engine.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import 'linter.dart';
import 'rule.dart';
import 'rules/no_debug.dart';
import 'rules/no_empty_style.dart';
import 'rules/no_condition_parens.dart';
import 'rules/no_loud_comment.dart';
import 'rules/non_numeric_dimension.dart';
import 'rules/quote_map_keys.dart';
Expand All @@ -21,6 +22,7 @@ import 'rules/use_falsey_null.dart';
final allRules = <Rule>[
new NoDebugRule(),
new NoEmptyStyleRule(),
new NoConditionParensRule(),
new NoLoudCommentRule(),
new NonNumericDimensionRule(),
new QuoteMapKeysRule(),
Expand Down Expand Up @@ -86,7 +88,7 @@ class Engine {
}

Iterable<String> _scssFilesInDir(String path) => new Directory(path)
.listSync(recursive: true)
.where((entity) => entity is File)
.map((entity) => entity.path)
.where((path) => path.endsWith('.scss'));
.listSync(recursive: true)
.where((entity) => entity is File)
.map((entity) => entity.path)
.where((path) => path.endsWith('.scss'));
49 changes: 49 additions & 0 deletions lib/src/rules/no_condition_parens.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright 2018 Google Inc. Use of this source code is governed by an
// MIT-style license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

// The sass package's API is not necessarily stable. It is being imported with
// the Sass team's explicit knowledge and approval. See
// https://github.com/sass/dart-sass/issues/236.
import 'package:sass/src/ast/sass.dart';

import '../lint.dart';
import '../rule.dart';

/// A lint rule that reports unnecessary parentheses in conditionals.
///
/// Sometimes users who are familiar with other languages forget that Sass
/// doesn't need parentheses around its conditionals (as in, `@if (...) {`, or
/// `@else if (...) {`, or `@while (...) {`). This rule suggests removing these
/// parentheses.
class NoConditionParensRule extends Rule {
NoConditionParensRule() : super('no_condition_parens_rule');

@override
List<Lint> visitIfRule(IfRule node) {
var lint = <Lint>[];
for (var clause in node.clauses) {
if (clause.expression is ParenthesizedExpression) {
lint.add(Lint(
rule: this,
span: clause.expression.span,
message:
'Parentheses around ${clause.expression.span.text} are unnecessary'));
}
}
return lint..addAll(super.visitIfRule(node));
}

@override
List<Lint> visitWhileRule(WhileRule node) {
var lint = <Lint>[];
if (node.condition is ParenthesizedExpression) {
lint.add(Lint(
rule: this,
span: node.condition.span,
message:
'Parentheses around ${node.condition.span.text} are unnecessary'));
}
return lint..addAll(super.visitWhileRule(node));
}
}
67 changes: 67 additions & 0 deletions test/rules/no_condition_parens_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Copyright 2018 Google Inc. Use of this source code is governed by an
// MIT-style license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

import 'package:sass_linter/src/rules/no_condition_parens.dart';
import 'package:sass_linter/src/lint.dart';
import 'package:sass_linter/src/linter.dart';
import 'package:test/test.dart';

final url = 'a.scss';
final rule = new NoConditionParensRule();

void main() {
test('does not report lint when there are no parens', () {
var lints = getLints(r'@if 1 != 7 { @debug("quack"); }');

expect(lints, isEmpty);
});

test('reports lint when there is a paren in @if', () {
var lints = getLints(r'@if (1 != 7) { @debug("quack"); }');

expect(lints, hasLength(1));

var lint = lints.single;
expect(lint.rule, rule);
expect(lint.message, contains('Parentheses'));
expect(lint.message, contains('(1 != 7)'));
expect(lint.message, contains('unnecessary'));
expect(lint.url, new Uri.file(url));
expect(lint.line, 0);
expect(lint.column, 4);
});

test('reports lint when there is a paren in @else if', () {
var lints = getLints(r'@if 1 {} @else if (2 != 3) { @debug("quack"); }');

expect(lints, hasLength(1));

var lint = lints.single;
expect(lint.rule, rule);
expect(lint.message, contains('Parentheses'));
expect(lint.message, contains('(2 != 3)'));
expect(lint.message, contains('unnecessary'));
expect(lint.url, new Uri.file(url));
expect(lint.line, 0);
expect(lint.column, 18);
});

test('reports lint when there is a paren in @while', () {
var lints = getLints(r'@while (2 == 3) { @debug("quack"); }');

expect(lints, hasLength(1));

var lint = lints.single;
expect(lint.rule, rule);
expect(lint.message, contains('Parentheses'));
expect(lint.message, contains('(2 == 3)'));
expect(lint.message, contains('unnecessary'));
expect(lint.url, new Uri.file(url));
expect(lint.line, 0);
expect(lint.column, 18);
});
}

List<Lint> getLints(String source) =>
new Linter(source, [rule], url: url).run();

0 comments on commit f9a1f1c

Please sign in to comment.