Skip to content
This repository was archived by the owner on Oct 19, 2021. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/coffeelint.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ coffeelint.registerRule(
)
coffeelint.registerRule require './rules/no_empty_functions.coffee'
coffeelint.registerRule require './rules/prefer_english_operator.coffee'
coffeelint.registerRule require './rules/prefer_logical_operator.coffee'
coffeelint.registerRule require './rules/spacing_after_comma.coffee'
coffeelint.registerRule(
require './rules/transform_messes_up_line_numbers.coffee'
Expand Down
34 changes: 34 additions & 0 deletions src/rules/prefer_logical_operator.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
module.exports = class PreferLogicalOperator

rule:
name: 'prefer_logical_operator'
level: 'ignore'
message: 'Don\'t use is, isnt, not, and, or, yes, on, no, off'
doubleNotLevel: 'ignore'
description: '''
This rule prohibits is, isnt, not, and, or, yes, on, no, off.
Use ==, !=, !, &&, ||, true, false instead.
'''

tokens: ['COMPARE', 'UNARY', 'LOGIC', 'BOOL', 'COMPOUND_ASSIGN']

lintToken: (token, tokenApi) ->
# Compare the actual token with the lexed token.
{ first_column, last_column } = token[2]
line = tokenApi.lines[tokenApi.lineNumber]
actual_token = line[first_column..last_column]
context =
switch actual_token
when 'is' then 'Replace "is" with "=="'
when 'isnt' then 'Replace "isnt" with "!="'
when 'or' then 'Replace "or" with "||"'
when 'and' then 'Replace "and" with "&&"'
when 'not' then 'Replace "not" with "!"'
when 'yes' then 'Replace "yes" with true'
when 'on' then 'Replace "on" with true'
when 'off' then 'Replace "off" with false'
when 'no' then 'Replace "no" with false'
else undefined

if context?
{ context }
122 changes: 122 additions & 0 deletions test/test_prefer_logical_operator.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
path = require 'path'
vows = require 'vows'
assert = require 'assert'
coffeelint = require path.join('..', 'lib', 'coffeelint')

configError = { prefer_logical_operator: { level: 'error' } }

RULE = 'prefer_logical_operator'

vows.describe(RULE).addBatch({

'English operators':
'should warn when \'is\' is used': ->
result = coffeelint.lint('1 is 1', configError)[0]
assert.equal result.context, 'Replace "is" with "=="'

'should warn when \'isnt\' is used': ->
result = coffeelint.lint('1 isnt 1', configError)[0]
assert.equal result.context, 'Replace "isnt" with "!="'

'should warn when \'and\' is used': ->
result = coffeelint.lint('1 and 1', configError)[0]
assert.equal result.context, 'Replace "and" with "&&"'

'should warn when \'or\' is used': ->
result = coffeelint.lint('1 or 1', configError)[0]
assert.equal result.context, 'Replace "or" with "||"'

'should warn when \'or=\' is used': ->
result = coffeelint.lint('a or= 1', configError)[0]
assert.equal result.context, 'Replace "or" with "||"'

'should warn when \'not\' is used': ->
result = coffeelint.lint('x = not 1', configError)[0]
assert.equal result.context, 'Replace "not" with "!"'

'should warn when \'yes\' is used': ->
result = coffeelint.lint('a = 1 || yes', configError)[0]
assert.equal result.context, 'Replace "yes" with true'

'should warn when \'on\' is used': ->
result = coffeelint.lint('a = 1 || on', configError)[0]
assert.equal result.context, 'Replace "on" with true'

'should warn when \'no\' is used': ->
result = coffeelint.lint('a = 1 || no', configError)[0]
assert.equal result.context, 'Replace "no" with false'

'should warn when \'off\' is used': ->
result = coffeelint.lint('a = 1 || off', configError)[0]
assert.equal result.context, 'Replace "off" with false'

'Logical operators':
'should not warn when \'==\' is used': ->
assert.isEmpty(coffeelint.lint('1 == 1', configError))

'should not warn when \'!=\' is used': ->
assert.isEmpty(coffeelint.lint('1 != 1', configError))

'should not warn when \'&&\' is used': ->
assert.isEmpty(coffeelint.lint('1 && 1', configError))

'should not warn when \'||\' is used': ->
assert.isEmpty(coffeelint.lint('1 || 1', configError))

'should not warn when \'!\' is used': ->
assert.isEmpty(coffeelint.lint('x = !1', configError))

'should not warn when \'true\' is used': ->
assert.isEmpty(coffeelint.lint('a = 1 || true', configError))

'should not warn when \'false\' is used': ->
assert.isEmpty(coffeelint.lint('a = 1 || false', configError))

'Comments': ->
topic:
'''
# 1 is 1
# 1 isnt 1
# 1 and 1
# 1 or 1
# a = not 1
# a = 1 or yes
# a = 1 or on
# a = 1 and no
# a = 1 and yes
###
1 is 1
1 isnt 1
1 and 1
1 or 1
a = not 1
a = 1 or yes
a = 1 or on
a = 1 and no
a = 1 and yes
###
'''

'should not warn when == is used in a comment': (source) ->
assert.isEmpty(coffeelint.lint(source, configError))

'Strings':
'should not warn when \'or\' is used in a single-quote string': ->
assert.isEmpty(coffeelint.lint('\'1 or 1\'', configError))

'should not warn when \'or\' is used in a double-quote string': ->
assert.isEmpty(coffeelint.lint('"1 or 1"', configError))

'should not warn when \'or\' is used in a multiline string': ->
source = '''
"""
1 or 1
"""
'''
assert.isEmpty(coffeelint.lint(source, configError))

'should warn when \'or\' is used inside string interpolation': ->
result = coffeelint.lint('a = "#{1 or 1}"', configError)[0]
assert.equal result.context, 'Replace "or" with "||"'

}).export(module)