@sap/eslint-plugin-cds
Version:
ESLint plugin including recommended SAP Cloud Application Programming model and environment rules
65 lines (56 loc) • 1.91 kB
JavaScript
const { forEachXprInDefinition } = require('../utils/csnTraversal')
const invalidComparisonOperators = [ '=', '<>' ]
module.exports = {
meta: {
schema: [{/* to avoid deprecation warning for ESLint 9 */}],
docs: {
description: 'Ensure SQL comparisons with \'null\' are valid',
category: 'Model Validation',
recommended: false,
url: 'https://cap.cloud.sap/docs/tools/cds-lint/rules/sql-null-comparison',
},
type: 'problem',
model: 'parsed',
messages: {
nullComparison: `Comparisons against 'null' using '=' and '<>' are always null. Did you mean 'is null'/'is not null'?`,
}
},
create(context) {
const model = context.getModel()
if (!model?.definitions)
return
return function checkSqlNullComparisonsInModel() {
for (const defName in model.definitions) {
const def = model.definitions[defName]
if (def.query || def.projection)
forEachXprInDefinition(def, checkExpression)
}
}
function checkExpression(xpr, ctx) {
if (!xpr || !Array.isArray(xpr))
return
for (let i = 0; i < xpr.length; i++) {
if (typeof xpr[i] !== 'object')
continue // scalar value, etc.
if (xpr[i]?.val === null) {
const prev = i > 0 && typeof xpr[i-1] === 'string' ? xpr[i-1] : null
if (prev && invalidComparisonOperators.includes(prev)) {
reportComparison(xpr, ctx)
continue
}
const next = i+1 < xpr.length && typeof xpr[i+1] === 'string' ? xpr[i+1] : null
if (next && invalidComparisonOperators.includes(next))
reportComparison(xpr, ctx)
}
}
}
function reportComparison(xpr, ctx) {
context.report({
messageId: 'nullComparison',
loc: context.getLocation('', ctx),
file: ctx.$location?.file,
})
}
}
}