f8c7e092fa
* upgrade from eslint version 8 to eslint version 10 * remove unsupported eslint-env directive * include jsx files in latexqc linting * use basePath and extends to maintain paths in writefull eslint * fix yarn.lock with ./bin/yarn install * preserve existing glob patterns in web eslint config * restore original comments * fix worker path * corrected comment about eslint-plugin-mocha * remove unused imports * remove unused import of includeIgnoreFile * switch to individual eslit.config.mjs files * fix lint errors on eslint.config.mjs in web * update build scripts for eslint.config.mjs * update volumes for RUN_LINTING_CI_MONOREPO in web Makefile updated manually as this makefile is not autogenerated the RUN_LINTING_CI_MONOREPO command is only used for prettier, not eslint, but updating for consistency. * migrate from mocha/no-skipped-tests to mocha/no-pending-tests see https://github.com/lo1tuma/eslint-plugin-mocha/pull/365 "rule no-skipped-tests has been removed, its functionality has been merged into the existing no-pending-tests rule" GitOrigin-RevId: 2c8f25c8049a0dba374a51df1214286bb5093a51
140 lines
4.1 KiB
JavaScript
140 lines
4.1 KiB
JavaScript
const path = require('node:path')
|
|
const fs = require('node:fs')
|
|
|
|
module.exports = {
|
|
meta: {
|
|
type: 'problem',
|
|
docs: {
|
|
description: 'Ensure vi.doMock first argument is a resolvable path.',
|
|
category: 'Best Practices',
|
|
recommended: false,
|
|
url: '',
|
|
},
|
|
fixable: 'code',
|
|
hasSuggestions: true,
|
|
schema: [],
|
|
messages: {
|
|
unresolvablePath:
|
|
'The path "{{pathValue}}" in vi.doMock() cannot be resolved relative to the current file.',
|
|
notAStringLiteral:
|
|
'The first argument of vi.doMock() must be (or resolve to) a string literal representing a path.',
|
|
noArguments: 'vi.doMock() called with no arguments.',
|
|
},
|
|
},
|
|
create(context) {
|
|
const currentFilePath = context.filename
|
|
// ESLint can sometimes pass <text> or <input> for snippets not in a file
|
|
if (currentFilePath === '<text>' || currentFilePath === '<input>') {
|
|
return {}
|
|
}
|
|
const currentDirectory = path.dirname(currentFilePath)
|
|
|
|
function canResolve(modulePath) {
|
|
try {
|
|
require.resolve(path.resolve(currentDirectory, modulePath))
|
|
return true
|
|
} catch (e) {
|
|
const absolutePath = path.resolve(currentDirectory, modulePath)
|
|
const extensions = [
|
|
'',
|
|
'.js',
|
|
'.mjs',
|
|
'.ts',
|
|
'.jsx',
|
|
'.tsx',
|
|
'.json',
|
|
'.node',
|
|
'/index.js',
|
|
'/index.ts',
|
|
] // Add common extensions
|
|
for (const ext of extensions) {
|
|
if (fs.existsSync(absolutePath + ext)) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
}
|
|
|
|
return {
|
|
CallExpression(node) {
|
|
if (
|
|
node.callee.type === 'MemberExpression' &&
|
|
node.callee.object.type === 'Identifier' &&
|
|
node.callee.object.name === 'vi' &&
|
|
node.callee.property.type === 'Identifier' &&
|
|
node.callee.property.name === 'doMock'
|
|
) {
|
|
if (node.arguments.length === 0) {
|
|
context.report({
|
|
node,
|
|
messageId: 'noArguments',
|
|
})
|
|
return
|
|
}
|
|
|
|
const firstArg = node.arguments[0]
|
|
let pathValue = firstArg.value
|
|
|
|
if (
|
|
firstArg.type !== 'Literal' ||
|
|
typeof firstArg.value !== 'string'
|
|
) {
|
|
if (firstArg.type === 'Identifier') {
|
|
const scope = context.sourceCode.getScope(node)
|
|
const variable = scope.variables.find(
|
|
v => v.name === firstArg.name
|
|
)
|
|
if (
|
|
variable &&
|
|
variable.defs.length > 0 &&
|
|
variable.defs[0].node.init &&
|
|
variable.defs[0].node.init.type === 'Literal' &&
|
|
typeof variable.defs[0].node.init.value === 'string'
|
|
) {
|
|
pathValue = variable.defs[0].node.init.value
|
|
if (canResolve(pathValue)) {
|
|
return
|
|
}
|
|
// If the first argument was a variable that didn't resolve then we can't auto-fix it
|
|
}
|
|
}
|
|
context.report({
|
|
node: firstArg,
|
|
messageId: 'notAStringLiteral',
|
|
})
|
|
return
|
|
}
|
|
|
|
if (!pathValue.startsWith('.')) {
|
|
return
|
|
}
|
|
|
|
if (!canResolve(pathValue)) {
|
|
const mjsPath = pathValue.replace('.js', '.mjs')
|
|
const additionalReportOptions = {}
|
|
if (canResolve(mjsPath)) {
|
|
additionalReportOptions.fix = fixer =>
|
|
fixer.replaceText(firstArg, `'${mjsPath}'`)
|
|
additionalReportOptions.suggest = [
|
|
{
|
|
desc: `Replace with "${pathValue.replace('.js', '.mjs')}"`,
|
|
fix: fixer => fixer.replaceText(firstArg, `'${mjsPath}'`),
|
|
},
|
|
]
|
|
}
|
|
context.report({
|
|
node: firstArg,
|
|
messageId: 'unresolvablePath',
|
|
data: {
|
|
pathValue,
|
|
},
|
|
...additionalReportOptions,
|
|
})
|
|
}
|
|
}
|
|
},
|
|
}
|
|
},
|
|
}
|