123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152 |
- /**
- * @author Toru Nagashima <https://github.com/mysticatea>
- * See LICENSE file in root directory for full license.
- */
- "use strict"
- const escapeStringRegexp = require("escape-string-regexp")
- const LINE_PATTERN = /[^\r\n\u2028\u2029]*(?:\r\n|[\r\n\u2028\u2029]|$)/gu
- const DIRECTIVE_PATTERN = /^(eslint(?:-env|-enable|-disable(?:(?:-next)?-line)?)?|exported|globals?)(?:\s|$)/u
- const LINE_COMMENT_PATTERN = /^eslint-disable-(next-)?line$/u
- module.exports = {
- /**
- * Make the location ignoring `eslint-disable` comments.
- *
- * @param {object} location - The location to convert.
- * @returns {object} Converted location.
- */
- toForceLocation(location) {
- return {
- start: {
- line: location.start.line,
- column: -1,
- },
- end: location.end,
- }
- },
- /**
- * Calculate the location of the given rule in the given comment token.
- *
- * @param {Token} comment - The comment token to calculate.
- * @param {string|null} ruleId - The rule name to calculate.
- * @returns {object} The location of the given information.
- */
- toRuleIdLocation(comment, ruleId) {
- if (ruleId == null) {
- return module.exports.toForceLocation(comment.loc)
- }
- const lines = comment.value.match(LINE_PATTERN)
- //eslint-disable-next-line require-unicode-regexp
- const ruleIdPattern = new RegExp(
- `([\\s,]|^)${escapeStringRegexp(ruleId)}(?:[\\s,]|$)`
- )
- {
- const m = ruleIdPattern.exec(lines[0])
- if (m != null) {
- const start = comment.loc.start
- return {
- start: {
- line: start.line,
- column: 2 + start.column + m.index + m[1].length,
- },
- end: {
- line: start.line,
- column:
- 2 +
- start.column +
- m.index +
- m[1].length +
- ruleId.length,
- },
- }
- }
- }
- for (let i = 1; i < lines.length; ++i) {
- const m = ruleIdPattern.exec(lines[i])
- if (m != null) {
- const start = comment.loc.start
- return {
- start: {
- line: start.line + i,
- column: m.index + m[1].length,
- },
- end: {
- line: start.line + i,
- column: m.index + m[1].length + ruleId.length,
- },
- }
- }
- }
- /*istanbul ignore next : foolproof */
- return comment.loc
- },
- /**
- * Checks `a` is less than `b` or `a` equals `b`.
- *
- * @param {{line: number, column: number}} a - A location to compare.
- * @param {{line: number, column: number}} b - Another location to compare.
- * @returns {boolean} `true` if `a` is less than `b` or `a` equals `b`.
- */
- lte(a, b) {
- return a.line < b.line || (a.line === b.line && a.column <= b.column)
- },
- /**
- * Parse the given comment token as a directive comment.
- *
- * @param {Token} comment - The comment token to parse.
- * @returns {{kind: string, value: string, description: string | null}|null} The parsed data of the given comment. If `null`, it is not a directive comment.
- */
- parseDirectiveComment(comment) {
- const { text, description } = divideDirectiveComment(comment.value)
- const match = DIRECTIVE_PATTERN.exec(text)
- if (!match) {
- return null
- }
- const directiveText = match[1]
- const lineCommentSupported = LINE_COMMENT_PATTERN.test(directiveText)
- if (comment.type === "Line" && !lineCommentSupported) {
- return null
- }
- if (
- lineCommentSupported &&
- comment.loc.start.line !== comment.loc.end.line
- ) {
- // disable-line comment should not span multiple lines.
- return null
- }
- const directiveValue = text.slice(match.index + directiveText.length)
- return {
- kind: directiveText,
- value: directiveValue.trim(),
- description,
- }
- },
- }
- /**
- * Divides and trims description text and directive comments.
- * @param {string} value The comment text to strip.
- * @returns {{text: string, description: string | null}} The stripped text.
- */
- function divideDirectiveComment(value) {
- const divided = value.split(/\s-{2,}\s/u)
- const text = divided[0].trim()
- return {
- text,
- description: divided.length > 1 ? divided[1].trim() : null,
- }
- }
|