routie dev init since i didn't adhere to any proper guidance up until now

This commit is contained in:
2026-04-29 22:27:29 -06:00
commit e1dabb71e2
15301 changed files with 3562618 additions and 0 deletions
@@ -0,0 +1,29 @@
import {isSemicolonToken} from '@eslint-community/eslint-utils';
/**
@import {TSESTree as ESTree} from '@typescript-eslint/types';
@import * as ESLint from 'eslint';
*/
/**
@param {ESLint.Rule.RuleFixer} fixer
@param {ESTree.ReturnStatement | ESTree.ThrowStatement} node
@param {ESLint.Rule.RuleContext} context - The ESLint rule context object.
@returns {ESLint.Rule.ReportFixer}
*/
export default function * addParenthesizesToReturnOrThrowExpression(fixer, node, context) {
if (node.type !== 'ReturnStatement' && node.type !== 'ThrowStatement') {
return;
}
const {sourceCode} = context;
const returnOrThrowToken = sourceCode.getFirstToken(node);
yield fixer.insertTextAfter(returnOrThrowToken, ' (');
const lastToken = sourceCode.getLastToken(node);
if (!isSemicolonToken(lastToken)) {
yield fixer.insertTextAfter(node, ')');
return;
}
yield fixer.insertTextBefore(lastToken, ')');
}
@@ -0,0 +1,30 @@
import {isCommaToken} from '@eslint-community/eslint-utils';
/**
@import {TSESTree as ESTree} from '@typescript-eslint/types';
@import * as ESLint from 'eslint';
*/
/**
@param {ESLint.Rule.RuleFixer} fixer
@param {ESTree.CallExpression} node
@param {string} text
@param {ESLint.Rule.RuleContext} context - The ESLint rule context object.
@returns {ESLint.Rule.ReportFixer}
*/
export default function appendArgument(fixer, node, text, context) {
// This function should also work for `NewExpression`
// But parentheses of `NewExpression` could be omitted, add this check to prevent accidental use on it
/* c8 ignore next 3 */
if (node.type !== 'CallExpression') {
throw new Error(`Unexpected node "${node.type}".`);
}
const {sourceCode} = context;
const [penultimateToken, lastToken] = sourceCode.getLastTokens(node, 2);
if (node.arguments.length > 0) {
text = isCommaToken(penultimateToken) ? ` ${text},` : `, ${text}`;
}
return fixer.insertTextBefore(lastToken, text);
}
@@ -0,0 +1,11 @@
/**
Extend fix range to prevent changes from other rules.
https://github.com/eslint/eslint/pull/13748/files#diff-c692f3fde09eda7c89f1802c908511a3fb59f5d207fe95eb009cb52e46a99e84R348
@param {ruleFixer} fixer - The fixer to fix.
@param {int[]} range - The extended range node.
*/
export default function * extendFixRange(fixer, range) {
yield fixer.insertTextBeforeRange(range, '');
yield fixer.insertTextAfterRange(range, '');
}
@@ -0,0 +1,43 @@
import {getParenthesizedRange} from '../utils/index.js';
/**
@import {TSESTree as ESTree} from '@typescript-eslint/types';
@import * as ESLint from 'eslint';
*/
const isProblematicToken = ({type, value}) => (
(type === 'Keyword' && /^[a-z]*$/.test(value))
// ForOfStatement
|| (type === 'Identifier' && value === 'of')
// AwaitExpression
|| (type === 'Identifier' && value === 'await')
);
/**
@param {ESLint.Rule.RuleFixer} fixer
@param {ESTree.Node} node
@param {ESLint.Rule.RuleContext} context - The ESLint rule context object.
*/
export default function * fixSpaceAroundKeyword(fixer, node, context) {
const {sourceCode} = context;
const range = getParenthesizedRange(node, context);
const tokenBefore = sourceCode.getTokenBefore({range}, {includeComments: true});
if (
tokenBefore
&& range[0] === sourceCode.getRange(tokenBefore)[1]
&& isProblematicToken(tokenBefore)
) {
yield fixer.insertTextAfter(tokenBefore, ' ');
}
const tokenAfter = sourceCode.getTokenAfter({range}, {includeComments: true});
if (
tokenAfter
&& range[1] === sourceCode.getRange(tokenAfter)[0]
&& isProblematicToken(tokenAfter)
) {
yield fixer.insertTextBefore(tokenAfter, ' ');
}
}
+23
View File
@@ -0,0 +1,23 @@
export {default as extendFixRange} from './extend-fix-range.js';
export {default as removeParentheses} from './remove-parentheses.js';
export {default as appendArgument} from './append-argument.js';
export {default as removeArgument} from './remove-argument.js';
export {default as replaceArgument} from './replace-argument.js';
export {default as switchNewExpressionToCallExpression} from './switch-new-expression-to-call-expression.js';
export {default as switchCallExpressionToNewExpression} from './switch-call-expression-to-new-expression.js';
export {
replaceMemberExpressionProperty,
removeMemberExpressionProperty,
} from './replace-member-expression-property.js';
export {default as removeMethodCall} from './remove-method-call.js';
export {default as removeExpressionStatement} from './remove-expression-statement.js';
export {default as removeSpacesAfter} from './remove-spaces-after.js';
export {default as removeSpecifier} from './remove-specifier.js';
export {default as removeObjectProperty} from './remove-object-property.js';
export {default as renameVariable} from './rename-variable.js';
export {default as replaceTemplateElement} from './replace-template-element.js';
export {default as replaceReferenceIdentifier} from './replace-reference-identifier.js';
export {default as replaceNodeOrTokenAndSpacesBefore} from './replace-node-or-token-and-spaces-before.js';
export {default as fixSpaceAroundKeyword} from './fix-space-around-keywords.js';
export {default as replaceStringRaw} from './replace-string-raw.js';
export {default as addParenthesizesToReturnOrThrowExpression} from './add-parenthesizes-to-return-or-throw-expression.js';
@@ -0,0 +1,40 @@
import {isCommaToken} from '@eslint-community/eslint-utils';
import {getParentheses} from '../utils/index.js';
/**
@import {TSESTree as ESTree} from '@typescript-eslint/types';
@import * as ESLint from 'eslint';
*/
/**
@param {ESLint.Rule.RuleFixer} fixer
@param {ESTree.NewExpression | ESTree.CallExpression} node
@param {ESLint.Rule.RuleContext} context - The ESLint rule context object.
@returns {ESLint.Rule.ReportFixer}
*/
export default function removeArgument(fixer, node, context) {
const callOrNewExpression = node.parent;
const index = callOrNewExpression.arguments.indexOf(node);
const parentheses = getParentheses(node, context);
const firstToken = parentheses[0] || node;
const lastToken = parentheses.at(-1) || node;
const {sourceCode} = context;
let [start] = sourceCode.getRange(firstToken);
let [, end] = sourceCode.getRange(lastToken);
if (index !== 0) {
const commaToken = sourceCode.getTokenBefore(firstToken);
[start] = sourceCode.getRange(commaToken);
}
// If the removed argument is the only argument, the trailing comma must be removed too
if (callOrNewExpression.arguments.length === 1) {
const tokenAfter = sourceCode.getTokenAfter(lastToken);
if (isCommaToken(tokenAfter)) {
[, end] = sourceCode.getRange(tokenAfter);
}
}
return fixer.removeRange([start, end]);
}
@@ -0,0 +1,35 @@
import {isSemicolonToken} from '@eslint-community/eslint-utils';
const isWhitespaceOnly = text => /^\s*$/.test(text);
function removeExpressionStatement(expressionStatement, context, fixer, preserveSemiColon = false) {
const {sourceCode} = context;
const {lines} = sourceCode;
let endToken = expressionStatement;
if (preserveSemiColon) {
const [penultimateToken, lastToken] = sourceCode.getLastTokens(expressionStatement, 2);
if (isSemicolonToken(lastToken)) {
endToken = penultimateToken;
}
}
const startLocation = sourceCode.getLoc(expressionStatement).start;
const endLocation = sourceCode.getLoc(endToken).end;
const textBefore = lines[startLocation.line - 1].slice(0, startLocation.column);
const textAfter = lines[endLocation.line - 1].slice(endLocation.column);
let [start] = sourceCode.getRange(expressionStatement);
let [, end] = sourceCode.getRange(endToken);
if (isWhitespaceOnly(textBefore) && isWhitespaceOnly(textAfter)) {
start = Math.max(0, start - textBefore.length - 1);
end += textAfter.length;
}
return fixer.removeRange([start, end]);
}
export default removeExpressionStatement;
@@ -0,0 +1,28 @@
import {getParenthesizedRange} from '../utils/index.js';
import {removeMemberExpressionProperty} from './replace-member-expression-property.js';
/**
@import {TSESTree as ESTree} from '@typescript-eslint/types';
@import * as ESLint from 'eslint';
*/
/**
@param {ESLint.Rule.RuleFixer} fixer
@param {ESTree.CallExpression} callExpression
@param {ESLint.Rule.RuleContext} context - The ESLint rule context object.
@returns {ESLint.Rule.ReportFixer}
*/
export default function * removeMethodCall(fixer, callExpression, context) {
const memberExpression = callExpression.callee;
// `(( (( foo )).bar ))()`
// ^^^^
yield removeMemberExpressionProperty(fixer, memberExpression, context);
// `(( (( foo )).bar ))()`
// ^^
const [, start] = getParenthesizedRange(memberExpression, context);
const [, end] = context.sourceCode.getRange(callExpression);
yield fixer.removeRange([start, end]);
}
@@ -0,0 +1,21 @@
import {isCommaToken} from '@eslint-community/eslint-utils';
export default function * removeObjectProperty(fixer, property, context) {
const {sourceCode} = context;
for (const token of sourceCode.getTokens(property)) {
yield fixer.remove(token);
}
const tokenAfter = sourceCode.getTokenAfter(property);
if (isCommaToken(tokenAfter)) {
yield fixer.remove(tokenAfter);
} else {
// If the property is the last one and there is no trailing comma
// remove the previous comma
const {properties} = property.parent;
if (properties.length > 1 && properties.at(-1) === property) {
const commaTokenBefore = sourceCode.getTokenBefore(property);
yield fixer.remove(commaTokenBefore);
}
}
}
@@ -0,0 +1,19 @@
import {getParentheses} from '../utils/index.js';
/**
@import {TSESTree as ESTree} from '@typescript-eslint/types';
@import * as ESLint from 'eslint';
*/
/**
@param {ESTree.Node} node
@param {ESLint.Rule.RuleFixer} fixer
@param {ESLint.Rule.RuleContext} context - The ESLint rule context object.
@returns {ESLint.Rule.ReportFixer}
*/
export default function * removeParentheses(node, fixer, context) {
const parentheses = getParentheses(node, context);
for (const token of parentheses) {
yield fixer.remove(token);
}
}
@@ -0,0 +1,22 @@
/**
@import {TSESTree as ESTree} from '@typescript-eslint/types';
@import * as ESLint from 'eslint';
*/
/**
@param {ESTree.Node | ESTree.Token | number} indexOrNodeOrToken
@param {ESLint.Rule.RuleContext} context - The ESLint rule context object.
@param {ESLint.Rule.RuleFixer} fixer
@returns {ESLint.Rule.ReportFixer}
*/
export default function removeSpacesAfter(indexOrNodeOrToken, context, fixer) {
let index = indexOrNodeOrToken;
if (typeof indexOrNodeOrToken === 'object') {
index = context.sourceCode.getRange(indexOrNodeOrToken)[1];
}
const textAfter = context.sourceCode.text.slice(index);
const [leadingSpaces] = textAfter.match(/^\s*/);
return fixer.removeRange([index, index + leadingSpaces.length]);
}
@@ -0,0 +1,59 @@
import {isCommaToken, isOpeningBraceToken} from '@eslint-community/eslint-utils';
/**
@import {TSESTree as ESTree} from '@typescript-eslint/types';
@import * as ESLint from 'eslint';
*/
/**
@param {ESTree.ImportSpecifier | ESTree.ExportSpecifier | ESTree.ImportDefaultSpecifier | ESTree.ImportNamespaceSpecifier} specifier
@param {ESLint.Rule.RuleFixer} fixer
@param {ESLint.Rule.RuleContext} context - The ESLint rule context object.
@param {boolean} [keepDeclaration = false]
@returns {ESLint.Rule.ReportFixer}
*/
export default function * removeSpecifier(specifier, fixer, context, keepDeclaration = false) {
const declaration = specifier.parent;
const {specifiers} = declaration;
if (specifiers.length === 1 && !keepDeclaration) {
yield fixer.remove(declaration);
return;
}
const {sourceCode} = context;
switch (specifier.type) {
case 'ImportSpecifier': {
const isTheOnlyNamedImport = specifiers.every(node => specifier === node || specifier.type !== node.type);
if (isTheOnlyNamedImport) {
const fromToken = sourceCode.getTokenAfter(specifier, token => token.type === 'Identifier' && token.value === 'from');
const hasDefaultImport = specifiers.some(node => node.type === 'ImportDefaultSpecifier');
const startToken = sourceCode.getTokenBefore(specifier, hasDefaultImport ? isCommaToken : isOpeningBraceToken);
const [start] = sourceCode.getRange(startToken);
const [end] = sourceCode.getRange(fromToken);
const tokenBefore = sourceCode.getTokenBefore(startToken);
const shouldInsertSpace = sourceCode.getRange(tokenBefore)[1] === start;
yield fixer.replaceTextRange([start, end], shouldInsertSpace ? ' ' : '');
return;
}
// Fallthrough
}
case 'ExportSpecifier':
case 'ImportNamespaceSpecifier':
case 'ImportDefaultSpecifier': {
yield fixer.remove(specifier);
const tokenAfter = sourceCode.getTokenAfter(specifier);
if (isCommaToken(tokenAfter)) {
yield fixer.remove(tokenAfter);
}
break;
}
// No default
}
}
@@ -0,0 +1,8 @@
import getVariableIdentifiers from '../utils/get-variable-identifiers.js';
import replaceReferenceIdentifier from './replace-reference-identifier.js';
const renameVariable = (variable, name, context, fixer) =>
getVariableIdentifiers(variable)
.map(identifier => replaceReferenceIdentifier(identifier, name, context, fixer));
export default renameVariable;
@@ -0,0 +1,17 @@
import {getParenthesizedRange} from '../utils/index.js';
/**
@import {TSESTree as ESTree} from '@typescript-eslint/types';
@import * as ESLint from 'eslint';
*/
/**
@param {ESLint.Rule.RuleFixer} fixer
@param {ESTree.CallExpression | ESTree.NewExpression} node
@param {string} text
@param {ESLint.Rule.RuleContext} context - The ESLint rule context object.
@returns {ESLint.Rule.ReportFixer}
*/
export default function replaceArgument(fixer, node, text, context) {
return fixer.replaceTextRange(getParenthesizedRange(node, context), text);
}
@@ -0,0 +1,25 @@
import {getParenthesizedRange} from '../utils/index.js';
/**
@import {TSESTree as ESTree} from '@typescript-eslint/types';
@import * as ESLint from 'eslint';
*/
/**
@param {ESTree.MemberExpression} memberExpression - The `MemberExpression` to fix.
@param {ESLint.Rule.RuleContext} context - The ESLint rule context object.
@param {string} text
@returns {ESLint.Rule.ReportFixer}
*/
export function replaceMemberExpressionProperty(fixer, memberExpression, context, text) {
const [, start] = getParenthesizedRange(memberExpression.object, context);
const [, end] = context.sourceCode.getRange(memberExpression);
return fixer.replaceTextRange([start, end], text);
}
/**
@param {ESTree.MemberExpression} memberExpression - The `MemberExpression` to fix.
@param {ESLint.Rule.RuleContext} context - The ESLint rule context object.
@returns {ESLint.Rule.ReportFixer}
*/
export const removeMemberExpressionProperty = (fixer, memberExpression, context) => replaceMemberExpressionProperty(fixer, memberExpression, context, '');
@@ -0,0 +1,31 @@
import {getParentheses} from '../utils/index.js';
/**
@import {TSESTree as ESTree} from '@typescript-eslint/types';
@import * as ESLint from 'eslint';
*/
/**
@param {ESTree.Node | ESTree.Token} nodeOrToken
@param {string} replacement
@param {ESLint.Rule.RuleFixer} fixer
@param {ESLint.Rule.RuleContext} context - The ESLint rule context object.
@param {ESLint.SourceCode} [tokenStore]
@returns {ESLint.Rule.ReportFixer}
*/
export default function * replaceNodeOrTokenAndSpacesBefore(nodeOrToken, replacement, fixer, context, tokenStore) {
const tokens = getParentheses(nodeOrToken, tokenStore ? {sourceCode: tokenStore} : context);
for (const token of tokens) {
yield replaceNodeOrTokenAndSpacesBefore(token, '', fixer, context, tokenStore);
}
const {sourceCode} = context;
let [start, end] = sourceCode.getRange(nodeOrToken);
const textBefore = sourceCode.text.slice(0, start);
const [trailingSpaces] = textBefore.match(/\s*$/);
const [lineBreak] = trailingSpaces.match(/(?:\r?\n|\r){0,1}/);
start -= trailingSpaces.length;
yield fixer.replaceTextRange([start, end], `${lineBreak}${replacement}`);
}
@@ -0,0 +1,32 @@
import isShorthandPropertyValue from '../utils/is-shorthand-property-value.js';
import isShorthandPropertyAssignmentPatternLeft from '../utils/is-shorthand-property-assignment-pattern-left.js';
import isShorthandImportLocal from '../utils/is-shorthand-import-local.js';
import isShorthandExportLocal from '../utils/is-shorthand-export-local.js';
export default function replaceReferenceIdentifier(identifier, replacement, context, fixer) {
if (
isShorthandPropertyValue(identifier)
|| isShorthandPropertyAssignmentPatternLeft(identifier)
) {
return fixer.replaceText(identifier, `${identifier.name}: ${replacement}`);
}
if (isShorthandImportLocal(identifier, context)) {
return fixer.replaceText(identifier, `${identifier.name} as ${replacement}`);
}
if (isShorthandExportLocal(identifier, context)) {
return fixer.replaceText(identifier, `${replacement} as ${identifier.name}`);
}
// `typeAnnotation`
if (identifier.typeAnnotation) {
const {sourceCode} = context;
return fixer.replaceTextRange(
[sourceCode.getRange(identifier)[0], sourceCode.getRange(identifier.typeAnnotation)[0]],
`${replacement}${identifier.optional ? '?' : ''}`,
);
}
return fixer.replaceText(identifier, replacement);
}
@@ -0,0 +1,12 @@
// Replace `StringLiteral` or `TemplateLiteral` node with raw text
const replaceStringRaw = (node, raw, context, fixer) =>
fixer.replaceTextRange(
// Ignore quotes and backticks
[
context.sourceCode.getRange(node)[0] + 1,
context.sourceCode.getRange(node)[1] - 1,
],
raw,
);
export default replaceStringRaw;
@@ -0,0 +1,10 @@
const replaceTemplateElement = (node, replacement, context, fixer) => {
const {tail} = node;
const [start, end] = context.sourceCode.getRange(node);
return fixer.replaceTextRange(
[start + 1, end - (tail ? 1 : 2)],
replacement,
);
};
export default replaceTemplateElement;
@@ -0,0 +1,31 @@
import {
isParenthesized,
shouldAddParenthesesToNewExpressionCallee,
} from '../utils/index.js';
import fixSpaceAroundKeyword from './fix-space-around-keywords.js';
/**
@import {TSESTree as ESTree} from '@typescript-eslint/types';
@import * as ESLint from 'eslint';
*/
/**
@param {ESTree.CallExpression} node
@param {ESLint.Rule.RuleContext} context - The ESLint rule context object.
@param {ESLint.Rule.RuleFixer} fixer
@returns {ESLint.Rule.ReportFixer}
*/
export default function * switchCallExpressionToNewExpression(node, context, fixer) {
yield fixSpaceAroundKeyword(fixer, node, context);
yield fixer.insertTextBefore(node, 'new ');
const {callee} = node;
if (
!isParenthesized(callee, context)
&& shouldAddParenthesesToNewExpressionCallee(callee)
) {
yield fixer.insertTextBefore(callee, '(');
yield fixer.insertTextAfter(callee, ')');
}
}
@@ -0,0 +1,44 @@
import {
isNewExpressionWithParentheses,
isParenthesized,
isOnSameLine,
} from '../utils/index.js';
import addParenthesizesToReturnOrThrowExpression from './add-parenthesizes-to-return-or-throw-expression.js';
import removeSpaceAfter from './remove-spaces-after.js';
/**
@import {TSESTree as ESTree} from '@typescript-eslint/types';
@import * as ESLint from 'eslint';
*/
/**
@param {ESTree.NewExpression} newExpression
@param {ESLint.Rule.RuleContext} context - The ESLint rule context object.
@param {ESLint.Rule.RuleFixer} fixer
@returns {ESLint.Rule.ReportFixer}
*/
export default function * switchNewExpressionToCallExpression(newExpression, context, fixer) {
const newToken = context.sourceCode.getFirstToken(newExpression);
yield fixer.remove(newToken);
yield removeSpaceAfter(newToken, context, fixer);
if (!isNewExpressionWithParentheses(newExpression, context)) {
yield fixer.insertTextAfter(newExpression, '()');
}
/*
Remove `new` from this code will makes the function return `undefined`
```js
() => {
return new // comment
Foo()
}
```
*/
if (!isOnSameLine(newToken, newExpression.callee, context) && !isParenthesized(newExpression, context)) {
// Ideally, we should use first parenthesis of the `callee`, and should check spaces after the `new` token
// But adding extra parentheses is harmless, no need to be too complicated
yield addParenthesizesToReturnOrThrowExpression(fixer, newExpression.parent, context);
}
}