Giter Club home page Giter Club logo

coderaiser / putout Goto Github PK

View Code? Open in Web Editor NEW
656.0 11.0 38.0 15.7 MB

๐ŸŠ Pluggable and configurable JavaScript Linter, code transformer and formatter, drop-in ESLint superpower replacement ๐Ÿ’ช with built-in support for js, jsx typescript, flow, markdown, yaml and json. Write declarative codemods in a simplest possible way ๐Ÿ˜

Home Page: https://putout.cloudcmd.io/

License: MIT License

JavaScript 99.00% TypeScript 0.71% CSS 0.03% HTML 0.20% Shell 0.01% WebAssembly 0.06% Svelte 0.01%
javascript nodejs ast eslint babel codeshift codemod plugin transform hacktoberfest

putout's People

Contributors

asieduernest12 avatar atablash avatar coderaiser avatar deepsourcebot avatar dimamachina avatar egilll avatar em- avatar fluentinstroll avatar fregante avatar hans5958 avatar jmlavoier avatar matwilko avatar mridulsharma03 avatar niranjan-kurhade avatar oprogramador avatar pcarn avatar pvinis avatar rastaalex avatar sobolevn avatar sonicdoe avatar tejaswankalluri avatar tsmmark avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

putout's Issues

eslint-plugin-putout and ESLint Shareable Configs

I am trying to integrate eslint-plugin-putout into my ESLint shareable config - eslint-config-hardcore.

The integration of putout itself was straightforward.
But I don't understand how I can override putout rules in my shareable ESLint config.

I see that it is possible to create .putout.json in projects that will be using eslint-hardcore-config, but I would like to avoid having to create and maintain .putout.json in each project. I would like my putout config to be shared along with my eslint-hardcore-config.

For example, eslint-plugin-prettier allows you to specify Prettier options like this (in .eslintrc.json):

{
  "plugins": ["prettier"],
  "rules": {
    "prettier/prettier": ["error", { "singleQuote": true }]
                                   ^^^^^^^^^^^^^^^^^^^^^^^
  }
}

I would like to be able to do something like that with putout:

{
  "plugins": ["putout"],
  "rules": {
    "putout/putout": [
      "error",
      {
        "rules": {
          "apply-optional-chaining": "on",
          "apply-nullish-coalescing": "on",
          "remove-unused-variables": "off"
        }
      }
    ]
  }
}

feat: autofix error "Maximum call stack size exceeded" in array push spread

calling someArray.push(...otherArray) can be considered a code smell,
since otherArray.length is limited to about 100K in nodejs (500K in firefox)

// problem
[].push(...Array.from({ length: 1000*1000 })) // ... = spread operator
// Uncaught RangeError: Maximum call stack size exceeded

// solution
var input = Array.from({ length: 1000*1000 }); var output = [];
for (let i = 0; i < input.length; i++) output.push(input[i]);
output.length
// 1000000

// solution
Array.prototype._concat_inplace = function(other) { // aka _push_array
  for (let i = 0; i < other.length; i++) {
    this.push(other[i]);
  }
  return this; // chainable
};
var input = Array.from({ length: 1000*1000 }); var output = [];
output._concat_inplace(input), output.length;
// 1000000

see sveltejs/svelte#4694 (comment)

remove async/await

I have a class definition that looks like

class X {

    constructor() {
        this._analyzer = null;
    }

    async init(arg) {
       await something()
    }
}

and I need to strip async and await from/in method init. This is a source that is not under my control, but which I know will work without async in my own context, where I need it to be sync. How would I do this with putout?

feat: remove relative require to node_modules

solution in bash:

find . -name '*.js' -or -name '*.ts' | while read f
do
  echo "$f"
  sed -E -i "s|require\('(\\.\\./)+node_modules/(.*?)'\)|require('\2')|" "$f"
done

sample from github.com/aethereans/aether-app

-const minimatch = require('../../node_modules/minimatch')
+const minimatch = require('minimatch')

convert-commonjs-to-esm breaks these imports:

-const minimatch = require('../../node_modules/minimatch')
+import minimatch from '../../node_modules/minimatch.js';

Document usage of putout with a single rule or plugin

How can I use putout to apply a single rule, such as remove-unused-variables?

It would be helpful if there was a simple, documented approach for this. Ideally, it should be possible to do this with a single command and without creating a .putout.json file.

It seems that specifying a limited set of rules or plugins in the local .putout.json file does not by default disable rules or plugins specified in the default putout.json file. That is, it seems that the local plugins are added to the default, instead of replacing them. For the rules, it appears as though certain rules are on by default (even without appearing in the default .putout.json file) and I have not found a comprehensive list of all rules.

Using putout --disable-all source.js seems to only disable rules which are currently violated in the source files being evaluated, not all rules comprehensively.

Further, the documentation seems to be somewhat redundantly duplicated between the top level readme https://github.com/coderaiser/putout/blob/master/README.md and the readme in the putout package https://github.com/coderaiser/putout/blob/master/packages/putout/README.md which I find confusing.

Destructuring Iterable that is not an Array uses .slice()

Using the eslint plugin, I'm seeing a destructured Set be undestructured (restructured?) with a .slice() call, in typescript. So this:

const draftSet = new Set<string>([...rejected]);

becomes:

const draftSet = new Set<string>(rejected.slice());

Where rejected is a Set.

A Set, of course, does not have a slice method.

plugin-apply-shorthand-properties: ignore imports

Currently, plugin-apply-shorthand-properties transforms this code

import evolve from "ramda/src/evolve";
import not from "ramda/src/not";
import mergeDeepRight from "ramda/src/mergeDeepRight";

export default evolve({
  isPanelVisible: not,
  items: mergeDeepRight,
});

into this:

import evolve from "ramda/src/evolve";
import isPanelVisible from "ramda/src/not";
import items from "ramda/src/mergeDeepRight";

export default evolve({
  isPanelVisible,
  items,
});

I think aliasing generic utility functions like this is a bad practice. I would like for plugin-apply-shorthand-properties to ignore cases like this.

SyntaxError: 'import' and 'export' may only appear at the top level

ESlint version: 7.32.0
Putout: v20.0.0
eslint-plugin-putout: v10.0.0

Eslint Parser:

  "parser": "@babel/eslint-parser",
  "parserOptions": {
    "ecmaVersion": "latest",
    "jsx": true,
    "requireConfigFile": false,
    "sourceType": "module"
  },

Input file:

const testMissingColon = '123'

Output:

ESLint: 7.32.0

SyntaxError: 'import' and 'export' may only appear at the top level. (3:8)
  1 | /* @babel/template */;
  2 | {
> 3 |         import {createMockImport} from 'mock-import';
    |        ^
  4 |         const {mockImport, stopAll, reImport} = createMockImport(import.meta.url);
  5 |     }
Occurred while linting D:\Web\test\app.js:1
    at Object._raise (C:\Users\Virgil\AppData\Local\Yarn\Data\global\node_modules\@babel\parser\lib\index.js:796:17)
    at Object.raiseWithData (C:\Users\Virgil\AppData\Local\Yarn\Data\global\node_modules\@babel\parser\lib\index.js:789:17)
    at Object.raise (C:\Users\Virgil\AppData\Local\Yarn\Data\global\node_modules\@babel\parser\lib\index.js:750:17)
    at Object.parseStatementContent (C:\Users\Virgil\AppData\Local\Yarn\Data\global\node_modules\@babel\parser\lib\index.js:12899:18)
    at Object.parseStatementContent (C:\Users\Virgil\AppData\Local\Yarn\Data\global\node_modules\@babel\parser\lib\index.js:9201:18)
    at Object.parseStatement (C:\Users\Virgil\AppData\Local\Yarn\Data\global\node_modules\@babel\parser\lib\index.js:12806:17)
    at Object.parseBlockOrModuleBlockBody (C:\Users\Virgil\AppData\Local\Yarn\Data\global\node_modules\@babel\parser\lib\index.js:13395:25)
    at Object.parseBlockBody (C:\Users\Virgil\AppData\Local\Yarn\Data\global\node_modules\@babel\parser\lib\index.js:13386:10)
    at Object.parseBlock (C:\Users\Virgil\AppData\Local\Yarn\Data\global\node_modules\@babel\parser\lib\index.js:13370:10)
    at Object.parseBlock (C:\Users\Virgil\AppData\Local\Yarn\Data\global\node_modules\@babel\parser\lib\index.js:10018:61)

False CJS detection

Hi there, if I use this:

export * from './foo.js';

I get this warning:

"use strict" directive should be on top of commonjs file (strict-mode/add) eslint(putout/putout)

disable formatting

I opened oprogramador#1 and I used the same .putout.json file but with "remove-unused-variables": "on",.

Generally it works fine, removing only unused variables bot for some JSX files it changed formatting.

e.g. it used to be:

export const Teams = props => (
  <>
    <header

it was changed to:

export const Teams = () => <>
  <header

plugin-regexp/remove-useless-group should not remove groups in `.split()` or `.replace()`

plugin-regexp/remove-useless-group changes:

'lala'.split(/(a)/g); // Output: ["l", "a", "l", "a", ""]

into:

'lala'.split(/a/g); // Output: ["l", "l", ""]

It also changes:

'lala'.replace(/(a)/g,'-$1-'); // Output: "l-a-l-a-"

into:

'lala'.replace(/a/g,'-$1-'); // Output: "l-$1-l-$1-"

This plugin is safe to use in .test(), but should likely ignore regex that appears in any other function (match, split, replace).

TypeError: Cannot read property 'raw' of undefined

Looks like @putout/plugin-regexp can't handle named capturing groups.

const regexp = /(?<foo>a)/;

gives the following error:

TypeError: Cannot read property 'raw' of undefined
Occurred while linting /home/user/example.js:1
    at RegExpLiteral (/home/user/node_modules/@putout/plugin-regexp/lib/remove-useless-group/index.js:14:38)

ESLint: 7.30.0
putout: 18.4.0
eslint-plugin-putout: 8.1.0
@putout/plugin-regexp: 2.3.3

remove unused variables keeping methods invocation

Generally remove-unused-variables rule works correctly but sometimes there's a situation like:

const result = await API.put(id, payload);

so we need to remove unused const result = but keep await API.put(id, payload);.

This rule could accept some options:

  • to always invoke functions/ methods and remove only assignments
  • to detect in some way whether a function/ method modifies anything:
    • having knowledge about lodash methods
    • assuming that if a method name starts with get or is or check, it doesn't modify anything

Local plugins

How can I use a plugin that is local to my code, and not published on npmjs? I tried

putout(source.code, { plugins: './trace' })

and

putout(source.code, { plugins: require('./trace') })

http://putout.cloudcmd.io/ fails to load with error "TypeError: t.iter is not a function"

When trying to navigate to http://putout.cloudcmd.io/ there is a JavaScript error and the page fails to load. The only visible content is a contribution footer. The link http://putout.cloudcmd.io/ appears in the description for the GitHub project https://github.com/coderaiser/putout/, so it may be one of the first links that a potential user will look at when exploring the project.

Tested in Chrome and Firefox. The error below is from Chrome Version 76.0.3809.100 (Official Build) (64-bit)

vendors~app-be21591da1b5607b3eb3-26.js:50 TypeError: t.iter is not a function
    at estimateLineHeights (vendors~app-be21591da1b5607b3eb3-26.js:19)
    at attachDoc (vendors~app-be21591da1b5607b3eb3-26.js:19)
    at new CodeMirror (vendors~app-be21591da1b5607b3eb3-26.js:19)
    at CodeMirror (vendors~app-be21591da1b5607b3eb3-26.js:19)
    at Editor.componentDidMount (app-6544ad61fc0ebc2847bb-26.js:2167)
    at nj (vendors~app-be21591da1b5607b3eb3-26.js:50)
    at t.unstable_runWithPriority (vendors~app-be21591da1b5607b3eb3-26.js:9)
    at vf (vendors~app-be21591da1b5607b3eb3-26.js:50)
    at ij (vendors~app-be21591da1b5607b3eb3-26.js:50)
    at eg (vendors~app-be21591da1b5607b3eb3-26.js:50)
di @ vendors~app-be21591da1b5607b3eb3-26.js:50
vendors~app-be21591da1b5607b3eb3-26.js:50 Uncaught TypeError: t.iter is not a function
    at estimateLineHeights (vendors~app-be21591da1b5607b3eb3-26.js:19)
    at attachDoc (vendors~app-be21591da1b5607b3eb3-26.js:19)
    at new CodeMirror (vendors~app-be21591da1b5607b3eb3-26.js:19)
    at CodeMirror (vendors~app-be21591da1b5607b3eb3-26.js:19)
    at Editor.componentDidMount (app-6544ad61fc0ebc2847bb-26.js:2167)
    at nj (vendors~app-be21591da1b5607b3eb3-26.js:50)
    at t.unstable_runWithPriority (vendors~app-be21591da1b5607b3eb3-26.js:9)
    at vf (vendors~app-be21591da1b5607b3eb3-26.js:50)
    at ij (vendors~app-be21591da1b5607b3eb3-26.js:50)
    at eg (vendors~app-be21591da1b5607b3eb3-26.js:50)
app-6544ad61fc0ebc2847bb-26.js:2167 Unable to write to local storage.
i @ app-6544ad61fc0ebc2847bb-26.js:2167

Unclear how to run only a single rule

I'm unable to figure out how to run Putout with only a single rule enabled. One would assume that putout src --enable remove-unused-variables, or that only having one plugin/rule specified in .putout.json would do the trick, but that turns out not to be the case, instead all default rules are enabled.

(This is not an issue as such, but if anyone could tell me how to do this I would like to add it to the docs. I do see now what --enable does, but it's not quite what one would expect.)

Putout never completes

Putout 13.2.0 worked fine. After I upgraded to 13.7.0, Putout can no longer complete, it just eats ~10% of my CPU and never finishes.

I'm using eslint-plugin-putout. I also tried running node_modules/.bin/putout, same result, it never finishes.

I does NOT reproduce on my CI, but it reproduces on my local machine (Windows 10, Node.js v14.15.4).

What can I do to gather more info?

Suggestion to have `remove-empty/import` off by default

Hi. Importing a module for its side effects only is very common, such as with:

import "core-js/stable";
import "regenerator-runtime/runtime";
import "styles.scss";

plugin-remove-empty's removal of the above is pretty unexpected, I would assume that any developer writing empty imports does so knowingly for the side effects. My question is therefore whether it would be valuable to turn this transformation off by default, in order for Putout's defaults to seem more helpful and sensible to the general developer.

This is just a suggestion, if you disagree please feel free to just close this issue.

Disable all rules

I'd like to use only the convert-commonjs-to-esm rule and not all the others that come in the default configuration. Is there a way to disable all rules without specifying them individually? e.g. something like "all": "off"?

Generally, I'd argue the default configuration should contain no rules, just like eslint does it.

eslint-plugin-putout can't detect JSX

When I try to lint a simple *.tsx file, like

function MyComponent() {
  return (
    <div>Hello</div>
  );
}

ESLint gives me the following error:

SyntaxError: Unterminated regular expression

With other *.tsx files it gives me the following error:

SyntaxError: Unexpected token, expected "</>/<=/>="

When I disable the putout/putout rule, ESLint and all other plugins start to work fine.

So, as I understand it, Putout can't detect that *.tsx files use JSX.

plugin-apply-destructuring changes code behavior

Before:

const objectA = { property: "" };
const objectB = { property: "foo" };

const property = objectA.property || objectB.property;

console.log(property); // prints "foo" (the value from objectB)

After:

const objectA = { property: "" };
const objectB = { property: "foo" };

const { property = objectB.property } = objectA;

console.log(property); // prints "" (the value from objectA)

putout fails with error if .eslintrc.js specifies an eslint plugin that is installed locally

If putout is installed globally (as recommended, via npm i putout -g) but eslint and a plugin, such as eslint-plugin-prettier are installed locally (via npm i eslint eslint-plugin-prettier --save-dev) and enabled in the .eslintrc.js file, attempting to run putout will fail.

Example .eslintrc.js file (must exist in the current working directory):

'use strict';

module.exports = {
    env: {
        node: true,
        es6: true,
        browser: true
    },
    plugins: ['prettier'],
    extends: ['eslint:recommended']
};

Command tested: putout --fix source.js. Note that the error does not occur when --fix is not specified (such as putout source.js).

Example of the error:

Error: Cannot find module 'eslint-plugin-prettier'
    at Function.Module._resolveFilename (module.js:548:15)
    at Function.Module._load (module.js:475:25)
    at Module.require (module.js:597:17)
    at require (internal/module.js:11:18)
    at loadPlugin (/Users/sgilroy/.nvm/versions/node/v8.15.0/lib/node_modules/putout/lib/eslint.js:26:12)
    at /Users/sgilroy/.nvm/versions/node/v8.15.0/lib/node_modules/putout/lib/eslint.js:36:25
    at getLinter (/Users/sgilroy/.nvm/versions/node/v8.15.0/lib/node_modules/putout/lib/eslint.js:57:28)
    at module.exports (/Users/sgilroy/.nvm/versions/node/v8.15.0/lib/node_modules/putout/lib/eslint.js:85:36)
    at /Users/sgilroy/.nvm/versions/node/v8.15.0/lib/node_modules/putout/lib/process-file.js:77:38
    at Array.map (<anonymous>)

Project to use to reproduce the problem:
eslint-plugin-error.zip

Workaround: install the eslint plugin globally npm i eslint-plugin-prettier -g.

Putout doesn't work in VS Code via ESLint

VS Code comes bundled with Node v12, but Putout now requires Node v14.

image

ESLint with Putout just doesn't work, this is what I get in VS Code log:

[Info  - 2:41:11 PM] ESLint server is starting
[Info  - 2:41:12 PM] ESLint server running in node v12.14.1
[Info  - 2:41:12 PM] ESLint server is running.
[Info  - 2:41:16 PM] ESLint library loaded from: C:\eslint-config-hardcore\node_modules\eslint\lib\api.js
[Info  - 2:41:21 PM] Failed to load plugin 'putout' declared in '.eslintrc.json ยป ./index.json ยป ./base.json': Cannot find module 'putout/parse-options' Require stack: - C:\eslint-config-hardcore\node_modules\eslint-plugin-putout\lib\putout\index.js - C:\eslint-config-hardcore\node_modules\eslint-plugin-putout\lib\index.js - C:\eslint-config-hardcore\node_modules\@eslint\eslintrc\lib\config-array-factory.js - C:\eslint-config-hardcore\node_modules\@eslint\eslintrc\lib\index.js - C:\eslint-config-hardcore\node_modules\eslint\lib\cli-engine\cli-engine.js - C:\eslint-config-hardcore\node_modules\eslint\lib\cli-engine\index.js - C:\eslint-config-hardcore\node_modules\eslint\lib\api.js - c:\Users\user\.vscode\extensions\dbaeumer.vscode-eslint-2.1.14\server\out\eslintServer.js

regexp/remove-useless-group false positives

regexp/remove-useless-group produces too many false positives.

Example code from MDN:

const imageDescription = 'This image has a resolution of 1440ร—900 pixels.';
const regexpSize = /([0-9]+)ร—([0-9]+)/;
const match = imageDescription.match(regexpSize);
console.log(`Width: ${match[1]} / Height: ${match[2]}.`);

Putout recommends using /[0-9]+ร—[0-9]+/, but the console.log() line will not work in that case.

Another example (an ember-cli-showdown initializer):

function initialize() {
  showdown.extension("smallLinks", function smallLinks() {
    return [
      {
        type: "output",
        regex: /<a (?<attributes>.*)>/u,
        replace: '<a class="link link--small" $<attributes>>',
      },
    ];
  });
}

Putout recommends using /<a .*>/u, but it will break the code (the replace will stop working properly).

Basically, there is no way to know whether capture groups will be used or not.

Putout doesn't work with Vue

ESlint version: 7.3.0
Bug: Putout doesn't work with Vuejs

Capture

When I comment out "putout" in the plugins's array, it works fine

This is my eslint's config file

{
  "env": {
    "browser": true,
    "es2020": true,
    "jest/globals": true,
    "jquery": true,
    "node": true,
    "react-native/react-native": true
  },
  "extends": [
    "airbnb",
    "airbnb-typescript",
    "airbnb/hooks",
    "plugin:@typescript-eslint/eslint-recommended",
    "plugin:@typescript-eslint/recommended",
    "plugin:json/recommended",
    "plugin:jsx-a11y/recommended",
    "plugin:lodash/recommended",
    "plugin:node/recommended",
    "plugin:optimize-regex/recommended",
    "plugin:react-hooks/recommended",
    "plugin:react-native/all",
    "plugin:react-redux/recommended",
    "plugin:react/recommended",
    "plugin:vue/vue3-recommended",
    "plugin:vue-scoped-css/vue3-recommended",
    "plugin:security/recommended",
    "plugin:sonarjs/recommended",
    "plugin:unicorn/recommended",
    "plugin:import/errors",
    "plugin:import/typescript",
    "plugin:array-func/recommended",
    "plugin:@getify/proper-arrows/getify-says",
    "plugin:no-unsanitized/DOM",
    "plugin:putout/recommended"
  ],
  "overrides": [
    {
      "files": [
        "**/*.ts",
        "**/*.tsx"
      ],
      "parser": "@typescript-eslint/parser",
      "rules": {
        "@typescript-eslint/ban-ts-ignore": 0,
        "@typescript-eslint/explicit-function-return-type": "error",
        "@typescript-eslint/explicit-module-boundary-types": "error",
        "@typescript-eslint/interface-name-prefix": 0,
        "@typescript-eslint/no-explicit-any": 0,
        "@typescript-eslint/no-non-null-assertion": 0,
        "@typescript-eslint/no-var-requires": "error"
      }
    },
    {
      "files": [
        "**/*.vue"
      ],
      "parser": "vue-eslint-parser",
      "parserOptions": {
        "parser": "@typescript-eslint/parser"
      }
    }
  ],
  "parser": "@babel/eslint-parser",
  "parserOptions": {
    "ecmaVersion": "latest",
    "jsx": true,
    "requireConfigFile": false,
    "sourceType": "module"
  },
  "plugins": [
    "@typescript-eslint",
    "html",
    "json",
    "json-format",
    "jsx-a11y",
    "lodash",
    "node",
    "optimize-regex",
    "react",
    "react-hooks",
    "react-native",
    "react-redux",
    "security",
    "sonarjs",
    "unicorn",
    "import",
    "array-func",
    "@getify/proper-arrows",
    "jest",
    "putout"
  ],
  "rules": {
    "@getify/proper-arrows/name": 0,
    "@getify/proper-arrows/params": 0,
    "@getify/proper-arrows/return": 0,
    "@getify/proper-arrows/this": 0,
    "@getify/proper-arrows/where": 0,
    "@typescript-eslint/ban-ts-comment": 0,
    "@typescript-eslint/dot-notation": 0,
    "@typescript-eslint/explicit-function-return-type": 0,
    "@typescript-eslint/explicit-module-boundary-types": 0,
    "@typescript-eslint/naming-convention": 0,
    "@typescript-eslint/no-implied-eval": 0,
    "@typescript-eslint/no-throw-literal": 0,
    "@typescript-eslint/no-unused-expressions": 0,
    "@typescript-eslint/no-var-requires": 0,
    "@typescript-eslint/return-await": 0,
    "@typescript-eslint/space-before-function-paren": [
      "error"
    ],
    "@typescript-eslint/triple-slash-reference": 0,
    "camelcase": 0,
    "func-names": 0,
    "global-require": 0,
    "import/extensions": [
      "error",
      "ignorePackages",
      {
        "js": "never",
        "jsx": "never",
        "ts": "never",
        "tsx": "never"
      }
    ],
    "import/no-dynamic-require": 0,
    "import/no-extraneous-dependencies": 0,
    "import/no-named-as-default-member": 0,
    "import/prefer-default-export": 0,
    "indent": 0,
    "jest/no-disabled-tests": "warn",
    "jest/no-focused-tests": "error",
    "jest/no-identical-title": "error",
    "jest/prefer-to-have-length": "warn",
    "jest/valid-expect": "error",
    "jsx-a11y/click-events-have-key-events": 0,
    "jsx-a11y/label-has-associated-control": 0,
    "jsx-a11y/no-static-element-interactions": 0,
    "linebreak-style": 0,
    "lodash/chaining": 0,
    "lodash/import-scope": 0,
    "lodash/prefer-constant": 0,
    "lodash/prefer-immutable-method": 0,
    "lodash/prefer-lodash-method": 0,
    "lodash/prefer-some": 0,
    "max-classes-per-file": 0,
    "max-len": 0,
    "new-cap": 0,
    "no-async-promise-executor": 0,
    "no-console": 0,
    "no-extend-native": 0,
    "no-param-reassign": 0,
    "no-plusplus": 0,
    "no-process-exit": 0,
    "no-restricted-properties": 0,
    "no-underscore-dangle": 0,
    "node/no-missing-import": 0,
    "node/no-unpublished-import": 0,
    "node/no-unpublished-require": 0,
    "node/no-unsupported-features/es-syntax": 0,
    "putout/destructuring-as-function-argument": 0,
    "putout/keyword-spacing": 0,
    "putout/newline-function-call-arguments": 0,
    "putout/putout": [
      "error",
      {
        "plugins": [
          "remove-duplicate-interface-keys"
        ],
        "rules": {
          "apply-numeric-separators": "off",
          "convert-for-each-to-for-of": "off",
          "promises/add-missing-await": "off",
          "remove-console": "off",
          "remove-constant-conditions": "off",
          "remove-empty/import": "off",
          "remove-unused-types": "off",
          "remove-unused-variables": "off",
          "split-nested-destructuring": "off",
          "strict-mode/add": "off"
        }
      }
    ],
    "quote-props": 0,
    "react-native/no-color-literals": 0,
    "react-native/no-raw-text": 0,
    "react-native/no-single-element-style-arrays": 0,
    "react/destructuring-assignment": 0,
    "react/display-name": 0,
    "react/forbid-prop-types": 0,
    "react/jsx-filename-extension": [
      1,
      {
        "extensions": [
          ".js",
          ".jsx",
          ".tsx"
        ]
      }
    ],
    "react/jsx-fragments": 0,
    "react/jsx-props-no-spreading": 0,
    "react/no-access-state-in-setstate": 0,
    "react/prop-types": 0,
    "react/require-default-props": 0,
    "react/state-in-constructor": 0,
    "react/style-prop-object": 0,
    "security/detect-child-process": 0,
    "security/detect-non-literal-fs-filename": 0,
    "security/detect-non-literal-regexp": 0,
    "security/detect-object-injection": 0,
    "security/detect-possible-timing-attacks": 0,
    "sonarjs/cognitive-complexity": 0,
    "sonarjs/no-small-switch": 0,
    "space-before-function-paren": "off",
    "unicorn/catch-error-name": 0,
    "unicorn/filename-case": 0,
    "unicorn/no-array-for-each": 0,
    "unicorn/no-array-reduce": 0,
    "unicorn/no-process-exit": 0,
    "unicorn/no-reduce": 0,
    "unicorn/no-useless-undefined": 0,
    "unicorn/numeric-separators-style": 0,
    "unicorn/prefer-module": 0,
    "unicorn/prefer-node-protocol": 0,
    "unicorn/prefer-spread": 0,
    "unicorn/prevent-abbreviations": 0
  },
  "settings": {
    "import/resolver": {
      "node": {
        "extensions": [
          ".js",
          ".jsx",
          ".ts",
          ".tsx"
        ]
      }
    },
    "json/ignore-files": [
      "**/package-lock.json"
    ],
    "json/json-with-comments-files": [
      "**/tsconfig.json",
      ".vscode/**"
    ],
    "json/sort-package-json": "standard",
    "react": {
      "version": "latest"
    }
  }
}

Destructuring Array assignment with type annotation creates invalid syntax

The code I'm working with has a type annotation and that gets carried over to the destructured array assignment. This:

const nextProps: DialogProps = dialogProps[0];

Becomes:

const [nextProps: DialogProps] = dialogProps;

This is not valid syntax and breaks the TypeScript compiler. It would probably be best to strip the type annotation and let TypeScript infer the type. There is no guarantee that dialogProps has a length > 0, so the initial code is bad form anyway because the type annotation acts as an assertion as well in this case.

remove-useless-arguments/destructuring false positive

const foo = bar(({ baz }) => ({ baz }));
foo({ qux: "qux" });

Expected result: there should be no remove-useless-arguments/destructuring warning.

Actual result:

2:7  error  "qux" is useless argument of a function "foo" (remove-useless-arguments/destructuring)  putout/putout

Looks like putout infers the signature of foo from the fat arrow function, but it should not do that. The signature of foo is unknown here.

ReferenceError: unknown node of type "ChainExpression" with constructor "Object"

Reproduction:

const bar = foo?.bar;

Full stack trace:

ESLint: 7.31.0

ReferenceError: unknown node of type "ChainExpression" with constructor "Object"
Occurred while linting /example/src/App.ts:1
    at Generator.print (/example/node_modules/@babel/generator/lib/printer.js:258:13)
    at Generator.generate (/example/node_modules/@babel/generator/lib/printer.js:38:10)
    at Generator.generate (/example/node_modules/@babel/generator/lib/index.js:23:18)
    at generate (/example/node_modules/@babel/generator/lib/index.js:95:14)
    at NodePath.toString (/example/node_modules/@babel/traverse/lib/path/index.js:164:35)
    at const __identifier = __b (/example/node_modules/@putout/plugin-reuse-duplicate-init/lib/reuse-duplicate-init.js:17:57)
    at module.exports (/example/node_modules/try-catch/lib/try-catch.js:5:23)
    at /example/node_modules/@putout/engine-runner/lib/template/index.js:87:21
    at NodePath._call (/example/node_modules/@babel/traverse/lib/path/context.js:53:20)
    at NodePath.call (/example/node_modules/@babel/traverse/lib/path/context.js:40:17)
    at NodePath.visit (/example/node_modules/@babel/traverse/lib/path/context.js:90:31)
    at TraversalContext.visitQueue (/example/node_modules/@babel/traverse/lib/context.js:99:16)
    at TraversalContext.visitMultiple (/example/node_modules/@babel/traverse/lib/context.js:68:17)
    at TraversalContext.visit (/example/node_modules/@babel/traverse/lib/context.js:125:19)
    at Function.traverse.node (/example/node_modules/@babel/traverse/lib/index.js:76:17)
    at NodePath.visit (/example/node_modules/@babel/traverse/lib/path/context.js:97:18)
    at TraversalContext.visitQueue (/example/node_modules/@babel/traverse/lib/context.js:99:16)
    at TraversalContext.visitSingle (/example/node_modules/@babel/traverse/lib/context.js:73:19)
    at TraversalContext.visit (/example/node_modules/@babel/traverse/lib/context.js:127:19)
    at Function.traverse.node (/example/node_modules/@babel/traverse/lib/index.js:76:17)
    at traverse (/example/node_modules/@babel/traverse/lib/index.js:56:12)
    at runWithMerge (/example/node_modules/@putout/engine-runner/lib/index.js:65:5)
    at run (/example/node_modules/@putout/engine-runner/lib/index.js:54:12)
    at module.exports.runPlugins (/example/node_modules/@putout/engine-runner/lib/index.js:32:18)
    at transform (/example/node_modules/putout/lib/putout.js:99:20)
    at module.exports.findPlaces (/example/node_modules/putout/lib/putout.js:71:12)
    at Program (/example/node_modules/eslint-plugin-putout/lib/putout/index.js:54:32)
    at /example/node_modules/eslint/lib/linter/safe-emitter.js:45:58
    at Array.forEach (<anonymous>)
    at Object.emit (/example/node_modules/eslint/lib/linter/safe-emitter.js:45:38)
    at NodeEventGenerator.applySelector (/example/node_modules/eslint/lib/linter/node-event-generator.js:293:26)
    at NodeEventGenerator.applySelectors (/example/node_modules/eslint/lib/linter/node-event-generator.js:322:22)
    at NodeEventGenerator.enterNode (/example/node_modules/eslint/lib/linter/node-event-generator.js:336:14)
    at CodePathAnalyzer.enterNode (/example/node_modules/eslint/lib/linter/code-path-analysis/code-path-analyzer.js:711:23)
    at /example/node_modules/eslint/lib/linter/linter.js:960:32
    at Array.forEach (<anonymous>)
    at runRules (/example/node_modules/eslint/lib/linter/linter.js:955:15)
    at Linter._verifyWithoutProcessors (/example/node_modules/eslint/lib/linter/linter.js:1181:31)
    at Linter._verifyWithoutProcessors (/example/node_modules/eslint-plugin-eslint-comments/lib/utils/patch.js:181:42)
    at Linter._verifyWithConfigArray (/example/node_modules/eslint/lib/linter/linter.js:1280:21)
    at Linter.verify (/example/node_modules/eslint/lib/linter/linter.js:1235:25)
    at Linter.verifyAndFix (/example/node_modules/eslint/lib/linter/linter.js:1428:29)
    at verifyText (/example/node_modules/eslint/lib/cli-engine/cli-engine.js:234:48)
    at CLIEngine.executeOnFiles (/example/node_modules/eslint/lib/cli-engine/cli-engine.js:802:28)
    at ESLint.lintFiles (/example/node_modules/eslint/lib/eslint/eslint.js:563:23)
    at Object.execute (/example/node_modules/eslint/lib/cli.js:299:36)
    at main (/example/node_modules/eslint/bin/eslint.js:132:52)
    at Object.<anonymous> (/example/node_modules/eslint/bin/eslint.js:136:2)
    at Module._compile (internal/modules/cjs/loader.js:1085:14)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1114:10)
    at Module.load (internal/modules/cjs/loader.js:950:32)
    at Function.Module._load (internal/modules/cjs/loader.js:790:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:76:12)
    at internal/main/run_main_module.js:17:47

codemod request: trace function calls

I'm looking to instrument code for debugging so I can trace what functions are being called -- a simple console.log('function name', arguments) added as the first command in functions would go a long way. If the class name (for non-anomymous classes) could be included for method calls, that'd be fantastic.

eslint-plugin-putout requires putout package

I really appreciate that 'eslint-plugin-putout' includes the following options:

{
  "putout/single-property-destructuring": "error",
  "putout/multiple-properties-destructuring": "error"
}

That said, the plugin doesn't work out-of-the-box w/ the provided instructions. 'eslint-plugin-putout' plugin requires the 'putout' package. However, its read me doesn't instruct us to npm i putout, nor does the 'eslint-plugin-putout' package install it or warn us that it needs to be intalled

The error that happens, silently in VS Code, is this

[Info  - 0:00:00 PM] Failed to load plugin 'eslint-plugin-putout' declared in '.eslintrc': 
Cannot find module 'putout' 
Require stack: - ./node_modules/eslint-plugin-putout/lib/keyword-spacing/index.js ...

My suggestion is to do the following

  1. Add putout to the npm i eslint eslint-plugin-putout line of the read me
  2. Add putout to the peerDependencies
  3. Add a try/catch around a root require('putout') w/ a clear+friendly error message

If that sounds right to y'all, I'd be happy to open a pull request to that effect

remove-unreachable-code deletes useful code

I faced with this issue on a real project, putout breaks the code when removing everything after the return statement.

Example

function test() {
	functionAfterReturn();
	return console.info('test');

	function functionAfterReturn() {
		console.info('functionAfterReturn');
	}
}
test()

After putout

'use strict';
function test() {
    functionAfterReturn(); //  <--- ReferenceError: functionAfterReturn is not defined
    return console.info('test');
}
test();

eslint-plugin-putout: comments break location reporting

Example:

// comment
foo;
eslint .

Expected result: reported line number should be 2

2:1  error  Unused expression statement (remove-unused-expressions)  putout/putout

Actual result: reported line number is 1

1:1  error  Unused expression statement (remove-unused-expressions)  putout/putout

breaking JSX

I had this code:

export const Hamburger = props => (
  <>
    <div className="bg-blue">
      <MenuContainer />
    </div>
  </>
);

putout changed it to:

export const Hamburger = () => (
  <>
    <div className="bg-blue">
      <MenuContainer />
    </div>
                                     </>;

so beside a formatting issue, the closing bracket is removed causing a syntax error.
Only remove-unused-variables rule was switched on.

removing empty imports

Running remove-unused-variables on
import { Foo } from 'bar';
produces
import 'bar';

Logically, i'd think this is expected, but I still need to get rid of these imports somehow.
Writing a plugin seems like the only option, but I have no idea how to "connect" these plugins together to get the result i'm looking for

// use remove-unused-vars
import { Foo } from 'bar';
import 'foo';
// use remove-unused-imports
import 'bar';  // <-- fix this
import 'foo'

Issue with relative paths

I had an issue with this on windows with relative paths

RangeError: path should be a 'path.relative()'d string, but got "C:\<path\to\root>\dist\main.js"

if (ignores(dir, resolvedName, options)) {

I fixed this with:

if (ignores(dir, name.replace(/^\./, cwd), options)) {

Improve code coverage

According to ci or npm run coverage in the root of repository.
There is some red places, would be great to add tests for them in the similar to existing tests.

Error: no plugin found for a rule: "apply-shorthand-properties"

I saw this in the changelog:

  • (putout) plugin-apply-shorthand-properties: remove from default install

After I upgraded Putout to v14, I ran npm i @putout/plugin-apply-shorthand-properties, but I'm still getting this error:

eslint .

Oops! Something went wrong! :(

ESLint: 7.18.0

Error: no plugin found for a rule: "apply-shorthand-properties"

This is what I have in my .eslintrc.json:

  "rules": {
    "putout/putout": [
      "error",
      {
        "rules": {
          "apply-shorthand-properties": "on"
        }
      }
    ]
  }

Did I do something wrong? How do I use apply-shorthand-properties with Putout v14 via ESLint?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.