mirror of
https://github.com/overleaf/overleaf.git
synced 2024-12-27 22:31:42 +00:00
1be43911b4
Set Prettier's "trailingComma" setting to "es5" GitOrigin-RevId: 9f14150511929a855b27467ad17be6ab262fe5d5
126 lines
3.9 KiB
JavaScript
126 lines
3.9 KiB
JavaScript
function functionArgsFilter(j, path) {
|
|
if (path.get('params') && path.get('params').value[0]) {
|
|
return ['err', 'error'].includes(path.get('params').value[0].name)
|
|
} else {
|
|
return false
|
|
}
|
|
}
|
|
|
|
function isReturningFunctionCallWithError(path, errorVarName) {
|
|
return (
|
|
path.value.argument &&
|
|
path.value.argument.arguments &&
|
|
path.value.argument.arguments[0] &&
|
|
path.value.argument.arguments[0].name === errorVarName
|
|
)
|
|
}
|
|
|
|
function expressionIsLoggingError(path) {
|
|
return ['warn', 'error', 'err'].includes(
|
|
path.get('callee').get('property').value.name
|
|
)
|
|
}
|
|
|
|
function createTagErrorExpression(j, path, errorVarName) {
|
|
let message = 'error'
|
|
if (path.value.arguments.length >= 2) {
|
|
message = path.value.arguments[1].value || message
|
|
}
|
|
|
|
let info
|
|
try {
|
|
info = j.objectExpression(
|
|
// add properties from original logger info object to the
|
|
// OError info object, filtering out the err object itself,
|
|
// which is typically one of the args when doing intermediate
|
|
// error logging
|
|
// TODO: this can fail when the property name does not match
|
|
// the variable name. e.g. { err: error } so need to check
|
|
// both in the filter
|
|
path
|
|
.get('arguments')
|
|
.value[0].properties.filter(
|
|
property => property.key.name !== errorVarName
|
|
)
|
|
)
|
|
} catch (error) {
|
|
// if info retrieval fails it remains empty
|
|
}
|
|
const args = [j.identifier(errorVarName), j.literal(message)]
|
|
if (info) {
|
|
args.push(info)
|
|
}
|
|
return j.callExpression(
|
|
j.memberExpression(j.identifier('OError'), j.identifier('tag')),
|
|
args
|
|
)
|
|
}
|
|
|
|
function functionBodyProcessor(j, path) {
|
|
// the error variable should be the first parameter to the function
|
|
const errorVarName = path.get('params').value[0].name
|
|
j(path)
|
|
.find(j.IfStatement) // look for if statements
|
|
.filter(path =>
|
|
j(path)
|
|
// find returns inside the if statement where the error from
|
|
// the args is explicitly returned
|
|
.find(j.ReturnStatement)
|
|
.some(path => isReturningFunctionCallWithError(path, errorVarName))
|
|
)
|
|
.forEach(path => {
|
|
j(path)
|
|
.find(j.CallExpression, {
|
|
callee: {
|
|
object: { name: 'logger' },
|
|
},
|
|
})
|
|
.filter(path => expressionIsLoggingError(path))
|
|
.replaceWith(path => {
|
|
return createTagErrorExpression(j, path, errorVarName)
|
|
})
|
|
})
|
|
}
|
|
|
|
export default function transformer(file, api) {
|
|
const j = api.jscodeshift
|
|
let source = file.source
|
|
// apply transformer to declared functions
|
|
source = j(source)
|
|
.find(j.FunctionDeclaration)
|
|
.filter(path => functionArgsFilter(j, path))
|
|
.forEach(path => functionBodyProcessor(j, path))
|
|
.toSource()
|
|
// apply transformer to inline-functions
|
|
source = j(source)
|
|
.find(j.FunctionExpression)
|
|
.filter(path => functionArgsFilter(j, path))
|
|
.forEach(path => functionBodyProcessor(j, path))
|
|
.toSource()
|
|
// apply transformer to inline-arrow-functions
|
|
source = j(source)
|
|
.find(j.ArrowFunctionExpression)
|
|
.filter(path => functionArgsFilter(j, path))
|
|
.forEach(path => functionBodyProcessor(j, path))
|
|
.toSource()
|
|
// do a plain text search to see if OError is used but not imported
|
|
if (source.includes('OError') && !source.includes('@overleaf/o-error')) {
|
|
const root = j(source)
|
|
// assume the first variable declaration is an import
|
|
// TODO: this should check that there is actually a require/import here
|
|
// but in most cases it will be
|
|
const imports = root.find(j.VariableDeclaration)
|
|
const importOError = "const OError = require('@overleaf/o-error')\n"
|
|
// if there were imports insert into list, format can re-order
|
|
if (imports.length) {
|
|
j(imports.at(0).get()).insertAfter(importOError)
|
|
}
|
|
// otherwise insert at beginning
|
|
else {
|
|
root.get().node.program.body.unshift(importOError)
|
|
}
|
|
source = root.toSource()
|
|
}
|
|
|
|
return source
|
|
}
|