diff --git a/conf/eslint.json b/conf/eslint.json index 5d0b947c5a9c..fe1c4afb9250 100755 --- a/conf/eslint.json +++ b/conf/eslint.json @@ -172,6 +172,7 @@ "keyword-spacing": "off", "linebreak-style": "off", "lines-around-comment": "off", + "lines-around-directive": "off", "max-depth": "off", "max-len": "off", "max-lines": "off", diff --git a/docs/rules/lines-around-directive.md b/docs/rules/lines-around-directive.md new file mode 100644 index 000000000000..1d63f592cb15 --- /dev/null +++ b/docs/rules/lines-around-directive.md @@ -0,0 +1,304 @@ +# enforce or disallow newlines around directives (lines-around-directive) + +The `"strict mode";` directive is used in JavaScript to invoke strict mode. It must occur either at the top of a file or function block and is applied to the scope in which it occurs. + +```js +// Strict mode is invoked for the entire script +"use strict"; + +var foo; + +function bar() { + var baz; +} +``` + +```js +var foo; + +// Strict mode is only invoked within the following function +function bar() { + "use strict"; + + var baz; +} +``` + +## Rule Details + +This rule enforces or disallows blank newlines around directives. It does not enforce blank newlines before directives unless they are preceded by a comment. Please use the [padded-blocks](padded-blocks.md) rule if this is a style you would like to enforce. + +## Options + +This rule has one option. It can either be a string or an object: + +* `"always"` (default) enforces blank newlines around directives. +* `"never"` disallows blank newlines around directives. + +or + +```js +{ + "before": "always" or "never" + "after": "always" or "never", +} +``` + +### always + +This is the default option. + +Examples of **incorrect** code for this rule with the `"always"` option: + +```js +/* eslint lines-around-directive: ["error", "always"] */ + +/* Top of file */ +"use strict"; +var foo; + +/* Top of file */ +// comment +"use strict"; +var foo; + +function foo() { + "use strict"; + var bar; +} + +function foo() { + // comment + "use strict"; + var bar; +} +``` + +Examples of **correct** code for this rule with the `"always"` option: + +```js +/* eslint lines-around-directive: ["error", "always"] */ + +/* Top of file */ +"use strict"; + +var foo; + +/* Top of file */ +// comment + +"use strict"; + +var foo; + +function foo() { + "use strict"; + + var bar; +} + +function foo() { + // comment + + "use strict"; + + var bar; +} +``` + +### never + +Examples of **incorrect** code for this rule with the `"never"` option: + +```js +/* eslint lines-around-directive: ["error", "never"] */ + +/* Top of file */ + +"use strict"; + +var foo; + + +/* Top of file */ +// comment + +"use strict"; + +var foo; + + +function foo() { + "use strict"; + + var bar; +} + + +function foo() { + // comment + + "use strict"; + + var bar; +} +``` + +Examples of **correct** code for this rule with the `"never"` option: + +```js +/* eslint lines-around-directive: ["error", "never"] */ + +/* Top of file */ +"use strict"; +var foo; + +/* Top of file */ +// comment +"use strict"; +var foo; + +function foo() { + "use strict"; + var bar; +} + +function foo() { + // comment + "use strict"; + var bar; +} +``` + +### before & after + +Examples of **incorrect** code for this rule with the `{ "before": "never", "after": "always" }` option: + +```js +/* eslint lines-around-directive: ["error", { "before": "never", "after": "always" }] */ + +/* Top of file */ + +"use strict"; +var foo; + +/* Top of file */ +// comment + +"use strict"; +var foo; + +function foo() { + "use strict"; + var bar; +} + +function foo() { + // comment + + "use strict"; + var bar; +} +``` + +Examples of **correct** code for this rule with the `{ "before": "never", "after": "always" }` option: + +```js +/* eslint lines-around-directive: ["error", { "before": "never", "after": "always" }] */ + +/* Top of file */ +"use strict"; + +var foo; + +/* Top of file */ +// comment +"use strict"; + +var foo; + +function foo() { + "use strict"; + + var bar; +} + +function foo() { + // comment + "use strict"; + + var bar; +} +``` + +Examples of **incorrect** code for this rule with the `{ "before": "always", "after": "never" }` option: + +```js +/* eslint lines-around-directive: ["error", { "before": "always", "after": "never" }] */ + +/* Top of file */ +"use strict"; + +var foo; + +/* Top of file */ +// comment +"use strict"; + +var foo; + +function foo() { + "use strict"; + + var bar; +} + +function foo() { + // comment + "use strict"; + + var bar; +} +``` + +Examples of **correct** code for this rule with the `{ "before": "always", "after": "never" }` option: + +```js +/* eslint lines-around-directive: ["error", { "before": "always", "after": "never" }] */ + +/* Top of file */ +"use strict"; +var foo; + +/* Top of file */ +// comment + +"use strict"; +var foo; + +function foo() { + "use strict"; + var bar; +} + +function foo() { + // comment + + "use strict"; + var bar; +} +``` + +## When Not To Use It + +You can safely disable this rule if you do not have any strict conventions about whether or not directives should have blank newlines before or after them. + +## Related Rules + +* [lines-around-comment](lines-around-comment.md) +* [padded-blocks](padded-blocks.md) + +## Compatibility + +* **JSCS**: [requirePaddingNewLinesAfterUseStrict](http://jscs.info/rule/requirePaddingNewLinesAfterUseStrict) +* **JSCS**: [disallowPaddingNewLinesAfterUseStrict](http://jscs.info/rule/disallowPaddingNewLinesAfterUseStrict) diff --git a/lib/ast-utils.js b/lib/ast-utils.js index f0b6fc48ce67..f5944bb0dd63 100644 --- a/lib/ast-utils.js +++ b/lib/ast-utils.js @@ -680,5 +680,46 @@ module.exports = { } return null; + }, + + /** + * Get directives from directive prologue of a Program or Function node. + * @param {ASTNode} node - The node to check. + * @returns {ASTNode[]|null} The directives found in the directive prologue or + * null if none are found. + */ + getDirectivePrologue(node) { + if ( + node.type !== "Program" && + node.type !== "FunctionDeclaration" && + node.type !== "FunctionExpression" && + node.type !== "ArrowFunctionExpression" || + + // Do not check arrow functions with implicit return. + // `() => "use strict";` returns the string `"use strict"`. + node.type === "ArrowFunctionExpression" && node.body.type !== "BlockStatement" + ) { + return null; + } + + const statements = node.type === "Program" ? node.body : node.body.body; + const directives = []; + + for (const statement of statements) { + if ( + statement.type === "ExpressionStatement" && + statement.expression.type === "Literal" + ) { + directives.push(statement); + } else { + if (!directives.length) { + return null; + } + + break; + } + } + + return directives; } }; diff --git a/lib/rules/lines-around-directive.js b/lib/rules/lines-around-directive.js new file mode 100644 index 000000000000..9afadd8c04cc --- /dev/null +++ b/lib/rules/lines-around-directive.js @@ -0,0 +1,173 @@ +/** + * @fileoverview Require or disallow newlines around directives. + * @author Kai Cataldo + */ + +"use strict"; + +const astUtils = require("../ast-utils"); + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ + +module.exports = { + meta: { + docs: { + description: "require or disallow newlines around directives", + category: "Stylistic Issues", + recommended: false + }, + schema: [{ + oneOf: [ + { + enum: ["always", "never"] + }, + { + type: "object", + properties: { + before: { + enum: ["always", "never"] + }, + after: { + enum: ["always", "never"] + }, + }, + additionalProperties: false, + minProperties: 2 + } + ] + }] + }, + + create(context) { + const sourceCode = context.getSourceCode(); + const config = context.options[0] || "always"; + let checkBefore; + let checkAfter; + + if (typeof config === "string") { + checkBefore = config; + checkAfter = config; + } else if (typeof config === "object") { + checkBefore = config.before; + checkAfter = config.after; + } + + //-------------------------------------------------------------------------- + // Helpers + //-------------------------------------------------------------------------- + + /** + * Check if node is preceded by a blank newline. + * @param {ASTNode} node Node to check. + * @returns {boolean} Whether or not the passed in node is preceded by a blank newline. + */ + function hasNewlineBefore(node) { + const tokenBefore = sourceCode.getTokenOrCommentBefore(node); + const tokenLineBefore = tokenBefore ? tokenBefore.loc.end.line : 0; + + return node.loc.start.line - tokenLineBefore >= 2; + } + + /** + * Check if node is followed by a blank newline. + * @param {ASTNode} node Node to check. + * @returns {boolean} Whether or not the passed in node is followed by a blank newline. + */ + function hasNewlineAfter(node) { + const tokenAfter = sourceCode.getTokenOrCommentAfter(node); + + return tokenAfter.loc.start.line - node.loc.end.line >= 2; + } + + /** + * Report errors for newlines around directives. + * @param {ASTNode} node Node to check. + * @param {string} location Whether the error was found before or after the directive. + * @param {boolean} expected Whether or not a newline was expected or unexpected. + * @returns {void} + */ + function reportError(node, location, expected) { + context.report({ + node, + message: "{{expected}} newline {{location}} \"{{value}}\" directive.", + data: { + expected: expected ? "Expected" : "Unexpected", + value: node.expression.value, + location + } + }); + } + + /** + * Check lines around directives in node + * @param {ASTNode} node - node to check + * @returns {void} + */ + function checkDirectives(node) { + const directives = astUtils.getDirectivePrologue(node); + + if (!directives) { + return; + } + + const firstDirective = directives[0]; + const hasTokenOrCommentBefore = !!sourceCode.getTokenOrCommentBefore(firstDirective); + + // Only check before the first directive if it is preceded by a comment or if it is at the top of + // the file and checkBefore is set to "never". This is to not force a newline at the top of + // the file if there are no comments as well as for compatibility with padded-blocks. + if ( + firstDirective.leadingComments && firstDirective.leadingComments.length || + + // Shebangs are not added to leading comments but are accounted for by the following. + node.type === "Program" && hasTokenOrCommentBefore + ) { + if (checkBefore === "always" && !hasNewlineBefore(firstDirective)) { + reportError(firstDirective, "before", true); + } + + if (checkBefore === "never" && hasNewlineBefore(firstDirective)) { + reportError(firstDirective, "before", false); + } + } else if ( + node.type === "Program" && + checkBefore === "never" && + !hasTokenOrCommentBefore && + hasNewlineBefore(firstDirective) + ) { + reportError(firstDirective, "before", false); + } + + const lastDirective = directives[directives.length - 1]; + const statements = node.type === "Program" ? node.body : node.body.body; + + // Do not check after the last directive if the body only + // contains a directive prologue and isn't followed by a comment to ensure + // this rule behaves well with padded-blocks. + if (lastDirective === statements[statements.length - 1] && !lastDirective.trailingComments) { + return; + } + + if (checkAfter === "always" && !hasNewlineAfter(lastDirective)) { + reportError(lastDirective, "after", true); + } + + if (checkAfter === "never" && hasNewlineAfter(lastDirective)) { + reportError(lastDirective, "after", false); + } + } + + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- + + return { + Program: checkDirectives, + FunctionDeclaration: checkDirectives, + FunctionExpression: checkDirectives, + ArrowFunctionExpression: checkDirectives + }; + } +}; diff --git a/tests/lib/ast-utils.js b/tests/lib/ast-utils.js index ef211a7009ff..841033877f59 100644 --- a/tests/lib/ast-utils.js +++ b/tests/lib/ast-utils.js @@ -566,4 +566,84 @@ describe("ast-utils", function() { assert.strictEqual(astUtils.getStaticPropertyName(null), null); }); }); + + describe("getDirectivePrologue", function() { + it("should return null if node is not a Program, FunctionDeclaration, FunctionExpression, or ArrowFunctionExpression", function() { + const ast = espree.parse("if (a) { b(); }"); + const node = ast.body[0]; + + assert.strictEqual(astUtils.getDirectivePrologue(node), null); + }); + + it("should return null if node is a braceless ArrowFunctionExpression node", function() { + const ast = espree.parse("var foo = () => 'use strict';", { ecmaVersion: 6 }); + const node = ast.body[0].declarations[0].init; + + assert.strictEqual(astUtils.getDirectivePrologue(node), null); + }); + + it("should return null if there are no directives in Program body", function() { + const ast = espree.parse("var foo;"); + const node = ast; + + assert.strictEqual(astUtils.getDirectivePrologue(node), null); + }); + + it("should return null if there are no directives in FunctionDeclaration body", function() { + const ast = espree.parse("function foo() { return bar; }"); + const node = ast.body[0]; + + assert.strictEqual(astUtils.getDirectivePrologue(node), null); + }); + + it("should return null if there are no directives in FunctionExpression body", function() { + const ast = espree.parse("var foo = function() { return bar; }"); + const node = ast.body[0].declarations[0].init; + + assert.strictEqual(astUtils.getDirectivePrologue(node), null); + }); + + it("should return null if there are no directives in ArrowFunctionExpression body", function() { + const ast = espree.parse("var foo = () => { return bar; };", { ecmaVersion: 6 }); + const node = ast.body[0].declarations[0].init; + + assert.strictEqual(astUtils.getDirectivePrologue(node), null); + }); + + it("should return directives in Program body", function() { + const ast = espree.parse("'use strict'; 'use asm'; var foo;"); + const result = astUtils.getDirectivePrologue(ast); + + assert.equal(result.length, 2); + assert.equal(result[0].expression.value, "use strict"); + assert.equal(result[1].expression.value, "use asm"); + }); + + it("should return directives in FunctionDeclaration body", function() { + const ast = espree.parse("function foo() { 'use strict'; 'use asm'; return bar; }"); + const result = astUtils.getDirectivePrologue(ast.body[0]); + + assert.equal(result.length, 2); + assert.equal(result[0].expression.value, "use strict"); + assert.equal(result[1].expression.value, "use asm"); + }); + + it("should return directives in FunctionExpression body", function() { + const ast = espree.parse("var foo = function() { 'use strict'; 'use asm'; return bar; }"); + const result = astUtils.getDirectivePrologue(ast.body[0].declarations[0].init); + + assert.equal(result.length, 2); + assert.equal(result[0].expression.value, "use strict"); + assert.equal(result[1].expression.value, "use asm"); + }); + + it("should return directives in ArrowFunctionExpression body", function() { + const ast = espree.parse("var foo = () => { 'use strict'; 'use asm'; return bar; };", { ecmaVersion: 6 }); + const result = astUtils.getDirectivePrologue(ast.body[0].declarations[0].init); + + assert.equal(result.length, 2); + assert.equal(result[0].expression.value, "use strict"); + assert.equal(result[1].expression.value, "use asm"); + }); + }); }); diff --git a/tests/lib/rules/lines-around-directive.js b/tests/lib/rules/lines-around-directive.js new file mode 100644 index 000000000000..51f20bf3afb1 --- /dev/null +++ b/tests/lib/rules/lines-around-directive.js @@ -0,0 +1,1495 @@ +/** + * @fileoverview Require or disallow newlines around directives. + * @author Kai Cataldo + */ + +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const rule = require("../../../lib/rules/lines-around-directive"); +const RuleTester = require("../../../lib/testers/rule-tester"); + +//------------------------------------------------------------------------------ +// Tests +//------------------------------------------------------------------------------ + +const ruleTester = new RuleTester(); + +ruleTester.run("lines-around-directive", rule, { + valid: [ + + // use "always" by default + "//comment\n\n'use strict';\n'use asm';\n\nvar foo;", + + // "always" + // at top of file + // single directive + { + code: "'use strict';\n\nvar foo;", + options: ["always"] + }, + { + code: "\n'use strict';\n\nvar foo;", + options: ["always"] + }, + { + code: "'use strict';\n\n//comment\nvar foo;", + options: ["always"] + }, + { + code: "'use strict';\n\n/*\nmultiline comment\n*/\nvar foo;", + options: ["always"] + }, + + // multiple directives + { + code: "'use strict';\n'use asm';\n\nvar foo;", + options: ["always"] + }, + { + code: "\n'use strict';\n'use asm';\n\nvar foo;", + options: ["always"] + }, + { + code: "'use strict';\n'use asm';\n\n//comment\nvar foo;", + options: ["always"] + }, + { + code: "'use strict';\n'use asm';\n\n/*\nmultiline comment\n*/\nvar foo;", + options: ["always"] + }, + + // after comment at top of file + // single directive + { + code: "#!/usr/bin/env node\n\n'use strict';\n\nvar foo;", + options: ["always"] + }, + { + code: "#!/usr/bin/env node\n//comment\n\n'use strict';\n\nvar foo;", + options: ["always"] + }, + { + code: "//comment\n\n'use strict';\n\nvar foo;", + options: ["always"] + }, + { + code: "/*\nmultiline comment\n*/\n\n'use strict';\n\nvar foo;", + options: ["always"] + }, + + // multiple directives + { + code: "#!/usr/bin/env node\n\n'use strict';\n'use asm';\n\nvar foo;", + options: ["always"] + }, + { + code: "#!/usr/bin/env node\n//comment\n\n'use strict';\n'use asm';\n\nvar foo;", + options: ["always"] + }, + { + code: "//comment\n\n'use strict';\n'use asm';\n\nvar foo;", + options: ["always"] + }, + { + code: "/*\nmultiline comment\n*/\n\n'use strict';\n'use asm';\n\nvar foo;", + options: ["always"] + }, + + // at the top of function blocks + // single directive + { + code: "function foo() {\n'use strict';\n\nvar bar;\n}", + options: ["always"] + }, + { + code: "function foo() {\n\n'use strict';\n\nvar bar;\n}", + options: ["always"] + }, + { + code: "() => {\n'use strict';\n\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: ["always"] + }, + { + code: "() => {\n\n'use strict';\n\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: ["always"] + }, + + // multiple directives + { + code: "function foo() {\n'use strict';\n'use asm';\n\nvar bar;\n}", + options: ["always"] + }, + { + code: "function foo() {\n\n'use strict';\n'use asm';\n\nvar bar;\n}", + options: ["always"] + }, + { + code: "() => {\n'use strict';\n'use asm';\n\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: ["always"] + }, + { + code: "() => {\n\n'use strict';\n'use asm';\n\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: ["always"] + }, + + // after comment at top of function blocks + // single directive + { + code: "function foo() {\n//comment\n\n'use strict';\n\nvar bar;\n}", + options: ["always"] + }, + { + code: "function foo() {\n/*\nmultiline comment\n*/\n\n'use strict';\n\nvar bar;\n}", + options: ["always"] + }, + { + code: "() => {\n//comment\n\n'use strict';\n\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: ["always"] + }, + { + code: "() => {\n/*\nmultiline comment\n*/\n\n'use strict';\n\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: ["always"] + }, + + // multiple directives + { + code: "function foo() {\n//comment\n\n'use strict';\n'use asm';\n\nvar bar;\n}", + options: ["always"] + }, + { + code: "function foo() {\n/*\nmultiline comment\n*/\n\n'use strict';\n'use asm';\n\nvar bar;\n}", + options: ["always"] + }, + { + code: "() => {\n//comment\n\n'use strict';\n'use asm';\n\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: ["always"] + }, + { + code: "() => {\n/*\nmultiline comment\n*/\n\n'use strict';\n'use asm';\n\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: ["always"] + }, + + // does not warn about lack of blank newlines between directives + { + code: "//comment\n\n'use strict';\n'use asm';\n\nvar foo;", + options: ["always"] + }, + + // is not affected by JSDoc comments when at top of function block + { + code: "/*\n * JSDoc comment\n */\nfunction foo() {\n'use strict';\n\nvar bar;\n}", + options: ["always"] + }, + + // does not warn if the directive is the only statement in the function block and there are no comments + { + code: "function foo() {\n'use strict';\n}", + options: ["always"] + }, + + // "never" + // at top of file + // single directive + { + code: "'use strict';\nvar foo;", + options: ["never"] + }, + { + code: "'use strict';\n//comment\nvar foo;", + options: ["never"] + }, + { + code: "'use strict';\n/*\nmultiline comment\n*/\nvar foo;", + options: ["never"] + }, + + // multiple directives + { + code: "'use strict';\n'use asm';\nvar foo;", + options: ["never"] + }, + { + code: "'use strict';\n'use asm';\n//comment\nvar foo;", + options: ["never"] + }, + { + code: "'use strict';\n'use asm';\n/*\nmultiline comment\n*/\nvar foo;", + options: ["never"] + }, + + // after comment at top of file + // single directive + { + code: "#!/usr/bin/env node\n'use strict';\nvar foo;", + options: ["never"] + }, + { + code: "#!/usr/bin/env node\n//comment\n'use strict';\nvar foo;", + options: ["never"] + }, + { + code: "//comment\n'use strict';\nvar foo;", + options: ["never"] + }, + { + code: "/*\nmultiline comment\n*/\n'use strict';\nvar foo;", + options: ["never"] + }, + + // multiple directives + { + code: "#!/usr/bin/env node\n'use strict';\n'use asm';\nvar foo;", + options: ["never"] + }, + { + code: "#!/usr/bin/env node\n//comment\n'use strict';\n'use asm';\nvar foo;", + options: ["never"] + }, + { + code: "//comment\n'use strict';\n'use asm';\nvar foo;", + options: ["never"] + }, + { + code: "/*\nmultiline comment\n*/\n'use strict';\n'use asm';\nvar foo;", + options: ["never"] + }, + + // at the top of function blocks + // single directive + { + code: "function foo() {\n'use strict';\nvar bar;\n}", + options: ["never"] + }, + { + code: "function foo() {\n\n'use strict';\nvar bar;\n}", + options: ["never"] + }, + { + code: "() => {\n'use strict';\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: ["never"] + }, + { + code: "() => {\n\n'use strict';\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: ["never"] + }, + + // multiple directives + { + code: "function foo() {\n'use strict';\n'use asm';\nvar bar;\n}", + options: ["never"] + }, + { + code: "function foo() {\n\n'use strict';\n'use asm';\nvar bar;\n}", + options: ["never"] + }, + { + code: "() => {\n'use strict';\n'use asm';\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: ["never"] + }, + { + code: "() => {\n\n'use strict';\n'use asm';\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: ["never"] + }, + + // after comment at top of function blocks + // single directive + { + code: "function foo() {\n//comment\n'use strict';\nvar bar;\n}", + options: ["never"] + }, + { + code: "function foo() {\n/*\nmultiline comment\n*/\n'use strict';\nvar bar;\n}", + options: ["never"] + }, + { + code: "() => {\n//comment\n'use strict';\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: ["never"] + }, + { + code: "() => {\n/*\nmultiline comment\n*/\n'use strict';\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: ["never"] + }, + + // multiple directives + { + code: "function foo() {\n//comment\n'use strict';\n'use asm';\nvar bar;\n}", + options: ["never"] + }, + { + code: "function foo() {\n/*\nmultiline comment\n*/\n'use strict';\n'use asm';\nvar bar;\n}", + options: ["never"] + }, + { + code: "() => {\n//comment\n'use strict';\n'use asm';\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: ["never"] + }, + { + code: "() => {\n/*\nmultiline comment\n*/\n'use strict';\n'use asm';\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: ["never"] + }, + + // does not warn about blank newlines between directives + { + code: "//comment\n'use strict';\n\n'use asm';\nvar foo;", + options: ["never"] + }, + + // is not affected by JSDoc comments when at top of function block + { + code: "/*\n * JSDoc comment\n */\nfunction foo() {\n'use strict';\nvar bar;\n}", + options: ["never"] + }, + + // does not warn if the directive is the only statement in the function block and there are no comments + { + code: "function foo() {\n'use strict';\n}", + options: ["never"] + }, + + // { "before": "never", "after": "always" } + // at top of file + // single directive + { + code: "'use strict';\n\nvar foo;", + options: [{ before: "never", after: "always" }] + }, + { + code: "'use strict';\n\n//comment\nvar foo;", + options: [{ before: "never", after: "always" }] + }, + { + code: "'use strict';\n\n/*\nmultiline comment\n*/\nvar foo;", + options: [{ before: "never", after: "always" }] + }, + + // multiple directives + { + code: "'use strict';\n'use asm';\n\nvar foo;", + options: [{ before: "never", after: "always" }] + }, + { + code: "'use strict';\n'use asm';\n\n//comment\nvar foo;", + options: [{ before: "never", after: "always" }] + }, + { + code: "'use strict';\n'use asm';\n\n/*\nmultiline comment\n*/\nvar foo;", + options: [{ before: "never", after: "always" }] + }, + + // after comment at top of file + // single directive + { + code: "#!/usr/bin/env node\n'use strict';\n\nvar foo;", + options: [{ before: "never", after: "always" }] + }, + { + code: "//comment\n'use strict';\n\nvar foo;", + options: [{ before: "never", after: "always" }] + }, + { + code: "/*\nmultiline comment\n*/\n'use strict';\n\nvar foo;", + options: [{ before: "never", after: "always" }] + }, + + // multiple directives + { + code: "#!/usr/bin/env node\n'use strict';\n'use asm';\n\nvar foo;", + options: [{ before: "never", after: "always" }] + }, + { + code: "//comment\n'use strict';\n'use asm';\n\nvar foo;", + options: [{ before: "never", after: "always" }] + }, + { + code: "/*\nmultiline comment\n*/\n'use strict';\n'use asm';\n\nvar foo;", + options: [{ before: "never", after: "always" }] + }, + + // at the top of function blocks + // single directive + { + code: "function foo() {\n'use strict';\n\nvar bar;\n}", + options: [{ before: "never", after: "always" }] + }, + { + code: "function foo() {\n\n'use strict';\n\nvar bar;\n}", + options: [{ before: "never", after: "always" }] + }, + { + code: "() => {\n'use strict';\n\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: [{ before: "never", after: "always" }] + }, + { + code: "() => {\n\n'use strict';\n\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: [{ before: "never", after: "always" }] + }, + + // multiple directives + { + code: "function foo() {\n'use strict';\n'use asm';\n\nvar bar;\n}", + options: [{ before: "never", after: "always" }] + }, + { + code: "function foo() {\n\n'use strict';\n'use asm';\n\nvar bar;\n}", + options: [{ before: "never", after: "always" }] + }, + { + code: "() => {\n'use strict';\n'use asm';\n\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: [{ before: "never", after: "always" }] + }, + { + code: "() => {\n\n'use strict';\n'use asm';\n\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: [{ before: "never", after: "always" }] + }, + + // after comment at top of function blocks + // single directive + { + code: "function foo() {\n//comment\n'use strict';\n\nvar bar;\n}", + options: [{ before: "never", after: "always" }] + }, + { + code: "function foo() {\n/*\nmultiline comment\n*/\n'use strict';\n\nvar bar;\n}", + options: [{ before: "never", after: "always" }] + }, + { + code: "() => {\n//comment\n'use strict';\n\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: [{ before: "never", after: "always" }] + }, + { + code: "() => {\n/*\nmultiline comment\n*/\n'use strict';\n\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: [{ before: "never", after: "always" }] + }, + + // multiple directives + { + code: "function foo() {\n//comment\n'use strict';\n'use asm';\n\nvar bar;\n}", + options: [{ before: "never", after: "always" }] + }, + { + code: "function foo() {\n/*\nmultiline comment\n*/\n'use strict';\n'use asm';\n\nvar bar;\n}", + options: [{ before: "never", after: "always" }] + }, + { + code: "() => {\n//comment\n'use strict';\n'use asm';\n\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: [{ before: "never", after: "always" }] + }, + { + code: "() => {\n/*\nmultiline comment\n*/\n'use strict';\n'use asm';\n\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: [{ before: "never", after: "always" }] + }, + + // { "before": "always", "after": "never" } + // at top of file + // single directive + { + code: "'use strict';\nvar foo;", + options: [{ before: "always", after: "never" }] + }, + { + code: "\n'use strict';\nvar foo;", + options: [{ before: "always", after: "never" }] + }, + { + code: "'use strict';\n//comment\nvar foo;", + options: [{ before: "always", after: "never" }] + }, + { + code: "'use strict';\n/*\nmultiline comment\n*/\nvar foo;", + options: [{ before: "always", after: "never" }] + }, + + // multiple directives + { + code: "'use strict';\n'use asm';\nvar foo;", + options: [{ before: "always", after: "never" }] + }, + { + code: "\n'use strict';\n'use asm';\nvar foo;", + options: [{ before: "always", after: "never" }] + }, + { + code: "'use strict';\n'use asm';\n//comment\nvar foo;", + options: [{ before: "always", after: "never" }] + }, + { + code: "'use strict';\n'use asm';\n/*\nmultiline comment\n*/\nvar foo;", + options: [{ before: "always", after: "never" }] + }, + + // after comment at top of file + // single directive + { + code: "#!/usr/bin/env node\n\n'use strict';\nvar foo;", + options: [{ before: "always", after: "never" }] + }, + { + code: "//comment\n\n'use strict';\nvar foo;", + options: [{ before: "always", after: "never" }] + }, + { + code: "/*\nmultiline comment\n*/\n\n'use strict';\nvar foo;", + options: [{ before: "always", after: "never" }] + }, + + // multiple directives + { + code: "#!/usr/bin/env node\n\n'use strict';\n'use asm';\nvar foo;", + options: [{ before: "always", after: "never" }] + }, + { + code: "//comment\n\n'use strict';\n'use asm';\nvar foo;", + options: [{ before: "always", after: "never" }] + }, + { + code: "/*\nmultiline comment\n*/\n\n'use strict';\n'use asm';\nvar foo;", + options: [{ before: "always", after: "never" }] + }, + + // at the top of function blocks + // single directive + { + code: "function foo() {\n'use strict';\nvar bar;\n}", + options: [{ before: "always", after: "never" }] + }, + { + code: "function foo() {\n\n'use strict';\nvar bar;\n}", + options: [{ before: "always", after: "never" }] + }, + { + code: "() => {\n'use strict';\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: [{ before: "always", after: "never" }] + }, + { + code: "() => {\n\n'use strict';\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: [{ before: "always", after: "never" }] + }, + + // multiple directives + { + code: "function foo() {\n'use strict';\n'use asm';\nvar bar;\n}", + options: [{ before: "always", after: "never" }] + }, + { + code: "function foo() {\n\n'use strict';\n'use asm';\nvar bar;\n}", + options: [{ before: "always", after: "never" }] + }, + { + code: "() => {\n'use strict';\n'use asm';\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: [{ before: "always", after: "never" }] + }, + { + code: "() => {\n\n'use strict';\n'use asm';\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: [{ before: "always", after: "never" }] + }, + + // after comment at top of function blocks + // single directive + { + code: "function foo() {\n//comment\n\n'use strict';\nvar bar;\n}", + options: [{ before: "always", after: "never" }] + }, + { + code: "function foo() {\n/*\nmultiline comment\n*/\n\n'use strict';\nvar bar;\n}", + options: [{ before: "always", after: "never" }] + }, + { + code: "() => {\n//comment\n\n'use strict';\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: [{ before: "always", after: "never" }] + }, + { + code: "() => {\n/*\nmultiline comment\n*/\n\n'use strict';\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: [{ before: "always", after: "never" }] + }, + + // multiple directives + { + code: "function foo() {\n//comment\n\n'use strict';\n'use asm';\nvar bar;\n}", + options: [{ before: "always", after: "never" }] + }, + { + code: "function foo() {\n/*\nmultiline comment\n*/\n\n'use strict';\n'use asm';\nvar bar;\n}", + options: [{ before: "always", after: "never" }] + }, + { + code: "() => {\n//comment\n\n'use strict';\n'use asm';\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: [{ before: "always", after: "never" }] + }, + { + code: "() => {\n/*\nmultiline comment\n*/\n\n'use strict';\n'use asm';\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: [{ before: "always", after: "never" }] + }, + ], + + invalid: [ + + // "always" + // at top of file + // single directive + { + code: "'use strict';\nvar foo;", + options: ["always"], + errors: ["Expected newline after \"use strict\" directive."] + }, + { + code: "'use strict';\n//comment\nvar foo;", + options: ["always"], + errors: ["Expected newline after \"use strict\" directive."] + }, + { + code: "'use strict';\n/*\nmultiline comment\n*/\nvar foo;", + options: ["always"], + errors: ["Expected newline after \"use strict\" directive."] + }, + + // multiple directives + { + code: "'use strict';\n'use asm';\nvar foo;", + options: ["always"], + errors: ["Expected newline after \"use asm\" directive."] + }, + { + code: "'use strict';\n'use asm';\n//comment\nvar foo;", + options: ["always"], + errors: ["Expected newline after \"use asm\" directive."] + }, + { + code: "'use strict';\n'use asm';\n/*\nmultiline comment\n*/\nvar foo;", + options: ["always"], + errors: ["Expected newline after \"use asm\" directive."] + }, + + // after comment at top of file + // single directive + { + code: "#!/usr/bin/env node\n'use strict';\nvar foo;", + options: ["always"], + errors: [ + "Expected newline before \"use strict\" directive.", + "Expected newline after \"use strict\" directive." + ] + }, + { + code: "#!/usr/bin/env node\n//comment\n'use strict';\nvar foo;", + options: ["always"], + errors: [ + "Expected newline before \"use strict\" directive.", + "Expected newline after \"use strict\" directive." + ] + }, + { + code: "//comment\n'use strict';\nvar foo;", + options: ["always"], + errors: [ + "Expected newline before \"use strict\" directive.", + "Expected newline after \"use strict\" directive." + ] + }, + { + code: "/*\nmultiline comment\n*/\n'use strict';\nvar foo;", + options: ["always"], + errors: [ + "Expected newline before \"use strict\" directive.", + "Expected newline after \"use strict\" directive." + ] + }, + + // multiple directives + { + code: "#!/usr/bin/env node\n'use strict';\n'use asm';\nvar foo;", + options: ["always"], + errors: [ + "Expected newline before \"use strict\" directive.", + "Expected newline after \"use asm\" directive." + ] + }, + { + code: "#!/usr/bin/env node\n//comment\n'use strict';\n'use asm';\nvar foo;", + options: ["always"], + errors: [ + "Expected newline before \"use strict\" directive.", + "Expected newline after \"use asm\" directive." + ] + }, + { + code: "//comment\n'use strict';\n'use asm';\nvar foo;", + options: ["always"], + errors: [ + "Expected newline before \"use strict\" directive.", + "Expected newline after \"use asm\" directive." + ] + }, + { + code: "/*\nmultiline comment\n*/\n'use strict';\n'use asm';\nvar foo;", + options: ["always"], + errors: [ + "Expected newline before \"use strict\" directive.", + "Expected newline after \"use asm\" directive." + ] + }, + + // at the top of function blocks + // single directive + { + code: "function foo() {\n'use strict';\nvar bar;\n}", + options: ["always"], + errors: ["Expected newline after \"use strict\" directive."] + }, + { + code: "() => {\n'use strict';\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: ["always"], + errors: ["Expected newline after \"use strict\" directive."] + }, + + // multiple directives + { + code: "function foo() {\n'use strict';\n'use asm';\nvar bar;\n}", + options: ["always"], + errors: ["Expected newline after \"use asm\" directive."] + }, + { + code: "() => {\n'use strict';\n'use asm';\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: ["always"], + errors: ["Expected newline after \"use asm\" directive."] + }, + + // after comment at top of function blocks + // single directive + { + code: "function foo() {\n//comment\n'use strict';\nvar bar;\n}", + options: ["always"], + errors: [ + "Expected newline before \"use strict\" directive.", + "Expected newline after \"use strict\" directive." + ] + }, + { + code: "function foo() {\n/*\nmultiline comment\n*/\n'use strict';\nvar bar;\n}", + options: ["always"], + errors: [ + "Expected newline before \"use strict\" directive.", + "Expected newline after \"use strict\" directive." + ] + }, + { + code: "() => {\n//comment\n'use strict';\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: ["always"], + errors: [ + "Expected newline before \"use strict\" directive.", + "Expected newline after \"use strict\" directive." + ] + }, + { + code: "() => {\n/*\nmultiline comment\n*/\n'use strict';\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: ["always"], + errors: [ + "Expected newline before \"use strict\" directive.", + "Expected newline after \"use strict\" directive." + ] + }, + + // multiple directives + { + code: "function foo() {\n//comment\n'use strict';\n'use asm';\nvar bar;\n}", + options: ["always"], + errors: [ + "Expected newline before \"use strict\" directive.", + "Expected newline after \"use asm\" directive." + ] + }, + { + code: "function foo() {\n/*\nmultiline comment\n*/\n'use strict';\n'use asm';\nvar bar;\n}", + options: ["always"], + errors: [ + "Expected newline before \"use strict\" directive.", + "Expected newline after \"use asm\" directive." + ] + }, + { + code: "() => {\n//comment\n'use strict';\n'use asm';\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: ["always"], + errors: [ + "Expected newline before \"use strict\" directive.", + "Expected newline after \"use asm\" directive." + ] + }, + { + code: "() => {\n/*\nmultiline comment\n*/\n'use strict';\n'use asm';\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: ["always"], + errors: [ + "Expected newline before \"use strict\" directive.", + "Expected newline after \"use asm\" directive." + ] + }, + + // "never" + // at top of file + // single directive + { + code: "'use strict';\n\nvar foo;", + options: ["never"], + errors: ["Unexpected newline after \"use strict\" directive."] + }, + { + code: "'use strict';\n\n//comment\nvar foo;", + options: ["never"], + errors: ["Unexpected newline after \"use strict\" directive."] + }, + { + code: "'use strict';\n\n/*\nmultiline comment\n*/\nvar foo;", + options: ["never"], + errors: ["Unexpected newline after \"use strict\" directive."] + }, + + // multiple directives + { + code: "'use strict';\n'use asm';\n\nvar foo;", + options: ["never"], + errors: ["Unexpected newline after \"use asm\" directive."] + }, + { + code: "'use strict';\n'use asm';\n\n//comment\nvar foo;", + options: ["never"], + errors: ["Unexpected newline after \"use asm\" directive."] + }, + { + code: "'use strict';\n'use asm';\n\n/*\nmultiline comment\n*/\nvar foo;", + options: ["never"], + errors: ["Unexpected newline after \"use asm\" directive."] + }, + + // after comment at top of file + // single directive + { + code: "#!/usr/bin/env node\n\n'use strict';\n\nvar foo;", + options: ["never"], + errors: [ + "Unexpected newline before \"use strict\" directive.", + "Unexpected newline after \"use strict\" directive." + ] + }, + { + code: "#!/usr/bin/env node\n//comment\n\n'use strict';\n\nvar foo;", + options: ["never"], + errors: [ + "Unexpected newline before \"use strict\" directive.", + "Unexpected newline after \"use strict\" directive." + ] + }, + { + code: "//comment\n\n'use strict';\n\nvar foo;", + options: ["never"], + errors: [ + "Unexpected newline before \"use strict\" directive.", + "Unexpected newline after \"use strict\" directive." + ] + }, + { + code: "/*\nmultiline comment\n*/\n\n'use strict';\n\nvar foo;", + options: ["never"], + errors: [ + "Unexpected newline before \"use strict\" directive.", + "Unexpected newline after \"use strict\" directive." + ] + }, + + // multiple directives + { + code: "#!/usr/bin/env node\n\n'use strict';\n'use asm';\n\nvar foo;", + options: ["never"], + errors: [ + "Unexpected newline before \"use strict\" directive.", + "Unexpected newline after \"use asm\" directive." + ] + }, + { + code: "#!/usr/bin/env node\n//comment\n\n'use strict';\n'use asm';\n\nvar foo;", + options: ["never"], + errors: [ + "Unexpected newline before \"use strict\" directive.", + "Unexpected newline after \"use asm\" directive." + ] + }, + { + code: "//comment\n\n'use strict';\n'use asm';\n\nvar foo;", + options: ["never"], + errors: [ + "Unexpected newline before \"use strict\" directive.", + "Unexpected newline after \"use asm\" directive." + ] + }, + { + code: "/*\nmultiline comment\n*/\n\n'use strict';\n'use asm';\n\nvar foo;", + options: ["never"], + errors: [ + "Unexpected newline before \"use strict\" directive.", + "Unexpected newline after \"use asm\" directive." + ] + }, + + // at the top of function blocks + // single directive + { + code: "function foo() {\n'use strict';\n\nvar bar;\n}", + options: ["never"], + errors: ["Unexpected newline after \"use strict\" directive."] + }, + { + code: "() => {\n'use strict';\n\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: ["never"], + errors: ["Unexpected newline after \"use strict\" directive."] + }, + + // multiple directives + { + code: "function foo() {\n'use strict';\n'use asm';\n\nvar bar;\n}", + options: ["never"], + errors: ["Unexpected newline after \"use asm\" directive."] + }, + { + code: "() => {\n'use strict';\n'use asm';\n\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: ["never"], + errors: ["Unexpected newline after \"use asm\" directive."] + }, + + // after comment at top of function blocks + // single directive + { + code: "function foo() {\n//comment\n\n'use strict';\n\nvar bar;\n}", + options: ["never"], + errors: [ + "Unexpected newline before \"use strict\" directive.", + "Unexpected newline after \"use strict\" directive." + ] + }, + { + code: "function foo() {\n/*\nmultiline comment\n*/\n\n'use strict';\n\nvar bar;\n}", + options: ["never"], + errors: [ + "Unexpected newline before \"use strict\" directive.", + "Unexpected newline after \"use strict\" directive." + ] + }, + { + code: "() => {\n//comment\n\n'use strict';\n\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: ["never"], + errors: [ + "Unexpected newline before \"use strict\" directive.", + "Unexpected newline after \"use strict\" directive." + ] + }, + { + code: "() => {\n/*\nmultiline comment\n*/\n\n'use strict';\n\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: ["never"], + errors: [ + "Unexpected newline before \"use strict\" directive.", + "Unexpected newline after \"use strict\" directive." + ] + }, + + // multiple directives + { + code: "function foo() {\n//comment\n\n'use strict';\n'use asm';\n\nvar bar;\n}", + options: ["never"], + errors: [ + "Unexpected newline before \"use strict\" directive.", + "Unexpected newline after \"use asm\" directive." + ] + }, + { + code: "function foo() {\n/*\nmultiline comment\n*/\n\n'use strict';\n'use asm';\n\nvar bar;\n}", + options: ["never"], + errors: [ + "Unexpected newline before \"use strict\" directive.", + "Unexpected newline after \"use asm\" directive." + ] + }, + { + code: "() => {\n//comment\n\n'use strict';\n'use asm';\n\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: ["never"], + errors: [ + "Unexpected newline before \"use strict\" directive.", + "Unexpected newline after \"use asm\" directive." + ] + }, + { + code: "() => {\n/*\nmultiline comment\n*/\n\n'use strict';\n'use asm';\n\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: ["never"], + errors: [ + "Unexpected newline before \"use strict\" directive.", + "Unexpected newline after \"use asm\" directive." + ] + }, + + + // { "before": "never", "after": "always" } + // at top of file + // single directive + { + code: "'use strict';\nvar foo;", + options: [{ before: "never", after: "always" }], + errors: ["Expected newline after \"use strict\" directive."] + }, + { + code: "'use strict';\n//comment\nvar foo;", + options: [{ before: "never", after: "always" }], + errors: ["Expected newline after \"use strict\" directive."] + }, + { + code: "'use strict';\n/*\nmultiline comment\n*/\nvar foo;", + options: [{ before: "never", after: "always" }], + errors: ["Expected newline after \"use strict\" directive."] + }, + + // multiple directives + { + code: "'use strict';\n'use asm';\nvar foo;", + options: [{ before: "never", after: "always" }], + errors: ["Expected newline after \"use asm\" directive."] + }, + { + code: "'use strict';\n'use asm';\n//comment\nvar foo;", + options: [{ before: "never", after: "always" }], + errors: ["Expected newline after \"use asm\" directive."] + }, + { + code: "'use strict';\n'use asm';\n/*\nmultiline comment\n*/\nvar foo;", + options: [{ before: "never", after: "always" }], + errors: ["Expected newline after \"use asm\" directive."] + }, + + // after comment at top of file + // single directive + { + code: "#!/usr/bin/env node\n\n'use strict';\nvar foo;", + options: [{ before: "never", after: "always" }], + errors: [ + "Unexpected newline before \"use strict\" directive.", + "Expected newline after \"use strict\" directive." + ] + }, + { + code: "//comment\n\n'use strict';\nvar foo;", + options: [{ before: "never", after: "always" }], + errors: [ + "Unexpected newline before \"use strict\" directive.", + "Expected newline after \"use strict\" directive." + ] + }, + { + code: "/*\nmultiline comment\n*/\n\n'use strict';\nvar foo;", + options: [{ before: "never", after: "always" }], + errors: [ + "Unexpected newline before \"use strict\" directive.", + "Expected newline after \"use strict\" directive." + ] + }, + + // multiple directives + { + code: "#!/usr/bin/env node\n\n'use strict';\n'use asm';\nvar foo;", + options: [{ before: "never", after: "always" }], + errors: [ + "Unexpected newline before \"use strict\" directive.", + "Expected newline after \"use asm\" directive." + ] + }, + { + code: "//comment\n\n'use strict';\n'use asm';\nvar foo;", + options: [{ before: "never", after: "always" }], + errors: [ + "Unexpected newline before \"use strict\" directive.", + "Expected newline after \"use asm\" directive." + ] + }, + { + code: "/*\nmultiline comment\n*/\n\n'use strict';\n'use asm';\nvar foo;", + options: [{ before: "never", after: "always" }], + errors: [ + "Unexpected newline before \"use strict\" directive.", + "Expected newline after \"use asm\" directive." + ] + }, + + // at the top of function blocks + // single directive + { + code: "function foo() {\n'use strict';\nvar bar;\n}", + options: [{ before: "never", after: "always" }], + errors: ["Expected newline after \"use strict\" directive."] + }, + { + code: "function foo() {\n\n'use strict';\nvar bar;\n}", + options: [{ before: "never", after: "always" }], + errors: ["Expected newline after \"use strict\" directive."] + }, + { + code: "() => {\n'use strict';\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: [{ before: "never", after: "always" }], + errors: ["Expected newline after \"use strict\" directive."] + }, + { + code: "() => {\n\n'use strict';\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: [{ before: "never", after: "always" }], + errors: ["Expected newline after \"use strict\" directive."] + }, + + // multiple directives + { + code: "function foo() {\n'use strict';\n'use asm';\nvar bar;\n}", + options: [{ before: "never", after: "always" }], + errors: ["Expected newline after \"use asm\" directive."] + }, + { + code: "function foo() {\n\n'use strict';\n'use asm';\nvar bar;\n}", + options: [{ before: "never", after: "always" }], + errors: ["Expected newline after \"use asm\" directive."] + }, + { + code: "() => {\n'use strict';\n'use asm';\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: [{ before: "never", after: "always" }], + errors: ["Expected newline after \"use asm\" directive."] + }, + { + code: "() => {\n\n'use strict';\n'use asm';\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: [{ before: "never", after: "always" }], + errors: ["Expected newline after \"use asm\" directive."] + }, + + // after comment at top of function blocks + // single directive + { + code: "function foo() {\n//comment\n\n'use strict';\nvar bar;\n}", + options: [{ before: "never", after: "always" }], + errors: [ + "Unexpected newline before \"use strict\" directive.", + "Expected newline after \"use strict\" directive." + ] + }, + { + code: "function foo() {\n/*\nmultiline comment\n*/\n\n'use strict';\nvar bar;\n}", + options: [{ before: "never", after: "always" }], + errors: [ + "Unexpected newline before \"use strict\" directive.", + "Expected newline after \"use strict\" directive." + ] + }, + { + code: "() => {\n//comment\n\n'use strict';\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: [{ before: "never", after: "always" }], + errors: [ + "Unexpected newline before \"use strict\" directive.", + "Expected newline after \"use strict\" directive." + ] + }, + { + code: "() => {\n/*\nmultiline comment\n*/\n\n'use strict';\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: [{ before: "never", after: "always" }], + errors: [ + "Unexpected newline before \"use strict\" directive.", + "Expected newline after \"use strict\" directive." + ] + }, + + // multiple directives + { + code: "function foo() {\n//comment\n\n'use strict';\n'use asm';\nvar bar;\n}", + options: [{ before: "never", after: "always" }], + errors: [ + "Unexpected newline before \"use strict\" directive.", + "Expected newline after \"use asm\" directive." + ] + }, + { + code: "function foo() {\n/*\nmultiline comment\n*/\n\n'use strict';\n'use asm';\nvar bar;\n}", + options: [{ before: "never", after: "always" }], + errors: [ + "Unexpected newline before \"use strict\" directive.", + "Expected newline after \"use asm\" directive." + ] + }, + { + code: "() => {\n//comment\n\n'use strict';\n'use asm';\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: [{ before: "never", after: "always" }], + errors: [ + "Unexpected newline before \"use strict\" directive.", + "Expected newline after \"use asm\" directive." + ] + }, + { + code: "() => {\n/*\nmultiline comment\n*/\n\n'use strict';\n'use asm';\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: [{ before: "never", after: "always" }], + errors: [ + "Unexpected newline before \"use strict\" directive.", + "Expected newline after \"use asm\" directive." + ] + }, + + // { "before": "always", "after": "never" } + // at top of file + // single directive + { + code: "'use strict';\n\nvar foo;", + options: [{ before: "always", after: "never" }], + errors: ["Unexpected newline after \"use strict\" directive."] + }, + { + code: "'use strict';\n\n//comment\nvar foo;", + options: [{ before: "always", after: "never" }], + errors: ["Unexpected newline after \"use strict\" directive."] + }, + { + code: "'use strict';\n\n/*\nmultiline comment\n*/\nvar foo;", + options: [{ before: "always", after: "never" }], + errors: ["Unexpected newline after \"use strict\" directive."] + }, + + // multiple directives + { + code: "'use strict';\n'use asm';\n\nvar foo;", + options: [{ before: "always", after: "never" }], + errors: ["Unexpected newline after \"use asm\" directive."] + }, + { + code: "'use strict';\n'use asm';\n\n//comment\nvar foo;", + options: [{ before: "always", after: "never" }], + errors: ["Unexpected newline after \"use asm\" directive."] + }, + { + code: "'use strict';\n'use asm';\n\n/*\nmultiline comment\n*/\nvar foo;", + options: [{ before: "always", after: "never" }], + errors: ["Unexpected newline after \"use asm\" directive."] + }, + + // after comment at top of file + // single directive + { + code: "#!/usr/bin/env node\n'use strict';\n\nvar foo;", + options: [{ before: "always", after: "never" }], + errors: [ + "Expected newline before \"use strict\" directive.", + "Unexpected newline after \"use strict\" directive." + ] + }, + { + code: "//comment\n'use strict';\n\nvar foo;", + options: [{ before: "always", after: "never" }], + errors: [ + "Expected newline before \"use strict\" directive.", + "Unexpected newline after \"use strict\" directive." + ] + }, + { + code: "/*\nmultiline comment\n*/\n'use strict';\n\nvar foo;", + options: [{ before: "always", after: "never" }], + errors: [ + "Expected newline before \"use strict\" directive.", + "Unexpected newline after \"use strict\" directive." + ] + }, + + // multiple directives + { + code: "#!/usr/bin/env node\n'use strict';\n'use asm';\n\nvar foo;", + options: [{ before: "always", after: "never" }], + errors: [ + "Expected newline before \"use strict\" directive.", + "Unexpected newline after \"use asm\" directive." + ] + }, + { + code: "//comment\n'use strict';\n'use asm';\n\nvar foo;", + options: [{ before: "always", after: "never" }], + errors: [ + "Expected newline before \"use strict\" directive.", + "Unexpected newline after \"use asm\" directive." + ] + }, + { + code: "/*\nmultiline comment\n*/\n'use strict';\n'use asm';\n\nvar foo;", + options: [{ before: "always", after: "never" }], + errors: [ + "Expected newline before \"use strict\" directive.", + "Unexpected newline after \"use asm\" directive." + ] + }, + + // at the top of function blocks + // single directive + { + code: "function foo() {\n'use strict';\n\nvar bar;\n}", + options: [{ before: "always", after: "never" }], + errors: ["Unexpected newline after \"use strict\" directive."] + }, + { + code: "function foo() {\n\n'use strict';\n\nvar bar;\n}", + options: [{ before: "always", after: "never" }], + errors: ["Unexpected newline after \"use strict\" directive."] + }, + { + code: "() => {\n'use strict';\n\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: [{ before: "always", after: "never" }], + errors: ["Unexpected newline after \"use strict\" directive."] + }, + { + code: "() => {\n\n'use strict';\n\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: [{ before: "always", after: "never" }], + errors: ["Unexpected newline after \"use strict\" directive."] + }, + + // multiple directives + { + code: "function foo() {\n'use strict';\n'use asm';\n\nvar bar;\n}", + options: [{ before: "always", after: "never" }], + errors: ["Unexpected newline after \"use asm\" directive."] + }, + { + code: "function foo() {\n\n'use strict';\n'use asm';\n\nvar bar;\n}", + options: [{ before: "always", after: "never" }], + errors: ["Unexpected newline after \"use asm\" directive."] + }, + { + code: "() => {\n'use strict';\n'use asm';\n\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: [{ before: "always", after: "never" }], + errors: ["Unexpected newline after \"use asm\" directive."] + }, + { + code: "() => {\n\n'use strict';\n'use asm';\n\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: [{ before: "always", after: "never" }], + errors: ["Unexpected newline after \"use asm\" directive."] + }, + + // after comment at top of function blocks + // single directive + { + code: "function foo() {\n//comment\n'use strict';\n\nvar bar;\n}", + options: [{ before: "always", after: "never" }], + errors: [ + "Expected newline before \"use strict\" directive.", + "Unexpected newline after \"use strict\" directive." + ] + }, + { + code: "function foo() {\n/*\nmultiline comment\n*/\n'use strict';\n\nvar bar;\n}", + options: [{ before: "always", after: "never" }], + errors: [ + "Expected newline before \"use strict\" directive.", + "Unexpected newline after \"use strict\" directive." + ] + }, + { + code: "() => {\n//comment\n'use strict';\n\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: [{ before: "always", after: "never" }], + errors: [ + "Expected newline before \"use strict\" directive.", + "Unexpected newline after \"use strict\" directive." + ] + }, + { + code: "() => {\n/*\nmultiline comment\n*/\n'use strict';\n\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: [{ before: "always", after: "never" }], + errors: [ + "Expected newline before \"use strict\" directive.", + "Unexpected newline after \"use strict\" directive." + ] + }, + + // multiple directives + { + code: "function foo() {\n//comment\n'use strict';\n'use asm';\n\nvar bar;\n}", + options: [{ before: "always", after: "never" }], + errors: [ + "Expected newline before \"use strict\" directive.", + "Unexpected newline after \"use asm\" directive." + ] + }, + { + code: "function foo() {\n/*\nmultiline comment\n*/\n'use strict';\n'use asm';\n\nvar bar;\n}", + options: [{ before: "always", after: "never" }], + errors: [ + "Expected newline before \"use strict\" directive.", + "Unexpected newline after \"use asm\" directive." + ] + }, + { + code: "() => {\n//comment\n'use strict';\n'use asm';\n\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: [{ before: "always", after: "never" }], + errors: [ + "Expected newline before \"use strict\" directive.", + "Unexpected newline after \"use asm\" directive." + ] + }, + { + code: "() => {\n/*\nmultiline comment\n*/\n'use strict';\n'use asm';\n\nvar foo;\n}", + parserOptions: { ecmaVersion: 6 }, + options: [{ before: "always", after: "never" }], + errors: [ + "Expected newline before \"use strict\" directive.", + "Unexpected newline after \"use asm\" directive." + ] + } + ] +});