"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.defineVisitor = void 0; const SV = __importStar(require("./svelte")); const ES = __importStar(require("./es")); const TS = __importStar(require("./ts")); const ast_1 = require("./ast"); const eslint_utils_1 = require("@eslint-community/eslint-utils"); const offset_context_1 = require("./offset-context"); const compat_1 = require("../../utils/compat"); function parseOptions(options, defaultOptions) { const ret = { indentChar: ' ', indentScript: true, indentSize: 2, switchCase: 1, alignAttributesVertically: false, ignoredNodes: [], ...defaultOptions }; if (Number.isSafeInteger(options.indent)) { ret.indentSize = Number(options.indent); } else if (options.indent === 'tab') { ret.indentChar = '\t'; ret.indentSize = 1; } if (typeof options.indentScript === 'boolean') { ret.indentScript = options.indentScript; } if (options.switchCase != null && Number.isSafeInteger(options.switchCase)) { ret.switchCase = options.switchCase; } if (options.ignoredNodes != null) { ret.ignoredNodes = options.ignoredNodes; } if (options.alignAttributesVertically && ret.indentChar === ' ') { ret.alignAttributesVertically = true; } else if (ret.indentChar !== ' ') { ret.alignAttributesVertically = false; } return ret; } function defineVisitor(context, defaultOptions) { if (!(0, compat_1.getFilename)(context).endsWith('.svelte')) return {}; const options = parseOptions(context.options[0] || {}, defaultOptions); const sourceCode = (0, compat_1.getSourceCode)(context); const offsets = new offset_context_1.OffsetContext({ sourceCode, options }); function getIndentText({ line, column }) { return sourceCode.lines[line - 1].slice(0, column); } function validateToken(token, expectedIndent) { const line = token.loc.start.line; const indentText = getIndentText(token.loc.start); if (indentText.trim() !== '') { return; } const actualIndent = token.loc.start.column; const mismatchCharIndexes = []; for (let i = 0; i < indentText.length; ++i) { if (indentText[i] !== options.indentChar) { mismatchCharIndexes.push(i); } } if (actualIndent !== expectedIndent) { const loc = { start: { line, column: 0 }, end: { line, column: actualIndent } }; context.report({ loc, messageId: 'unexpectedIndentation', data: { expectedIndent: String(expectedIndent), actualIndent: String(actualIndent), expectedUnit: options.indentChar === '\t' ? 'tab' : 'space', actualUnit: mismatchCharIndexes.length ? 'whitespace' : options.indentChar === '\t' ? 'tab' : 'space', expectedIndentPlural: expectedIndent === 1 ? '' : 's', actualIndentPlural: actualIndent === 1 ? '' : 's' }, fix(fixer) { return fixer.replaceTextRange([sourceCode.getIndexFromLoc(loc.start), sourceCode.getIndexFromLoc(loc.end)], options.indentChar.repeat(expectedIndent)); } }); return; } for (const i of mismatchCharIndexes) { const loc = { start: { line, column: i }, end: { line, column: i + 1 } }; context.report({ loc, messageId: 'unexpectedChar', data: { expected: JSON.stringify(options.indentChar), actual: JSON.stringify(indentText[i]) }, fix(fixer) { return fixer.replaceTextRange([sourceCode.getIndexFromLoc(loc.start), sourceCode.getIndexFromLoc(loc.end)], options.indentChar); } }); } } function processLine(tokens, prevComments, prevToken, calculator) { const firstToken = tokens[0]; const actualIndent = firstToken.loc.start.column; const expectedIndent = calculator.getExpectedIndentFromTokens(tokens); if (expectedIndent == null) { calculator.saveExpectedIndent(tokens, actualIndent); return; } calculator.saveExpectedIndent(tokens, Math.min(...tokens .map((t) => calculator.getExpectedIndentFromToken(t)) .filter((i) => i != null))); let prev = prevToken; if (prevComments.length) { if (prev && prev.loc.end.line < prevComments[0].loc.start.line) { validateToken(prevComments[0], expectedIndent); } prev = prevComments[prevComments.length - 1]; } if (prev && prev.loc.end.line < tokens[0].loc.start.line) { validateToken(tokens[0], expectedIndent); } } const indentContext = { sourceCode, options, offsets }; const nodesVisitor = { ...ES.defineVisitor(indentContext), ...SV.defineVisitor(indentContext), ...TS.defineVisitor(indentContext) }; const knownNodes = new Set(Object.keys(nodesVisitor)); function compositingIgnoresVisitor(visitor) { for (const ignoreSelector of options.ignoredNodes) { const key = `${ignoreSelector}:exit`; if (visitor[key]) { const handler = visitor[key]; visitor[key] = function (node, ...args) { const ret = handler.call(this, node, ...args); offsets.ignore(node); return ret; }; } else { visitor[key] = (node) => offsets.ignore(node); } } return visitor; } return compositingIgnoresVisitor({ ...nodesVisitor, '*:exit'(node) { if (!knownNodes.has(node.type)) { offsets.ignore(node); } }, 'Program:exit'(node) { const calculator = offsets.getOffsetCalculator(); let prevToken = null; for (const { prevComments, tokens } of iterateLineTokens()) { processLine(tokens, prevComments, prevToken, calculator); prevToken = tokens[tokens.length - 1]; } function* iterateLineTokens() { let line = 0; let prevComments = []; let bufferTokens = []; for (const token of sourceCode.getTokens(node, { includeComments: true, filter: ast_1.isNotWhitespace })) { const thisLine = token.loc.start.line; if (line === thisLine || bufferTokens.length === 0) { bufferTokens.push(token); } else { if ((0, eslint_utils_1.isCommentToken)(bufferTokens[0]) && bufferTokens.every(eslint_utils_1.isCommentToken)) { prevComments.push(bufferTokens[0]); } else { yield { prevComments, tokens: bufferTokens }; prevComments = []; } bufferTokens = [token]; } line = thisLine; } if (bufferTokens.length && !bufferTokens.every(eslint_utils_1.isCommentToken)) { yield { prevComments, tokens: bufferTokens }; } } } }); } exports.defineVisitor = defineVisitor;