3 changes: 2 additions & 1 deletion .eslintrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ extends:
- plugin:@mysticatea/+node

rules:
"@mysticatea/node/no-unsupported-features":
init-declarations: "off"
"@mysticatea/node/no-unsupported-features/es-syntax":
- error
- ignores:
- modules
7 changes: 7 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@
home: true
actionText: Get Started →
actionLink: /guide/getting-started
features:
- title: Scope Utilities
details: Finding the specific global variables and their members with tracking assignments, finding variables, etc...
- title: AST Utilities
details: Computing the runtime value of a node, Getting the property name of a Property|MemberExpression|MemberExpression node, etc...
- title: Token Utilities
details: Distinguishing the token types of a given token, etc...
---

<center>
Expand Down
129 changes: 129 additions & 0 deletions docs/api/ast-utils.md
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,135 @@ function getStringIfConstant(node, initialScope) {

----

## hasSideEffect

```js
const ret = utils.hasSideEffect(node, sourceCode, options)
```

Check whether a given node has any side effect or not.

The side effect means that it *may* modify a certain variable or object member. This function considers the node which contains the following types as the node which has side effects:

- `AssignmentExpression`
- `AwaitExpression`
- `CallExpression`
- `ImportExpression`
- `NewExpression`
- `UnaryExpression` (`[operator = "delete"]`)
- `UpdateExpression`
- `YieldExpression`
- When `options.considerGetters` is `true`:
- `MemberExpression`
- When `options.considerImplicitTypeConversion` is `true`:
- `BinaryExpression` (`[operator = "==" | "!=" | "<" | "<=" | ">" | ">=" | "<<" | ">>" | ">>>" | "+" | "-" | "*" | "/" | "%" | "|" | "^" | "&" | "in"]`)
- `MemberExpression` (`[computed = true]`)
- `MethodDefinition` (`[computed = true]`)
- `Property` (`[computed = true]`)
- `UnaryExpression` (`[operator = "-" | "+" | "!" | "~"]`)

### Parameters

Name | Type | Description
:-----|:-----|:------------
node | Node | The node to check.
sourceCode | SourceCode | The source code object to get visitor keys.
options.considerGetters | boolean | Default is `false`. If `true` then it considers member accesses as the node which has side effects.
options.considerImplicitTypeConversion | boolean | Default is `false`. If `true` then it considers implicit type conversion as the node which has side effects.

### Return value

`true` if the node has a certain side effect.

### Example

```js{9}
const { hasSideEffect } = require("eslint-utils")
module.exports = {
meta: {},
create(context) {
const sourceCode = context.getSourceCode()
return {
":expression"(node) {
if (hasSideEffect(node, sourceCode)) {
// ...
}
},
}
},
}
```

----

## isParenthesized

```js
const ret1 = utils.isParenthesized(times, node, sourceCode)
const ret2 = utils.isParenthesized(node, sourceCode)
```

Check whether a given node is parenthesized or not.

This function detects it correctly even if it's parenthesized by specific syntax.

```js
// those `a` are not parenthesized.
f(a);
new C(a);
if (a) {}
switch (a) {}
while (a) {}
do {} while (a);
with (a) {}

// those `b` are parenthesized.
f((b));
new C((b));
if ((b)) {}
switch ((b)) {}
while ((b)) {}
do {} while ((b));
with ((b)) {}
```

### Parameters

Name | Type | Description
:-----|:-----|:------------
times | number | Optional. The number of redundant parenthesized. Default is `1`.
node | Node | The node to check.
sourceCode | SourceCode | The source code object to get tokens.

### Return value

`true` if the node is parenthesized.

If `times` was given, it returns `true` only if the node is parenthesized the `times` times. For example, `isParenthesized(2, node, sourceCode)` returns `true` for `((foo))`, but not for `(foo)`.

### Example

```js{9}
const { isParenthesized } = require("eslint-utils")
module.exports = {
meta: {},
create(context) {
const sourceCode = context.getSourceCode()
return {
":expression"(node) {
if (isParenthesized(node, sourceCode)) {
// ...
}
},
}
},
}
```

----

## PatternMatcher class

```js
Expand Down
24 changes: 15 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,28 +1,34 @@
{
"name": "eslint-utils",
"version": "1.3.1",
"version": "1.4.2",
"description": "Utilities for ESLint plugins.",
"engines": {
"node": ">=6"
},
"sideEffects": false,
"main": "index",
"module": "index.mjs",
"files": [
"index.*"
],
"dependencies": {},
"dependencies": {
"eslint-visitor-keys": "^1.0.0"
},
"devDependencies": {
"@mysticatea/eslint-plugin": "^5.0.1",
"@mysticatea/eslint-plugin": "^10.0.3",
"codecov": "^3.0.2",
"eslint": "^5.0.1",
"dot-prop": "^4.2.0",
"eslint": "^5.16.0",
"esm": "^3.0.55",
"espree": "^4.0.0",
"espree": "^5.0.1",
"mocha": "^5.2.0",
"nyc": "^12.0.2",
"nyc": "^13.0.1",
"opener": "^1.4.3",
"rimraf": "^2.6.2",
"rollup": "^0.62.0",
"rollup": "^1.16.7",
"rollup-plugin-sourcemaps": "^0.4.2",
"vuepress": "github:mysticatea/vuepress#skip-waiting"
"vuepress": "^0.14.4",
"warun": "^1.0.0"
},
"scripts": {
"prebuild": "npm run -s clean",
Expand All @@ -38,7 +44,7 @@
"preversion": "npm test && npm run -s build",
"postversion": "git push && git push --tags",
"prewatch": "npm run -s clean",
"watch": "mocha --require esm --reporter dot --watch --growl \"test/*.js\""
"watch": "warun \"{src,test}/**/*.js\" -- nyc --reporter lcov mocha --reporter dot \"test/*.js\""
},
"repository": {
"type": "git",
Expand Down
6 changes: 3 additions & 3 deletions rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ function config(ext) {
file: `index${ext}`,
format: ext === ".mjs" ? "es" : "cjs",
sourcemap: true,
sourcemapFile: `index${ext}.map`,
strict: true,
banner: `/*! @author Toru Nagashima <https://github.com/mysticatea> */`,
banner:
"/*! @author Toru Nagashima <https://github.com/mysticatea> */",
},
plugins: [sourcemaps()],
external: Object.keys(require("./package.json").dependencies),
}
}

Expand Down
Loading