Skip to content
This repository has been archived by the owner on Oct 2, 2021. It is now read-only.

Commit

Permalink
feat(rules): add rule prefer-session-equals
Browse files Browse the repository at this point in the history
closes #118
  • Loading branch information
dferber90 committed Mar 7, 2016
1 parent 18d7a4a commit a06d2db
Show file tree
Hide file tree
Showing 5 changed files with 212 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ For a more thorough introduction, read the [setup guide](/docs/guides/setup.md).
* [no-blaze-lifecycle-assignment](docs/rules/no-blaze-lifecycle-assignment.md): Prevent deprecated template lifecycle callback assignments
* [no-zero-timeout](docs/rules/no-zero-timeout.md): Prevent usage of Meteor.setTimeout with zero delay
* [blaze-consistent-eventmap-params](docs/rules/blaze-consistent-eventmap-params.md): Force consistent event handler parameters in event maps
* [prefer-session-equals](docs/prefer-session-equals.md): Prefer `Session.equals` in conditions


## Core API
Expand Down
57 changes: 57 additions & 0 deletions docs/rules/prefer-session-equals.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Prefer `Session.equals` in conditions (prefer-session-equals)

Using `Session.equals('foo', bar)` toggles fewer invalidations compared to `Session.get('foo') === bar`.


## Rule Details

While the above is only true for scalar types, this rule encourages use over `Session.equals` in all conditional statements.

The following patterns are considered warnings:

```js
if (Session.get("foo")) {/* ... */}

if (Session.get("foo") == bar) {/* ... */}

if (Session.get("foo") === bar) {/* ... */}

Session.get("foo") ? true : false

Session.get("foo") === bar ? true : false
```

The following patterns are not warnings:

```js
if (Session.equals("foo", true)) {/* ... */}

if (Session.equals("foo", 1)) {/* ... */}

if (Session.equals("foo", "hello")) {/* ... */}

if (Session.equals("foo", bar)) {/* ... */}

if (_.isEqual(Session.get("foo"), otherValue)) {/* ... */}

Session.equals("foo", true) ? true : false
```

```js
const foo = Session.get("foo")
if (foo === 'bar') {/* ... */}
```

## When Not To Use It

Turn this rule off when you are comparing compound types, e.g. Arrays.


## Further Reading

- http://docs.meteor.com/#/full/session_equals


## Possible Improvements

* Track which variables were set through `Session.get` and warn when they are used in conditions
2 changes: 2 additions & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ module.exports = {
'no-blaze-lifecycle-assignment': require('./rules/no-blaze-lifecycle-assignment'),
'no-zero-timeout': require('./rules/no-zero-timeout'),
'blaze-consistent-eventmap-params': require('./rules/blaze-consistent-eventmap-params'),
'prefer-session-equals': require('./rules/prefer-session-equals'),
},
configs: {
parserOptions: {
Expand All @@ -19,6 +20,7 @@ module.exports = {
'meteor/no-blaze-lifecycle-assignment': 2,
'meteor/no-zero-timeout': 2,
'meteor/blaze-consistent-eventmap-params': 2,
'meteor/prefer-session-equals': 0,
},
},
},
Expand Down
68 changes: 68 additions & 0 deletions lib/rules/prefer-session-equals.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/**
* @fileoverview Prefer Session.equals in conditions
* @author Dominik Ferber
* @copyright 2016 Dominik Ferber. All rights reserved.
* See LICENSE file in root directory for full license.
*/


const isSessionGetCallExpression = node => (
node.type === 'CallExpression' &&
node.callee.type === 'MemberExpression' &&
(
node.callee.type === 'MemberExpression' &&
node.callee.object.type === 'Identifier' && node.callee.object.name === 'Session' &&
(
(
!node.callee.computed &&
node.callee.property.type === 'Identifier' &&
node.callee.property.name === 'get'
) ||
(
node.callee.computed &&
node.callee.property.type === 'Literal' &&
node.callee.property.value === 'get'
)
)
)
)


// -----------------------------------------------------------------------------
// Rule Definition
// -----------------------------------------------------------------------------
module.exports = context => {
// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
const errorMessage = 'Use "Session.equals" instead'

const checkTest = (node) => {
switch (node.type) {
case 'BinaryExpression':
case 'LogicalExpression':
checkTest(node.left)
checkTest(node.right)
break
case 'CallExpression':
if (isSessionGetCallExpression(node)) {
context.report(node.callee, errorMessage)
}
break
default:
return
}
}

// ---------------------------------------------------------------------------
// Public
// ---------------------------------------------------------------------------
return {
ConditionalExpression: node => {
checkTest(node.test)
},
IfStatement: node => checkTest(node.test),
}
}

module.exports.schema = []
84 changes: 84 additions & 0 deletions tests/lib/rules/prefer-session-equals.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/**
* @fileoverview Prefer Session.equals in conditions
* @author Dominik Ferber
* @copyright 2016 Dominik Ferber. All rights reserved.
* See LICENSE file in root directory for full license.
*/

// -----------------------------------------------------------------------------
// Requirements
// -----------------------------------------------------------------------------

const rule = require('../../../dist/rules/prefer-session-equals')
const RuleTester = require('eslint').RuleTester
const ruleTester = new RuleTester()

ruleTester.run('prefer-session-equals', rule, {
valid: [
'if (Session.equals("foo", true)) {}',
'if (Session.equals("foo", false)) {}',
'if (Session.equals("foo", 1)) {}',
'if (Session.equals("foo", "hello")) {}',
'if (!Session.equals("foo", "hello")) {}',
'if (_.isEqual(Session.get("foo"), otherValue)) {}',
'Session.equals("foo", true) ? true : false',
'if (Session.set("foo")) {}',
],

invalid: [
{
code: 'if (Session.get("foo")) {}',
errors: [
{ message: 'Use "Session.equals" instead', type: 'MemberExpression' },
],
},
{
code: 'if (Session.get("foo") == 3) {}',
errors: [
{ message: 'Use "Session.equals" instead', type: 'MemberExpression' },
],
},
{
code: 'if (Session.get("foo") === 3) {}',
errors: [
{ message: 'Use "Session.equals" instead', type: 'MemberExpression' },
],
},
{
code: 'if (Session.get("foo") === bar) {}',
errors: [
{ message: 'Use "Session.equals" instead', type: 'MemberExpression' },
],
},
{
code: 'if (Session.get("foo") !== bar) {}',
errors: [
{ message: 'Use "Session.equals" instead', type: 'MemberExpression' },
],
},
{
code: 'Session.get("foo") ? true : false',
errors: [
{ message: 'Use "Session.equals" instead', type: 'MemberExpression' },
],
},
{
code: 'Session.get("foo") && false ? true : false',
errors: [
{ message: 'Use "Session.equals" instead', type: 'MemberExpression' },
],
},
{
code: 'Session.get("foo") === 2 ? true : false',
errors: [
{ message: 'Use "Session.equals" instead', type: 'MemberExpression' },
],
},
{
code: 'true || Session.get("foo") === 2 ? true : false',
errors: [
{ message: 'Use "Session.equals" instead', type: 'MemberExpression' },
],
},
],
})

0 comments on commit a06d2db

Please sign in to comment.