Files
codeql-action/node_modules/eslint/lib/rules/lines-around-comment.js
dependabot[bot] 80150c2141 Bump the npm group with 12 updates (#2003)
* Bump the npm group with 12 updates

Bumps the npm group with 12 updates:

| Package | From | To |
| --- | --- | --- |
| [@octokit/types](https://github.com/octokit/types.ts) | `12.1.1` | `12.3.0` |
| [@types/uuid](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/uuid) | `9.0.6` | `9.0.7` |
| [@types/adm-zip](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/adm-zip) | `0.5.3` | `0.5.4` |
| [@types/js-yaml](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/js-yaml) | `4.0.8` | `4.0.9` |
| [@types/semver](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/semver) | `7.5.4` | `7.5.5` |
| [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) | `6.9.1` | `6.12.0` |
| [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) | `6.9.1` | `6.12.0` |
| [eslint](https://github.com/eslint/eslint) | `8.52.0` | `8.54.0` |
| [nock](https://github.com/nock/nock) | `13.3.7` | `13.3.8` |
| [sinon](https://github.com/sinonjs/sinon) | `17.0.0` | `17.0.1` |
| [@types/sinon](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/sinon) | `10.0.20` | `17.0.1` |
| [typescript](https://github.com/Microsoft/TypeScript) | `5.2.2` | `5.3.2` |


Updates `@octokit/types` from 12.1.1 to 12.3.0
- [Release notes](https://github.com/octokit/types.ts/releases)
- [Commits](https://github.com/octokit/types.ts/compare/v12.1.1...v12.3.0)

Updates `@types/uuid` from 9.0.6 to 9.0.7
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/uuid)

Updates `@types/adm-zip` from 0.5.3 to 0.5.4
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/adm-zip)

Updates `@types/js-yaml` from 4.0.8 to 4.0.9
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/js-yaml)

Updates `@types/semver` from 7.5.4 to 7.5.5
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/semver)

Updates `@typescript-eslint/eslint-plugin` from 6.9.1 to 6.12.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.12.0/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 6.9.1 to 6.12.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.12.0/packages/parser)

Updates `eslint` from 8.52.0 to 8.54.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.52.0...v8.54.0)

Updates `nock` from 13.3.7 to 13.3.8
- [Release notes](https://github.com/nock/nock/releases)
- [Changelog](https://github.com/nock/nock/blob/main/CHANGELOG.md)
- [Commits](https://github.com/nock/nock/compare/v13.3.7...v13.3.8)

Updates `sinon` from 17.0.0 to 17.0.1
- [Release notes](https://github.com/sinonjs/sinon/releases)
- [Changelog](https://github.com/sinonjs/sinon/blob/main/docs/changelog.md)
- [Commits](https://github.com/sinonjs/sinon/compare/v17.0.0...v17.0.1)

Updates `@types/sinon` from 10.0.20 to 17.0.1
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/sinon)

Updates `typescript` from 5.2.2 to 5.3.2
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Commits](https://github.com/Microsoft/TypeScript/commits)

---
updated-dependencies:
- dependency-name: "@octokit/types"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: "@types/uuid"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: "@types/adm-zip"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: "@types/js-yaml"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: "@types/semver"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm
- dependency-name: nock
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: sinon
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: npm
- dependency-name: "@types/sinon"
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: npm
- dependency-name: typescript
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>

* Update checked-in dependencies

* Rebuild

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-11-20 14:35:28 -08:00

472 lines
18 KiB
JavaScript

/**
* @fileoverview Enforces empty lines around comments.
* @author Jamund Ferguson
* @deprecated in ESLint v8.53.0
*/
"use strict";
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
const astUtils = require("./utils/ast-utils");
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
/**
* Return an array with any line numbers that are empty.
* @param {Array} lines An array of each line of the file.
* @returns {Array} An array of line numbers.
*/
function getEmptyLineNums(lines) {
const emptyLines = lines.map((line, i) => ({
code: line.trim(),
num: i + 1
})).filter(line => !line.code).map(line => line.num);
return emptyLines;
}
/**
* Return an array with any line numbers that contain comments.
* @param {Array} comments An array of comment tokens.
* @returns {Array} An array of line numbers.
*/
function getCommentLineNums(comments) {
const lines = [];
comments.forEach(token => {
const start = token.loc.start.line;
const end = token.loc.end.line;
lines.push(start, end);
});
return lines;
}
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
deprecated: true,
replacedBy: [],
type: "layout",
docs: {
description: "Require empty lines around comments",
recommended: false,
url: "https://eslint.org/docs/latest/rules/lines-around-comment"
},
fixable: "whitespace",
schema: [
{
type: "object",
properties: {
beforeBlockComment: {
type: "boolean",
default: true
},
afterBlockComment: {
type: "boolean",
default: false
},
beforeLineComment: {
type: "boolean",
default: false
},
afterLineComment: {
type: "boolean",
default: false
},
allowBlockStart: {
type: "boolean",
default: false
},
allowBlockEnd: {
type: "boolean",
default: false
},
allowClassStart: {
type: "boolean"
},
allowClassEnd: {
type: "boolean"
},
allowObjectStart: {
type: "boolean"
},
allowObjectEnd: {
type: "boolean"
},
allowArrayStart: {
type: "boolean"
},
allowArrayEnd: {
type: "boolean"
},
ignorePattern: {
type: "string"
},
applyDefaultIgnorePatterns: {
type: "boolean"
},
afterHashbangComment: {
type: "boolean",
default: false
}
},
additionalProperties: false
}
],
messages: {
after: "Expected line after comment.",
before: "Expected line before comment."
}
},
create(context) {
const options = Object.assign({}, context.options[0]);
const ignorePattern = options.ignorePattern;
const defaultIgnoreRegExp = astUtils.COMMENTS_IGNORE_PATTERN;
const customIgnoreRegExp = new RegExp(ignorePattern, "u");
const applyDefaultIgnorePatterns = options.applyDefaultIgnorePatterns !== false;
options.beforeBlockComment = typeof options.beforeBlockComment !== "undefined" ? options.beforeBlockComment : true;
const sourceCode = context.sourceCode;
const lines = sourceCode.lines,
numLines = lines.length + 1,
comments = sourceCode.getAllComments(),
commentLines = getCommentLineNums(comments),
emptyLines = getEmptyLineNums(lines),
commentAndEmptyLines = new Set(commentLines.concat(emptyLines));
/**
* Returns whether or not comments are on lines starting with or ending with code
* @param {token} token The comment token to check.
* @returns {boolean} True if the comment is not alone.
*/
function codeAroundComment(token) {
let currentToken = token;
do {
currentToken = sourceCode.getTokenBefore(currentToken, { includeComments: true });
} while (currentToken && astUtils.isCommentToken(currentToken));
if (currentToken && astUtils.isTokenOnSameLine(currentToken, token)) {
return true;
}
currentToken = token;
do {
currentToken = sourceCode.getTokenAfter(currentToken, { includeComments: true });
} while (currentToken && astUtils.isCommentToken(currentToken));
if (currentToken && astUtils.isTokenOnSameLine(token, currentToken)) {
return true;
}
return false;
}
/**
* Returns whether or not comments are inside a node type or not.
* @param {ASTNode} parent The Comment parent node.
* @param {string} nodeType The parent type to check against.
* @returns {boolean} True if the comment is inside nodeType.
*/
function isParentNodeType(parent, nodeType) {
return parent.type === nodeType ||
(parent.body && parent.body.type === nodeType) ||
(parent.consequent && parent.consequent.type === nodeType);
}
/**
* Returns the parent node that contains the given token.
* @param {token} token The token to check.
* @returns {ASTNode|null} The parent node that contains the given token.
*/
function getParentNodeOfToken(token) {
const node = sourceCode.getNodeByRangeIndex(token.range[0]);
/*
* For the purpose of this rule, the comment token is in a `StaticBlock` node only
* if it's inside the braces of that `StaticBlock` node.
*
* Example where this function returns `null`:
*
* static
* // comment
* {
* }
*
* Example where this function returns `StaticBlock` node:
*
* static
* {
* // comment
* }
*
*/
if (node && node.type === "StaticBlock") {
const openingBrace = sourceCode.getFirstToken(node, { skip: 1 }); // skip the `static` token
return token.range[0] >= openingBrace.range[0]
? node
: null;
}
return node;
}
/**
* Returns whether or not comments are at the parent start or not.
* @param {token} token The Comment token.
* @param {string} nodeType The parent type to check against.
* @returns {boolean} True if the comment is at parent start.
*/
function isCommentAtParentStart(token, nodeType) {
const parent = getParentNodeOfToken(token);
if (parent && isParentNodeType(parent, nodeType)) {
let parentStartNodeOrToken = parent;
if (parent.type === "StaticBlock") {
parentStartNodeOrToken = sourceCode.getFirstToken(parent, { skip: 1 }); // opening brace of the static block
} else if (parent.type === "SwitchStatement") {
parentStartNodeOrToken = sourceCode.getTokenAfter(parent.discriminant, {
filter: astUtils.isOpeningBraceToken
}); // opening brace of the switch statement
}
return token.loc.start.line - parentStartNodeOrToken.loc.start.line === 1;
}
return false;
}
/**
* Returns whether or not comments are at the parent end or not.
* @param {token} token The Comment token.
* @param {string} nodeType The parent type to check against.
* @returns {boolean} True if the comment is at parent end.
*/
function isCommentAtParentEnd(token, nodeType) {
const parent = getParentNodeOfToken(token);
return !!parent && isParentNodeType(parent, nodeType) &&
parent.loc.end.line - token.loc.end.line === 1;
}
/**
* Returns whether or not comments are at the block start or not.
* @param {token} token The Comment token.
* @returns {boolean} True if the comment is at block start.
*/
function isCommentAtBlockStart(token) {
return (
isCommentAtParentStart(token, "ClassBody") ||
isCommentAtParentStart(token, "BlockStatement") ||
isCommentAtParentStart(token, "StaticBlock") ||
isCommentAtParentStart(token, "SwitchCase") ||
isCommentAtParentStart(token, "SwitchStatement")
);
}
/**
* Returns whether or not comments are at the block end or not.
* @param {token} token The Comment token.
* @returns {boolean} True if the comment is at block end.
*/
function isCommentAtBlockEnd(token) {
return (
isCommentAtParentEnd(token, "ClassBody") ||
isCommentAtParentEnd(token, "BlockStatement") ||
isCommentAtParentEnd(token, "StaticBlock") ||
isCommentAtParentEnd(token, "SwitchCase") ||
isCommentAtParentEnd(token, "SwitchStatement")
);
}
/**
* Returns whether or not comments are at the class start or not.
* @param {token} token The Comment token.
* @returns {boolean} True if the comment is at class start.
*/
function isCommentAtClassStart(token) {
return isCommentAtParentStart(token, "ClassBody");
}
/**
* Returns whether or not comments are at the class end or not.
* @param {token} token The Comment token.
* @returns {boolean} True if the comment is at class end.
*/
function isCommentAtClassEnd(token) {
return isCommentAtParentEnd(token, "ClassBody");
}
/**
* Returns whether or not comments are at the object start or not.
* @param {token} token The Comment token.
* @returns {boolean} True if the comment is at object start.
*/
function isCommentAtObjectStart(token) {
return isCommentAtParentStart(token, "ObjectExpression") || isCommentAtParentStart(token, "ObjectPattern");
}
/**
* Returns whether or not comments are at the object end or not.
* @param {token} token The Comment token.
* @returns {boolean} True if the comment is at object end.
*/
function isCommentAtObjectEnd(token) {
return isCommentAtParentEnd(token, "ObjectExpression") || isCommentAtParentEnd(token, "ObjectPattern");
}
/**
* Returns whether or not comments are at the array start or not.
* @param {token} token The Comment token.
* @returns {boolean} True if the comment is at array start.
*/
function isCommentAtArrayStart(token) {
return isCommentAtParentStart(token, "ArrayExpression") || isCommentAtParentStart(token, "ArrayPattern");
}
/**
* Returns whether or not comments are at the array end or not.
* @param {token} token The Comment token.
* @returns {boolean} True if the comment is at array end.
*/
function isCommentAtArrayEnd(token) {
return isCommentAtParentEnd(token, "ArrayExpression") || isCommentAtParentEnd(token, "ArrayPattern");
}
/**
* Checks if a comment token has lines around it (ignores inline comments)
* @param {token} token The Comment token.
* @param {Object} opts Options to determine the newline.
* @param {boolean} opts.after Should have a newline after this line.
* @param {boolean} opts.before Should have a newline before this line.
* @returns {void}
*/
function checkForEmptyLine(token, opts) {
if (applyDefaultIgnorePatterns && defaultIgnoreRegExp.test(token.value)) {
return;
}
if (ignorePattern && customIgnoreRegExp.test(token.value)) {
return;
}
let after = opts.after,
before = opts.before;
const prevLineNum = token.loc.start.line - 1,
nextLineNum = token.loc.end.line + 1,
commentIsNotAlone = codeAroundComment(token);
const blockStartAllowed = options.allowBlockStart &&
isCommentAtBlockStart(token) &&
!(options.allowClassStart === false &&
isCommentAtClassStart(token)),
blockEndAllowed = options.allowBlockEnd && isCommentAtBlockEnd(token) && !(options.allowClassEnd === false && isCommentAtClassEnd(token)),
classStartAllowed = options.allowClassStart && isCommentAtClassStart(token),
classEndAllowed = options.allowClassEnd && isCommentAtClassEnd(token),
objectStartAllowed = options.allowObjectStart && isCommentAtObjectStart(token),
objectEndAllowed = options.allowObjectEnd && isCommentAtObjectEnd(token),
arrayStartAllowed = options.allowArrayStart && isCommentAtArrayStart(token),
arrayEndAllowed = options.allowArrayEnd && isCommentAtArrayEnd(token);
const exceptionStartAllowed = blockStartAllowed || classStartAllowed || objectStartAllowed || arrayStartAllowed;
const exceptionEndAllowed = blockEndAllowed || classEndAllowed || objectEndAllowed || arrayEndAllowed;
// ignore top of the file and bottom of the file
if (prevLineNum < 1) {
before = false;
}
if (nextLineNum >= numLines) {
after = false;
}
// we ignore all inline comments
if (commentIsNotAlone) {
return;
}
const previousTokenOrComment = sourceCode.getTokenBefore(token, { includeComments: true });
const nextTokenOrComment = sourceCode.getTokenAfter(token, { includeComments: true });
// check for newline before
if (!exceptionStartAllowed && before && !commentAndEmptyLines.has(prevLineNum) &&
!(astUtils.isCommentToken(previousTokenOrComment) && astUtils.isTokenOnSameLine(previousTokenOrComment, token))) {
const lineStart = token.range[0] - token.loc.start.column;
const range = [lineStart, lineStart];
context.report({
node: token,
messageId: "before",
fix(fixer) {
return fixer.insertTextBeforeRange(range, "\n");
}
});
}
// check for newline after
if (!exceptionEndAllowed && after && !commentAndEmptyLines.has(nextLineNum) &&
!(astUtils.isCommentToken(nextTokenOrComment) && astUtils.isTokenOnSameLine(token, nextTokenOrComment))) {
context.report({
node: token,
messageId: "after",
fix(fixer) {
return fixer.insertTextAfter(token, "\n");
}
});
}
}
//--------------------------------------------------------------------------
// Public
//--------------------------------------------------------------------------
return {
Program() {
comments.forEach(token => {
if (token.type === "Line") {
if (options.beforeLineComment || options.afterLineComment) {
checkForEmptyLine(token, {
after: options.afterLineComment,
before: options.beforeLineComment
});
}
} else if (token.type === "Block") {
if (options.beforeBlockComment || options.afterBlockComment) {
checkForEmptyLine(token, {
after: options.afterBlockComment,
before: options.beforeBlockComment
});
}
} else if (token.type === "Shebang") {
if (options.afterHashbangComment) {
checkForEmptyLine(token, {
after: options.afterHashbangComment,
before: false
});
}
}
});
}
};
}
};