├── .editorconfig ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .jscsrc ├── .jshintignore ├── .jshintrc ├── .travis.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── MAINTAIN.md ├── OVERVIEW.md ├── README.md ├── appveyor.yml ├── bin └── jscs ├── lib ├── checker.js ├── cli-config.js ├── cli.js ├── config │ ├── configuration.js │ ├── generator.js │ └── node-configuration.js ├── errors.js ├── extract-js.js ├── get-cli.js ├── js-file.js ├── reporters │ ├── checkstyle.js │ ├── console.js │ ├── inline.js │ ├── inlinesingle.js │ ├── json.js │ ├── junit.js │ ├── summary.js │ ├── text.js │ └── unix.js ├── rules │ ├── disallow-anonymous-functions.js │ ├── disallow-array-destructuring-return.js │ ├── disallow-arrow-functions.js │ ├── disallow-capitalized-comments.js │ ├── disallow-comma-before-line-break.js │ ├── disallow-curly-braces.js │ ├── disallow-dangling-underscores.js │ ├── disallow-empty-blocks.js │ ├── disallow-function-declarations.js │ ├── disallow-identical-destructuring-names.js │ ├── disallow-identifier-names.js │ ├── disallow-implicit-type-conversion.js │ ├── disallow-keywords-in-comments.js │ ├── disallow-keywords-on-new-line.js │ ├── disallow-keywords.js │ ├── disallow-mixed-spaces-and-tabs.js │ ├── disallow-multi-line-ternary.js │ ├── disallow-multiple-line-breaks.js │ ├── disallow-multiple-line-strings.js │ ├── disallow-multiple-spaces.js │ ├── disallow-multiple-var-decl.js │ ├── disallow-named-unassigned-functions.js │ ├── disallow-nested-ternaries.js │ ├── disallow-newline-before-block-statements.js │ ├── disallow-node-types.js │ ├── disallow-not-operators-in-conditionals.js │ ├── disallow-object-keys-on-new-line.js │ ├── disallow-operator-before-line-break.js │ ├── disallow-padding-newlines-after-blocks.js │ ├── disallow-padding-newlines-after-use-strict.js │ ├── disallow-padding-newlines-before-export.js │ ├── disallow-padding-newlines-before-keywords.js │ ├── disallow-padding-newlines-before-line-comments.js │ ├── disallow-padding-newlines-in-blocks.js │ ├── disallow-padding-newlines-in-objects.js │ ├── disallow-parentheses-around-arrow-param.js │ ├── disallow-quoted-keys-in-objects.js │ ├── disallow-semicolons.js │ ├── disallow-shorthand-arrow-functions.js │ ├── disallow-space-after-binary-operators.js │ ├── disallow-space-after-comma.js │ ├── disallow-space-after-keywords.js │ ├── disallow-space-after-line-comment.js │ ├── disallow-space-after-object-keys.js │ ├── disallow-space-after-prefix-unary-operators.js │ ├── disallow-space-before-binary-operators.js │ ├── disallow-space-before-block-statements.js │ ├── disallow-space-before-comma.js │ ├── disallow-space-before-keywords.js │ ├── disallow-space-before-object-values.js │ ├── disallow-space-before-postfix-unary-operators.js │ ├── disallow-space-before-semicolon.js │ ├── disallow-space-between-arguments.js │ ├── disallow-spaces-in-anonymous-function-expression.js │ ├── disallow-spaces-in-call-expression.js │ ├── disallow-spaces-in-conditional-expression.js │ ├── disallow-spaces-in-for-statement.js │ ├── disallow-spaces-in-function-declaration.js │ ├── disallow-spaces-in-function-expression.js │ ├── disallow-spaces-in-function.js │ ├── disallow-spaces-in-generator.js │ ├── disallow-spaces-in-named-function-expression.js │ ├── disallow-spaces-inside-array-brackets.js │ ├── disallow-spaces-inside-brackets.js │ ├── disallow-spaces-inside-imported-object-braces.js │ ├── disallow-spaces-inside-object-brackets.js │ ├── disallow-spaces-inside-parentheses.js │ ├── disallow-spaces-inside-parenthesized-expression.js │ ├── disallow-spaces-inside-template-string-placeholders.js │ ├── disallow-tabs.js │ ├── disallow-trailing-comma.js │ ├── disallow-trailing-whitespace.js │ ├── disallow-unused-params.js │ ├── disallow-unused-variables.js │ ├── disallow-var.js │ ├── disallow-yoda-conditions.js │ ├── jsdoc.js │ ├── maximum-line-length.js │ ├── maximum-number-of-lines.js │ ├── require-aligned-multiline-params.js │ ├── require-aligned-object-values.js │ ├── require-anonymous-functions.js │ ├── require-array-destructuring.js │ ├── require-arrow-functions.js │ ├── require-blocks-on-newline.js │ ├── require-camelcase-or-uppercase-identifiers.js │ ├── require-capitalized-comments.js │ ├── require-capitalized-constructors-new.js │ ├── require-capitalized-constructors.js │ ├── require-comma-before-line-break.js │ ├── require-curly-braces.js │ ├── require-dollar-before-jquery-assignment.js │ ├── require-dot-notation.js │ ├── require-early-return.js │ ├── require-enhanced-object-literals.js │ ├── require-function-declarations.js │ ├── require-imports-alphabetized.js │ ├── require-keywords-on-new-line.js │ ├── require-line-break-after-variable-assignment.js │ ├── require-line-feed-at-file-end.js │ ├── require-matching-function-name.js │ ├── require-multi-line-ternary.js │ ├── require-multiple-var-decl.js │ ├── require-named-unassigned-functions.js │ ├── require-newline-before-block-statements.js │ ├── require-newline-before-single-statements-in-if.js │ ├── require-numeric-literals.js │ ├── require-object-destructuring.js │ ├── require-object-keys-on-new-line.js │ ├── require-operator-before-line-break.js │ ├── require-padding-newline-after-variable-declaration.js │ ├── require-padding-newlines-after-blocks.js │ ├── require-padding-newlines-after-use-strict.js │ ├── require-padding-newlines-before-export.js │ ├── require-padding-newlines-before-keywords.js │ ├── require-padding-newlines-before-line-comments.js │ ├── require-padding-newlines-in-blocks.js │ ├── require-padding-newlines-in-objects.js │ ├── require-parentheses-around-arrow-param.js │ ├── require-parentheses-around-iife.js │ ├── require-quoted-keys-in-objects.js │ ├── require-semicolons.js │ ├── require-shorthand-arrow-functions.js │ ├── require-space-after-binary-operators.js │ ├── require-space-after-comma.js │ ├── require-space-after-keywords.js │ ├── require-space-after-line-comment.js │ ├── require-space-after-object-keys.js │ ├── require-space-after-prefix-unary-operators.js │ ├── require-space-before-binary-operators.js │ ├── require-space-before-block-statements.js │ ├── require-space-before-comma.js │ ├── require-space-before-destructured-values.js │ ├── require-space-before-keywords.js │ ├── require-space-before-object-values.js │ ├── require-space-before-postfix-unary-operators.js │ ├── require-space-between-arguments.js │ ├── require-spaces-in-anonymous-function-expression.js │ ├── require-spaces-in-call-expression.js │ ├── require-spaces-in-conditional-expression.js │ ├── require-spaces-in-for-statement.js │ ├── require-spaces-in-function-declaration.js │ ├── require-spaces-in-function-expression.js │ ├── require-spaces-in-function.js │ ├── require-spaces-in-generator.js │ ├── require-spaces-in-named-function-expression.js │ ├── require-spaces-inside-array-brackets.js │ ├── require-spaces-inside-brackets.js │ ├── require-spaces-inside-imported-object-braces.js │ ├── require-spaces-inside-object-brackets.js │ ├── require-spaces-inside-parentheses.js │ ├── require-spaces-inside-parenthesized-expression.js │ ├── require-spread.js │ ├── require-template-strings.js │ ├── require-trailing-comma.js │ ├── require-use-strict.js │ ├── require-var-decl-first.js │ ├── require-yoda-conditions.js │ ├── safe-context-keyword.js │ ├── validate-aligned-function-parameters.js │ ├── validate-comment-position.js │ ├── validate-indentation.js │ ├── validate-line-breaks.js │ ├── validate-newline-after-array-elements.js │ ├── validate-order-in-object-keys.js │ ├── validate-parameter-separator.js │ └── validate-quote-marks.js ├── string-checker.js ├── token-assert.js ├── token-categorizer.js ├── token-index.js ├── tree-iterator.js └── utils.js ├── package.json ├── patterns ├── L.js ├── Ll.js ├── Lu.js ├── identifiers-ES5.js └── identifiers-ES6.js ├── presets ├── airbnb.json ├── crockford.json ├── google.json ├── grunt.json ├── idiomatic.json ├── jquery.json ├── mdcs.json ├── node-style-guide.json └── wordpress.json ├── publish ├── helpers │ ├── generate-patterns.js │ └── plugins.js └── prepublish.js ├── templates └── pr-create.md.ejs └── test ├── chai-extensions.js ├── data ├── autofixing │ └── spaces.js ├── checker │ ├── empty.js │ ├── file.js │ ├── sub │ │ └── file.js │ └── without-extension ├── cli │ ├── cli.json │ ├── error.js │ ├── errorFilter.json │ ├── esnext.js │ ├── maxErrors.json │ ├── modules │ │ └── node_modules │ │ │ └── jscs │ │ │ └── lib │ │ │ └── cli.js │ ├── stdin.js │ └── success.js ├── config.json ├── configs │ ├── additionalRules │ │ ├── .jscsrc │ │ ├── gh-1932 │ │ │ ├── .jscsrc │ │ │ └── success-rule.js │ │ └── success-rule.js │ ├── custom │ │ └── config.js │ ├── emptyPackage │ │ └── package.json │ ├── excludeFiles │ │ ├── .withdot │ │ │ └── error.js │ │ ├── exclude-files.js │ │ ├── nested │ │ │ └── exclude-files.js │ │ ├── test1.jscs.json │ │ ├── test2.jscs.json │ │ ├── test3.jscs.json │ │ └── test4.jscs.json │ ├── generator │ │ └── crockfordClone.json │ ├── jscsrc │ │ ├── .jscsrc │ │ └── external.jscsrc │ ├── json │ │ ├── .jscs.json │ │ ├── corrupted.json │ │ ├── withBOM.json │ │ └── withComments.json │ ├── mixedWithEmptyPkg │ │ ├── .jscsrc │ │ └── package.json │ ├── mixedWithPkg │ │ ├── .jscs.json │ │ ├── .jscsrc │ │ └── package.json │ ├── mixedWithUpperPkg │ │ ├── jscsrc │ │ │ ├── .jscs.json │ │ │ └── .jscsrc │ │ └── package.json │ ├── mixedWithoutPkg │ │ ├── .jscs.json │ │ └── .jscsrc │ ├── modules │ │ └── node_modules │ │ │ ├── jscs-config-first-test │ │ │ ├── index.json │ │ │ └── package.json │ │ │ ├── jscs-esprima │ │ │ ├── esprima.js │ │ │ ├── index.json │ │ │ └── package.json │ │ │ ├── jscs-filter │ │ │ ├── filter.js │ │ │ ├── index.json │ │ │ └── package.json │ │ │ ├── jscs-mod │ │ │ ├── index.json │ │ │ ├── js-module.js │ │ │ ├── module.json │ │ │ └── package.json │ │ │ ├── jscs-plugin │ │ │ ├── index.json │ │ │ ├── package.json │ │ │ └── plugin.js │ │ │ ├── jscs-preset-module │ │ │ ├── index.json │ │ │ ├── js-module.js │ │ │ ├── module.json │ │ │ └── package.json │ │ │ ├── jscs-preset-nm │ │ │ ├── index.json │ │ │ ├── node_modules │ │ │ │ └── jscs-config-test │ │ │ │ │ ├── index.json │ │ │ │ │ └── package.json │ │ │ ├── package.json │ │ │ └── rule.js │ │ │ ├── jscs-preset-s-test │ │ │ ├── index.json │ │ │ └── package.json │ │ │ ├── jscs-preset-wikimedia │ │ │ ├── index.json │ │ │ └── package.json │ │ │ ├── jscs-rule │ │ │ ├── index.json │ │ │ ├── package.json │ │ │ └── rule.js │ │ │ ├── jscs-t-test │ │ │ ├── .jscsrc │ │ │ ├── index.json │ │ │ └── package.json │ │ │ └── test │ │ │ ├── index.json │ │ │ └── package.json │ ├── package │ │ └── package.json │ └── yaml │ │ ├── .jscs.yaml │ │ └── .jscsrc ├── error-filter │ ├── index.js │ └── modules │ │ └── node_modules │ │ ├── jscs-config-filter │ │ ├── index.json │ │ └── package.json │ │ └── jscs-error-filter │ │ ├── index.json │ │ └── package.json ├── extract │ ├── always.htm │ ├── index.html │ ├── plain.txt │ └── valid.xhtml ├── options │ ├── file-extensions │ │ ├── file-extensions │ │ ├── file-extensions-2.jS │ │ ├── file-extensions.js │ │ └── file-extensions.jsx │ └── preset │ │ ├── airbnb.js │ │ ├── crockford.js │ │ ├── google.js │ │ ├── grunt.js │ │ ├── idiomatic.js │ │ ├── jquery.js │ │ ├── mdcs.js │ │ ├── node-style-guide.js │ │ └── wordpress.js ├── plugin │ └── plugin.js ├── render │ ├── comments.js │ ├── hashbang.js │ ├── ios-includes.js │ └── strings.js ├── reporter │ └── test-reporter.js ├── rules │ ├── additional-rules.js │ └── skip.error ├── tree-iterator │ ├── jsx-ast.js │ └── xjs-ast.js └── validate-indentation │ ├── check.js │ ├── fix-expected.js │ ├── fix-include-empty-expected.js │ ├── fix-include-empty-input.js │ └── fix-input.js ├── lib └── assertHelpers.js ├── mocha.opts ├── scripts ├── forgotten-rules.json └── integration.js └── specs ├── .jshintrc ├── checker.js ├── cli-config.js ├── cli.js ├── config ├── configuration.js ├── generator.js └── node-configuration.js ├── errors.js ├── extract-js.js ├── get-cli.js ├── js-file.js ├── reporters ├── checkstyle.js ├── console.js ├── inline.js ├── inlinesingle.js ├── json.js ├── junit.js ├── summary.js ├── text.js └── unix.js ├── rules ├── disallow-anonymous-functions.js ├── disallow-array-destructuring-return.js ├── disallow-arrow-functions.js ├── disallow-capitalized-comments.js ├── disallow-comma-before-line-break.js ├── disallow-curly-braces.js ├── disallow-dangling-underscores.js ├── disallow-empty-blocks.js ├── disallow-function-declarations.js ├── disallow-identical-destructuring-names.js ├── disallow-identifier-names.js ├── disallow-implicit-type-conversion.js ├── disallow-keywords-in-comments.js ├── disallow-keywords-on-new-line.js ├── disallow-keywords.js ├── disallow-mixed-spaces-and-tabs.js ├── disallow-multi-line-ternary.js ├── disallow-multiple-line-breaks.js ├── disallow-multiple-line-strings.js ├── disallow-multiple-spaces.js ├── disallow-multiple-var-decl.js ├── disallow-named-unassigned-functions.js ├── disallow-nested-ternaries.js ├── disallow-newline-before-block-statements.js ├── disallow-node-types.js ├── disallow-not-operators-in-conditionals.js ├── disallow-object-keys-on-new-line.js ├── disallow-operator-before-line-break.js ├── disallow-padding-newlines-after-blocks.js ├── disallow-padding-newlines-after-use-strict.js ├── disallow-padding-newlines-before-export.js ├── disallow-padding-newlines-before-keywords.js ├── disallow-padding-newlines-before-line-comments.js ├── disallow-padding-newlines-in-blocks.js ├── disallow-padding-newlines-in-objects.js ├── disallow-parentheses-around-arrow-param.js ├── disallow-quoted-keys-in-objects.js ├── disallow-semicolons.js ├── disallow-shorthand-arrow-functions.js ├── disallow-space-after-binary-operators.js ├── disallow-space-after-comma.js ├── disallow-space-after-keywords.js ├── disallow-space-after-line-comment.js ├── disallow-space-after-object-keys.js ├── disallow-space-after-prefix-unary-operators.js ├── disallow-space-before-binary-operators.js ├── disallow-space-before-block-statements.js ├── disallow-space-before-comma.js ├── disallow-space-before-keywords.js ├── disallow-space-before-object-values.js ├── disallow-space-before-postfix-unary-operators.js ├── disallow-space-before-semicolon.js ├── disallow-space-between-arguments.js ├── disallow-spaces-in-anonymous-function-expression.js ├── disallow-spaces-in-call-expression.js ├── disallow-spaces-in-conditional-expression.js ├── disallow-spaces-in-for-statement.js ├── disallow-spaces-in-function-declaration.js ├── disallow-spaces-in-function-expression.js ├── disallow-spaces-in-function.js ├── disallow-spaces-in-generator.js ├── disallow-spaces-in-named-function-expression.js ├── disallow-spaces-inside-array-brackets.js ├── disallow-spaces-inside-brackets.js ├── disallow-spaces-inside-imported-object-braces.js ├── disallow-spaces-inside-object-brackets.js ├── disallow-spaces-inside-parentheses.js ├── disallow-spaces-inside-parenthesized-expression.js ├── disallow-spaces-inside-template-string-placeholders.js ├── disallow-tabs.js ├── disallow-trailing-comma.js ├── disallow-trailing-whitespace.js ├── disallow-unused-params.js ├── disallow-unused-variables.js ├── disallow-var.js ├── disallow-yoda-conditions.js ├── maximum-line-length.js ├── maximum-number-of-lines.js ├── require-aligned-multiline-params.js ├── require-aligned-object-values.js ├── require-anonymous-functions.js ├── require-array-destructuring.js ├── require-arrow-functions.js ├── require-blocks-on-newline.js ├── require-camelcase-or-uppercase-identifiers.js ├── require-capitalized-comments.js ├── require-capitalized-constructors-new.js ├── require-capitalized-constructors.js ├── require-comma-before-line-break.js ├── require-curly-braces.js ├── require-dollar-before-jquery-assignment.js ├── require-dot-notation.js ├── require-early-return.js ├── require-enhanced-object-literals.js ├── require-function-declarations.js ├── require-imports-alphabetized.js ├── require-keywords-on-new-line.js ├── require-line-break-after-variable-assignment.js ├── require-line-feed-at-file-end.js ├── require-matching-function-name.js ├── require-multi-line-ternary.js ├── require-multiple-var-decl.js ├── require-named-unassigned-functions.js ├── require-newline-before-block-statements.js ├── require-newline-before-single-statements-in-if.js ├── require-numeric-literals.js ├── require-object-destructuring.js ├── require-object-keys-on-new-line.js ├── require-operator-before-line-break.js ├── require-padding-newline-after-variable-declaration.js ├── require-padding-newlines-after-blocks.js ├── require-padding-newlines-after-use-strict.js ├── require-padding-newlines-before-export.js ├── require-padding-newlines-before-keywords.js ├── require-padding-newlines-before-line-comments.js ├── require-padding-newlines-in-blocks.js ├── require-padding-newlines-in-objects.js ├── require-parentheses-around-arrow-param.js ├── require-parentheses-around-iife.js ├── require-quoted-keys-in-objects.js ├── require-semicolons.js ├── require-shorthand-arrow-functions.js ├── require-space-after-binary-operators.js ├── require-space-after-comma.js ├── require-space-after-keywords.js ├── require-space-after-line-comment.js ├── require-space-after-object-keys.js ├── require-space-after-prefix-unary-operators.js ├── require-space-before-binary-operators.js ├── require-space-before-block-statements.js ├── require-space-before-comma.js ├── require-space-before-destructured-values.js ├── require-space-before-keywords.js ├── require-space-before-object-values.js ├── require-space-before-postfix-unary-operators.js ├── require-space-between-arguments.js ├── require-spaces-in-anonymous-function-expression.js ├── require-spaces-in-call-expression.js ├── require-spaces-in-conditional-expression.js ├── require-spaces-in-for-statement.js ├── require-spaces-in-function-declaration.js ├── require-spaces-in-function-expression.js ├── require-spaces-in-function.js ├── require-spaces-in-generator.js ├── require-spaces-in-named-function-expression.js ├── require-spaces-inside-array-brackets.js ├── require-spaces-inside-brackets.js ├── require-spaces-inside-imported-object-braces.js ├── require-spaces-inside-object-brackets.js ├── require-spaces-inside-parentheses.js ├── require-spaces-inside-parenthesized-expression.js ├── require-spread.js ├── require-template-strings.js ├── require-trailing-comma.js ├── require-use-strict.js ├── require-var-decl-first.js ├── require-yoda-conditions.js ├── safe-context-keyword.js ├── validate-aligned-function-parameters.js ├── validate-comment-position.js ├── validate-indentation.js ├── validate-line-breaks.js ├── validate-newline-after-array-elements.js ├── validate-order-in-object-keys.js ├── validate-parameter-separator.js └── validate-quote-marks.js ├── string-checker.js ├── token-assert.js ├── token-categorizer.js ├── token-index.js ├── tree-iterator.js └── utils.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # This file is for unifying the coding style for different editors and IDEs 2 | # editorconfig.org 3 | 4 | root = true 5 | 6 | [*] 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | end_of_line = lf 10 | insert_final_newline = true 11 | indent_style = space 12 | indent_size = 4 13 | 14 | [package.json] 15 | indent_size = 2 16 | 17 | [*.md] 18 | trim_trailing_whitespace = false 19 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text eol=lf 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### JSCS is deprecated 2 | 3 | Thanks for wanting to contribute, but this project is deprecated. 4 | 5 | We recommend using [ESLint](http://eslint.org/) instead (the JSCS team will be contributing there). 6 | 7 | Check out our blog posts for more information: 8 | 9 | * [JSCS — end of the line](https://medium.com/@markelog/jscs-end-of-the-line-bc9bf0b3fdb2) 10 | * [Welcoming JSCS to ESLint](http://eslint.org/blog/2016/04/welcoming-jscs-to-eslint) 11 | * [JSCS End of Life](http://eslint.org/blog/2016/07/jscs-end-of-life) 12 | 13 | > If you would like to contribute to the JSCS Compatibility Effort, follow the [milestone here](https://github.com/eslint/eslint/milestone/15). 14 | 15 | Since we won't be maintaining the project, please do not open issues/PRs here. Thanks! 16 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### JSCS is deprecated 2 | 3 | Thanks for wanting to contribute, but this project is deprecated. 4 | 5 | We recommend using [ESLint](http://eslint.org/) instead (the JSCS team will be contributing there). 6 | 7 | Check out our blog posts for more information: 8 | 9 | * [JSCS — end of the line](https://medium.com/@markelog/jscs-end-of-the-line-bc9bf0b3fdb2) 10 | * [Welcoming JSCS to ESLint](http://eslint.org/blog/2016/04/welcoming-jscs-to-eslint) 11 | * [JSCS End of Life](http://eslint.org/blog/2016/07/jscs-end-of-life) 12 | 13 | > If you would like to contribute to the JSCS Compatibility Effort, follow the [milestone here](https://github.com/eslint/eslint/milestone/15). 14 | 15 | Since we won't be maintaining the project, please do not open issues/PRs here. Thanks! 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | .idea 3 | *.sublime-* 4 | /npm-debug.log 5 | /coverage.html 6 | -------------------------------------------------------------------------------- /.jscsrc: -------------------------------------------------------------------------------- 1 | { 2 | "preset": "google", 3 | "fileExtensions": [".js", "jscs"], 4 | 5 | "requireSemicolons": true, 6 | "requireParenthesesAroundIIFE": true, 7 | "maximumLineLength": 120, 8 | "validateLineBreaks": "LF", 9 | "validateIndentation": 4, 10 | "disallowTrailingComma": true, 11 | "disallowUnusedParams": true, 12 | 13 | "disallowSpacesInsideObjectBrackets": null, 14 | "disallowImplicitTypeConversion": ["string"], 15 | 16 | "safeContextKeyword": "_this", 17 | 18 | "jsDoc": { 19 | "checkAnnotations": "closurecompiler", 20 | "checkParamNames": true, 21 | "requireParamTypes": true, 22 | "checkRedundantParams": true, 23 | "checkReturnTypes": true, 24 | "checkRedundantReturns": true, 25 | "requireReturnTypes": true, 26 | "checkTypes": "capitalizedNativeCase", 27 | "checkRedundantAccess": true, 28 | "requireNewlineAfterDescription": true 29 | }, 30 | 31 | "excludeFiles": [ 32 | "test/data/**", 33 | "patterns/*" 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /.jshintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | test/data/** 3 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node" : true, 3 | "bitwise" : true, 4 | "undef" : true, 5 | "eqeqeq" : true, 6 | "noarg" : true, 7 | "mocha" : true, 8 | "unused" : true, 9 | "asi" : true, 10 | "esnext" : true 11 | } 12 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | git: 2 | depth: 1 3 | 4 | sudo: false 5 | 6 | language: node_js 7 | node_js: 8 | - "6" 9 | - "5" 10 | - "4" 11 | - "0.12" 12 | - "0.10" 13 | 14 | script: "npm run $TEST_SUITE" 15 | 16 | env: 17 | - TEST_SUITE=test 18 | - TEST_SUITE=integration TEST_PRESET=airbnb,google,jquery 19 | 20 | matrix: 21 | fast_finish: true 22 | include: 23 | - node_js: "0.10" 24 | env: TEST_SUITE=integration TEST_PRESET=./test/scripts/forgotten-rules.json 25 | - node_js: "0.12" 26 | env: TEST_SUITE=integration TEST_PRESET=node-style-guide,wordpress 27 | - node_js: "4" 28 | env: TEST_SUITE=integration TEST_PRESET=crockford,idiomatic 29 | - node_js: "5" 30 | env: TEST_SUITE=integration TEST_PRESET=grunt,mdcs 31 | - node_js: "5" 32 | env: TEST_SUITE=coveralls 33 | 34 | cache: 35 | directories: 36 | - node_modules 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright 2013-2016 Dulin Marat and other contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JSCS has [merged](https://medium.com/@markelog/jscs-end-of-the-line-bc9bf0b3fdb2#.x0o1xqkk9) with ESLint! 2 | 3 | [![NPM Version](https://img.shields.io/npm/v/jscs.svg?style=flat)](https://www.npmjs.com/package/jscs) 4 | [![Build Status](https://travis-ci.org/jscs-dev/node-jscs.svg?branch=master)](https://travis-ci.org/jscs-dev/node-jscs) 5 | [![Coverage Status](https://img.shields.io/coveralls/jscs-dev/node-jscs.svg?style=flat)](https://coveralls.io/r/jscs-dev/node-jscs?branch=master) 6 | 7 | **JSCS** is a code style linter and formatter for your style guide 8 | 9 | 10 | 11 | * [Tutorial and Overview](http://jscs.info/overview) 12 | * [Codestyle Rules](http://jscs.info/rules) 13 | * [How to Contribute](http://jscs.info/contributing) 14 | 15 | ## Security contact information 16 | 17 | To report a security vulnerability, please use the 18 | [Tidelift security contact](https://tidelift.com/security). 19 | Tidelift will coordinate the fix and disclosure. 20 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: "{build}" 2 | 3 | environment: 4 | nodejs_version: "0.12" 5 | 6 | matrix: 7 | fast_finish: true 8 | 9 | install: 10 | - ps: Install-Product node $env:nodejs_version 11 | - node --version 12 | - npm --version 13 | - npm install 14 | 15 | test_script: 16 | - npm test 17 | 18 | build: off 19 | -------------------------------------------------------------------------------- /bin/jscs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | var cli = require('../lib/get-cli'); 3 | 4 | /** 5 | * Command line implementation for JSCS. 6 | * 7 | * Common usage case is: 8 | * 9 | * ./node_modules/.bin/jscs file1 dir1 file2 dir2 10 | */ 11 | var program = require('commander'); 12 | 13 | program 14 | .version(require('../package.json').version) 15 | .usage('[options] ') 16 | .description('A code style linter for programmatically enforcing your style guide.') 17 | .option('-c, --config [path]', 'configuration file path') 18 | .option('--auto-configure [paths]', 'auto-generate a JSCS configuration file') 19 | .option('-x, --fix', 'fix code style violations (applies to fixable violations)') 20 | .option('--extract ', 'set file masks from which to extract JavaScript', function(value, memo) { 21 | return memo ? memo.concat(value) : [value]; 22 | }) 23 | .option('--es3', 'validates code as es3') 24 | .option('-n, --no-colors', 'clean output without colors') 25 | .option('-p, --preset ', 'preset config') 26 | .option('-m, --max-errors ', 'maximum number of errors to report') 27 | .option('-f, --error-filter ', 'a module to filter errors') 28 | .option('-r, --reporter ', 29 | 'error reporter, console - default, text, checkstyle, junit, inline, unix, summary, json') 30 | .option('', 'Also accepts relative or absolute path to custom reporter') 31 | .option('', 'For instance:') 32 | .option('', '\t ../some-dir/my-reporter.js\t(relative path with extension)') 33 | .option('', '\t ../some-dir/my-reporter\t(relative path without extension)') 34 | .option('', '\t /path/to/my-reporter.js\t(absolute path with extension)') 35 | .option('', '\t /path/to/my-reporter\t\t(absolute path without extension)') 36 | .parse(process.argv); 37 | 38 | cli(program); 39 | -------------------------------------------------------------------------------- /lib/get-cli.js: -------------------------------------------------------------------------------- 1 | var resolve = require('resolve'); 2 | 3 | var cli; 4 | try { 5 | cli = require( 6 | resolve.sync('jscs/lib/cli', { basedir: process.cwd() }) 7 | ); 8 | } catch (e) { 9 | cli = require('./cli'); 10 | } 11 | 12 | module.exports = cli; 13 | -------------------------------------------------------------------------------- /lib/reporters/checkstyle.js: -------------------------------------------------------------------------------- 1 | function escapeAttrValue(attrValue) { 2 | return String(attrValue) 3 | .replace(/&/g, '&') 4 | .replace(/"/g, '"') 5 | .replace(//g, '>'); 7 | } 8 | 9 | module.exports = function(errorCollection) { 10 | console.log('\n'); 11 | errorCollection.forEach(function(errors) { 12 | console.log(' '); 13 | errors.getErrorList().forEach(function(error) { 14 | console.log( 15 | ' ' 21 | ); 22 | }); 23 | console.log(' '); 24 | }); 25 | console.log(''); 26 | }; 27 | -------------------------------------------------------------------------------- /lib/reporters/console.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {Errors[]} errorsCollection 3 | */ 4 | module.exports = function(errorsCollection) { 5 | var errorCount = 0; 6 | /** 7 | * Formatting every error set. 8 | */ 9 | errorsCollection.forEach(function(errors) { 10 | if (!errors.isEmpty()) { 11 | /** 12 | * Formatting every single error. 13 | */ 14 | errors.getErrorList().forEach(function(error) { 15 | errorCount++; 16 | console.log(errors.explainError(error, true) + '\n'); 17 | }); 18 | } 19 | }); 20 | if (errorCount) { 21 | /** 22 | * Printing summary. 23 | */ 24 | console.log('\n' + errorCount + ' code style ' + (errorCount === 1 ? 'error' : 'errors') + ' found.'); 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /lib/reporters/inline.js: -------------------------------------------------------------------------------- 1 | var util = require('util'); 2 | /** 3 | * @param {Errors[]} errorsCollection 4 | */ 5 | module.exports = function(errorsCollection) { 6 | var errorCount = 0; 7 | /** 8 | * Formatting every error set. 9 | */ 10 | errorsCollection.forEach(function(errors) { 11 | var file = errors.getFilename(); 12 | if (!errors.isEmpty()) { 13 | errors.getErrorList().forEach(function(error) { 14 | errorCount++; 15 | console.log(util.format('%s: line %d, col %d, %s', file, error.line, error.column, error.message)); 16 | }); 17 | } 18 | }); 19 | }; 20 | -------------------------------------------------------------------------------- /lib/reporters/inlinesingle.js: -------------------------------------------------------------------------------- 1 | /** 2 | * inlinesingle solves an issue that Windows (7+) users have been 3 | * experiencing using SublimeLinter-jscs. It appears this is due to 4 | * SublimeText not managing multi-line output properly on these machines. 5 | * This reporter differs from inline.js by producing one comment line 6 | * separated by linebreaks rather than a series of separate lines. 7 | */ 8 | 9 | var util = require('util'); 10 | 11 | /** 12 | * @param {Errors[]} errorsCollection 13 | */ 14 | module.exports = function(errorsCollection) { 15 | errorsCollection.forEach(function(errors) { 16 | if (!errors.isEmpty()) { 17 | var file = errors.getFilename(); 18 | var out = errors.getErrorList().map(function(error) { 19 | return util.format('%s: line %d, col %d, %s', file, error.line, error.column, error.message); 20 | }); 21 | console.log(out.join('\n')); 22 | } 23 | }); 24 | }; 25 | -------------------------------------------------------------------------------- /lib/reporters/json.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {Errors[]} errorsCollection 3 | */ 4 | module.exports = function(errorsCollection) { 5 | var jsonOutput = {}; 6 | var anyError = false; 7 | errorsCollection.forEach(function(errors) { 8 | var file = errors.getFilename(); 9 | var arr = jsonOutput[file] = []; 10 | 11 | if (!errors.isEmpty()) { 12 | anyError = true; 13 | } 14 | errors.getErrorList().forEach(function(error) { 15 | arr.push({ 16 | line: error.line, 17 | column: error.column + 1, 18 | message: error.message 19 | }); 20 | }); 21 | }); 22 | if (anyError) { 23 | console.log(JSON.stringify(jsonOutput)); 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /lib/reporters/junit.js: -------------------------------------------------------------------------------- 1 | var xml = require('xmlbuilder'); 2 | 3 | module.exports = function(errorCollection) { 4 | var i = 0; 5 | var testsuite = xml.create('testsuite'); 6 | 7 | testsuite.att('name', 'JSCS'); 8 | testsuite.att('tests', errorCollection.length); 9 | 10 | errorCollection.forEach(function(errors) { 11 | var errorsCount = errors.getErrorCount(); 12 | var testcase = testsuite.ele('testcase', { 13 | name: errors.getFilename(), 14 | failures: errorsCount 15 | }); 16 | 17 | i += errorsCount; 18 | 19 | errors.getErrorList().forEach(function(error) { 20 | testcase.ele('failure', {}, errors.explainError(error)); 21 | }); 22 | }); 23 | 24 | testsuite.att('failures', i); 25 | 26 | console.log(testsuite.end({pretty: true})); 27 | }; 28 | -------------------------------------------------------------------------------- /lib/reporters/text.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {Errors[]} errorsCollection 3 | */ 4 | module.exports = function(errorsCollection) { 5 | var errorCount = 0; 6 | /** 7 | * Formatting every error set. 8 | */ 9 | errorsCollection.forEach(function(errors) { 10 | if (!errors.isEmpty()) { 11 | /** 12 | * Formatting every single error. 13 | */ 14 | errors.getErrorList().forEach(function(error) { 15 | errorCount++; 16 | console.log(errors.explainError(error) + '\n'); 17 | }); 18 | } 19 | }); 20 | if (errorCount) { 21 | /** 22 | * Printing summary. 23 | */ 24 | console.log('\n' + errorCount + ' code style ' + (errorCount === 1 ? 'error' : 'errors') + ' found.'); 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /lib/reporters/unix.js: -------------------------------------------------------------------------------- 1 | var util = require('util'); 2 | 3 | /** 4 | * @param {Errors[]} errorsCollection 5 | */ 6 | module.exports = function(errorsCollection) { 7 | errorsCollection.forEach(function(errors) { 8 | var file = errors.getFilename(); 9 | if (!errors.isEmpty()) { 10 | errors.getErrorList().forEach(function(error) { 11 | console.log(util.format('%s:%d:%d: %s', file, error.line, error.column, error.message)); 12 | }); 13 | } 14 | }); 15 | }; 16 | -------------------------------------------------------------------------------- /lib/rules/disallow-anonymous-functions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Requires that a function expression be named. 3 | * Named functions provide more information in the error stack trace than anonymous functions. 4 | * 5 | * This option does not help if you use Arrow functions (ES6) which are always anonymous. 6 | * 7 | * Type: `Boolean` 8 | * 9 | * Value: `true` 10 | * 11 | * #### Example 12 | * 13 | * ```js 14 | * "disallowAnonymousFunctions": true 15 | * ``` 16 | * 17 | * ##### Valid 18 | * 19 | * ```js 20 | * var a = function foo(){ 21 | * 22 | * }; 23 | * 24 | * $('#foo').click(function bar(){ 25 | * 26 | * }); 27 | * ``` 28 | * 29 | * ##### Invalid 30 | * 31 | * ```js 32 | * var a = function(){ 33 | * 34 | * }; 35 | * 36 | * $('#foo').click(function(){ 37 | * 38 | * }); 39 | * ``` 40 | */ 41 | 42 | var assert = require('assert'); 43 | 44 | module.exports = function() {}; 45 | 46 | module.exports.prototype = { 47 | configure: function(options) { 48 | assert( 49 | options === true, 50 | this.getOptionName() + ' option requires a true value or should be removed' 51 | ); 52 | }, 53 | 54 | getOptionName: function() { 55 | return 'disallowAnonymousFunctions'; 56 | }, 57 | 58 | check: function(file, errors) { 59 | file.iterateNodesByType(['FunctionExpression', 'FunctionDeclaration'], function(node) { 60 | if (node.id === null) { 61 | errors.add('Anonymous functions need to be named', node); 62 | } 63 | }); 64 | } 65 | }; 66 | -------------------------------------------------------------------------------- /lib/rules/disallow-arrow-functions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Disallows arrow functions. 3 | * 4 | * Why enable this rule? Arrow functions might cause more problems than they 5 | * solve: 6 | * 7 | * - Object-orientation may be better without ECMAScript's `this`. 8 | * - You can't name an arrow function. 9 | * - Arrow functions' syntax can cause maintenance issues; see 10 | * `disallowShorthandArrowFunctions`. 11 | * - Arrow functions shouldn't be used on prototypes, as objects' methods, 12 | * as event listeners, or as anything polymorhpic- or mixin-related. See 13 | * [here](https://gist.github.com/qubyte/43e0093274e793cc82ba#gistcomment-1292183). 14 | * 15 | * Type: `Boolean` 16 | * 17 | * Value: `true` 18 | * 19 | * Version: `ES6` 20 | * 21 | * #### Example 22 | * 23 | * ```js 24 | * "disallowArrowFunctions": true 25 | * ``` 26 | * 27 | * ##### Valid 28 | * 29 | * ```js 30 | * // function expression in a callback 31 | * [1, 2, 3].map(function (x) { 32 | * return x * x; 33 | * }); 34 | * ``` 35 | * 36 | * ##### Invalid 37 | * 38 | * ```js 39 | * // arrow function 40 | * [1, 2, 3].map((x) => { 41 | * return x * x; 42 | * }); 43 | * ``` 44 | */ 45 | 46 | var assert = require('assert'); 47 | 48 | module.exports = function() {}; 49 | 50 | module.exports.prototype = { 51 | configure: function(options) { 52 | assert( 53 | options === true, 54 | this.getOptionName() + ' option requires a true value or should be removed' 55 | ); 56 | }, 57 | 58 | getOptionName: function() { 59 | return 'disallowArrowFunctions'; 60 | }, 61 | 62 | check: function(file, errors) { 63 | file.iterateNodesByType(['ArrowFunctionExpression'], function(node) { 64 | errors.add('Do not use arrow functions', node); 65 | }); 66 | } 67 | }; 68 | -------------------------------------------------------------------------------- /lib/rules/disallow-capitalized-comments.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Requires the first alphabetical character of a comment to be lowercase. 3 | * 4 | * Type: `Boolean` 5 | * 6 | * Value: `true` 7 | * 8 | * #### Example 9 | * 10 | * `"disallowCapitalizedComments": true` 11 | * 12 | * Valid: 13 | * 14 | * ``` 15 | * // valid 16 | * //valid 17 | * 18 | * /* 19 | * valid 20 | * *\/ 21 | * 22 | * /** 23 | * * valid 24 | * *\/ 25 | * 26 | * // 123 or any non-alphabetical starting character 27 | * ``` 28 | * 29 | * Invalid: 30 | * ``` 31 | * // Invalid 32 | * //Invalid 33 | * /** Invalid *\/ 34 | * /** 35 | * * Invalid 36 | * *\/ 37 | * ``` 38 | */ 39 | 40 | var assert = require('assert'); 41 | 42 | module.exports = function() {}; 43 | 44 | module.exports.prototype = { 45 | configure: function(options) { 46 | assert( 47 | options === true, 48 | this.getOptionName() + ' option requires a true value or should be removed' 49 | ); 50 | }, 51 | 52 | getOptionName: function() { 53 | return 'disallowCapitalizedComments'; 54 | }, 55 | 56 | check: function(file, errors) { 57 | var letterPattern = require('../../patterns/L'); 58 | var lowerCasePattern = require('../../patterns/Ll'); 59 | 60 | file.iterateTokensByType(['CommentLine', 'CommentBlock'], function(comment) { 61 | var stripped = comment.value.replace(/[\n\s\*]/g, ''); 62 | var firstChar = stripped[0]; 63 | 64 | if (letterPattern.test(firstChar) && !lowerCasePattern.test(firstChar)) { 65 | errors.add( 66 | 'Comments must start with a lowercase letter', 67 | comment 68 | ); 69 | } 70 | }); 71 | } 72 | }; 73 | -------------------------------------------------------------------------------- /lib/rules/disallow-function-declarations.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Disallows function declarations. 3 | * 4 | * Type: `Boolean` 5 | * 6 | * Value: `true` 7 | * 8 | * #### Example 9 | * 10 | * ```js 11 | * "disallowFunctionDeclarations": true 12 | * ``` 13 | * 14 | * ##### Valid 15 | * 16 | * ```js 17 | * var expressed = function() { 18 | * 19 | * }; 20 | * 21 | * var expressed = function deeply() { 22 | * 23 | * }; 24 | * 25 | * $('#foo').click(function bar() { 26 | * 27 | * }); 28 | * ``` 29 | * 30 | * ##### Invalid 31 | * 32 | * ```js 33 | * function stated() { 34 | * 35 | * } 36 | * ``` 37 | */ 38 | 39 | var assert = require('assert'); 40 | 41 | module.exports = function() {}; 42 | 43 | module.exports.prototype = { 44 | configure: function(options) { 45 | assert( 46 | options === true, 47 | this.getOptionName() + ' option requires a true value or should be removed' 48 | ); 49 | }, 50 | 51 | getOptionName: function() { 52 | return 'disallowFunctionDeclarations'; 53 | }, 54 | 55 | check: function(file, errors) { 56 | file.iterateNodesByType('FunctionDeclaration', function(node) { 57 | errors.add('Illegal function declaration', node); 58 | }); 59 | } 60 | }; 61 | -------------------------------------------------------------------------------- /lib/rules/disallow-identical-destructuring-names.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Disallows identical destructuring names for the key and value in favor of using shorthand destructuring. 3 | * 4 | * Type: `Boolean` 5 | * 6 | * Value: `true` 7 | * 8 | * #### Example 9 | * 10 | * ```js 11 | * "disallowIdenticalDestructuringNames": true 12 | * ``` 13 | * 14 | * ##### Valid for mode `true` 15 | * 16 | * ```js 17 | * var {left, top} = obj; // shorthand 18 | * var {left, top: topper} = obj; // different identifier 19 | * let { [key]: key } = obj; // computed property 20 | * ``` 21 | * 22 | * ##### Invalid for mode `true` 23 | * 24 | * ```js 25 | * var {left: left, top: top} = obj; 26 | * ``` 27 | */ 28 | 29 | var assert = require('assert'); 30 | 31 | module.exports = function() {}; 32 | 33 | module.exports.prototype = { 34 | configure: function(options) { 35 | assert( 36 | options === true, 37 | this.getOptionName() + ' option requires a true value or should be removed' 38 | ); 39 | }, 40 | 41 | getOptionName: function() { 42 | return 'disallowIdenticalDestructuringNames'; 43 | }, 44 | 45 | check: function(file, errors) { 46 | file.iterateNodesByType(['ObjectPattern'], function(node) { 47 | var props = node.properties; 48 | for (var i = 0; i < props.length; i++) { 49 | var prop = props[i]; 50 | if (prop.type === 'ObjectProperty' && !prop.shorthand && !prop.computed && 51 | prop.key.name === prop.value.name) { 52 | errors.add('Use the shorthand form of destructuring instead', prop); 53 | } 54 | } 55 | }); 56 | } 57 | }; 58 | -------------------------------------------------------------------------------- /lib/rules/disallow-identifier-names.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Disallows a specified set of identifier names. 3 | * 4 | * Type: `Array` 5 | * 6 | * Values: Array of strings, which should be disallowed as identifier names 7 | * 8 | * #### Example 9 | * 10 | * ```js 11 | * "disallowIdentifierNames": ['temp', 'foo'] 12 | * ``` 13 | * 14 | * ##### Valid 15 | * 16 | * ```js 17 | * var good = 1; 18 | * object['fine'] = 2; 19 | * object.fine = 3; 20 | * ``` 21 | * 22 | * ##### Invalid 23 | * 24 | * ```js 25 | * var temp = 1; 26 | * object['foo'] = 2; 27 | * object.foo = 3; 28 | * ``` 29 | */ 30 | 31 | var assert = require('assert'); 32 | 33 | module.exports = function() {}; 34 | 35 | module.exports.prototype = { 36 | 37 | configure: function(identifiers) { 38 | assert( 39 | Array.isArray(identifiers), 40 | 'disallowIdentifierNames option requires an array' 41 | ); 42 | 43 | this._identifierIndex = {}; 44 | for (var i = 0, l = identifiers.length; i < l; i++) { 45 | this._identifierIndex[identifiers[i]] = true; 46 | } 47 | }, 48 | 49 | getOptionName: function() { 50 | return 'disallowIdentifierNames'; 51 | }, 52 | 53 | check: function(file, errors) { 54 | var disallowedIdentifiers = this._identifierIndex; 55 | 56 | file.iterateNodesByType('Identifier', function(node) { 57 | if (Object.prototype.hasOwnProperty.call(disallowedIdentifiers, node.name)) { 58 | errors.add('Illegal Identifier name: ' + node.name, node); 59 | } 60 | }); 61 | 62 | file.iterateNodesByType('MemberExpression', function(node) { 63 | if (node.property.type === 'StringLiteral') { 64 | if (Object.prototype.hasOwnProperty.call(disallowedIdentifiers, node.property.value)) { 65 | errors.add('Illegal Identifier name: ' + node.property.value, node.property); 66 | } 67 | } 68 | }); 69 | 70 | } 71 | 72 | }; 73 | -------------------------------------------------------------------------------- /lib/rules/disallow-keywords.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Disallows usage of specified keywords. 3 | * 4 | * Type: `Array` 5 | * 6 | * Values: Array of quoted keywords 7 | * 8 | * #### Example 9 | * 10 | * ```js 11 | * "disallowKeywords": ["with"] 12 | * ``` 13 | * 14 | * ##### Invalid 15 | * 16 | * ```js 17 | * with (x) { 18 | * prop++; 19 | * } 20 | * ``` 21 | */ 22 | 23 | var assert = require('assert'); 24 | 25 | module.exports = function() {}; 26 | 27 | module.exports.prototype = { 28 | 29 | configure: function(keywords) { 30 | assert(Array.isArray(keywords), this.getOptionName() + ' option requires array value'); 31 | this._keywords = keywords; 32 | }, 33 | 34 | getOptionName: function() { 35 | return 'disallowKeywords'; 36 | }, 37 | 38 | check: function(file, errors) { 39 | file.iterateTokensByTypeAndValue('Keyword', this._keywords, function(token) { 40 | errors.add('Illegal keyword: ' + token.value, token); 41 | }); 42 | } 43 | 44 | }; 45 | -------------------------------------------------------------------------------- /lib/rules/disallow-multi-line-ternary.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Disallows the test, consequent and alternate to be on separate lines when using the ternary operator. 3 | * 4 | * Types: `Boolean` 5 | * 6 | * #### Example 7 | * 8 | * ```js 9 | * "disallowMultiLineTernary": true 10 | * ``` 11 | * 12 | * ##### Valid 13 | * 14 | * ```js 15 | * var foo = (a === b) ? 1 : 2; 16 | * ``` 17 | * 18 | * ##### Invalid 19 | * 20 | * ```js 21 | * var foo = (a === b) 22 | * ? 1 23 | * : 2; 24 | * ``` 25 | */ 26 | 27 | var assert = require('assert'); 28 | 29 | module.exports = function() {}; 30 | 31 | module.exports.prototype = { 32 | configure: function(options) { 33 | assert( 34 | options === true, 35 | this.getOptionName() + ' option requires a true value or should be removed' 36 | ); 37 | }, 38 | 39 | getOptionName: function() { 40 | return 'disallowMultiLineTernary'; 41 | }, 42 | 43 | check: function(file, errors) { 44 | file.iterateNodesByType('ConditionalExpression', function(node) { 45 | 46 | errors.assert.sameLine({ 47 | token: node.test, 48 | nextToken: node.consequent, 49 | message: 'Illegal new line after test' 50 | }); 51 | 52 | errors.assert.sameLine({ 53 | token: node.consequent, 54 | nextToken: node.alternate, 55 | message: 'Illegal new line after consequent' 56 | }); 57 | }); 58 | } 59 | 60 | }; 61 | -------------------------------------------------------------------------------- /lib/rules/disallow-multiple-line-breaks.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Disallows multiple blank lines in a row. 3 | * 4 | * Type: `Boolean` 5 | * 6 | * Value: `true` 7 | * 8 | * #### Example 9 | * 10 | * ```js 11 | * "disallowMultipleLineBreaks": true 12 | * ``` 13 | * 14 | * ##### Valid 15 | * ```js 16 | * var x = 1; 17 | * 18 | * x++; 19 | * ``` 20 | * 21 | * ##### Invalid 22 | * ```js 23 | * var x = 1; 24 | * 25 | * 26 | * x++; 27 | * ``` 28 | */ 29 | 30 | var assert = require('assert'); 31 | 32 | module.exports = function() {}; 33 | 34 | module.exports.prototype = { 35 | 36 | configure: function(options) { 37 | assert( 38 | options === true, 39 | this.getOptionName() + ' option requires a true value or should be removed' 40 | ); 41 | }, 42 | 43 | getOptionName: function() { 44 | return 'disallowMultipleLineBreaks'; 45 | }, 46 | 47 | check: function(file, errors) { 48 | // Iterate over all tokens (including comments) 49 | file.iterateTokensByType('Whitespace', function(whitespaceToken) { 50 | if (whitespaceToken.getNewlineCount() === 0) { 51 | return; 52 | } 53 | 54 | var token = whitespaceToken.getPreviousNonWhitespaceToken(); 55 | 56 | if (!token) { 57 | return; 58 | } 59 | 60 | var nextToken = token.getNextNonWhitespaceToken(); 61 | 62 | errors.assert.linesBetween({ 63 | token: token, 64 | nextToken: nextToken, 65 | atMost: 2 66 | }); 67 | }); 68 | } 69 | 70 | }; 71 | -------------------------------------------------------------------------------- /lib/rules/disallow-multiple-line-strings.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Disallows strings that span multiple lines without using concatenation. 3 | * 4 | * Type: `Boolean` 5 | * 6 | * Value: `true` 7 | * 8 | * JSHint: [`multistr`](http://www.jshint.com/docs/options/#multistr) 9 | * 10 | * #### Example 11 | * 12 | * ```js 13 | * "disallowMultipleLineStrings": true 14 | * ``` 15 | * 16 | * ##### Valid 17 | * ```js 18 | * var x = "multi" + 19 | * "line"; 20 | * var y = "single line"; 21 | * ``` 22 | * 23 | * ##### Invalid 24 | * ```js 25 | * var x = "multi \ 26 | * line"; 27 | * ``` 28 | */ 29 | 30 | var assert = require('assert'); 31 | 32 | module.exports = function() {}; 33 | 34 | module.exports.prototype = { 35 | 36 | configure: function(options) { 37 | assert( 38 | options === true, 39 | this.getOptionName() + ' option requires a true value or should be removed' 40 | ); 41 | }, 42 | 43 | getOptionName: function() { 44 | return 'disallowMultipleLineStrings'; 45 | }, 46 | 47 | check: function(file, errors) { 48 | file.iterateTokensByType('String', function(token) { 49 | if (token.getNewlineCount() !== 0) { 50 | errors.add('Multiline strings are disallowed.', token); 51 | } 52 | }); 53 | } 54 | 55 | }; 56 | -------------------------------------------------------------------------------- /lib/rules/disallow-multiple-spaces.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Disallows multiple indentation characters (tabs or spaces) between identifiers, keywords, and any other token 3 | * 4 | * Type: `Boolean` or `Object` 5 | * 6 | * Values: `true` or `{"allowEOLComments": true}` to allow on-line comments to be ignored 7 | * 8 | * #### Examples 9 | * 10 | * ```js 11 | * "disallowMultipleSpaces": true 12 | * // or 13 | * "disallowMultipleSpaces": {"allowEOLComments": true} 14 | * ``` 15 | * 16 | * ##### Valid 17 | * ```js 18 | * var x = "hello"; 19 | * function y() {} 20 | * ``` 21 | * 22 | * ##### Valid for `{"allowEOLComments": true}` 23 | * 24 | * ```js 25 | * var x = "hello" // world; 26 | * function y() {} 27 | * ``` 28 | * 29 | * ##### Invalid 30 | * ```js 31 | * var x = "hello"; 32 | * function y() {} 33 | * ``` 34 | */ 35 | 36 | var assert = require('assert'); 37 | 38 | module.exports = function() {}; 39 | 40 | module.exports.prototype = { 41 | 42 | configure: function(options) { 43 | assert( 44 | options === true || 45 | typeof options === 'object' && 46 | options.allowEOLComments === true, 47 | this.getOptionName() + ' option requires true value ' + 48 | 'or an object with `allowEOLComments` property' 49 | ); 50 | 51 | this._allowEOLComments = options.allowEOLComments; 52 | }, 53 | 54 | getOptionName: function() { 55 | return 'disallowMultipleSpaces'; 56 | }, 57 | 58 | check: function(file, errors) { 59 | var token = file.getProgram().getFirstToken(); 60 | var nextToken; 61 | 62 | while (token) { 63 | nextToken = token.getNextNonWhitespaceToken(); 64 | 65 | if (!nextToken) { 66 | break; 67 | } 68 | 69 | if (!this._allowEOLComments || nextToken.type !== 'CommentLine') { 70 | errors.assert.spacesBetween({ 71 | token: token, 72 | nextToken: nextToken, 73 | atMost: 1 74 | }); 75 | } 76 | 77 | token = token.getNextNonWhitespaceToken(); 78 | } 79 | } 80 | 81 | }; 82 | -------------------------------------------------------------------------------- /lib/rules/disallow-named-unassigned-functions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Disallows unassigned functions to be named inline 3 | * 4 | * Type: `Boolean` 5 | * 6 | * Value: `true` 7 | * 8 | * #### Example 9 | * 10 | * ```js 11 | * "disallowNamedUnassignedFunctions": true 12 | * ``` 13 | * 14 | * ##### Valid 15 | * ```js 16 | * [].forEach(function () {}); 17 | * var x = function() {}; 18 | * function y() {} 19 | * ``` 20 | * 21 | * ##### Invalid 22 | * ```js 23 | * [].forEach(function x() {}); 24 | * ``` 25 | */ 26 | 27 | var assert = require('assert'); 28 | 29 | module.exports = function() {}; 30 | 31 | module.exports.prototype = { 32 | configure: function(options) { 33 | assert( 34 | options === true, 35 | this.getOptionName() + ' option requires true value' 36 | ); 37 | }, 38 | 39 | getOptionName: function() { 40 | return 'disallowNamedUnassignedFunctions'; 41 | }, 42 | 43 | check: function(file, errors) { 44 | file.iterateNodesByType('FunctionExpression', function(node) { 45 | // If the function has been named via left hand assignment, skip it 46 | // e.g. `var hello = function() {`, `foo.bar = function() {` 47 | if (node.parentElement.type.match(/VariableDeclarator|Property|AssignmentExpression/)) { 48 | return; 49 | } 50 | 51 | // If the function has not been named, skip it 52 | // e.g. `[].forEach(function() {` 53 | if (node.id === null) { 54 | return; 55 | } 56 | 57 | // Otherwise, complain that it is being named 58 | errors.add('Inline functions cannot be named', node); 59 | }); 60 | } 61 | }; 62 | -------------------------------------------------------------------------------- /lib/rules/disallow-node-types.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Disallow use of certain AST Node types. 3 | * 4 | * Babylon node types 5 | * - [Core](https://github.com/babel/babel/blob/master/doc/ast/spec.md) 6 | * - [Flow](https://github.com/babel/babel/blob/master/doc/ast/flow.md) 7 | * - [JSX](https://github.com/babel/babel/blob/master/doc/ast/jsx.md) 8 | * 9 | * Type: `Array` 10 | * 11 | * Value: Array of parser node types to be disallowed. 12 | * 13 | * #### Example 14 | * 15 | * ```js 16 | * "disallowNodeTypes": ['LabeledStatement'] 17 | * ``` 18 | * 19 | * ##### Valid 20 | * 21 | * ```js 22 | * // use of an allowed node type 23 | * var a = 1; 24 | * // shorthand form of arrow function that returns an object 25 | * var f = () => ({ a: 1 }); 26 | * ``` 27 | * 28 | * ##### Invalid 29 | * 30 | * ```js 31 | * // label statement with loop 32 | * loop1: 33 | * for (i = 0; i < 10; i++) { 34 | * if (i === 3) { 35 | * break loop1; 36 | * } 37 | * } 38 | * // accidental label statement with arrow function 39 | * var f = () => { a: 1 }; 40 | * // label statement 41 | * { a: 1 } 42 | * ``` 43 | */ 44 | 45 | var assert = require('assert'); 46 | 47 | module.exports = function() {}; 48 | 49 | module.exports.prototype = { 50 | configure: function(nodeTypes) { 51 | assert( 52 | Array.isArray(nodeTypes), 53 | 'disallowNodeTypes option requires an array' 54 | ); 55 | 56 | this._nodeTypes = nodeTypes; 57 | }, 58 | 59 | getOptionName: function() { 60 | return 'disallowNodeTypes'; 61 | }, 62 | 63 | check: function(file, errors) { 64 | var disallowedNodeTypes = this._nodeTypes; 65 | file.iterateNodesByType(disallowedNodeTypes, function(node) { 66 | errors.add('Illegal use of disallowed node type: ' + node.type, node); 67 | }); 68 | } 69 | }; 70 | -------------------------------------------------------------------------------- /lib/rules/disallow-object-keys-on-new-line.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Disallows placing object keys on new line 3 | * 4 | * Type: `Boolean` 5 | * 6 | * Value: `true` 7 | * 8 | * #### Example 9 | * 10 | * ```js 11 | * "disallowObjectKeysOnNewLine": true 12 | * ``` 13 | * 14 | * ##### Valid 15 | * 16 | * ```js 17 | * var a = { 18 | * b: 'b', c: 'c' 19 | * }; 20 | * ``` 21 | * 22 | * ##### Invalid 23 | * 24 | * ```js 25 | * var a = { 26 | * b: 'b', 27 | * c: 'c' 28 | * }; 29 | * ``` 30 | */ 31 | 32 | var assert = require('assert'); 33 | 34 | module.exports = function() {}; 35 | 36 | module.exports.prototype = { 37 | configure: function(options) { 38 | assert( 39 | options === true, 40 | this.getOptionName() + ' option requires a true value or should be removed' 41 | ); 42 | }, 43 | 44 | getOptionName: function() { 45 | return 'disallowObjectKeysOnNewLine'; 46 | }, 47 | 48 | check: function(file, errors) { 49 | file.iterateNodesByType('ObjectExpression', function(node) { 50 | var properties = node.properties; 51 | for (var i = 1; i < properties.length; i++) { 52 | var propertyNode = properties[i]; 53 | 54 | errors.assert.sameLine({ 55 | token: propertyNode.getPreviousCodeToken(), 56 | nextToken: propertyNode.getFirstToken(), 57 | message: 'Object keys should be on the same line' 58 | }); 59 | } 60 | }); 61 | } 62 | }; 63 | -------------------------------------------------------------------------------- /lib/rules/disallow-operator-before-line-break.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Requires putting certain operators on the next line rather than on the current line before a line break. 3 | * 4 | * Types: `Array` or `Boolean` 5 | * 6 | * Values: Array of operators to apply to or `true` 7 | * 8 | * #### Example 9 | * 10 | * ```js 11 | * "disallowOperatorBeforeLineBreak": ["+", "."] 12 | * ``` 13 | * 14 | * ##### Valid 15 | * 16 | * ```js 17 | * $el.on( 'click', fn ) 18 | * .appendTo( 'body' ); 19 | * 20 | * var x = 4 + 5 21 | * + 12 + 13; 22 | * ``` 23 | * 24 | * ##### Invalid 25 | * 26 | * ```js 27 | * $el.on( 'click', fn ). 28 | * appendTo( 'body' ); 29 | * 30 | * var x = 4 + 5 + 31 | * 12 + 13; 32 | * ``` 33 | */ 34 | 35 | var assert = require('assert'); 36 | var defaultOperators = require('../utils').binaryOperators.slice().concat(['.']); 37 | 38 | module.exports = function() {}; 39 | 40 | module.exports.prototype = { 41 | configure: function(operators) { 42 | assert(Array.isArray(operators) || operators === true, 43 | this.getOptionName() + ' option requires array or true value'); 44 | 45 | if (operators === true) { 46 | operators = defaultOperators; 47 | } 48 | this._operators = operators; 49 | }, 50 | 51 | getOptionName: function() { 52 | return 'disallowOperatorBeforeLineBreak'; 53 | }, 54 | 55 | check: function(file, errors) { 56 | file.iterateTokensByTypeAndValue('Punctuator', this._operators, function(token) { 57 | errors.assert.sameLine({ 58 | token: token, 59 | nextToken: file.getNextToken(token), 60 | message: 'Operator needs to either be on the same line or after a line break.' 61 | }); 62 | }); 63 | } 64 | }; 65 | -------------------------------------------------------------------------------- /lib/rules/disallow-padding-newlines-after-use-strict.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Disallow a blank line after `'use strict';` statements 3 | * 4 | * Values: `true` 5 | * 6 | * #### Example 7 | * 8 | * ```js 9 | * "disallowPaddingNewLinesAfterUseStrict": true 10 | * ``` 11 | * 12 | * ##### Valid 13 | * 14 | * ```js 15 | * 'use strict'; 16 | * // code 17 | * ``` 18 | * 19 | * ##### Invalid 20 | * 21 | * ```js 22 | * 'use strict'; 23 | * 24 | * // code 25 | * ``` 26 | */ 27 | 28 | var assert = require('assert'); 29 | 30 | module.exports = function() {}; 31 | 32 | module.exports.prototype = { 33 | 34 | configure: function(disallowPaddingNewLinesAfterUseStrict) { 35 | assert( 36 | disallowPaddingNewLinesAfterUseStrict === true, 37 | this.getOptionName() + ' option requires a true value or should be removed' 38 | ); 39 | }, 40 | 41 | getOptionName: function() { 42 | return 'disallowPaddingNewLinesAfterUseStrict'; 43 | }, 44 | 45 | check: function(file, errors) { 46 | file.iterateNodesByType('Directive', function(node) { 47 | var literal = node.value; 48 | 49 | if (literal.value !== 'use strict') { 50 | return; 51 | } 52 | 53 | var endOfNode = file.getLastNodeToken(node); 54 | var nextToken = file.getNextToken(endOfNode, { 55 | includeComments: true 56 | }); 57 | 58 | errors.assert.linesBetween({ 59 | atMost: 1, 60 | token: endOfNode, 61 | nextToken: nextToken 62 | }); 63 | }); 64 | } 65 | }; 66 | -------------------------------------------------------------------------------- /lib/rules/disallow-padding-newlines-before-export.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Disallows newline before module.exports 3 | * 4 | * Type: `Boolean` 5 | * 6 | * Value: `true` 7 | * 8 | * #### Example 9 | * 10 | * ```js 11 | * "disallowPaddingNewLinesBeforeExport": true 12 | * ``` 13 | * 14 | * ##### Valid 15 | * 16 | * ```js 17 | * var a = 2; 18 | * module.exports = a; 19 | * ``` 20 | * 21 | * ##### Invalid 22 | * 23 | * ```js 24 | * var a = 2; 25 | * 26 | * module.exports = a; 27 | * ``` 28 | */ 29 | 30 | var assert = require('assert'); 31 | 32 | module.exports = function() {}; 33 | 34 | module.exports.prototype = { 35 | 36 | configure: function(value) { 37 | assert( 38 | value === true, 39 | this.getOptionName() + ' option requires a true value or should be removed' 40 | ); 41 | }, 42 | 43 | getOptionName: function() { 44 | return 'disallowPaddingNewLinesBeforeExport'; 45 | }, 46 | 47 | check: function(file, errors) { 48 | file.iterateNodesByType('AssignmentExpression', function(node) { 49 | var left = node.left; 50 | 51 | if (!( 52 | left.object && 53 | left.object.name === 'module' && 54 | left.property && 55 | left.property.name === 'exports')) { 56 | return; 57 | } 58 | 59 | var firstToken = node.getFirstToken(); 60 | var prevToken = file.getPrevToken(firstToken, {includeComments: true}); 61 | 62 | errors.assert.linesBetween({ 63 | atMost: 1, 64 | token: prevToken, 65 | nextToken: firstToken, 66 | message: 'Unexpected extra newline before export' 67 | }); 68 | }); 69 | } 70 | 71 | }; 72 | -------------------------------------------------------------------------------- /lib/rules/disallow-padding-newlines-before-line-comments.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Disallows newline before line comments 3 | * 4 | * Type: `Boolean` 5 | * 6 | * Value: `true` 7 | * 8 | * #### Example 9 | * 10 | * ```js 11 | * "disallowPaddingNewLinesBeforeLineComments": true 12 | * ``` 13 | * 14 | * ##### Valid 15 | * 16 | * ```js 17 | * var a = 2; 18 | * // comment 19 | * return a; 20 | * ``` 21 | * 22 | * ##### Invalid 23 | * 24 | * ```js 25 | * var a = 2; 26 | * 27 | * //comment 28 | * return a; 29 | * ``` 30 | */ 31 | 32 | var assert = require('assert'); 33 | 34 | module.exports = function() {}; 35 | 36 | module.exports.prototype = { 37 | 38 | configure: function(value) { 39 | assert( 40 | value === true, 41 | this.getOptionName() + ' option requires a true value or should be removed' 42 | ); 43 | }, 44 | 45 | getOptionName: function() { 46 | return 'disallowPaddingNewLinesBeforeLineComments'; 47 | }, 48 | 49 | check: function(file, errors) { 50 | file.iterateTokensByType('CommentLine', function(comment) { 51 | if (comment.getLoc().start.line === 1) { 52 | return; 53 | } 54 | 55 | errors.assert.linesBetween({ 56 | token: file.getPrevToken(comment, {includeComments: true}), 57 | nextToken: comment, 58 | atMost: 1, 59 | message: 'Line comments must not be preceded with a blank line' 60 | }); 61 | }); 62 | } 63 | }; 64 | -------------------------------------------------------------------------------- /lib/rules/disallow-padding-newlines-in-objects.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Disallows newlines adjacent to curly braces in all object literals. 3 | * 4 | * Type: `Boolean` 5 | * 6 | * Value: `true` 7 | * 8 | * #### Example 9 | * 10 | * ```js 11 | * "disallowPaddingNewLinesInObjects": true 12 | * ``` 13 | * 14 | * ##### Valid 15 | * 16 | * ```js 17 | * var x = { a: 1 }; 18 | * var y = { a: 1, 19 | * b: 2 }; 20 | * var z = { a: 2, 21 | * b: 2, 22 | * 23 | * c: 3, 24 | * 25 | * 26 | * 27 | * d: 4 }; 28 | * foo({a: {b: 1}}); 29 | * ``` 30 | * 31 | * ##### Invalid 32 | * 33 | * ```js 34 | * var x = { 35 | * a: 1 36 | * }; 37 | * foo({ 38 | * a: { 39 | * b: 1 40 | * } 41 | * }); 42 | * ``` 43 | */ 44 | 45 | var assert = require('assert'); 46 | 47 | module.exports = function() {}; 48 | 49 | module.exports.prototype = { 50 | 51 | configure: function(value) { 52 | assert( 53 | value === true, 54 | this.getOptionName() + ' option requires a true value or should be removed' 55 | ); 56 | }, 57 | 58 | getOptionName: function() { 59 | return 'disallowPaddingNewLinesInObjects'; 60 | }, 61 | 62 | check: function(file, errors) { 63 | file.iterateNodesByType('ObjectExpression', function(node) { 64 | var openingBracket = node.getFirstToken(); 65 | var nextToken = file.getNextToken(openingBracket); 66 | 67 | if (nextToken.type === 'Punctuator' && nextToken.value === '}') { 68 | return; 69 | } 70 | 71 | errors.assert.sameLine({ 72 | token: openingBracket, 73 | nextToken: nextToken, 74 | message: 'Illegal newline after opening curly brace' 75 | }); 76 | 77 | var closingBracket = file.getLastNodeToken(node); 78 | 79 | errors.assert.sameLine({ 80 | token: file.getPrevToken(closingBracket), 81 | nextToken: closingBracket, 82 | message: 'Illegal newline before closing curly brace' 83 | }); 84 | }); 85 | } 86 | 87 | }; 88 | -------------------------------------------------------------------------------- /lib/rules/disallow-semicolons.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Disallows lines from ending in a semicolon. 3 | * 4 | * Type: `Boolean` 5 | * 6 | * Value: `true` 7 | * 8 | * #### Example 9 | * 10 | * ```js 11 | * "disallowSemicolons": true 12 | * ``` 13 | * 14 | * ##### Valid 15 | * 16 | * ```js 17 | * var a = 1 18 | * ;[b].forEach(c) 19 | * ``` 20 | * 21 | * ##### Invalid 22 | * 23 | * ```js 24 | * var a = 1; 25 | * [b].forEach(c); 26 | * ``` 27 | */ 28 | 29 | var assert = require('assert'); 30 | 31 | var nodeExceptions = { 32 | ForStatement: true 33 | }; 34 | 35 | var tokenExceptions = { 36 | '[': true, 37 | '(': true 38 | }; 39 | 40 | module.exports = function() {}; 41 | 42 | module.exports.prototype = { 43 | configure: function(options) { 44 | assert( 45 | options === true, 46 | this.getOptionName() + ' option requires a true value or should be removed' 47 | ); 48 | }, 49 | 50 | getOptionName: function() { 51 | return 'disallowSemicolons'; 52 | }, 53 | 54 | check: function(file, errors) { 55 | file.iterateTokensByTypeAndValue('Punctuator', ';', function(token) { 56 | var nextToken = file.getNextToken(token); 57 | 58 | var node = token.parentElement; 59 | 60 | // Ignore node exceptions 61 | if (node.type in nodeExceptions) { 62 | return; 63 | } 64 | 65 | // Ignore next token exceptions 66 | if (nextToken.value in tokenExceptions) { 67 | return; 68 | } 69 | 70 | if (nextToken.type === 'EOF' || !file.isOnTheSameLine(token, nextToken)) { 71 | errors.cast({ 72 | message: 'semicolons are disallowed at the end of a line.', 73 | element: token 74 | }); 75 | } 76 | }); 77 | }, 78 | 79 | _fix: function(file, error) { 80 | error.element.remove(); 81 | } 82 | }; 83 | -------------------------------------------------------------------------------- /lib/rules/disallow-shorthand-arrow-functions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Require arrow functions to use a block statement (explicit return). 3 | * 4 | * Why enable this rule? Arrow functions' syntax can cause maintenance issues: 5 | * 6 | * - When you add additional lines to an arrow function's expression body, the 7 | * function will now return `undefined`, unless you remember to add an 8 | * explicit `return`. 9 | * - The shorthand syntax is ambiguous in terms of returning objects. 10 | * `(name) => {id: name}` is interpreted as a longhand arrow function with the 11 | * label `id:`. 12 | * 13 | * Type: `Boolean` 14 | * 15 | * Value: `true` 16 | * 17 | * Version: `ES6` 18 | * 19 | * #### Example 20 | * 21 | * ```js 22 | * "disallowShorthandArrowFunctions": true 23 | * ``` 24 | * 25 | * ##### Valid 26 | * 27 | * ```js 28 | * // block statement 29 | * evens.map(v => { 30 | * return v + 1; 31 | * }); 32 | * ``` 33 | * 34 | * ##### Invalid 35 | * 36 | * ```js 37 | * // single expression 38 | * evens.map(v => v + 1); 39 | * ``` 40 | */ 41 | 42 | var assert = require('assert'); 43 | 44 | module.exports = function() {}; 45 | 46 | module.exports.prototype = { 47 | 48 | configure: function(options) { 49 | assert( 50 | options === true, 51 | this.getOptionName() + ' option requires a true value or should be removed' 52 | ); 53 | }, 54 | 55 | getOptionName: function() { 56 | return 'disallowShorthandArrowFunctions'; 57 | }, 58 | 59 | check: function(file, errors) { 60 | file.iterateNodesByType('ArrowFunctionExpression', function(node) { 61 | if (node.expression) { 62 | errors.add('Use arrow function with explicit block and explicit return', node.body); 63 | } 64 | }); 65 | } 66 | 67 | }; 68 | -------------------------------------------------------------------------------- /lib/rules/disallow-space-after-keywords.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Disallows space after keyword. 3 | * 4 | * Types: `Array` or `Boolean` 5 | * 6 | * Values: Array of quoted keywords or `true` to disallow spaces after all possible keywords. 7 | * 8 | * #### Example 9 | * 10 | * ```js 11 | * "disallowSpaceAfterKeywords": [ 12 | * "if", 13 | * "else", 14 | * "for", 15 | * "while", 16 | * "do", 17 | * "switch", 18 | * "try", 19 | * "catch" 20 | * ] 21 | * ``` 22 | * 23 | * ##### Valid 24 | * 25 | * ```js 26 | * if(x > y) { 27 | * y++; 28 | * } 29 | * ``` 30 | * 31 | * ##### Invalid 32 | * 33 | * ```js 34 | * if (x > y) { 35 | * y++; 36 | * } 37 | * ``` 38 | */ 39 | 40 | var assert = require('assert'); 41 | var defaultKeywords = require('../utils').spacedKeywords; 42 | 43 | module.exports = function() {}; 44 | 45 | module.exports.prototype = { 46 | 47 | configure: function(keywords) { 48 | assert( 49 | Array.isArray(keywords) || keywords === true, 50 | this.getOptionName() + ' option requires array or true value' 51 | ); 52 | 53 | if (keywords === true) { 54 | keywords = defaultKeywords; 55 | } 56 | 57 | this._keywords = keywords; 58 | }, 59 | 60 | getOptionName: function() { 61 | return 'disallowSpaceAfterKeywords'; 62 | }, 63 | 64 | check: function(file, errors) { 65 | file.iterateTokensByTypeAndValue('Keyword', this._keywords, function(token) { 66 | var nextToken = file.getNextToken(token); 67 | 68 | // Make an exception if the next token is not a Punctuator such as a Keyword or Identifier 69 | if (nextToken.type !== 'Punctuator') { 70 | return; 71 | } 72 | errors.assert.noWhitespaceBetween({ 73 | token: token, 74 | nextToken: nextToken 75 | }); 76 | }); 77 | } 78 | 79 | }; 80 | -------------------------------------------------------------------------------- /lib/rules/disallow-space-after-line-comment.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Requires that a line comment (`//`) not be followed by a space. 3 | * 4 | * Type: `Boolean` 5 | * 6 | * Value: `true` 7 | * 8 | * #### Example 9 | * 10 | * ```js 11 | * "disallowSpaceAfterLineComment": true 12 | * ``` 13 | * 14 | * ##### Valid 15 | * 16 | * ```js 17 | * //A comment 18 | * /* A comment*\/ 19 | * ``` 20 | * 21 | * ##### Invalid 22 | * 23 | * ```js 24 | * // A comment 25 | * ``` 26 | */ 27 | 28 | var assert = require('assert'); 29 | 30 | module.exports = function() {}; 31 | 32 | module.exports.prototype = { 33 | 34 | configure: function(options) { 35 | assert( 36 | options === true, 37 | this.getOptionName() + ' option requires a true value or should be removed' 38 | ); 39 | }, 40 | 41 | getOptionName: function() { 42 | return 'disallowSpaceAfterLineComment'; 43 | }, 44 | 45 | check: function(file, errors) { 46 | file.iterateTokensByType('CommentLine', function(comment) { 47 | var value = comment.value; 48 | if (value.length > 0 && value[0] === ' ') { 49 | errors.add('Illegal space after line comment', comment); 50 | } 51 | }); 52 | } 53 | }; 54 | -------------------------------------------------------------------------------- /lib/rules/disallow-space-after-prefix-unary-operators.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Requires sticking unary operators to the right. 3 | * 4 | * Types: `Array` or `Boolean` 5 | * 6 | * Values: Array of quoted operators or `true` to disallow space after prefix for all unary operators 7 | * 8 | * #### Example 9 | * 10 | * ```js 11 | * "disallowSpaceAfterPrefixUnaryOperators": ["++", "--", "+", "-", "~", "!"] 12 | * ``` 13 | * 14 | * ##### Valid 15 | * 16 | * ```js 17 | * x = !y; y = ++z; 18 | * ``` 19 | * 20 | * ##### Invalid 21 | * 22 | * ```js 23 | * x = ! y; y = ++ z; 24 | * ``` 25 | */ 26 | 27 | var assert = require('assert'); 28 | var defaultOperators = require('../utils').unaryOperators; 29 | 30 | module.exports = function() {}; 31 | 32 | module.exports.prototype = { 33 | 34 | configure: function(operators) { 35 | var isTrue = operators === true; 36 | 37 | assert( 38 | Array.isArray(operators) || isTrue, 39 | this.getOptionName() + ' option requires array or true value' 40 | ); 41 | 42 | if (isTrue) { 43 | operators = defaultOperators; 44 | } 45 | 46 | this._operatorIndex = {}; 47 | for (var i = 0, l = operators.length; i < l; i++) { 48 | this._operatorIndex[operators[i]] = true; 49 | } 50 | }, 51 | 52 | getOptionName: function() { 53 | return 'disallowSpaceAfterPrefixUnaryOperators'; 54 | }, 55 | 56 | check: function(file, errors) { 57 | var operatorIndex = this._operatorIndex; 58 | 59 | file.iterateNodesByType(['UnaryExpression', 'UpdateExpression'], function(node) { 60 | // Check "node.prefix" for prefix type of (inc|dec)rement 61 | if (node.prefix && operatorIndex[node.operator]) { 62 | var operatorToken = node.getFirstToken(); 63 | errors.assert.noWhitespaceBetween({ 64 | token: operatorToken, 65 | nextToken: file.getNextToken(operatorToken), 66 | message: 'Operator ' + node.operator + ' should stick to operand' 67 | }); 68 | } 69 | }); 70 | } 71 | }; 72 | -------------------------------------------------------------------------------- /lib/rules/disallow-space-before-keywords.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Disallows space before keyword. 3 | * 4 | * Types: `Array` or `Boolean` 5 | * 6 | * Values: Array of quoted keywords or `true` to disallow spaces before all possible keywords. 7 | * 8 | * #### Example 9 | * 10 | * ```js 11 | * "disallowSpaceBeforeKeywords": [ 12 | * "else", 13 | * "catch" 14 | * ] 15 | * ``` 16 | * 17 | * ##### Valid 18 | * 19 | * ```js 20 | * }else { 21 | * y--; 22 | * } 23 | * ``` 24 | * 25 | * ##### Invalid 26 | * 27 | * ```js 28 | * } else { 29 | * y--; 30 | * } 31 | * ``` 32 | */ 33 | 34 | var assert = require('assert'); 35 | 36 | var defaultKeywords = require('../utils').spacedKeywords; 37 | 38 | module.exports = function() {}; 39 | 40 | module.exports.prototype = { 41 | 42 | configure: function(keywords) { 43 | assert( 44 | Array.isArray(keywords) || keywords === true, 45 | this.getOptionName() + ' option requires array or true value'); 46 | 47 | if (keywords === true) { 48 | keywords = defaultKeywords; 49 | } 50 | 51 | this._keywords = keywords; 52 | }, 53 | 54 | getOptionName: function() { 55 | return 'disallowSpaceBeforeKeywords'; 56 | }, 57 | 58 | check: function(file, errors) { 59 | file.iterateTokensByTypeAndValue('Keyword', this._keywords, function(token) { 60 | var prevToken = file.getPrevToken(token, {includeComments: true}); 61 | if (!prevToken || prevToken.isComment) { 62 | return; 63 | } 64 | 65 | if (prevToken.type !== 'Keyword' && prevToken.value !== ';') { 66 | errors.assert.noWhitespaceBetween({ 67 | token: prevToken, 68 | nextToken: token, 69 | message: 'Illegal space before "' + token.value + '" keyword' 70 | }); 71 | } 72 | }); 73 | } 74 | 75 | }; 76 | -------------------------------------------------------------------------------- /lib/rules/disallow-space-before-object-values.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Disallows space before object values. 3 | * 4 | * Type: `Boolean` 5 | * 6 | * Value: `true` 7 | * 8 | * #### Example 9 | * 10 | * ```js 11 | * "disallowSpaceBeforeObjectValues": true 12 | * ``` 13 | * 14 | * ##### Valid 15 | * ```js 16 | * var x = {a:1}; 17 | * ``` 18 | * ##### Invalid 19 | * ```js 20 | * var x = {a: 1}; 21 | * ``` 22 | */ 23 | 24 | var assert = require('assert'); 25 | 26 | module.exports = function() {}; 27 | 28 | module.exports.prototype = { 29 | 30 | configure: function(disallow) { 31 | assert( 32 | disallow === true, 33 | this.getOptionName() + ' option requires a true value or should be removed' 34 | ); 35 | }, 36 | 37 | getOptionName: function() { 38 | return 'disallowSpaceBeforeObjectValues'; 39 | }, 40 | 41 | check: function(file, errors) { 42 | file.iterateNodesByType('ObjectExpression', function(node) { 43 | node.properties.forEach(function(property) { 44 | if (property.shorthand || 45 | property.type === 'ObjectMethod' || 46 | property.type === 'SpreadProperty') { 47 | return; 48 | } 49 | 50 | var keyToken = file.getFirstNodeToken(property.key); 51 | var colon = file.findNextToken(keyToken, 'Punctuator', ':'); 52 | 53 | errors.assert.noWhitespaceBetween({ 54 | token: colon, 55 | nextToken: file.getNextToken(colon), 56 | message: 'Illegal space after key colon' 57 | }); 58 | }); 59 | }); 60 | } 61 | 62 | }; 63 | -------------------------------------------------------------------------------- /lib/rules/disallow-space-between-arguments.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Ensure there are no spaces after argument separators in call expressions. 3 | * 4 | * Type: `Boolean` 5 | * 6 | * Value: `true` 7 | * 8 | * #### Example 9 | * 10 | * ```js 11 | * "disallowSpaceBetweenArguments": true 12 | * ``` 13 | * 14 | * ##### Valid 15 | * 16 | * ```js 17 | * a(b,c); 18 | * ``` 19 | * 20 | * ##### Invalid 21 | * 22 | * ```js 23 | * a(b, c); 24 | * ``` 25 | */ 26 | 27 | var assert = require('assert'); 28 | 29 | module.exports = function() {}; 30 | 31 | module.exports.prototype = { 32 | 33 | configure: function(options) { 34 | assert( 35 | options === true, 36 | this.getOptionName() + ' option requires a true value or should be removed' 37 | ); 38 | }, 39 | 40 | getOptionName: function() { 41 | return 'disallowSpaceBetweenArguments'; 42 | }, 43 | 44 | check: function(file, errors) { 45 | file.iterateNodesByType(['CallExpression'], function(node) { 46 | node.arguments.forEach(function(param) { 47 | var token = file.getFirstNodeToken(param); 48 | var punctuatorToken = file.getPrevToken(token); 49 | 50 | if (punctuatorToken.value === ',') { 51 | errors.assert.noWhitespaceBetween({ 52 | token: punctuatorToken, 53 | nextToken: file.getNextToken(punctuatorToken), 54 | message: 'Illegal space between arguments' 55 | }); 56 | } 57 | }); 58 | }); 59 | } 60 | }; 61 | -------------------------------------------------------------------------------- /lib/rules/disallow-spaces-in-call-expression.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Disallows space before `()` in call expressions. 3 | * 4 | * Type: `Boolean` 5 | * 6 | * Value: `true` 7 | * 8 | * #### Example 9 | * 10 | * ```js 11 | * "disallowSpacesInCallExpression": true 12 | * ``` 13 | * 14 | * ##### Valid 15 | * 16 | * ```js 17 | * var x = foobar(); 18 | * ``` 19 | * 20 | * ##### Invalid 21 | * 22 | * ```js 23 | * var x = foobar (); 24 | * ``` 25 | */ 26 | 27 | var assert = require('assert'); 28 | 29 | module.exports = function() {}; 30 | 31 | module.exports.prototype = { 32 | configure: function(options) { 33 | assert( 34 | options === true, 35 | this.getOptionName() + ' option requires a true value or should be removed' 36 | ); 37 | }, 38 | 39 | getOptionName: function() { 40 | return 'disallowSpacesInCallExpression'; 41 | }, 42 | 43 | check: function(file, errors) { 44 | file.iterateNodesByType(['CallExpression', 'NewExpression'], function(node) { 45 | var lastCalleeToken = file.getLastNodeToken(node.callee); 46 | var roundBraceToken = file.findNextToken(lastCalleeToken, 'Punctuator', '('); 47 | 48 | // CallExpressions can't have missing parens, otherwise they're identifiers 49 | if (node.type === 'NewExpression') { 50 | if (roundBraceToken === null || roundBraceToken.parentElement !== node) { 51 | return; 52 | } 53 | } 54 | 55 | errors.assert.noWhitespaceBetween({ 56 | token: file.getPrevToken(roundBraceToken), 57 | nextToken: roundBraceToken, 58 | message: 'Illegal space before opening round brace' 59 | }); 60 | }); 61 | } 62 | }; 63 | -------------------------------------------------------------------------------- /lib/rules/disallow-spaces-in-for-statement.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Disallow spaces in between for statement. 3 | * 4 | * Type: `Boolean` 5 | * 6 | * Value: `true` to disallow spaces in between for statement. 7 | * 8 | * #### Example 9 | * 10 | * ```js 11 | * "disallowSpacesInForStatement": true 12 | * ``` 13 | * 14 | * ##### Valid 15 | * 16 | * ```js 17 | * for(var i=0;i -1 || 70 | (node.left.type === 'Identifier' && node.left.name === 'undefined') 71 | ) { 72 | errors.add('Yoda condition', node.left); 73 | } 74 | } 75 | }); 76 | } 77 | 78 | }; 79 | -------------------------------------------------------------------------------- /lib/rules/require-array-destructuring.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Requires that variable assignment from array values are * destructured. 3 | * 4 | * Type: `Boolean` 5 | * 6 | * Values: `true` 7 | * 8 | * Version: `ES6` 9 | * 10 | * #### Example 11 | * 12 | * ```js 13 | * "requireArrayDestructuring": true 14 | * ``` 15 | * 16 | * ##### Valid 17 | * 18 | * ```js 19 | * var colors = ['red', 'green', 'blue']; 20 | * var [ red ] = colors; 21 | * 22 | * var attributes = { 23 | * colors: ['red', 'green', 'blue']; 24 | * }; 25 | * 26 | * var [ red ] = attributes.colors; 27 | * ``` 28 | * 29 | * ##### Invalid 30 | * 31 | * ```js 32 | * var colors = ['red', 'green', 'blue']; 33 | * var red = colors[0]; 34 | * 35 | * var attributes = { 36 | * colors: ['red', 'green', 'blue']; 37 | * }; 38 | * 39 | * var red = attributes.colors[0]; 40 | * ``` 41 | */ 42 | 43 | var assert = require('assert'); 44 | 45 | module.exports = function() {}; 46 | 47 | module.exports.prototype = { 48 | configure: function(option) { 49 | assert(option === true, this.getOptionName() + ' requires a true value'); 50 | }, 51 | 52 | getOptionName: function() { 53 | return 'requireArrayDestructuring'; 54 | }, 55 | 56 | check: function(file, errors) { 57 | file.iterateNodesByType('VariableDeclaration', function(node) { 58 | 59 | node.declarations.forEach(function(declaration) { 60 | if (!declaration.init || declaration.init.type !== 'MemberExpression') { 61 | return; 62 | } 63 | 64 | var property = declaration.init.property || {}; 65 | if (property.type.indexOf('Literal') > -1 && /^\d+$/.test(property.value)) { 66 | errors.add('Use array destructuring', property); 67 | } 68 | }); 69 | }); 70 | } 71 | }; 72 | -------------------------------------------------------------------------------- /lib/rules/require-capitalized-constructors-new.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Requires capitalized constructors to to use the `new` keyword 3 | * 4 | * Types: `Boolean` or `Object` 5 | * 6 | * Values: `true` or Object with `allExcept` Array of quoted identifiers which are exempted 7 | * 8 | * JSHint: [`newcap`](http://jshint.com/docs/options/#newcap) 9 | * 10 | * #### Example 11 | * 12 | * ```js 13 | * "requireCapitalizedConstructorsNew": true 14 | * "requireCapitalizedConstructorsNew": { 15 | * "allExcept": ["SomethingNative"] 16 | * } 17 | * ``` 18 | * 19 | * ##### Valid 20 | * 21 | * ```js 22 | * var a = new B(); 23 | * var c = SomethingNative(); 24 | * ``` 25 | * 26 | * ##### Invalid 27 | * 28 | * ```js 29 | * var d = E(); 30 | * ``` 31 | */ 32 | 33 | var assert = require('assert'); 34 | 35 | module.exports = function() {}; 36 | 37 | module.exports.prototype = { 38 | configure: function(options) { 39 | assert( 40 | options === true || Array.isArray(options.allExcept), 41 | this.getOptionName() + ' option requires a true value or an object of exceptions' 42 | ); 43 | this._allowedConstructors = {}; 44 | 45 | var allExcept = options.allExcept; 46 | if (allExcept) { 47 | for (var i = 0, l = allExcept.length; i < l; i++) { 48 | this._allowedConstructors[allExcept[i]] = true; 49 | } 50 | } 51 | }, 52 | 53 | getOptionName: function() { 54 | return 'requireCapitalizedConstructorsNew'; 55 | }, 56 | 57 | check: function(file, errors) { 58 | var allowedConstructors = this._allowedConstructors; 59 | 60 | file.iterateNodesByType('CallExpression', function(node) { 61 | if (node.callee.type === 'Identifier' && 62 | !allowedConstructors[node.callee.name] && 63 | node.callee.name[0].toLowerCase() !== node.callee.name[0] 64 | ) { 65 | errors.add( 66 | 'Constructor functions should use the "new" keyword', 67 | node.callee 68 | ); 69 | } 70 | }); 71 | } 72 | 73 | }; 74 | -------------------------------------------------------------------------------- /lib/rules/require-capitalized-constructors.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Requires constructors to be capitalized (except for `this`) 3 | * 4 | * Types: `Boolean` or `Object` 5 | * 6 | * Values: `true` or Object with `allExcept` Array of quoted identifiers which are exempted 7 | * 8 | * JSHint: [`newcap`](http://jshint.com/docs/options/#newcap) 9 | * 10 | * #### Example 11 | * 12 | * ```js 13 | * "requireCapitalizedConstructors": true 14 | * "requireCapitalizedConstructors": { 15 | * "allExcept": ["somethingNative"] 16 | * } 17 | * ``` 18 | * 19 | * ##### Valid 20 | * 21 | * ```js 22 | * var a = new B(); 23 | * var c = new this(); 24 | * var d = new somethingNative(); 25 | * ``` 26 | * 27 | * ##### Invalid 28 | * 29 | * ```js 30 | * var d = new e(); 31 | * ``` 32 | */ 33 | 34 | var assert = require('assert'); 35 | 36 | module.exports = function() {}; 37 | 38 | module.exports.prototype = { 39 | configure: function(options) { 40 | assert( 41 | options === true || Array.isArray(options.allExcept), 42 | this.getOptionName() + ' option requires a true value or an object of exceptions' 43 | ); 44 | this._allowedConstructors = {}; 45 | 46 | var allExcept = options.allExcept; 47 | if (allExcept) { 48 | for (var i = 0, l = allExcept.length; i < l; i++) { 49 | this._allowedConstructors[allExcept[i]] = true; 50 | } 51 | } 52 | }, 53 | 54 | getOptionName: function() { 55 | return 'requireCapitalizedConstructors'; 56 | }, 57 | 58 | check: function(file, errors) { 59 | var allowedConstructors = this._allowedConstructors; 60 | 61 | file.iterateNodesByType('NewExpression', function(node) { 62 | if (node.callee.type === 'Identifier' && 63 | !allowedConstructors[node.callee.name] && 64 | node.callee.name[0].toUpperCase() !== node.callee.name[0] 65 | ) { 66 | errors.add( 67 | 'Constructor functions should be capitalized', 68 | node.callee 69 | ); 70 | } 71 | }); 72 | } 73 | 74 | }; 75 | -------------------------------------------------------------------------------- /lib/rules/require-comma-before-line-break.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Requires commas as last token on a line in lists. 3 | * 4 | * Type: `Boolean` 5 | * 6 | * Value: `true` 7 | * 8 | * JSHint: [`laxcomma`](http://www.jshint.com/docs/options/#laxcomma) 9 | * 10 | * #### Example 11 | * 12 | * ```js 13 | * "requireCommaBeforeLineBreak": true 14 | * ``` 15 | * 16 | * ##### Valid 17 | * 18 | * ```js 19 | * var x = { 20 | * one: 1, 21 | * two: 2 22 | * }; 23 | * var y = { three: 3, four: 4}; 24 | * ``` 25 | * 26 | * ##### Invalid 27 | * 28 | * ```js 29 | * var x = { 30 | * one: 1 31 | * , two: 2 32 | * }; 33 | * ``` 34 | */ 35 | 36 | var assert = require('assert'); 37 | 38 | module.exports = function() {}; 39 | 40 | module.exports.prototype = { 41 | 42 | configure: function(options) { 43 | assert( 44 | options === true, 45 | this.getOptionName() + ' option requires a true value or should be removed' 46 | ); 47 | }, 48 | 49 | getOptionName: function() { 50 | return 'requireCommaBeforeLineBreak'; 51 | }, 52 | 53 | check: function(file, errors) { 54 | file.iterateTokensByTypeAndValue('Punctuator', ',', function(token) { 55 | var prevToken = token.getPreviousCodeToken(); 56 | 57 | if (prevToken.value === ',') { 58 | return; 59 | } 60 | errors.assert.sameLine({ 61 | token: prevToken, 62 | nextToken: token, 63 | message: 'Commas should not be placed on new line' 64 | }); 65 | }); 66 | } 67 | 68 | }; 69 | -------------------------------------------------------------------------------- /lib/rules/require-keywords-on-new-line.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Requires placing keywords on a new line. 3 | * 4 | * Type: `Array` 5 | * 6 | * Values: Array of quoted keywords 7 | * 8 | * #### Example 9 | * 10 | * ```js 11 | * "requireKeywordsOnNewLine": ["else"] 12 | * ``` 13 | * 14 | * ##### Valid 15 | * 16 | * ```js 17 | * if (x < 0) { 18 | * x++; 19 | * } 20 | * else { 21 | * x--; 22 | * } 23 | * ``` 24 | * 25 | * ##### Invalid 26 | * 27 | * ```js 28 | * if (x < 0) { 29 | * x++; 30 | * } else { 31 | * x--; 32 | * } 33 | * ``` 34 | */ 35 | 36 | var assert = require('assert'); 37 | 38 | module.exports = function() {}; 39 | 40 | module.exports.prototype = { 41 | 42 | configure: function(keywords) { 43 | assert(Array.isArray(keywords), this.getOptionName() + ' option requires array value'); 44 | this._keywords = keywords; 45 | }, 46 | 47 | getOptionName: function() { 48 | return 'requireKeywordsOnNewLine'; 49 | }, 50 | 51 | check: function(file, errors) { 52 | file.iterateTokensByTypeAndValue('Keyword', this._keywords, function(token) { 53 | errors.assert.differentLine({ 54 | token: token.getPreviousCodeToken(), 55 | nextToken: token 56 | }); 57 | }); 58 | } 59 | 60 | }; 61 | -------------------------------------------------------------------------------- /lib/rules/require-line-feed-at-file-end.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Requires placing line feed at file end. 3 | * 4 | * Type: `Boolean` 5 | * 6 | * Value: `true` 7 | * 8 | * #### Example 9 | * 10 | * ```js 11 | * "requireLineFeedAtFileEnd": true 12 | * ``` 13 | */ 14 | 15 | var assert = require('assert'); 16 | 17 | module.exports = function() {}; 18 | 19 | module.exports.prototype = { 20 | 21 | configure: function(options) { 22 | assert( 23 | options === true, 24 | this.getOptionName() + ' option requires a true value or should be removed' 25 | ); 26 | }, 27 | 28 | getOptionName: function() { 29 | return 'requireLineFeedAtFileEnd'; 30 | }, 31 | 32 | check: function(file, errors) { 33 | var lastToken = file.getLastToken({includeComments: true}); 34 | var prevToken = file.getPrevToken(lastToken, {includeComments: true}); 35 | errors.assert.differentLine({ 36 | token: prevToken, 37 | nextToken: lastToken, 38 | message: 'Missing line feed at file end' 39 | }); 40 | } 41 | 42 | }; 43 | -------------------------------------------------------------------------------- /lib/rules/require-multi-line-ternary.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Requires the test, consequent and alternate to be on separate lines when using the ternary operator. 3 | * 4 | * Types: `Boolean` 5 | * 6 | * #### Example 7 | * 8 | * ```js 9 | * "requireMultiLineTernary": true 10 | * ``` 11 | * 12 | * ##### Valid 13 | * 14 | * ```js 15 | * var foo = (a === b) 16 | * ? 1 17 | * : 2; 18 | * ``` 19 | * 20 | * ##### Invalid 21 | * 22 | * ```js 23 | * var foo = (a === b) ? 1 : 2; 24 | * ``` 25 | */ 26 | 27 | var assert = require('assert'); 28 | 29 | module.exports = function() {}; 30 | 31 | module.exports.prototype = { 32 | configure: function(options) { 33 | assert( 34 | options === true, 35 | this.getOptionName() + ' option requires a true value or should be removed' 36 | ); 37 | }, 38 | 39 | getOptionName: function() { 40 | return 'requireMultiLineTernary'; 41 | }, 42 | 43 | check: function(file, errors) { 44 | file.iterateNodesByType('ConditionalExpression', function(node) { 45 | 46 | errors.assert.differentLine({ 47 | token: node.test, 48 | nextToken: node.consequent, 49 | message: 'Missing new line after test' 50 | }); 51 | 52 | errors.assert.differentLine({ 53 | token: node.consequent, 54 | nextToken: node.alternate, 55 | message: 'Missing new line after consequent' 56 | }); 57 | 58 | }); 59 | } 60 | 61 | }; 62 | -------------------------------------------------------------------------------- /lib/rules/require-numeric-literals.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Requires use of binary, hexadecimal, and octal literals instead of parseInt. 3 | * 4 | * Type: `Boolean` 5 | * 6 | * Value: `true` 7 | * 8 | * Version: `ES6` 9 | * 10 | * #### Example 11 | * 12 | * ```js 13 | * "requireNumericLiterals": true 14 | * ``` 15 | * 16 | * ##### Valid 17 | * 18 | * ```js 19 | * 0b111110111 === 503; 20 | * 0o767 === 503; 21 | * 0x1F7 === 503; 22 | * ``` 23 | * 24 | * ##### Invalid 25 | * 26 | * ```js 27 | * parseInt("111110111", 2) === 503; 28 | * parseInt("767", 8) === 503; 29 | * parseInt("1F7", 16) === 255; 30 | * ``` 31 | */ 32 | 33 | var assert = require('assert'); 34 | 35 | module.exports = function() {}; 36 | 37 | module.exports.prototype = { 38 | configure: function(options) { 39 | assert( 40 | options === true, 41 | this.getOptionName() + ' option requires a true value or should be removed' 42 | ); 43 | 44 | this._radixMap = { 45 | 2: 'binary', 46 | 8: 'octal', 47 | 16: 'hexadecimal' 48 | }; 49 | }, 50 | 51 | getOptionName: function() { 52 | return 'requireNumericLiterals'; 53 | }, 54 | 55 | check: function(file, errors) { 56 | var radixMap = this._radixMap; 57 | file.iterateNodesByType(['CallExpression'], function(node) { 58 | // don't check for parseInt(1) 59 | if (node.arguments.length !== 2) { 60 | return; 61 | } 62 | 63 | // only error if the radix is 2, 8, or 16 64 | var radixName = radixMap[node.arguments[1].value]; 65 | 66 | if (node.callee.type === 'Identifier' && 67 | node.callee.name === 'parseInt' && 68 | radixName && 69 | node.arguments[0].type.indexOf('Literal') > -1 70 | ) { 71 | errors.add('Use ' + radixName + ' literals instead of parseInt', node); 72 | } 73 | }); 74 | } 75 | }; 76 | -------------------------------------------------------------------------------- /lib/rules/require-padding-newlines-in-objects.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Requires newline inside curly braces of all objects. 3 | * 4 | * Type: `Boolean` 5 | * 6 | * Value: `true` 7 | * 8 | * #### Example 9 | * 10 | * ```js 11 | * "requirePaddingNewLinesInObjects": true 12 | * ``` 13 | * 14 | * ##### Valid 15 | * 16 | * ```js 17 | * var x = { 18 | * a: 1 19 | * }; 20 | * foo({ 21 | * a: { 22 | * b: 1 23 | * } 24 | * }); 25 | * ``` 26 | * 27 | * ##### Invalid 28 | * 29 | * ```js 30 | * var x = { a: 1 }; 31 | * foo({a:{b:1}}); 32 | * ``` 33 | */ 34 | 35 | var assert = require('assert'); 36 | 37 | module.exports = function() {}; 38 | 39 | module.exports.prototype = { 40 | 41 | configure: function(value) { 42 | assert( 43 | value === true, 44 | this.getOptionName() + ' option requires a true value or should be removed' 45 | ); 46 | }, 47 | 48 | getOptionName: function() { 49 | return 'requirePaddingNewLinesInObjects'; 50 | }, 51 | 52 | check: function(file, errors) { 53 | file.iterateNodesByType('ObjectExpression', function(node) { 54 | var openingBracket = node.getFirstToken(); 55 | var nextToken = file.getNextToken(openingBracket); 56 | 57 | if (nextToken.type === 'Punctuator' && nextToken.value === '}') { 58 | return; 59 | } 60 | 61 | errors.assert.differentLine({ 62 | token: openingBracket, 63 | nextToken: nextToken, 64 | message: 'Missing newline after opening curly brace' 65 | }); 66 | 67 | var closingBracket = file.getLastNodeToken(node); 68 | 69 | errors.assert.differentLine({ 70 | token: file.getPrevToken(closingBracket), 71 | nextToken: closingBracket, 72 | message: 'Missing newline before closing curly brace' 73 | }); 74 | }); 75 | } 76 | 77 | }; 78 | -------------------------------------------------------------------------------- /lib/rules/require-parentheses-around-arrow-param.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Requires parentheses around arrow function expressions with a single parameter. 3 | * 4 | * Type: `Boolean` 5 | * 6 | * Value: `true` 7 | * 8 | * Version: `ES6` 9 | * 10 | * #### Example 11 | * 12 | * ```js 13 | * "requireParenthesesAroundArrowParam": true 14 | * ``` 15 | * 16 | * ##### Valid 17 | * 18 | * ```js 19 | * [1, 2, 3].map((x) => x * x); 20 | * // params are always required for multiple parameters 21 | * [1, 2, 3].map((x, y, z) => x * x); 22 | * ``` 23 | * 24 | * ##### Invalid 25 | * 26 | * ```js 27 | * [1, 2, 3].map(x => x * x); 28 | * ``` 29 | */ 30 | 31 | var assert = require('assert'); 32 | 33 | module.exports = function() {}; 34 | 35 | module.exports.prototype = { 36 | 37 | configure: function(options) { 38 | assert( 39 | options === true, 40 | this.getOptionName() + ' option requires a true value or should be removed' 41 | ); 42 | }, 43 | 44 | getOptionName: function() { 45 | return 'requireParenthesesAroundArrowParam'; 46 | }, 47 | 48 | check: function(file, errors) { 49 | function isWrapped(node) { 50 | var openParensToken = file.getPrevToken(file.getFirstNodeToken(node)); 51 | var closingParensToken = file.getNextToken(file.getLastNodeToken(node)); 52 | var closingTokenValue = closingParensToken ? closingParensToken.value : ''; 53 | 54 | return openParensToken.value + closingTokenValue === '()'; 55 | } 56 | 57 | file.iterateNodesByType('ArrowFunctionExpression', function(node) { 58 | var params = node.params; 59 | var firstParam = params[0]; 60 | 61 | if (params.length === 1 && !isWrapped(firstParam)) { 62 | errors.add( 63 | 'Wrap arrow function expressions in parentheses', 64 | firstParam 65 | ); 66 | } 67 | }); 68 | } 69 | 70 | }; 71 | -------------------------------------------------------------------------------- /lib/rules/require-shorthand-arrow-functions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Require arrow functions to use an expression body when returning a single statement 3 | * (no block statement, implicit return). 4 | * 5 | * Type: `Boolean` 6 | * 7 | * Value: `true` 8 | * 9 | * Version: `ES6` 10 | * 11 | * #### Example 12 | * 13 | * ```js 14 | * "requireShorthandArrowFunctions": true 15 | * ``` 16 | * 17 | * ##### Valid 18 | * 19 | * ```js 20 | * // single expression 21 | * evens.map(v => v + 1); 22 | * // multiple statments require a block 23 | * evens.map(v => { 24 | * v = v + 1; 25 | * return v; 26 | * }); 27 | * ``` 28 | * 29 | * ##### Invalid 30 | * 31 | * ```js 32 | * evens.map(v => { return v + 1; }); 33 | * ``` 34 | */ 35 | 36 | var assert = require('assert'); 37 | 38 | module.exports = function() {}; 39 | 40 | module.exports.prototype = { 41 | 42 | configure: function(options) { 43 | assert( 44 | options === true, 45 | this.getOptionName() + ' option requires a true value or should be removed' 46 | ); 47 | }, 48 | 49 | getOptionName: function() { 50 | return 'requireShorthandArrowFunctions'; 51 | }, 52 | 53 | check: function(file, errors) { 54 | file.iterateNodesByType('ArrowFunctionExpression', function(node) { 55 | var body = node.body; 56 | if (body.type === 'BlockStatement' && 57 | body.body.length === 1 && 58 | body.body[0].type === 'ReturnStatement') { 59 | errors.add( 60 | 'Use the shorthand arrow function form', 61 | node.body 62 | ); 63 | } 64 | }); 65 | } 66 | 67 | }; 68 | -------------------------------------------------------------------------------- /lib/rules/require-space-after-keywords.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Requires space after keyword. 3 | * 4 | * Types: `Array` or `Boolean` 5 | * 6 | * Values: Array of quoted keywords or `true` to require all of the keywords below to have a space afterward. 7 | * 8 | * #### Example 9 | * 10 | * ```js 11 | * "requireSpaceAfterKeywords": [ 12 | * "do", 13 | * "for", 14 | * "if", 15 | * "else", 16 | * "switch", 17 | * "case", 18 | * "try", 19 | * "catch", 20 | * "void", 21 | * "while", 22 | * "with", 23 | * "return", 24 | * "typeof", 25 | * "function" 26 | * ] 27 | * ``` 28 | * 29 | * ##### Valid 30 | * 31 | * ```js 32 | * if (x) { 33 | * x++; 34 | * } 35 | * ``` 36 | * 37 | * ##### Invalid 38 | * 39 | * ```js 40 | * if(x) { 41 | * x++; 42 | * } 43 | * ``` 44 | */ 45 | 46 | var assert = require('assert'); 47 | 48 | var defaultKeywords = require('../utils').spacedKeywords; 49 | 50 | module.exports = function() {}; 51 | 52 | module.exports.prototype = { 53 | 54 | configure: function(keywords) { 55 | assert( 56 | Array.isArray(keywords) || keywords === true, 57 | this.getOptionName() + ' option requires array or true value'); 58 | 59 | if (keywords === true) { 60 | keywords = defaultKeywords; 61 | } 62 | 63 | this._keywords = keywords; 64 | }, 65 | 66 | getOptionName: function() { 67 | return 'requireSpaceAfterKeywords'; 68 | }, 69 | 70 | check: function(file, errors) { 71 | file.iterateTokensByTypeAndValue('Keyword', this._keywords, function(token) { 72 | var nextToken = file.getNextToken(token, {includeComments: true}); 73 | 74 | if (nextToken.type === 'Punctuator' && nextToken.value === ';') { 75 | return; 76 | } 77 | 78 | errors.assert.spacesBetween({ 79 | token: token, 80 | nextToken: nextToken, 81 | exactly: 1, 82 | message: 'One space required after "' + token.value + '" keyword' 83 | }); 84 | }); 85 | } 86 | 87 | }; 88 | -------------------------------------------------------------------------------- /lib/rules/require-space-after-object-keys.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Requires space after object keys. 3 | * 4 | * Type: `Boolean` 5 | * 6 | * Value: `true` 7 | * 8 | * #### Example 9 | * 10 | * ```js 11 | * "requireSpaceAfterObjectKeys": true 12 | * ``` 13 | * 14 | * ##### Valid 15 | * ```js 16 | * var x = {a : 1}; 17 | * ``` 18 | * ##### Invalid 19 | * ```js 20 | * var x = {a: 1}; 21 | * ``` 22 | */ 23 | 24 | var assert = require('assert'); 25 | 26 | module.exports = function() {}; 27 | 28 | module.exports.prototype = { 29 | 30 | configure: function(options) { 31 | assert( 32 | options === true, 33 | this.getOptionName() + ' option requires a true value or should be removed' 34 | ); 35 | }, 36 | 37 | getOptionName: function() { 38 | return 'requireSpaceAfterObjectKeys'; 39 | }, 40 | 41 | check: function(file, errors) { 42 | file.iterateNodesByType('ObjectExpression', function(node) { 43 | node.properties.forEach(function(property) { 44 | if ( 45 | property.type === 'ObjectMethod' && 46 | (property.kind === 'get' || property.kind === 'set') 47 | ) { 48 | return; 49 | } 50 | 51 | if (property.shorthand || 52 | property.type === 'SpreadProperty') { 53 | return; 54 | } 55 | 56 | var token = file.getLastNodeToken(property.key); 57 | 58 | if (property.computed === true) { 59 | token = file.getNextToken(token); 60 | } 61 | 62 | errors.assert.whitespaceBetween({ 63 | token: token, 64 | nextToken: file.getNextToken(token), 65 | message: 'Missing space after key' 66 | }); 67 | }); 68 | }); 69 | } 70 | 71 | }; 72 | -------------------------------------------------------------------------------- /lib/rules/require-space-before-comma.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Requires space before comma 3 | * 4 | * Types: `Boolean` 5 | * 6 | * Values: `true` to require a space before any comma 7 | * 8 | * #### Example 9 | * 10 | * ```js 11 | * "requireSpaceBeforeComma": true 12 | * ``` 13 | * 14 | * ##### Valid 15 | * 16 | * ```js 17 | * var a ,b; 18 | * ``` 19 | * 20 | * ##### Invalid 21 | * 22 | * ```js 23 | * var a,b; 24 | * ``` 25 | */ 26 | 27 | var assert = require('assert'); 28 | 29 | module.exports = function() { 30 | }; 31 | 32 | module.exports.prototype = { 33 | 34 | configure: function(option) { 35 | assert( 36 | option === true, 37 | this.getOptionName() + ' option requires true value' 38 | ); 39 | }, 40 | 41 | getOptionName: function() { 42 | return 'requireSpaceBeforeComma'; 43 | }, 44 | 45 | check: function(file, errors) { 46 | file.iterateTokensByTypeAndValue('Punctuator', ',', function(token) { 47 | var prevToken = token.getPreviousCodeToken(); 48 | 49 | errors.assert.whitespaceBetween({ 50 | token: prevToken, 51 | nextToken: token, 52 | message: 'Space required before comma' 53 | }); 54 | }); 55 | } 56 | 57 | }; 58 | -------------------------------------------------------------------------------- /lib/rules/require-space-before-object-values.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Requires space after object keys. 3 | * 4 | * Type: `Boolean` 5 | * 6 | * Value: `true` 7 | * 8 | * #### Example 9 | * 10 | * ```js 11 | * "requireSpaceBeforeObjectValues": true 12 | * ``` 13 | * 14 | * ##### Valid 15 | * ```js 16 | * var x = {a: 1}; 17 | * ``` 18 | * ##### Invalid 19 | * ```js 20 | * var x = {a:1}; 21 | * ``` 22 | */ 23 | 24 | var assert = require('assert'); 25 | 26 | module.exports = function() {}; 27 | 28 | module.exports.prototype = { 29 | 30 | configure: function(options) { 31 | assert( 32 | options === true, 33 | this.getOptionName() + ' option requires a true value or should be removed' 34 | ); 35 | }, 36 | 37 | getOptionName: function() { 38 | return 'requireSpaceBeforeObjectValues'; 39 | }, 40 | 41 | check: function(file, errors) { 42 | file.iterateNodesByType('ObjectExpression', function(node) { 43 | node.properties.forEach(function(property) { 44 | if ( 45 | property.type === 'ObjectMethod' && 46 | (property.kind === 'get' || property.kind === 'set') 47 | ) { 48 | return; 49 | } 50 | 51 | if (property.shorthand || property.method || 52 | property.type === 'SpreadProperty') { 53 | return; 54 | } 55 | 56 | var keyToken = file.getFirstNodeToken(property.key); 57 | 58 | var colon = file.findNextToken(keyToken, 'Punctuator', ':'); 59 | 60 | errors.assert.whitespaceBetween({ 61 | token: colon, 62 | nextToken: file.getNextToken(colon), 63 | message: 'Missing space after key colon' 64 | }); 65 | }); 66 | }); 67 | } 68 | 69 | }; 70 | -------------------------------------------------------------------------------- /lib/rules/require-space-between-arguments.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Ensure there are spaces after argument separators in call expressions. 3 | * 4 | * Type: `Boolean` 5 | * 6 | * Value: `true` 7 | * 8 | * #### Example 9 | * 10 | * ```js 11 | * "requireSpaceBetweenArguments": true 12 | * ``` 13 | * 14 | * ##### Valid 15 | * 16 | * ```js 17 | * a(b, c); 18 | * ``` 19 | * 20 | * ##### Invalid 21 | * 22 | * ```js 23 | * a(b,c); 24 | * ``` 25 | */ 26 | 27 | var assert = require('assert'); 28 | 29 | module.exports = function() {}; 30 | 31 | module.exports.prototype = { 32 | 33 | configure: function(options) { 34 | assert( 35 | options === true, 36 | this.getOptionName() + ' option requires a true value or should be removed' 37 | ); 38 | }, 39 | 40 | getOptionName: function() { 41 | return 'requireSpaceBetweenArguments'; 42 | }, 43 | 44 | check: function(file, errors) { 45 | file.iterateNodesByType(['CallExpression'], function(node) { 46 | node.arguments.forEach(function(param) { 47 | var punctuatorToken = file.getPrevToken(file.getFirstNodeToken(param)); 48 | if (punctuatorToken.value === ',') { 49 | errors.assert.whitespaceBetween({ 50 | token: punctuatorToken, 51 | nextToken: file.getNextToken(punctuatorToken) 52 | }); 53 | } 54 | }); 55 | }); 56 | } 57 | }; 58 | -------------------------------------------------------------------------------- /lib/rules/require-spaces-in-call-expression.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Requires space before `()` in call expressions. 3 | * 4 | * Type: `Boolean` 5 | * 6 | * Value: `true` 7 | * 8 | * #### Example 9 | * 10 | * ```js 11 | * "requireSpacesInCallExpression": true 12 | * ``` 13 | * 14 | * ##### Valid 15 | * 16 | * ```js 17 | * var x = foobar (); 18 | * ``` 19 | * 20 | * ##### Invalid 21 | * 22 | * ```js 23 | * var x = foobar(); 24 | * ``` 25 | */ 26 | 27 | var assert = require('assert'); 28 | 29 | module.exports = function() {}; 30 | 31 | module.exports.prototype = { 32 | configure: function(options) { 33 | assert( 34 | options === true, 35 | this.getOptionName() + ' option requires a true value or should be removed' 36 | ); 37 | }, 38 | 39 | getOptionName: function() { 40 | return 'requireSpacesInCallExpression'; 41 | }, 42 | 43 | check: function(file, errors) { 44 | file.iterateNodesByType('CallExpression', function(node) { 45 | var lastCalleeToken = file.getLastNodeToken(node.callee); 46 | var roundBraceToken = file.findNextToken(lastCalleeToken, 'Punctuator', '('); 47 | 48 | errors.assert.whitespaceBetween({ 49 | token: file.getPrevToken(roundBraceToken), 50 | nextToken: roundBraceToken, 51 | message: 'Missing space before opening round brace' 52 | }); 53 | }); 54 | } 55 | }; 56 | -------------------------------------------------------------------------------- /lib/rules/require-spread.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Disallows using `.apply` in favor of the spread operator 3 | * 4 | * Types: `Boolean` 5 | * 6 | * Values: 7 | * - `true` specifies that apply `.apply` is disallowed 8 | * 9 | * Version: `ES6` 10 | * 11 | * #### Example 12 | * 13 | * ```js 14 | * "requireSpread": true 15 | * ``` 16 | * 17 | * ##### Valid for mode `true` 18 | * 19 | * ```js 20 | * const wrap = (f, g) => (...args) => g(f, ...args) 21 | * instance.method(...args) 22 | * ``` 23 | * 24 | * ##### Invalid for mode `true` 25 | * 26 | * ```js 27 | * const wrap = (f, g) => (...args) => g.apply(g, [f].concat(args)) 28 | * instance.method.apply(instance, args); 29 | * ``` 30 | */ 31 | 32 | var assert = require('assert'); 33 | 34 | module.exports = function() {}; 35 | 36 | module.exports.prototype = { 37 | 38 | configure: function(options) { 39 | assert( 40 | options === true, 41 | this.getOptionName() + ' option requires a true value or should be removed' 42 | ); 43 | }, 44 | 45 | getOptionName: function() { 46 | return 'requireSpread'; 47 | }, 48 | 49 | check: function(file, errors) { 50 | file.iterateNodesByType('CallExpression', function(node) { 51 | var callee = node.callee; 52 | var firstParameter = node.arguments[0]; 53 | 54 | if (node.arguments.length === 2 && 55 | callee.property && callee.property.name === 'apply' && 56 | callee.object && callee.object.name === firstParameter.name) { 57 | errors.add( 58 | 'Illegal use of apply method. Use the spread operator instead', 59 | node.callee.property 60 | ); 61 | } 62 | }); 63 | } 64 | }; 65 | -------------------------------------------------------------------------------- /lib/rules/require-use-strict.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Requires `'use strict';` statements 3 | * 4 | * Values: 5 | * - `true` for default behavior (require 'use strict' statements for files) 6 | * 7 | * #### Example 8 | * 9 | * ```js 10 | * "requireUseStrict": true 11 | * ``` 12 | * 13 | * ##### Valid 14 | * 15 | * ```js 16 | * 'use strict'; 17 | * // code 18 | * ``` 19 | * 20 | * ```js 21 | * // comment line or block 22 | * 'use strict'; 23 | * // code 24 | * ``` 25 | * 26 | * ```js 27 | * // comment line or block 28 | * 29 | * 'use strict'; 30 | * // code 31 | * ``` 32 | * 33 | * ##### Invalid 34 | * 35 | * ```js 36 | * // code 37 | * ``` 38 | */ 39 | 40 | var assert = require('assert'); 41 | 42 | module.exports = function() {}; 43 | 44 | module.exports.prototype = { 45 | 46 | configure: function(options) { 47 | if (typeof options !== 'object') { 48 | assert( 49 | options === true, 50 | this.getOptionName() + ' option requires either a true value or an object' 51 | ); 52 | 53 | var _options = {files: true}; 54 | return this.configure(_options); 55 | } 56 | 57 | this._checkFiles = (options.files === true); 58 | }, 59 | 60 | getOptionName: function() { 61 | return 'requireUseStrict'; 62 | }, 63 | 64 | check: function(file, errors) { 65 | var program = file.getProgram(); 66 | var directive = program.directives[0]; 67 | 68 | if (directive) { 69 | return; 70 | } 71 | 72 | errors.add( 73 | '`"use strict";` is required at the top of each file', 74 | program 75 | ); 76 | } 77 | }; 78 | -------------------------------------------------------------------------------- /lib/tree-iterator.js: -------------------------------------------------------------------------------- 1 | var estraverse = require('estraverse'); 2 | var VISITOR_KEYS = require('cst').visitorKeys; 3 | 4 | module.exports.iterate = function iterate(node, cb) { 5 | if ('type' in node) { 6 | estraverse.traverse(node, { 7 | enter: function(node, parent) { 8 | var parentCollection = []; 9 | 10 | // parentCollection support 11 | var path = this.path(); 12 | if (path) { 13 | var collectionKey; 14 | while (path.length > 0) { 15 | var pathElement = path.pop(); 16 | if (typeof pathElement === 'string') { 17 | collectionKey = pathElement; 18 | break; 19 | } 20 | } 21 | 22 | parentCollection = parent[collectionKey]; 23 | if (!Array.isArray(parentCollection)) { 24 | parentCollection = [parentCollection]; 25 | } 26 | } 27 | 28 | if (cb(node, parent, parentCollection) === false) { 29 | return estraverse.VisitorOption.Skip; 30 | } 31 | }, 32 | keys: VISITOR_KEYS 33 | }); 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /presets/grunt.json: -------------------------------------------------------------------------------- 1 | { 2 | "preset": "google", 3 | "maximumLineLength": 120, 4 | "requireCamelCaseOrUpperCaseIdentifiers": "ignoreProperties", 5 | "validateQuoteMarks": { "mark": "'", "escape": true }, 6 | "disallowMultipleVarDecl": "exceptUndefined" 7 | } 8 | -------------------------------------------------------------------------------- /presets/idiomatic.json: -------------------------------------------------------------------------------- 1 | { 2 | "preset": "jquery", 3 | "requireEarlyReturn": true, 4 | "requireSpacesInsideParentheses": { 5 | "all": true, 6 | "ignoreParenthesizedExpression": true, 7 | "except": [ "{", "}", "[", "]", "function", "\"" ] 8 | }, 9 | "disallowSpacesInsideParentheses": { 10 | "only": [ "{", "}", "[", "]", "function" ] 11 | }, 12 | "disallowSpacesInCallExpression": true, 13 | "requirePaddingNewLinesBeforeLineComments": null, 14 | "requireSpaceAfterLineComment": { 15 | "allExcept": ["#", "="] 16 | }, 17 | "disallowMultipleLineBreaks": null, 18 | "requireCapitalizedComments": null, 19 | "validateIndentation": null, 20 | "validateCommentPosition": { "position": "above" } 21 | } 22 | -------------------------------------------------------------------------------- /presets/mdcs.json: -------------------------------------------------------------------------------- 1 | { 2 | "requireCurlyBraces": ["while", "do", "try", "catch"], 3 | "requireSpaceAfterKeywords": ["if", "else", "for", "while", "do", "switch", "return", "try", "catch"], 4 | "requireSpacesInFunctionExpression": { 5 | "beforeOpeningCurlyBrace": true 6 | }, 7 | "requirePaddingNewlinesInBlocks": true, 8 | "requireSpacesInsideParentheses": "all", 9 | "requireSpacesInsideObjectBrackets": "all", 10 | "requireSpacesInsideBrackets": { 11 | "allExcept": [ "[", "]" ] 12 | }, 13 | "requireSpaceBeforeBlockStatements": true, 14 | "requireSpacesInForStatement": true, 15 | "requireSpaceBeforeObjectValues":true, 16 | "requireSpaceBetweenArguments": true, 17 | "disallowKeywords": [ "with" ], 18 | "requireLineFeedAtFileEnd": true, 19 | "validateLineBreaks": "LF", 20 | "validateIndentation": "\t", 21 | "requireSpaceAfterPrefixUnaryOperators": true, 22 | "requireSpaceBeforePostfixUnaryOperators": ["++", "--"], 23 | "requireSpaceBeforeBinaryOperators": true, 24 | "requireSpaceAfterBinaryOperators": true, 25 | "disallowSpaceBeforeBinaryOperators": [","], 26 | "requireSpacesInConditionalExpression": { 27 | "afterTest": true, 28 | "beforeConsequent": true, 29 | "afterConsequent": true, 30 | "beforeAlternate": true 31 | }, 32 | "disallowTrailingWhitespace": true, 33 | "disallowNewlineBeforeBlockStatements": true 34 | } 35 | -------------------------------------------------------------------------------- /presets/node-style-guide.json: -------------------------------------------------------------------------------- 1 | { 2 | "disallowKeywords": ["with"], 3 | "disallowKeywordsOnNewLine": ["else"], 4 | "disallowMixedSpacesAndTabs": true, 5 | "disallowMultipleVarDecl": "exceptUndefined", 6 | "disallowNewlineBeforeBlockStatements": true, 7 | "disallowQuotedKeysInObjects": true, 8 | "disallowSpaceAfterObjectKeys": true, 9 | "disallowSpaceAfterPrefixUnaryOperators": true, 10 | "disallowSpacesInFunction": { 11 | "beforeOpeningRoundBrace": true 12 | }, 13 | "disallowSpacesInsideParentheses": true, 14 | "disallowTrailingWhitespace": true, 15 | "maximumLineLength": 80, 16 | "requireCamelCaseOrUpperCaseIdentifiers": true, 17 | "requireCapitalizedComments": true, 18 | "requireCapitalizedConstructors": true, 19 | "requireCurlyBraces": true, 20 | "requireSpaceAfterKeywords": [ 21 | "if", 22 | "else", 23 | "for", 24 | "while", 25 | "do", 26 | "switch", 27 | "case", 28 | "return", 29 | "try", 30 | "catch", 31 | "typeof" 32 | ], 33 | "requireSpaceAfterLineComment": true, 34 | "requireSpaceAfterBinaryOperators": true, 35 | "requireSpaceBeforeBinaryOperators": true, 36 | "requireSpaceBeforeBlockStatements": true, 37 | "requireSpaceBeforeObjectValues": true, 38 | "requireSpacesInFunction": { 39 | "beforeOpeningCurlyBrace": true 40 | }, 41 | "requireTrailingComma": { 42 | "ignoreSingleLine": true 43 | }, 44 | "requireEarlyReturn": true, 45 | "validateIndentation": 2, 46 | "validateLineBreaks": "LF", 47 | "validateQuoteMarks": "'" 48 | } 49 | -------------------------------------------------------------------------------- /presets/wordpress.json: -------------------------------------------------------------------------------- 1 | { 2 | "preset": "jquery", 3 | "requireDotNotation": { 4 | "allExcept": ["snake_case", "keywords"] 5 | }, 6 | "disallowSpaceAfterPrefixUnaryOperators": ["++", "--", "+", "-", "~"], 7 | "disallowSpaceBeforePostfixUnaryOperators": true, 8 | "maximumLineLength": null, 9 | "requireVarDeclFirst": true, 10 | "requireSpaceAfterPrefixUnaryOperators": ["!"], 11 | "requireSpacesInsideBrackets": null, 12 | "requireSpacesInsideParentheses": { 13 | "all": true, 14 | "except": [ "{", "}", "[", "]", "function" ] 15 | }, 16 | "requireYodaConditions": ["==", "!=", "===", "!=="], 17 | "validateQuoteMarks": "'", 18 | "requireCapitalizedComments": { 19 | "allExcept": ["global", "exported", "jshint", "eslint", "jslint"] 20 | }, 21 | "requireCamelCaseOrUpperCaseIdentifiers": "ignoreProperties", 22 | "requireBlocksOnNewline": true 23 | } 24 | -------------------------------------------------------------------------------- /publish/prepublish.js: -------------------------------------------------------------------------------- 1 | require('./helpers/generate-patterns'); 2 | 3 | -------------------------------------------------------------------------------- /templates/pr-create.md.ejs: -------------------------------------------------------------------------------- 1 | ### JSCS is deprecated 2 | 3 | Thanks for wanting to contribute, but this project is deprecated. 4 | 5 | We recommend using [ESLint](http://eslint.org/) instead (the JSCS team will be contributing there). 6 | 7 | ![jscs-merged-eslint](https://cloud.githubusercontent.com/assets/588473/16885375/4353ea64-4a9c-11e6-9d60-da1c98c7c8d0.png) 8 | 9 | Check out our blog posts for more information: 10 | 11 | * [JSCS — end of the line](https://medium.com/@markelog/jscs-end-of-the-line-bc9bf0b3fdb2) 12 | * [Welcoming JSCS to ESLint](http://eslint.org/blog/2016/04/welcoming-jscs-to-eslint) 13 | * [JSCS End of Life](http://eslint.org/blog/2016/07/jscs-end-of-life) 14 | 15 | > If you would like to contribute to the JSCS Compatibility Effort, follow the [milestone here](https://github.com/eslint/eslint/milestone/15). 16 | 17 | Since we won't be maintaining the project, please do not open issues/PRs here. Thanks! 18 | -------------------------------------------------------------------------------- /test/data/autofixing/spaces.js: -------------------------------------------------------------------------------- 1 | var y=2; 2 | var x=y+1; 3 | if(x); -------------------------------------------------------------------------------- /test/data/checker/empty.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jscs-dev/node-jscs/5d16bda74dd881ac5201e53496696cd8373e1136/test/data/checker/empty.js -------------------------------------------------------------------------------- /test/data/checker/file.js: -------------------------------------------------------------------------------- 1 | with (x) { y++; } 2 | -------------------------------------------------------------------------------- /test/data/checker/sub/file.js: -------------------------------------------------------------------------------- 1 | with (x) { y++; } 2 | -------------------------------------------------------------------------------- /test/data/checker/without-extension: -------------------------------------------------------------------------------- 1 | with (x) { y++; } 2 | -------------------------------------------------------------------------------- /test/data/cli/cli.json: -------------------------------------------------------------------------------- 1 | { 2 | "disallowKeywords": ["with"] 3 | } 4 | -------------------------------------------------------------------------------- /test/data/cli/error.js: -------------------------------------------------------------------------------- 1 | with (x) { y++; } 2 | -------------------------------------------------------------------------------- /test/data/cli/errorFilter.json: -------------------------------------------------------------------------------- 1 | { 2 | "errorFilter": "../error-filter/index.js", 3 | "disallowKeywords": ["with"] 4 | } 5 | -------------------------------------------------------------------------------- /test/data/cli/esnext.js: -------------------------------------------------------------------------------- 1 | import { foo } from "bar"; 2 | -------------------------------------------------------------------------------- /test/data/cli/maxErrors.json: -------------------------------------------------------------------------------- 1 | { 2 | "disallowKeywords": ["with"], 3 | "requireSpaceBeforePostfixUnaryOperators": ["++"] 4 | } 5 | -------------------------------------------------------------------------------- /test/data/cli/modules/node_modules/jscs/lib/cli.js: -------------------------------------------------------------------------------- 1 | module.exports = function() {} 2 | module.exports.test = true; 3 | -------------------------------------------------------------------------------- /test/data/cli/stdin.js: -------------------------------------------------------------------------------- 1 | var x = {a: 'a'}; 2 | -------------------------------------------------------------------------------- /test/data/cli/success.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jscs-dev/node-jscs/5d16bda74dd881ac5201e53496696cd8373e1136/test/data/cli/success.js -------------------------------------------------------------------------------- /test/data/config.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jscs-dev/node-jscs/5d16bda74dd881ac5201e53496696cd8373e1136/test/data/config.json -------------------------------------------------------------------------------- /test/data/configs/additionalRules/.jscsrc: -------------------------------------------------------------------------------- 1 | { 2 | "successRule": true, 3 | "additionalRules": [ 4 | "./success-rule.js" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /test/data/configs/additionalRules/gh-1932/.jscsrc: -------------------------------------------------------------------------------- 1 | { 2 | "successRule": true 3 | } 4 | -------------------------------------------------------------------------------- /test/data/configs/additionalRules/gh-1932/success-rule.js: -------------------------------------------------------------------------------- 1 | module.exports = function() {}; 2 | 3 | module.exports.prototype = { 4 | 5 | configure: function() {}, 6 | 7 | getOptionName: function() { 8 | return 'successRule'; 9 | }, 10 | 11 | check: function(file, errors) {} 12 | }; 13 | -------------------------------------------------------------------------------- /test/data/configs/additionalRules/success-rule.js: -------------------------------------------------------------------------------- 1 | module.exports = function() {}; 2 | 3 | module.exports.prototype = { 4 | 5 | configure: function() {}, 6 | 7 | getOptionName: function() { 8 | return 'successRule'; 9 | }, 10 | 11 | check: function(file, errors) {} 12 | }; 13 | -------------------------------------------------------------------------------- /test/data/configs/custom/config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | from: 'js' 3 | }; 4 | -------------------------------------------------------------------------------- /test/data/configs/emptyPackage/package.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /test/data/configs/excludeFiles/.withdot/error.js: -------------------------------------------------------------------------------- 1 | with (x) { y++; } 2 | -------------------------------------------------------------------------------- /test/data/configs/excludeFiles/exclude-files.js: -------------------------------------------------------------------------------- 1 | with (x) { y++; } 2 | -------------------------------------------------------------------------------- /test/data/configs/excludeFiles/nested/exclude-files.js: -------------------------------------------------------------------------------- 1 | with (x) { y++; } 2 | -------------------------------------------------------------------------------- /test/data/configs/excludeFiles/test1.jscs.json: -------------------------------------------------------------------------------- 1 | { 2 | "disallowKeywords": ["with"], 3 | "excludeFiles": [ 4 | "*.js" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /test/data/configs/excludeFiles/test2.jscs.json: -------------------------------------------------------------------------------- 1 | { 2 | "disallowKeywords": ["with"], 3 | "excludeFiles": [ 4 | "exclude-files.js" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /test/data/configs/excludeFiles/test3.jscs.json: -------------------------------------------------------------------------------- 1 | { 2 | "disallowKeywords": ["with"], 3 | "excludeFiles": [ 4 | "*/exclude-files.js" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /test/data/configs/excludeFiles/test4.jscs.json: -------------------------------------------------------------------------------- 1 | { 2 | "disallowKeywords": ["with"], 3 | "excludeFiles": [ 4 | "../**/exclude-files.js" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /test/data/configs/jscsrc/.jscsrc: -------------------------------------------------------------------------------- 1 | // should allow comments in this type of config 2 | { 3 | "from": "jscsrc" 4 | } 5 | -------------------------------------------------------------------------------- /test/data/configs/jscsrc/external.jscsrc: -------------------------------------------------------------------------------- 1 | { 2 | "disallowKeywords": [ "with" ] 3 | } 4 | -------------------------------------------------------------------------------- /test/data/configs/json/.jscs.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /test/data/configs/json/corrupted.json: -------------------------------------------------------------------------------- 1 | { 2 | "error": true 3 | } } -------------------------------------------------------------------------------- /test/data/configs/json/withBOM.json: -------------------------------------------------------------------------------- 1 | { 2 | "test": true 3 | } 4 | -------------------------------------------------------------------------------- /test/data/configs/json/withComments.json: -------------------------------------------------------------------------------- 1 | 2 | // Error 3 | { 4 | "test": true 5 | } 6 | -------------------------------------------------------------------------------- /test/data/configs/mixedWithEmptyPkg/.jscsrc: -------------------------------------------------------------------------------- 1 | { "from": ".jscsrc" } 2 | -------------------------------------------------------------------------------- /test/data/configs/mixedWithEmptyPkg/package.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /test/data/configs/mixedWithPkg/.jscs.json: -------------------------------------------------------------------------------- 1 | { "from": ".jscs.json" } 2 | -------------------------------------------------------------------------------- /test/data/configs/mixedWithPkg/.jscsrc: -------------------------------------------------------------------------------- 1 | { "from": ".jscsrc" } 2 | -------------------------------------------------------------------------------- /test/data/configs/mixedWithPkg/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "jscsConfig": { "from": "package.json" } 3 | } 4 | -------------------------------------------------------------------------------- /test/data/configs/mixedWithUpperPkg/jscsrc/.jscs.json: -------------------------------------------------------------------------------- 1 | { "from": ".jscs.json" } 2 | -------------------------------------------------------------------------------- /test/data/configs/mixedWithUpperPkg/jscsrc/.jscsrc: -------------------------------------------------------------------------------- 1 | { "from": ".jscsrc" } 2 | -------------------------------------------------------------------------------- /test/data/configs/mixedWithUpperPkg/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "jscsConfig": { "from": "package.json" } 3 | } 4 | -------------------------------------------------------------------------------- /test/data/configs/mixedWithoutPkg/.jscs.json: -------------------------------------------------------------------------------- 1 | { "from": ".jscs.json" } 2 | -------------------------------------------------------------------------------- /test/data/configs/mixedWithoutPkg/.jscsrc: -------------------------------------------------------------------------------- 1 | { "from": ".jscsrc" } 2 | -------------------------------------------------------------------------------- /test/data/configs/modules/node_modules/jscs-config-first-test/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "test": true 3 | } 4 | -------------------------------------------------------------------------------- /test/data/configs/modules/node_modules/jscs-config-first-test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "index.json" 3 | } -------------------------------------------------------------------------------- /test/data/configs/modules/node_modules/jscs-esprima/esprima.js: -------------------------------------------------------------------------------- 1 | module.exports.parse = function() { 2 | } -------------------------------------------------------------------------------- /test/data/configs/modules/node_modules/jscs-esprima/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "esprima": "./esprima.js" 3 | } 4 | -------------------------------------------------------------------------------- /test/data/configs/modules/node_modules/jscs-esprima/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "index.json" 3 | } -------------------------------------------------------------------------------- /test/data/configs/modules/node_modules/jscs-filter/filter.js: -------------------------------------------------------------------------------- 1 | module.exports = function() {}; 2 | -------------------------------------------------------------------------------- /test/data/configs/modules/node_modules/jscs-filter/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "errorFilter": "./filter.js" 3 | } 4 | -------------------------------------------------------------------------------- /test/data/configs/modules/node_modules/jscs-filter/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "index.json" 3 | } -------------------------------------------------------------------------------- /test/data/configs/modules/node_modules/jscs-mod/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "test": true 3 | } 4 | -------------------------------------------------------------------------------- /test/data/configs/modules/node_modules/jscs-mod/js-module.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "module": true 3 | } 4 | -------------------------------------------------------------------------------- /test/data/configs/modules/node_modules/jscs-mod/module.json: -------------------------------------------------------------------------------- 1 | { 2 | "module": true 3 | } 4 | -------------------------------------------------------------------------------- /test/data/configs/modules/node_modules/jscs-mod/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "index.json" 3 | } -------------------------------------------------------------------------------- /test/data/configs/modules/node_modules/jscs-plugin/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": ["./plugin.js"], 3 | "test": true 4 | } 5 | -------------------------------------------------------------------------------- /test/data/configs/modules/node_modules/jscs-plugin/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "index.json" 3 | } -------------------------------------------------------------------------------- /test/data/configs/modules/node_modules/jscs-plugin/plugin.js: -------------------------------------------------------------------------------- 1 | module.exports = function(conf) { 2 | conf.registerRule({ 3 | getOptionName: function() { 4 | return 'test'; 5 | }, 6 | configure: function(config) { 7 | this.config = config; 8 | } 9 | }); 10 | } 11 | -------------------------------------------------------------------------------- /test/data/configs/modules/node_modules/jscs-preset-module/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "test": true 3 | } 4 | -------------------------------------------------------------------------------- /test/data/configs/modules/node_modules/jscs-preset-module/js-module.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "module": true 3 | } 4 | -------------------------------------------------------------------------------- /test/data/configs/modules/node_modules/jscs-preset-module/module.json: -------------------------------------------------------------------------------- 1 | { 2 | "module": true 3 | } 4 | -------------------------------------------------------------------------------- /test/data/configs/modules/node_modules/jscs-preset-module/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "index.json" 3 | } -------------------------------------------------------------------------------- /test/data/configs/modules/node_modules/jscs-preset-nm/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "preset": "test" 3 | } 4 | -------------------------------------------------------------------------------- /test/data/configs/modules/node_modules/jscs-preset-nm/node_modules/jscs-config-test/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "test": true 3 | } 4 | -------------------------------------------------------------------------------- /test/data/configs/modules/node_modules/jscs-preset-nm/node_modules/jscs-config-test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "index.json" 3 | } -------------------------------------------------------------------------------- /test/data/configs/modules/node_modules/jscs-preset-nm/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "index.json" 3 | } -------------------------------------------------------------------------------- /test/data/configs/modules/node_modules/jscs-preset-nm/rule.js: -------------------------------------------------------------------------------- 1 | module.exports = function() {}; 2 | 3 | module.exports.prototype = { 4 | 5 | configure: function(config) { 6 | this.config = config 7 | }, 8 | 9 | getOptionName: function() { 10 | return 'test'; 11 | }, 12 | 13 | check: function() { 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /test/data/configs/modules/node_modules/jscs-preset-s-test/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "test": true 3 | } 4 | -------------------------------------------------------------------------------- /test/data/configs/modules/node_modules/jscs-preset-s-test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "index.json" 3 | } -------------------------------------------------------------------------------- /test/data/configs/modules/node_modules/jscs-preset-wikimedia/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "test": true 3 | } 4 | -------------------------------------------------------------------------------- /test/data/configs/modules/node_modules/jscs-preset-wikimedia/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "index.json" 3 | } -------------------------------------------------------------------------------- /test/data/configs/modules/node_modules/jscs-rule/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "additionalRules": ["./rule.js"], 3 | "test": true 4 | } 5 | -------------------------------------------------------------------------------- /test/data/configs/modules/node_modules/jscs-rule/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "index.json" 3 | } -------------------------------------------------------------------------------- /test/data/configs/modules/node_modules/jscs-rule/rule.js: -------------------------------------------------------------------------------- 1 | module.exports = function() {}; 2 | 3 | module.exports.prototype = { 4 | 5 | configure: function(config) { 6 | this.config = config 7 | }, 8 | 9 | getOptionName: function() { 10 | return 'test'; 11 | }, 12 | 13 | check: function() { 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /test/data/configs/modules/node_modules/jscs-t-test/.jscsrc: -------------------------------------------------------------------------------- 1 | { 2 | "one": false, 3 | "second": true 4 | } 5 | -------------------------------------------------------------------------------- /test/data/configs/modules/node_modules/jscs-t-test/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "one": true, 3 | "preset": "./.jscsrc" 4 | } 5 | -------------------------------------------------------------------------------- /test/data/configs/modules/node_modules/jscs-t-test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "index.json" 3 | } -------------------------------------------------------------------------------- /test/data/configs/modules/node_modules/test/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "test": true 3 | } 4 | -------------------------------------------------------------------------------- /test/data/configs/modules/node_modules/test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "index.json" 3 | } -------------------------------------------------------------------------------- /test/data/configs/package/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "jscsConfig": {} 3 | } 4 | -------------------------------------------------------------------------------- /test/data/configs/yaml/.jscs.yaml: -------------------------------------------------------------------------------- 1 | # should allow comments in this type of config 2 | 3 | type: yaml 4 | -------------------------------------------------------------------------------- /test/data/configs/yaml/.jscsrc: -------------------------------------------------------------------------------- 1 | # should allow comments in this type of config 2 | 3 | type: yaml 4 | -------------------------------------------------------------------------------- /test/data/error-filter/index.js: -------------------------------------------------------------------------------- 1 | module.exports = function(error) { 2 | // Blocks all errors from being added 3 | return false; 4 | }; 5 | -------------------------------------------------------------------------------- /test/data/error-filter/modules/node_modules/jscs-config-filter/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "test": true 3 | } 4 | -------------------------------------------------------------------------------- /test/data/error-filter/modules/node_modules/jscs-config-filter/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "index.json" 3 | } -------------------------------------------------------------------------------- /test/data/error-filter/modules/node_modules/jscs-error-filter/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "test": true 3 | } 4 | -------------------------------------------------------------------------------- /test/data/error-filter/modules/node_modules/jscs-error-filter/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "index.json" 3 | } -------------------------------------------------------------------------------- /test/data/extract/always.htm: -------------------------------------------------------------------------------- 1 | should be ignored when not always 2 | 3 | 4 | 5 | 6 | Test file 7 | 8 | 11 | 12 | 13 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /test/data/extract/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Test file 6 | 9 | 11 | 12 | 14 | 18 | 21 | 22 | 23 | 26 | 30 | 34 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /test/data/extract/plain.txt: -------------------------------------------------------------------------------- 1 | should be ignored usually 2 | 5 | -------------------------------------------------------------------------------- /test/data/extract/valid.xhtml: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /test/data/options/file-extensions/file-extensions: -------------------------------------------------------------------------------- 1 | with (x) { y++; } 2 | -------------------------------------------------------------------------------- /test/data/options/file-extensions/file-extensions-2.jS: -------------------------------------------------------------------------------- 1 | with (x) { y++; } 2 | -------------------------------------------------------------------------------- /test/data/options/file-extensions/file-extensions.js: -------------------------------------------------------------------------------- 1 | with (x) { y++; } 2 | -------------------------------------------------------------------------------- /test/data/options/file-extensions/file-extensions.jsx: -------------------------------------------------------------------------------- 1 | with (x) { y++; } 2 | -------------------------------------------------------------------------------- /test/data/options/preset/google.js: -------------------------------------------------------------------------------- 1 | // includes portions of yo cli (c) Google 2 | var opts = nopt({ 3 | // requireOperatorBeforeLineBreak 4 | help: Boolean, 5 | version: Boolean 6 | }); 7 | 8 | // requireCamelCaseOrUpperCaseIdentifiers 9 | function test(opt_test) { 10 | var var_args = arguments; 11 | } 12 | 13 | // disallowMultipleLineBreaks 14 | // disallowMultipleVarDecl 15 | var insight = new Insight({ 16 | // validateIndentation: 2 17 | // validateQuoteMarks: '', 18 | trackingCode: 'UA-31537568-1', 19 | // requireCamelCaseOrUpperCaseIdentifiers 20 | packageName: pkg.name, 21 | packageVersion: pkg.version 22 | }); 23 | 24 | // requireSpacesInFunctionExpression: before curly brace 25 | var functionExpression = function fooFn() {}; 26 | // disallowSpacesInAnonymousFunctionExpression: before round brace 27 | var anonymousFunction = function() {}; 28 | 29 | // requireCurlyBraces 30 | // requireSpaceAfterKeywords 31 | // requireSpaceBeforeBinaryOperators 32 | // requireSpaceAfterBinaryOperators 33 | // requireSpacesInConditionalExpression 34 | if (opts.insight === false) { 35 | 36 | // requireSpaceBetweenArguments 37 | insight.config.set('optOut', true); 38 | } else if (opts.insight) { 39 | insight.config.set('optOut', false); 40 | } 41 | 42 | function rootCheck() { 43 | // requireSpaceBeforeBlockStatements 44 | // disallowSpaceAfterPrefixUnaryOperators 45 | if (!isRoot() && process.setuid) { 46 | try { 47 | // Try to force yo to run on a safe uid 48 | process.setuid(501); 49 | } catch (err) {} 50 | } 51 | } 52 | 53 | // disallowSpacesInsideArrayBrackets 54 | var arr = [1, 2, 3]; 55 | // disallowSpacesInsideObjectBrackets 56 | var obj = {a: 1, b: 2, c: 3}; 57 | // disallowSpacesInsideParentheses 58 | console.log('string'); 59 | 60 | // maximumLineLength 61 | // should ignore really long comment lines ....................................... 62 | // and regex 63 | var regex = /somesuperlongregex..................................................../; 64 | -------------------------------------------------------------------------------- /test/data/options/preset/grunt.js: -------------------------------------------------------------------------------- 1 | /* 2 | * grunt 3 | * http://gruntjs.com/ 4 | * 5 | * Copyright (c) 2014 "Cowboy" Ben Alman 6 | * Licensed under the MIT license. 7 | * https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT 8 | */ 9 | 10 | // Expose internal grunt libs. 11 | function gRequire(name) { 12 | return grunt[name] = require('./grunt/' + name); 13 | } 14 | 15 | var option = gRequire('option'); 16 | var help = gRequire('help'); 17 | 18 | // Expose the task interface. I've never called this manually, and have no idea 19 | // how it will work. But it might. 20 | grunt.tasks = function(tasks, options, done) { 21 | 22 | // Display the grunt version and quit if the user did --version. 23 | var _tasks, _options; 24 | if (option('version')) { 25 | 26 | if (option('verbose')) { 27 | // Initialize task system so that available tasks can be listed. 28 | grunt.task.init([], {help: true}); 29 | 30 | Object.keys(grunt.cli.optlist).forEach(function(long) { 31 | var o = grunt.cli.optlist[long]; 32 | _options.push('--' + (o.negate ? 'no-' : '') + long); 33 | if (o.short) { _options.push('-' + o.short); } 34 | }); 35 | } 36 | } 37 | 38 | // Determine and output which tasks will be run. 39 | var tasksSpecified = tasks && tasks.length > 0; 40 | tasks = task.parseArgs([tasksSpecified ? tasks : 'default']); 41 | 42 | if (!tasksSpecified) { 43 | verbose.writeln('No tasks specified, running default tasks.'); 44 | } 45 | 46 | // Report, etc when all tasks have completed. 47 | task.options({ 48 | done: function() { 49 | process.removeListener('uncaughtException', uncaughtHandler); 50 | fail.report(); 51 | 52 | if (done) { 53 | done(); 54 | } else { 55 | util.exit(0); 56 | } 57 | } 58 | }); 59 | }; 60 | 61 | // requireSpaceBetweenArguments 62 | console.log(1, 2); 63 | -------------------------------------------------------------------------------- /test/data/plugin/plugin.js: -------------------------------------------------------------------------------- 1 | var sinon = require('sinon'); 2 | module.exports = sinon.spy(function(configuration) {}); 3 | -------------------------------------------------------------------------------- /test/data/render/comments.js: -------------------------------------------------------------------------------- 1 | // Hello world! 2 | 3 | /* A little block comment */ 4 | 5 | console.log('Hello World'); 6 | 7 | // The rest of this file is an array of empty lines 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /test/data/render/hashbang.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | console.log('NodeJs!'); 4 | -------------------------------------------------------------------------------- /test/data/render/ios-includes.js: -------------------------------------------------------------------------------- 1 | 2 | #! random stuff 3 | #! 1234 4 | var a = 5; 5 | 6 | /* comment */ 7 | 8 | #import "abc.js" 9 | #import abc.js 10 | var a = 5; 11 | -------------------------------------------------------------------------------- /test/data/render/strings.js: -------------------------------------------------------------------------------- 1 | 2 | var a = "123"; // Double-quoted string 3 | 4 | var b = '123'; // Single-quoted string 5 | 6 | var c = `123`; // ES6 template string 7 | -------------------------------------------------------------------------------- /test/data/reporter/test-reporter.js: -------------------------------------------------------------------------------- 1 | module.exports = function() {} 2 | -------------------------------------------------------------------------------- /test/data/rules/additional-rules.js: -------------------------------------------------------------------------------- 1 | module.exports = function() {}; 2 | 3 | module.exports.prototype = { 4 | 5 | configure: function() {}, 6 | 7 | getOptionName: function() { 8 | return 'testAdditionalRules'; 9 | }, 10 | 11 | check: function(file, errors) { 12 | errors.add('test', { line: 1, column: 9 }); 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /test/data/rules/skip.error: -------------------------------------------------------------------------------- 1 | should skip this file 2 | -------------------------------------------------------------------------------- /test/data/validate-indentation/fix-expected.js: -------------------------------------------------------------------------------- 1 | if (a) { 2 | /* 3 | 123 4 | */ 5 | var b = c; 6 | var d = e 7 | * f; 8 | var e = f; // <- 9 | // MISALIGNED COMMENT 10 | function g() { 11 | if (h) { 12 | var i = j; 13 | } // <- 14 | } // <- 15 | 16 | while (k) l++; 17 | while (m) { 18 | n--; // -> 19 | } // <- 20 | 21 | do { 22 | o = p + 23 | q; // NO ERROR: DON'T VALIDATE MULTILINE STATEMENTS 24 | o = p + 25 | q; 26 | } while(r); // <- 27 | 28 | for (var s in t) { 29 | u++; 30 | } 31 | 32 | for (;;) { // <- 33 | v++; // <- 34 | } 35 | 36 | if ( w ) { 37 | x++; 38 | } else if (y) { 39 | z++; // <- 40 | aa++; 41 | } else { // <- 42 | bb++; // -> 43 | } // -> 44 | } 45 | 46 | if (g) { 47 | /** 48 | * DOCBLOCK 49 | 50 | */ 51 | var a = b + 52 | c; 53 | 54 | /** 55 | * DOCBLOCK 56 | 57 | */ 58 | var e = f + g; 59 | 60 | } 61 | else if(c) { 62 | d++; 63 | } 64 | 65 | var Detector = { 66 | webgl: ( function () { try { a++; } catch( e ) { return false; } } )(), 67 | workers: !! window.Worker 68 | }; 69 | 70 | for ( i = 0; i < len; i++ ) 71 | { 72 | a++; 73 | } 74 | -------------------------------------------------------------------------------- /test/data/validate-indentation/fix-include-empty-expected.js: -------------------------------------------------------------------------------- 1 | 2 | if (a) { 3 | 4 | var b = c; 5 | 6 | while (c) { 7 | d++; 8 | } 9 | 10 | 11 | } 12 | -------------------------------------------------------------------------------- /test/data/validate-indentation/fix-include-empty-input.js: -------------------------------------------------------------------------------- 1 | 2 | if (a) { 3 | 4 | var b = c; 5 | 6 | while (c) { 7 | d++; 8 | } 9 | 10 | 11 | } 12 | -------------------------------------------------------------------------------- /test/data/validate-indentation/fix-input.js: -------------------------------------------------------------------------------- 1 | if (a) { 2 | /* 3 | 123 4 | */ 5 | var b = c; 6 | var d = e 7 | * f; 8 | var e = f; // <- 9 | // MISALIGNED COMMENT 10 | function g() { 11 | if (h) { 12 | var i = j; 13 | } // <- 14 | } // <- 15 | 16 | while (k) l++; 17 | while (m) { 18 | n--; // -> 19 | } // <- 20 | 21 | do { 22 | o = p + 23 | q; // NO ERROR: DON'T VALIDATE MULTILINE STATEMENTS 24 | o = p + 25 | q; 26 | } while(r); // <- 27 | 28 | for (var s in t) { 29 | u++; 30 | } 31 | 32 | for (;;) { // <- 33 | v++; // <- 34 | } 35 | 36 | if ( w ) { 37 | x++; 38 | } else if (y) { 39 | z++; // <- 40 | aa++; 41 | } else { // <- 42 | bb++; // -> 43 | } // -> 44 | } 45 | 46 | if (g) { 47 | /** 48 | * DOCBLOCK 49 | 50 | */ 51 | var a = b + 52 | c; 53 | 54 | /** 55 | * DOCBLOCK 56 | 57 | */ 58 | var e = f + g; 59 | 60 | } 61 | else if(c) { 62 | d++; 63 | } 64 | 65 | var Detector = { 66 | webgl: ( function () { try { a++; } catch( e ) { return false; } } )(), 67 | workers: !! window.Worker 68 | }; 69 | 70 | for ( i = 0; i < len; i++ ) 71 | { 72 | a++; 73 | } 74 | -------------------------------------------------------------------------------- /test/mocha.opts: -------------------------------------------------------------------------------- 1 | test/chai-extensions.js 2 | test/specs/**/*.js 3 | -t 3000 4 | -R progress 5 | -u bdd 6 | -------------------------------------------------------------------------------- /test/scripts/forgotten-rules.json: -------------------------------------------------------------------------------- 1 | { 2 | "disallowSemicolons": true, 3 | "disallowUnusedParams": true 4 | } 5 | -------------------------------------------------------------------------------- /test/specs/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../.jshintrc", 3 | "expr": true 4 | } 5 | -------------------------------------------------------------------------------- /test/specs/get-cli.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect; 2 | var path = require('path'); 3 | 4 | var sinon = require('sinon'); 5 | 6 | describe('get-cli', function() { 7 | describe('local with global load', function() { 8 | function delCache() { 9 | delete require.cache[path.resolve(__dirname, '../../lib/get-cli.js')]; 10 | } 11 | 12 | beforeEach(delCache); 13 | afterEach(delCache); 14 | 15 | it('should load "global" version of jscs', function() { 16 | var p = path.resolve(__dirname, '../../lib/get-cli.js'); 17 | 18 | expect(!require(p).test).to.equal(true); 19 | }); 20 | 21 | it('should load local version of "jscs"', function() { 22 | sinon.stub(process, 'cwd', function() { 23 | return path.resolve(__dirname, '../data/cli/modules'); 24 | }); 25 | 26 | expect(!!require('../../lib/get-cli.js').test).to.equal(true); 27 | 28 | process.cwd.restore(); 29 | }); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /test/specs/reporters/checkstyle.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect; 2 | var sinon = require('sinon'); 3 | 4 | var parser = require('xml2js').parseString; 5 | 6 | var Checker = require('../../../lib/checker'); 7 | var checkstyle = require('../../../lib/reporters/checkstyle'); 8 | 9 | describe('reporters/checkstyle', function() { 10 | it('should correctly report error results', function(done) { 11 | var checker = new Checker(); 12 | 13 | checker.registerDefaultRules(); 14 | checker.configure({ disallowKeywords: ['with'] }); 15 | 16 | var output = ''; 17 | 18 | sinon.stub(console, 'log', function(xml) { 19 | output += xml; 20 | }); 21 | 22 | checkstyle([checker.checkString('with (x) { y++; }')]); 23 | 24 | console.log.restore(); 25 | 26 | parser(output, {trim: true}, function(err, result) { 27 | if (!err) { 28 | var checkstyle = result.checkstyle; 29 | 30 | expect(!!checkstyle).to.equal(true); 31 | expect(checkstyle.$.version).to.equal('4.3'); 32 | 33 | var file = checkstyle.file[0]; 34 | expect(!!file).to.equal(true); 35 | expect(file.$.name).to.equal('input'); 36 | 37 | var error = file.error[0]; 38 | expect(!!error).to.equal(true); 39 | expect(error.$.line).to.equal('1'); 40 | expect(error.$.column).to.equal('3'); 41 | expect(error.$.severity).to.equal('error'); 42 | expect(error.$.message).to.equal('disallowKeywords: Illegal keyword: with'); 43 | expect(error.$.source).to.equal('jscs'); 44 | } else { 45 | throw err; 46 | } 47 | 48 | done(); 49 | }); 50 | }); 51 | }); 52 | -------------------------------------------------------------------------------- /test/specs/reporters/console.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect; 2 | var sinon = require('sinon'); 3 | 4 | var Checker = require('../../../lib/checker'); 5 | var consoleReporter = require('../../../lib/reporters/console'); 6 | 7 | describe('reporters/console', function() { 8 | var checker; 9 | 10 | beforeEach(function() { 11 | checker = new Checker(); 12 | checker.registerDefaultRules(); 13 | checker.configure({ disallowKeywords: ['with'] }); 14 | 15 | sinon.stub(console, 'log'); 16 | }); 17 | 18 | afterEach(function() { 19 | console.log.restore(); 20 | }); 21 | 22 | it('should correctly reports no errors', function() { 23 | consoleReporter([checker.checkString('a++;')]); 24 | expect(console.log).to.have.callCount(0); 25 | }); 26 | 27 | it('should correctly report 1 error', function() { 28 | consoleReporter([checker.checkString('with (x) {}')]); 29 | 30 | expect(console.log.getCall(0).args[0].indexOf('Illegal keyword: with')).to.be.above(-1); 31 | expect(console.log.getCall(1).args[0]).to.equal('\n1 code style error found.'); 32 | expect(console.log).to.have.callCount(2); 33 | }); 34 | 35 | it('should correctly reports 2 errors', function() { 36 | consoleReporter([checker.checkString('with(x){} with(x){} ')]); 37 | 38 | expect(console.log.getCall(0).args[0].indexOf('Illegal keyword: with')).to.be.above(-1); 39 | expect(console.log.getCall(1).args[0].indexOf('Illegal keyword: with')).to.be.above(-1); 40 | expect(console.log.getCall(2).args[0]).to.equal('\n2 code style errors found.'); 41 | expect(console.log).to.have.callCount(3); 42 | }); 43 | }); 44 | -------------------------------------------------------------------------------- /test/specs/reporters/inline.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect; 2 | var sinon = require('sinon'); 3 | 4 | var Checker = require('../../../lib/checker'); 5 | var inline = require('../../../lib/reporters/inline'); 6 | 7 | describe('reporters/inline', function() { 8 | var checker; 9 | 10 | beforeEach(function() { 11 | checker = new Checker(); 12 | checker.registerDefaultRules(); 13 | checker.configure({ disallowKeywords: ['with'] }); 14 | 15 | sinon.stub(console, 'log'); 16 | }); 17 | 18 | afterEach(function() { 19 | console.log.restore(); 20 | }); 21 | 22 | it('should correctly reports no errors', function() { 23 | inline([checker.checkString('a++;')]); 24 | 25 | expect(console.log).to.have.callCount(0); 26 | }); 27 | 28 | it('should correctly reports 1 error', function() { 29 | inline([checker.checkString('with (x) {}')]); 30 | 31 | expect(console.log.getCall(0).args[0]) 32 | .to.equal('input: line 1, col 2, disallowKeywords: Illegal keyword: with'); 33 | expect(console.log).to.have.callCount(1); 34 | }); 35 | 36 | it('should correctly reports 2 errors', function() { 37 | inline([checker.checkString('with (x) {} with (x) {}')]); 38 | 39 | expect(console.log.getCall(0).args[0]) 40 | .to.equal('input: line 1, col 2, disallowKeywords: Illegal keyword: with'); 41 | expect(console.log.getCall(1).args[0]) 42 | .to.equal('input: line 1, col 14, disallowKeywords: Illegal keyword: with'); 43 | expect(console.log).to.have.callCount(2); 44 | }); 45 | }); 46 | -------------------------------------------------------------------------------- /test/specs/reporters/inlinesingle.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect; 2 | var sinon = require('sinon'); 3 | 4 | var Checker = require('../../../lib/checker'); 5 | var inlinesingle = require('../../../lib/reporters/inlinesingle'); 6 | 7 | describe('reporters/inlinesingle', function() { 8 | var checker; 9 | 10 | beforeEach(function() { 11 | checker = new Checker(); 12 | checker.registerDefaultRules(); 13 | checker.configure({ disallowKeywords: ['with'] }); 14 | 15 | sinon.stub(console, 'log'); 16 | }); 17 | 18 | afterEach(function() { 19 | console.log.restore(); 20 | }); 21 | 22 | it('should correctly reports no errors', function() { 23 | inlinesingle([checker.checkString('a++;')]); 24 | 25 | expect(console.log).to.have.callCount(0); 26 | }); 27 | 28 | it('should correctly reports 1 error', function() { 29 | inlinesingle([checker.checkString('with (x) {}')]); 30 | 31 | expect(console.log.getCall(0).args[0]) 32 | .to.equal('input: line 1, col 2, disallowKeywords: Illegal keyword: with'); 33 | expect(console.log).to.have.callCount(1); 34 | }); 35 | 36 | it('should correctly reports 2 errors', function() { 37 | inlinesingle([checker.checkString('with (x) {} with (x) {}')]); 38 | 39 | expect(console.log.getCall(0).args[0]) 40 | .to.equal('input: line 1, col 2, disallowKeywords: Illegal keyword:' + 41 | ' with\ninput: line 1, col 14, disallowKeywords: Illegal keyword: with'); 42 | expect(console.log).to.have.callCount(1); 43 | }); 44 | }); 45 | -------------------------------------------------------------------------------- /test/specs/reporters/json.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect; 2 | var sinon = require('sinon'); 3 | 4 | var Checker = require('../../../lib/checker'); 5 | var json = require('../../../lib/reporters/json'); 6 | 7 | describe('reporters/json', function() { 8 | var checker; 9 | 10 | beforeEach(function() { 11 | checker = new Checker(); 12 | checker.registerDefaultRules(); 13 | checker.configure({disallowKeywords: ['with']}); 14 | sinon.stub(console, 'log'); 15 | }); 16 | 17 | afterEach(function() { 18 | console.log.restore(); 19 | }); 20 | 21 | it('should correctly reports no errors', function() { 22 | json([checker.checkString('a++;')]); 23 | expect(console.log).to.have.callCount(0); 24 | }); 25 | 26 | it('should correctly reports 1 error', function() { 27 | json([checker.checkString('with (x) {}')]); 28 | var resultStr = '{"input":[{"line":1,"column":3,"message":"disallowKeywords: Illegal keyword: with"}]}'; 29 | expect(console.log.getCall(0).args[0]).to.equal(resultStr); 30 | expect(console.log).to.have.callCount(1); 31 | }); 32 | 33 | it('should correctly reports 2 errors', function() { 34 | json([checker.checkString('with (x) {} with (x) {}')]); 35 | var resultStr = '{"input":[{"line":1,"column":3,"message":"disallowKeywords: Illegal keyword: with"},' + 36 | '{"line":1,"column":15,"message":"disallowKeywords: Illegal keyword: with"}]}'; 37 | expect(console.log.getCall(0).args[0]).to.equal(resultStr); 38 | expect(console.log).to.have.callCount(1); 39 | }); 40 | }); 41 | -------------------------------------------------------------------------------- /test/specs/reporters/junit.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect; 2 | var sinon = require('sinon'); 3 | 4 | var parser = require('xml2js').parseString; 5 | 6 | var Checker = require('../../../lib/checker'); 7 | var junit = require('../../../lib/reporters/junit'); 8 | 9 | describe('reporters/junit', function() { 10 | var checker = new Checker(); 11 | 12 | checker.registerDefaultRules(); 13 | 14 | it('should correctly report error results', function(done) { 15 | sinon.stub(console, 'log', function(xml) { 16 | parser(xml, {trim: true}, function(err, result) { 17 | if (!err) { 18 | var testsuite = result.testsuite; 19 | 20 | expect(!!testsuite).to.equal(true); 21 | expect(testsuite.$.name).to.equal('JSCS'); 22 | expect(testsuite.$.tests).to.equal('1'); 23 | expect(testsuite.$.failures).to.equal('1'); 24 | 25 | var testcase = testsuite.testcase[0]; 26 | expect(!!testcase).to.equal(true); 27 | expect(testcase.$.name).to.equal('input'); 28 | expect(testcase.$.failures).to.equal('1'); 29 | 30 | expect(testcase.failure[0].length).to.be.at.least(1); 31 | } else { 32 | throw err; 33 | } 34 | 35 | console.log.restore(); 36 | done(); 37 | }); 38 | }); 39 | 40 | checker.configure({ disallowKeywords: ['with'] }); 41 | junit([checker.checkString('with (x) { y++; }')]); 42 | }); 43 | }); 44 | -------------------------------------------------------------------------------- /test/specs/reporters/summary.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect; 2 | var sinon = require('sinon'); 3 | 4 | var Checker = require('../../../lib/checker'); 5 | var summaryReporter = require('../../../lib/reporters/summary'); 6 | 7 | describe('reporters/summary', function() { 8 | var checker; 9 | 10 | beforeEach(function() { 11 | checker = new Checker(); 12 | checker.registerDefaultRules(); 13 | checker.configure({ disallowKeywords: ['with'] }); 14 | 15 | sinon.stub(console, 'log'); 16 | }); 17 | 18 | afterEach(function() { 19 | console.log.restore(); 20 | }); 21 | 22 | it('should correctly reports no errors', function() { 23 | summaryReporter([checker.checkString('a++;')]); 24 | expect(console.log.getCall(0).args[0]).to.contain('No code style errors found.'); 25 | expect(console.log).to.have.callCount(1); 26 | }); 27 | 28 | it('should correctly report 1 error', function() { 29 | var expectedByFile = /input.*1/; 30 | var expectedByRule = /disallowKeywords.*1.*1/; 31 | var expectedByRuleTotal = /All.*1.*1/; 32 | 33 | summaryReporter([checker.checkString('with (x) {}')]); 34 | expect(!!expectedByFile.test(console.log.getCall(0).args[0])).to.equal(true); 35 | expect(!!expectedByRule.test(console.log.getCall(1).args[0])).to.equal(true); 36 | expect(!!expectedByRuleTotal.test(console.log.getCall(1).args[0])).to.equal(true); 37 | expect(console.log).to.have.callCount(2); 38 | }); 39 | 40 | it('should correctly report 2 errors', function() { 41 | var expectedByFile = /input.*2/; 42 | var expectedByRule = /disallowKeywords.*2.*1/; 43 | var expectedByRuleTotal = /All.*2.*1/; 44 | 45 | summaryReporter([checker.checkString('with(x){} with(x){} ')]); 46 | expect(!!expectedByFile.test(console.log.getCall(0).args[0])).to.equal(true); 47 | expect(!!expectedByRule.test(console.log.getCall(1).args[0])).to.equal(true); 48 | expect(!!expectedByRuleTotal.test(console.log.getCall(1).args[0])).to.equal(true); 49 | expect(console.log).to.have.callCount(2); 50 | }); 51 | }); 52 | -------------------------------------------------------------------------------- /test/specs/reporters/unix.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect; 2 | var sinon = require('sinon'); 3 | 4 | var Checker = require('../../../lib/checker'); 5 | var unix = require('../../../lib/reporters/unix'); 6 | 7 | describe('reporters/unix', function() { 8 | var checker; 9 | 10 | beforeEach(function() { 11 | checker = new Checker(); 12 | checker.registerDefaultRules(); 13 | checker.configure({disallowKeywords: ['with']}); 14 | sinon.stub(console, 'log'); 15 | }); 16 | 17 | afterEach(function() { 18 | console.log.restore(); 19 | }); 20 | 21 | it('should correctly reports no errors', function() { 22 | unix([checker.checkString('a++;')]); 23 | expect(console.log).to.have.callCount(0); 24 | }); 25 | 26 | it('should correctly reports 1 error', function() { 27 | unix([checker.checkString('with (x) {}')]); 28 | expect(console.log.getCall(0).args[0]).to.equal('input:1:2: disallowKeywords: Illegal keyword: with'); 29 | expect(console.log).to.have.callCount(1); 30 | }); 31 | 32 | it('should correctly reports 2 errors', function() { 33 | unix([checker.checkString('with (x) {} with (x) {}')]); 34 | expect(console.log.getCall(0).args[0]).to.equal('input:1:2: disallowKeywords: Illegal keyword: with'); 35 | expect(console.log.getCall(1).args[0]).to.equal('input:1:14: disallowKeywords: Illegal keyword: with'); 36 | expect(console.log).to.have.callCount(2); 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /test/specs/rules/disallow-anonymous-functions.js: -------------------------------------------------------------------------------- 1 | var Checker = require('../../../lib/checker'); 2 | var expect = require('chai').expect; 3 | 4 | describe('rules/disallow-anonymous-functions', function() { 5 | var checker; 6 | 7 | beforeEach(function() { 8 | checker = new Checker(); 9 | checker.registerDefaultRules(); 10 | 11 | checker.configure({ 12 | disallowAnonymousFunctions: true 13 | }); 14 | }); 15 | 16 | it('should report on anonymous function declarations', function() { 17 | expect(checker.checkString('$("hi").click(function(){});')) 18 | .to.have.one.validation.error.from('disallowAnonymousFunctions'); 19 | }); 20 | 21 | it('should report on anonymous function expressions', function() { 22 | expect(checker.checkString('var x = function(){};')) 23 | .to.have.one.validation.error.from('disallowAnonymousFunctions'); 24 | expect(checker.checkString('var foo = {bar: function() {}};')) 25 | .to.have.one.validation.error.from('disallowAnonymousFunctions'); 26 | }); 27 | 28 | it('should not report on named function declarations', function() { 29 | expect(checker.checkString('function named(){};')).to.have.no.errors(); 30 | }); 31 | 32 | it('should not report on named function expressions', function() { 33 | expect(checker.checkString('$("hi").click(function named(){});')).to.have.no.errors(); 34 | expect(checker.checkString('var x = function named(){};')).to.have.no.errors(); 35 | }); 36 | }); 37 | -------------------------------------------------------------------------------- /test/specs/rules/disallow-array-destructuring-return.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect; 2 | var Checker = require('../../../lib/checker'); 3 | 4 | describe('rules/disallow-array-destructuring-return', function() { 5 | var checker; 6 | 7 | describe('when { disallowArrayDestructuringReturn: true }', function() { 8 | beforeEach(function() { 9 | checker = new Checker(); 10 | checker.registerDefaultRules(); 11 | checker.configure({disallowArrayDestructuringReturn: true}); 12 | }); 13 | 14 | it('should report on array destructuring with function call', function() { 15 | expect( 16 | checker.checkString('const [ a, b ] = func();') 17 | ).to.have.one.validation.error.from('disallowArrayDestructuringReturn'); 18 | }); 19 | 20 | it('should report on array destructuring with self invoking functions', function() { 21 | expect( 22 | checker.checkString('const [ a, b ] = (() => [1, 2])();') 23 | ).to.have.one.validation.error.from('disallowArrayDestructuringReturn'); 24 | }); 25 | 26 | it('should report on array destructuring in assignment expressions', function() { 27 | expect( 28 | checker.checkString('([ a, b ] = func());') 29 | ).to.have.one.validation.error.from('disallowArrayDestructuringReturn'); 30 | }); 31 | 32 | it('should not report on object destructuring', function() { 33 | expect(checker.checkString('const { a, b } = func();')). 34 | to.not.have.errors(); 35 | }); 36 | 37 | it('should not report on object destructuring in assignment expression', function() { 38 | expect(checker.checkString('({ a, b } = func());')). 39 | to.not.have.errors(); 40 | }); 41 | }); 42 | }); 43 | -------------------------------------------------------------------------------- /test/specs/rules/disallow-arrow-functions.js: -------------------------------------------------------------------------------- 1 | var Checker = require('../../../lib/checker'); 2 | var expect = require('chai').expect; 3 | 4 | describe('rules/disallow-arrow-functions', function() { 5 | var checker; 6 | 7 | beforeEach(function() { 8 | checker = new Checker(); 9 | checker.registerDefaultRules(); 10 | checker.configure({ disallowArrowFunctions: true }); 11 | }); 12 | 13 | it('should report use of arrow function', function() { 14 | expect(checker.checkString('a.map(n => n + 1);')).to.have.one.validation.error.from('disallowArrowFunctions'); 15 | }); 16 | 17 | it('should report use of multi line arrow function', function() { 18 | expect(checker.checkString([ 19 | 'a.map(n => {', 20 | 'return n + 1;', 21 | '});' 22 | ].join('\n'))).to.have.one.validation.error.from('disallowArrowFunctions'); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /test/specs/rules/disallow-function-declarations.js: -------------------------------------------------------------------------------- 1 | var Checker = require('../../../lib/checker'); 2 | var expect = require('chai').expect; 3 | 4 | describe('rules/disallow-function-declarations', function() { 5 | var checker; 6 | 7 | beforeEach(function() { 8 | checker = new Checker(); 9 | checker.registerDefaultRules(); 10 | 11 | checker.configure({ 12 | disallowFunctionDeclarations: true 13 | }); 14 | }); 15 | 16 | it('should report on function declarations', function() { 17 | expect(checker.checkString('function declared() { }')) 18 | .to.have.one.validation.error.from('disallowFunctionDeclarations'); 19 | }); 20 | 21 | it('should not report on anonymous function expressions', function() { 22 | expect(checker.checkString('var expressed = function (){};')).to.have.no.errors(); 23 | expect(checker.checkString('var foo = {bar: function() {}};')).to.have.no.errors(); 24 | }); 25 | 26 | it('should not report on named function expressions', function() { 27 | expect(checker.checkString('$("hi").click(function named(){});')).to.have.no.errors(); 28 | expect(checker.checkString('var x = function named(){};')).to.have.no.errors(); 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /test/specs/rules/disallow-identical-destructuring-names.js: -------------------------------------------------------------------------------- 1 | var Checker = require('../../../lib/checker'); 2 | var expect = require('chai').expect; 3 | 4 | describe('rules/disallow-identical-destructuring-names', function() { 5 | var checker; 6 | 7 | function assertNum(str, num) { 8 | expect(checker.checkString(str)).to.have.error.count.equal(num); 9 | } 10 | 11 | function assertEmpty(str) { 12 | assertNum(str, 0); 13 | } 14 | 15 | beforeEach(function() { 16 | checker = new Checker(); 17 | checker.registerDefaultRules(); 18 | checker.configure({ disallowIdenticalDestructuringNames: true }); 19 | }); 20 | 21 | it('should report identical destructuring names', function() { 22 | assertNum('var { a: a } = obj;', 1); 23 | }); 24 | 25 | it('should report multiple identical destructuring names', function() { 26 | assertNum('var { a: a, b: b, c: c } = obj;', 3); 27 | }); 28 | 29 | it('should report only identical destructuring names', function() { 30 | assertNum('var { a, b: b } = obj;', 1); 31 | }); 32 | 33 | it('should not report other destructuring', function() { 34 | assertEmpty('var { a } = obj;'); 35 | assertEmpty('var { a, b, c } = obj;'); 36 | assertEmpty('var { a: a1, b: b2, c: c3 } = obj;'); 37 | // TODO: 3.0 38 | // Use the shorthand form of destructuring instead 39 | // assertEmpty('var { [a]: a } = obj;'); 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /test/specs/rules/disallow-keywords.js: -------------------------------------------------------------------------------- 1 | var Checker = require('../../../lib/checker'); 2 | var expect = require('chai').expect; 3 | 4 | describe('rules/disallow-keywords', function() { 5 | var checker; 6 | beforeEach(function() { 7 | checker = new Checker(); 8 | checker.registerDefaultRules(); 9 | }); 10 | it('should report illegal keyword', function() { 11 | checker.configure({ disallowKeywords: ['with'] }); 12 | expect(checker.checkString('with (x) { y++; }')).to.have.one.validation.error.from('disallowKeywords'); 13 | }); 14 | it('should not report legal keywords', function() { 15 | checker.configure({ disallowKeywords: ['with'] }); 16 | expect(checker.checkString('if(x) { x++; }')).to.have.no.errors(); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /test/specs/rules/disallow-multiple-line-strings.js: -------------------------------------------------------------------------------- 1 | var Checker = require('../../../lib/checker'); 2 | var expect = require('chai').expect; 3 | 4 | describe('rules/disallow-multiple-line-strings', function() { 5 | var checker; 6 | 7 | beforeEach(function() { 8 | checker = new Checker(); 9 | checker.registerDefaultRules(); 10 | checker.configure({ disallowMultipleLineStrings: true }); 11 | }); 12 | 13 | it('should report multiple line strings', function() { 14 | expect(checker.checkString('x = " \\\n oops";')) 15 | .to.have.one.validation.error.from('disallowMultipleLineStrings'); 16 | }); 17 | 18 | it('should not fix multiple line strings', function() { 19 | var input = 'x = " \\\n oops";'; 20 | var result = checker.fixString(input); 21 | expect(result.output).to.equal(input); 22 | expect(result.errors).to.have.one.validation.error.from('disallowMultipleLineStrings'); 23 | }); 24 | 25 | it('should not report concatenated strings on multiple lines', function() { 26 | expect(checker.checkString('x = " " + \n " ok";')).to.have.no.errors(); 27 | }); 28 | 29 | it('should not report single line strings', function() { 30 | expect(checker.checkString('x = "ok"')).to.have.no.errors(); 31 | }); 32 | }); 33 | -------------------------------------------------------------------------------- /test/specs/rules/disallow-named-unassigned-functions.js: -------------------------------------------------------------------------------- 1 | var Checker = require('../../../lib/checker'); 2 | var expect = require('chai').expect; 3 | 4 | describe('rules/disallow-named-unassigned-functions', function() { 5 | var checker; 6 | 7 | beforeEach(function() { 8 | checker = new Checker(); 9 | checker.registerDefaultRules(); 10 | }); 11 | 12 | describe('option value true', function() { 13 | beforeEach(function() { 14 | checker.configure({ 15 | disallowNamedUnassignedFunctions: true 16 | }); 17 | }); 18 | 19 | it('should not report on unnamed unassigned function expressions', function() { 20 | expect(checker.checkString('$("hi").click(function(){});')).to.have.no.errors(); 21 | }); 22 | 23 | it('should report on named unassigned function expressions', function() { 24 | expect(checker.checkString('$("hi").click(function named(){});')) 25 | .to.have.one.validation.error.from('disallowNamedUnassignedFunctions'); 26 | }); 27 | 28 | it('should not report on named function declarations', function() { 29 | expect(checker.checkString('function named(){};')).to.have.no.errors(); 30 | }); 31 | 32 | it('should not report on assigned function expressions', function() { 33 | expect(checker.checkString('var x = function(){};')).to.have.no.errors(); 34 | expect(checker.checkString('var foo = {bar: function() {}};')).to.have.no.errors(); 35 | expect(checker.checkString('foo.bar = function() {};')).to.have.no.errors(); 36 | expect(checker.checkString('var x = function named(){};')).to.have.no.errors(); 37 | expect(checker.checkString('var foo = {bar: function named() {}};')).to.have.no.errors(); 38 | expect(checker.checkString('foo.bar = function named() {};')).to.have.no.errors(); 39 | }); 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /test/specs/rules/disallow-node-types.js: -------------------------------------------------------------------------------- 1 | var Checker = require('../../../lib/checker'); 2 | var expect = require('chai').expect; 3 | 4 | describe('rules/disallow-node-types', function() { 5 | var checker; 6 | 7 | beforeEach(function() { 8 | checker = new Checker(); 9 | checker.registerDefaultRules(); 10 | 11 | checker.configure({ 12 | disallowNodeTypes: ['LabeledStatement', 'DebuggerStatement', 'DoWhileStatement'] 13 | }); 14 | }); 15 | 16 | it('should report on use of LabeledStatement', function() { 17 | expect(checker.checkString('var f = () => { a: 1 };')).to.have.one.validation.error.from('disallowNodeTypes'); 18 | expect(checker.checkString([ 19 | 'loop1:', 20 | 'for (i = 0; i < 10; i++) {', 21 | 'if (i === 3) {', 22 | 'break loop1;', 23 | '}', 24 | '}' 25 | ].join('\n'))).to.have.one.validation.error.from('disallowNodeTypes'); 26 | }); 27 | 28 | it('should report on use of DebuggerStatement', function() { 29 | expect(checker.checkString('debugger;')).to.have.one.validation.error.from('disallowNodeTypes'); 30 | }); 31 | 32 | it('should report on use of DoWhileStatement', function() { 33 | expect(checker.checkString('do keep(); while (true)')).to.have.one.validation.error.from('disallowNodeTypes'); 34 | }); 35 | 36 | it('should report on use of another statement', function() { 37 | expect(checker.checkString('var a = { a: 1 };')).to.have.no.errors(); 38 | expect(checker.checkString('var f = () => ({ a: 1 });')).to.have.no.errors(); 39 | }); 40 | }); 41 | -------------------------------------------------------------------------------- /test/specs/rules/disallow-object-keys-on-new-line.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect; 2 | var Checker = require('../../../lib/checker'); 3 | var reportAndFix = require('../../lib/assertHelpers').reportAndFix; 4 | 5 | describe('rules/disallow-object-keys-on-new-line', function() { 6 | var rules = { disallowObjectKeysOnNewLine: true }; 7 | var checker; 8 | 9 | beforeEach(function() { 10 | checker = new Checker(); 11 | checker.registerDefaultRules(); 12 | checker.configure(rules); 13 | }); 14 | 15 | reportAndFix({ 16 | name: 'object assignment with missing padding', 17 | rules: rules, 18 | input: 'var a = {foo: "bar",\nbar: "baz"}', 19 | output: 'var a = {foo: "bar", bar: "baz"}' 20 | }); 21 | 22 | reportAndFix({ 23 | name: 'function argument with missing padding', 24 | rules: rules, 25 | input: 'foo({foo: "bar",\nbar: "baz"})', 26 | output: 'foo({foo: "bar", bar: "baz"})' 27 | }); 28 | 29 | it('should not report object without padding', function() { 30 | expect(checker.checkString('var a = {foo: "bar", bar: "baz"}')).to.have.no.errors(); 31 | }); 32 | 33 | it('should not report argument without padding', function() { 34 | expect(checker.checkString('foo({foo: "bar", bar: "baz"})')).to.have.no.errors(); 35 | }); 36 | 37 | it('should not report object with one key', function() { 38 | expect(checker.checkString('var a = {a: "b"};')).to.have.no.errors(); 39 | }); 40 | 41 | it('should report correct error message', function() { 42 | expect(checker.checkString('foo({foo: "bar",\nbar: "baz"})')).contains 43 | .one.error('disallowObjectKeysOnNewLine: Object keys should be on the same line'); 44 | }); 45 | }); 46 | -------------------------------------------------------------------------------- /test/specs/rules/disallow-padding-newlines-after-use-strict.js: -------------------------------------------------------------------------------- 1 | var Checker = require('../../../lib/checker'); 2 | var expect = require('chai').expect; 3 | var reportAndFix = require('../../lib/assertHelpers').reportAndFix; 4 | 5 | describe('rules/disallow-padding-newlines-after-use-strict', function() { 6 | var rules = { disallowPaddingNewLinesAfterUseStrict: true }; 7 | var checker; 8 | 9 | beforeEach(function() { 10 | checker = new Checker(); 11 | checker.registerDefaultRules(); 12 | checker.configure(rules); 13 | }); 14 | 15 | it('should not report if use strict is not present', function() { 16 | expect(checker.checkString('var a = 2;')).to.have.no.errors(); 17 | }); 18 | 19 | reportAndFix({ 20 | name: 'with blank line', 21 | rules: rules, 22 | input: '"use strict";\n\nvar a = 2;', 23 | output: '"use strict";\nvar a = 2;' 24 | }); 25 | 26 | it('should not report when followed by comment without blank line', function() { 27 | expect(checker.checkString('"use strict";\n// comment\nvar a = 2;')).to.have.no.errors(); 28 | }); 29 | 30 | it('should report when followed by comment with blank line', function() { 31 | expect(checker.checkString('"use strict";\n\n// comment\nvar a = 2;')) 32 | .to.have.one.validation.error.from('disallowPaddingNewLinesAfterUseStrict'); 33 | }); 34 | 35 | it('should not report with no blank line', function() { 36 | expect(checker.checkString('"use strict";\nvar a = 2;')).to.have.no.errors(); 37 | }); 38 | 39 | it('should not report on same line', function() { 40 | expect(checker.checkString('"use strict"; var a = 2;')).to.have.no.errors(); 41 | }); 42 | 43 | it('should not report other statements', function() { 44 | expect(checker.checkString('"use stricts";\n\nvar a = 2;')).to.have.no.errors(); 45 | expect(checker.checkString('2 + 2;\n\nvar a = 2;')).to.have.no.errors(); 46 | }); 47 | }); 48 | -------------------------------------------------------------------------------- /test/specs/rules/disallow-padding-newlines-before-export.js: -------------------------------------------------------------------------------- 1 | var Checker = require('../../../lib/checker'); 2 | var expect = require('chai').expect; 3 | 4 | describe('rules/disallow-padding-newlines-before-export', function() { 5 | var checker; 6 | 7 | beforeEach(function() { 8 | checker = new Checker(); 9 | checker.registerDefaultRules(); 10 | }); 11 | 12 | describe('value true', function() { 13 | beforeEach(function() { 14 | checker.configure({ disallowPaddingNewLinesBeforeExport: true }); 15 | }); 16 | 17 | it('should not report no padding before export', function() { 18 | expect(checker.checkString('var a = 2;\nmodule.exports = a;')).to.have.no.errors(); 19 | }); 20 | 21 | it('should not report missing padding if first line', function() { 22 | expect(checker.checkString('module.exports = 2;')).to.have.no.errors(); 23 | }); 24 | 25 | it('should report padding before export', function() { 26 | expect(checker.checkString('var a = 2;\n\nmodule.exports = a;')) 27 | .to.have.one.validation.error.from('disallowPaddingNewLinesBeforeExport'); 28 | }); 29 | 30 | it('should not report comment before export', function() { 31 | expect(checker.checkString('var a = 2;\n// foo\nmodule.exports = a;')).to.have.no.errors(); 32 | }); 33 | 34 | it('should not report comment with extra padding before export', function() { 35 | expect(checker.checkString('var a = 2;\n\n// foo\nmodule.exports = a;')).to.have.no.errors(); 36 | }); 37 | 38 | it('should not report padding before object assignment', function() { 39 | expect(checker.checkString('var a = 2;\n\nfoo.exports = a;')).to.have.no.errors(); 40 | expect(checker.checkString('var a = 2;\n\nmodule.foo = a;')).to.have.no.errors(); 41 | }); 42 | 43 | it('should not report if it is not a property assignment', function() { 44 | expect(checker.checkString('var a = 2;\n\nfoo = a;')).to.have.no.errors(); 45 | }); 46 | }); 47 | }); 48 | -------------------------------------------------------------------------------- /test/specs/rules/disallow-padding-newlines-in-objects.js: -------------------------------------------------------------------------------- 1 | var Checker = require('../../../lib/checker'); 2 | var expect = require('chai').expect; 3 | 4 | describe('rules/disallow-padding-newlines-in-objects', function() { 5 | var checker; 6 | beforeEach(function() { 7 | checker = new Checker(); 8 | checker.registerDefaultRules(); 9 | checker.configure({ disallowPaddingNewLinesInObjects: true }); 10 | }); 11 | 12 | it('should report existing newline after opening brace', function() { 13 | expect(checker.checkString('var x = {\na: 1};')) 14 | .to.have.one.validation.error.from('disallowPaddingNewLinesInObjects'); 15 | }); 16 | it('should report existing newline before closing brace', function() { 17 | expect(checker.checkString('var x = {a: 1\n};')) 18 | .to.have.one.validation.error.from('disallowPaddingNewLinesInObjects'); 19 | }); 20 | it('should report existing newline in both cases', function() { 21 | expect(checker.checkString('var x = {\na: 1\n};')).to.have.error.count.equal(2); 22 | }); 23 | it('should not report with no newlines', function() { 24 | expect(checker.checkString('var x = {a: 1};')).to.have.no.errors(); 25 | expect(checker.checkString('var x = { a: 1 };')).to.have.no.errors(); 26 | }); 27 | it('should not report for empty object', function() { 28 | expect(checker.checkString('var x = {};')).to.have.no.errors(); 29 | }); 30 | it('should report for nested object', function() { 31 | expect(checker.checkString('var x = { a: {\nb: 1\n} };')).to.have.error.count.equal(2); 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /test/specs/rules/disallow-shorthand-arrow-functions.js: -------------------------------------------------------------------------------- 1 | var Checker = require('../../../lib/checker'); 2 | var expect = require('chai').expect; 3 | 4 | describe('rules/disallow-shorthand-arrow-functions', function() { 5 | var checker; 6 | 7 | beforeEach(function() { 8 | checker = new Checker(); 9 | checker.registerDefaultRules(); 10 | checker.configure({ disallowShorthandArrowFunctions: true }); 11 | }); 12 | 13 | it('should report a shorthand arrow function expression', function() { 14 | expect(checker.checkString('evens.map(v => v + 1);')) 15 | .to.have.one.validation.error.from('disallowShorthandArrowFunctions'); 16 | }); 17 | 18 | it('should not report an arrow function with a block', function() { 19 | expect(checker.checkString('evens.map(v => { return v + 1; });')).to.have.no.errors(); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /test/specs/rules/disallow-space-after-line-comment.js: -------------------------------------------------------------------------------- 1 | var Checker = require('../../../lib/checker'); 2 | var expect = require('chai').expect; 3 | 4 | describe('rules/disallow-space-after-line-comment', function() { 5 | var checker; 6 | beforeEach(function() { 7 | checker = new Checker(); 8 | checker.registerDefaultRules(); 9 | }); 10 | 11 | describe('option value true', function() { 12 | beforeEach(function() { 13 | checker.configure({ disallowSpaceAfterLineComment: true }); 14 | }); 15 | 16 | it('should report space after line comment', function() { 17 | expect(checker.checkString('if (true) {abc();} // This is a comment')) 18 | .to.have.one.validation.error.from('disallowSpaceAfterLineComment'); 19 | }); 20 | it('should not report comment without space', function() { 21 | expect(checker.checkString('if (true) {abc();} //This is a good comment')).to.have.no.errors(); 22 | }); 23 | it('should not report block comments with a space', function() { 24 | expect(checker.checkString('if (true) {abc();} /* A comment*/')).to.have.no.errors(); 25 | }); 26 | it('should not report block comments without a space', function() { 27 | expect(checker.checkString('if (true) {abc();} /*A comment*/')).to.have.no.errors(); 28 | }); 29 | it('should not report a line comment with no characters after it', function() { 30 | expect(checker.checkString('if (true) {abc();} //')).to.have.no.errors(); 31 | }); 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /test/specs/rules/disallow-space-between-arguments.js: -------------------------------------------------------------------------------- 1 | var Checker = require('../../../lib/checker'); 2 | var expect = require('chai').expect; 3 | 4 | describe('rules/disallow-space-between-arguments', function() { 5 | var checker; 6 | 7 | beforeEach(function() { 8 | checker = new Checker(); 9 | checker.registerDefaultRules(); 10 | checker.configure({ disallowSpaceBetweenArguments: true }); 11 | }); 12 | 13 | it('should report unexpected space for a(b, c)', function() { 14 | expect(checker.checkString('a(b, c);')).to.have.one.validation.error.from('disallowSpaceBetweenArguments'); 15 | }); 16 | 17 | it('should report 2 unexpected spaces for a(b, c, d)', function() { 18 | expect(checker.checkString('a(b, c, d);')).to.have.error.count.equal(2); 19 | }); 20 | 21 | it('should not report any errors for a(b,c)', function() { 22 | expect(checker.checkString('a(b,c);')).to.have.no.errors(); 23 | }); 24 | 25 | it('should not report any errors for a(b)', function() { 26 | expect(checker.checkString('a(b);')).to.have.no.errors(); 27 | }); 28 | 29 | it('should not report for a(foo(),b)', function() { 30 | expect(checker.checkString('a(foo(),b);')).to.have.no.errors(); 31 | }); 32 | 33 | it('should not report for a(foo(1,2),b)', function() { 34 | expect(checker.checkString('a(foo(1,2),b);')).to.have.no.errors(); 35 | }); 36 | 37 | it('should report for a(foo(1, 2), b)', function() { 38 | expect(checker.checkString('a(foo(1, 2), b);')).to.have.error.count.equal(2); 39 | }); 40 | }); 41 | -------------------------------------------------------------------------------- /test/specs/rules/disallow-spaces-in-for-statement.js: -------------------------------------------------------------------------------- 1 | var Checker = require('../../../lib/checker'); 2 | var expect = require('chai').expect; 3 | 4 | describe('rules/disallow-spaces-in-for-statement', function() { 5 | var checker; 6 | 7 | beforeEach(function() { 8 | checker = new Checker(); 9 | checker.registerDefaultRules(); 10 | }); 11 | 12 | describe('true option', function() { 13 | beforeEach(function() { 14 | checker.configure({ disallowSpacesInForStatement: true }); 15 | }); 16 | 17 | it('should report spaces in for statement in both cases', function() { 18 | expect(checker.checkString('for(i=0; i y)\n' + 21 | ' ? 1\n' + 22 | ' : 2\n' + 23 | ' : (c === d)\n' + 24 | ' ? 3\n' + 25 | ' : 4;' 26 | )).to.have.no.errors(); 27 | }); 28 | 29 | it('should report correct amount of errors for nesting single line ternaries in multi-line ternaries', function() { 30 | expect(checker.checkString( 31 | 'var foo = (a === b)\n' + 32 | ' ? (x > y) ? 1 : 2\n' + 33 | ' : (c === d) ? 3 : 4;' 34 | )).to.have.error.count.equal(4); 35 | }); 36 | 37 | it('should not allow single line ternary', function() { 38 | expect(checker.checkString('var foo = (a === b) ? 1 : 2;')).to.have.error.count.equal(2); 39 | }); 40 | 41 | it('should not allow single line nested ternary', function() { 42 | expect(checker.checkString( 43 | 'var foo = (a === b) ? (x > y) ? 1 : 2 : (c === d) ? 3 : 4;' 44 | )).to.have.error.count.equal(6); 45 | }); 46 | 47 | describe('incorrect configuration', function() { 48 | it('should not accept objects', function() { 49 | expect(function() { 50 | checker.configure({ requireMultiLineTernary: {} }); 51 | }).to.throw('AssertionError'); 52 | }); 53 | }); 54 | }); 55 | -------------------------------------------------------------------------------- /test/specs/rules/require-padding-newlines-before-export.js: -------------------------------------------------------------------------------- 1 | var Checker = require('../../../lib/checker'); 2 | var expect = require('chai').expect; 3 | 4 | describe('rules/require-padding-newlines-before-export', function() { 5 | var checker; 6 | 7 | beforeEach(function() { 8 | checker = new Checker(); 9 | checker.registerDefaultRules(); 10 | }); 11 | 12 | describe('value true', function() { 13 | beforeEach(function() { 14 | checker.configure({ requirePaddingNewLinesBeforeExport: true }); 15 | }); 16 | 17 | it('should report missing padding before export', function() { 18 | expect(checker.checkString('var a = 2;\nmodule.exports = a;')) 19 | .to.have.one.validation.error.from('requirePaddingNewLinesBeforeExport'); 20 | }); 21 | 22 | it('should not report missing padding if first line', function() { 23 | expect(checker.checkString('module.exports = 2;')).to.have.no.errors(); 24 | }); 25 | 26 | it('should not report padding before export', function() { 27 | expect(checker.checkString('var a = 2;\n\nmodule.exports = a;')).to.have.no.errors(); 28 | }); 29 | 30 | it('should not report lack of padding before object assignment', function() { 31 | expect(checker.checkString('var a = 2;\nfoo.exports = a;')).to.have.no.errors(); 32 | expect(checker.checkString('var a = 2;\nmodule.foo = a;')).to.have.no.errors(); 33 | }); 34 | 35 | it('should not report missing padding if export is only statement in block', function() { 36 | expect(checker.checkString('if (true) {\nmodule.exports = a;\n}')).to.have.no.errors(); 37 | }); 38 | }); 39 | }); 40 | -------------------------------------------------------------------------------- /test/specs/rules/require-padding-newlines-in-objects.js: -------------------------------------------------------------------------------- 1 | var Checker = require('../../../lib/checker'); 2 | var expect = require('chai').expect; 3 | 4 | describe('rules/require-padding-newlines-in-objects', function() { 5 | var checker; 6 | beforeEach(function() { 7 | checker = new Checker(); 8 | checker.registerDefaultRules(); 9 | checker.configure({ requirePaddingNewLinesInObjects: true }); 10 | }); 11 | 12 | it('should report missing newline after opening brace', function() { 13 | expect(checker.checkString('var x = {a: 1\n};')) 14 | .to.have.one.validation.error.from('requirePaddingNewLinesInObjects'); 15 | expect(checker.checkString('var x = { a: 1\n};')) 16 | .to.have.one.validation.error.from('requirePaddingNewLinesInObjects'); 17 | }); 18 | it('should report missing newline before closing brace', function() { 19 | expect(checker.checkString('var x = {\na: 1};')) 20 | .to.have.one.validation.error.from('requirePaddingNewLinesInObjects'); 21 | expect(checker.checkString('var x = {\na: 1 };')) 22 | .to.have.one.validation.error.from('requirePaddingNewLinesInObjects'); 23 | }); 24 | it('should report missing newline in both cases', function() { 25 | expect(checker.checkString('var x = {a: 1};')).to.have.error.count.equal(2); 26 | expect(checker.checkString('var x = { a: 1 };')).to.have.error.count.equal(2); 27 | }); 28 | it('should not report with newlines', function() { 29 | expect(checker.checkString('var x = {\na: 1\n};')).to.have.no.errors(); 30 | }); 31 | it('should not report for empty object', function() { 32 | expect(checker.checkString('var x = {};')).to.have.no.errors(); 33 | }); 34 | it('should report for nested object', function() { 35 | expect(checker.checkString('var x = {\na: { b: 1 }\n};')).to.have.error.count.equal(2); 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /test/specs/rules/require-parentheses-around-arrow-param.js: -------------------------------------------------------------------------------- 1 | var Checker = require('../../../lib/checker'); 2 | var expect = require('chai').expect; 3 | 4 | describe('rules/require-parentheses-around-arrow-param', function() { 5 | var checker; 6 | 7 | beforeEach(function() { 8 | checker = new Checker(); 9 | checker.registerDefaultRules(); 10 | checker.configure({ requireParenthesesAroundArrowParam: true }); 11 | }); 12 | 13 | it('should report an arrow function expression without parens', function() { 14 | expect(checker.checkString('[1, 2].map(x => x * x);')) 15 | .to.have.one.validation.error.from('requireParenthesesAroundArrowParam'); 16 | }); 17 | 18 | it('should not report an arrow function expression with parens around a single parameter', function() { 19 | expect(checker.checkString('[1, 2].map((x) => x * x);')).to.have.no.errors(); 20 | }); 21 | 22 | it('should not report an arrow function expression with parens around multiple parameters', function() { 23 | expect(checker.checkString('[1, 2].map((x, y) => x * x);')).to.have.no.errors(); 24 | }); 25 | 26 | it('should not report an arrow function expression with a single rest param #1616', function() { 27 | expect(checker.checkString('[1, 2].map((...x) => x);')).to.have.no.errors(); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /test/specs/rules/require-shorthand-arrow-functions.js: -------------------------------------------------------------------------------- 1 | var Checker = require('../../../lib/checker'); 2 | var expect = require('chai').expect; 3 | 4 | describe('rules/require-shorthand-arrow-functions', function() { 5 | var checker; 6 | 7 | beforeEach(function() { 8 | checker = new Checker(); 9 | checker.registerDefaultRules(); 10 | checker.configure({ requireShorthandArrowFunctions: true }); 11 | }); 12 | 13 | it('should report a shorthand arrow function expression', function() { 14 | expect(checker.checkString('evens.map(v => v + 1);')).to.have.no.errors(); 15 | }); 16 | 17 | it('should report an arrow function expression that could be shorthand', function() { 18 | expect(checker.checkString('evens.map(v => { return v + 1; });')) 19 | .to.have.one.validation.error.from('requireShorthandArrowFunctions'); 20 | }); 21 | 22 | it('should not report an arrow function expression with multiple statements in the body', function() { 23 | expect(checker.checkString('evens.map(v => { v = v + 1; return v; });')).to.have.no.errors(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /test/specs/rules/require-space-between-arguments.js: -------------------------------------------------------------------------------- 1 | var Checker = require('../../../lib/checker'); 2 | var expect = require('chai').expect; 3 | 4 | describe('rules/require-space-between-arguments', function() { 5 | var checker; 6 | 7 | beforeEach(function() { 8 | checker = new Checker(); 9 | checker.registerDefaultRules(); 10 | checker.configure({ requireSpaceBetweenArguments: true }); 11 | }); 12 | 13 | it('should report expected space for a(b,c)', function() { 14 | expect(checker.checkString('a(b,c);')).to.have.one.validation.error.from('requireSpaceBetweenArguments'); 15 | }); 16 | 17 | it('should report 2 expected spaces for a(b,c,d)', function() { 18 | expect(checker.checkString('a(b,c,d);')).to.have.error.count.equal(2); 19 | }); 20 | 21 | it('should not report any errors for a(b, c)', function() { 22 | expect(checker.checkString('a(b, c);')).to.have.no.errors(); 23 | }); 24 | 25 | it('should not report any errors for a(b, c)', function() { 26 | expect(checker.checkString('a(b, c);')).to.have.no.errors(); 27 | }); 28 | 29 | it('should not report any errors for a(b)', function() { 30 | expect(checker.checkString('a(b);')).to.have.no.errors(); 31 | }); 32 | 33 | it('should report for a(foo(),b)', function() { 34 | expect(checker.checkString('a(foo(),b);')).to.have.one.validation.error.from('requireSpaceBetweenArguments'); 35 | }); 36 | 37 | it('should report for a(foo(1,2),b)', function() { 38 | expect(checker.checkString('a(foo(1,2),b);')).to.have.error.count.equal(2); 39 | }); 40 | 41 | it('should not report for a(foo(1, 2), b)', function() { 42 | expect(checker.checkString('a(foo(1, 2), b);')).to.have.no.errors(); 43 | }); 44 | }); 45 | -------------------------------------------------------------------------------- /test/specs/rules/require-spaces-inside-imported-object-braces.js: -------------------------------------------------------------------------------- 1 | var Checker = require('../../../lib/checker'); 2 | var expect = require('chai').expect; 3 | 4 | describe('rules/require-spaces-inside-imported-object-braces', function() { 5 | var checker; 6 | beforeEach(function() { 7 | checker = new Checker(); 8 | checker.registerDefaultRules(); 9 | }); 10 | 11 | describe('when { requireSpacesInsideImportedObjectBraces: true }', function() { 12 | beforeEach(function() { 13 | checker.configure({ requireSpacesInsideImportedObjectBraces: true }); 14 | }); 15 | 16 | it('should not report for import without braces', function() { 17 | expect(checker.checkString('import fooBar from "foo-bar";')).to.have.no.errors(); 18 | expect(checker.checkString('import * as fooBar from "foo-bar";')).to.have.no.errors(); 19 | expect(checker.checkString('import {} from "foo-bar";')).to.have.no.errors(); 20 | }); 21 | 22 | it('should report for import without spaces', function() { 23 | expect( 24 | checker.checkString('import {foo} from "foo-bar";') 25 | ).to.have.error.count.equal(2); 26 | 27 | expect( 28 | checker.checkString('import {foo, bar} from "foo-bar";') 29 | ).to.have.error.count.equal(2); 30 | 31 | expect( 32 | checker.checkString('import fooBar, {foo, bar} from "foo-bar";') 33 | ).to.have.error.count.equal(2); 34 | 35 | expect( 36 | checker.checkString('import {foo as bar, bar as foo} from "foo-bar";') 37 | ).to.have.error.count.equal(2); 38 | }); 39 | }); 40 | }); 41 | -------------------------------------------------------------------------------- /test/specs/rules/require-spread.js: -------------------------------------------------------------------------------- 1 | var Checker = require('../../../lib/checker'); 2 | var expect = require('chai').expect; 3 | 4 | describe('rules/require-spread', function() { 5 | var checker; 6 | 7 | beforeEach(function() { 8 | checker = new Checker(); 9 | checker.registerDefaultRules(); 10 | checker.configure({ requireSpread: true }); 11 | }); 12 | 13 | it('should report use of apply when the first param === the object of the member expression', function() { 14 | expect(checker.checkString('g.apply(g, arguments);')).to.have.one.validation.error.from('requireSpread'); 15 | }); 16 | 17 | it('should not report the use apply with only 1 argument', function() { 18 | expect(checker.checkString('g.apply(arguments);')).to.have.no.errors(); 19 | }); 20 | 21 | it('should not report the use of spread', function() { 22 | expect(checker.checkString('g(...args);')).to.have.no.errors(); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /test/specs/tree-iterator.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect; 2 | var cst = require('cst'); 3 | var Parser = cst.Parser; 4 | var sinon = require('sinon'); 5 | var iterate = require('../../lib/tree-iterator').iterate; 6 | 7 | describe('tree-iterator', function() { 8 | function createParser() { 9 | return new Parser({ 10 | strictMode: false, 11 | languageExtensions: { 12 | gritDirectives: true, 13 | appleInstrumentationDirectives: true 14 | } 15 | }); 16 | } 17 | 18 | it('should pass parent and parentCollection', function() { 19 | var spy = sinon.spy(); 20 | var parser = createParser(); 21 | iterate(parser.parse('1;'), spy); 22 | expect(spy).to.have.callCount(3); 23 | expect(spy.getCall(0).args[0].type).to.equal('Program'); 24 | expect(spy.getCall(0).args[1]).to.equal(null); 25 | expect(spy.getCall(1).args[0].type).to.equal('ExpressionStatement'); 26 | expect(spy.getCall(2).args[0].type).to.equal('NumericLiteral'); 27 | }); 28 | 29 | it('should not fail for empty object', function() { 30 | var spy = sinon.spy(); 31 | iterate({}, spy); 32 | expect(spy).to.have.callCount(0); 33 | }); 34 | 35 | it('should exit thread on false result', function() { 36 | var spy = sinon.spy(function() { 37 | return false; 38 | }); 39 | var parser = createParser(); 40 | iterate(parser.parse('1;'), spy); 41 | expect(spy).to.have.callCount(1); 42 | expect(spy.getCall(0).args[0].type).to.equal('Program'); 43 | }); 44 | 45 | }); 46 | --------------------------------------------------------------------------------