@sap/eslint-plugin-cds
Version:
ESLint plugin including recommended SAP Cloud Application Programming model and environment rules
90 lines (76 loc) • 2.37 kB
JavaScript
const { RULE_CATEGORIES } = require('../constants')
/**
* Util to check if an entity is part of an external service.
*/
class ExternalServices {
hasExternalServices = false
externalServices = Object.create(null)
static create(model) {
return new ExternalServices(model)
}
constructor(model) {
for (const defName in model.definitions) {
const def = model.definitions[defName]
if (def?.kind === 'service' && def['@cds.external']) {
this.externalServices[defName] = true
this.hasExternalServices = true
}
}
}
isInExternalService(defName) {
if (!this.hasExternalServices)
return false // shortcut
const segments = defName.split('.')
for (let i = segments.length - 1; i >= 0; i--)
if (this.externalServices[segments.slice(0, i).join('.')])
return true
return false
}
}
module.exports = {
meta: {
schema: [{/* to avoid deprecation warning for ESLint 9 */}],
docs: {
category: RULE_CATEGORIES.model,
description: 'Names must not start with $ to avoid possible shadowing of reserved variables.',
recommended: true,
url: 'https://cap.cloud.sap/docs/tools/cds-lint/rules/no-dollar-prefixed-names',
},
messages: {
dollarPrefix: `'{{name}}' is prefixed with a dollar sign ($)`,
},
type: 'problem'
},
create(context) {
const model = context.getModel()
if (!model?.definitions)
return
const externals = ExternalServices.create(model)
return function checkAllElementsForDollarPrefix() {
for (const defName in model.definitions) {
if (!externals.isInExternalService(defName))
checkElements(defName, model.definitions[defName])
}
}
function checkElements(defName, def) {
if (!Object.hasOwn(def,'elements') || !def.elements || typeof def.elements !== 'object')
return
for (const elementName in def.elements) {
const element = def.elements[elementName]
check(elementName, element)
if (element.elements)
checkElements(elementName, element)
}
}
function check(name, def) {
if (name.startsWith('$')) {
context.report({
messageId: 'dollarPrefix',
data: { name },
loc: context.getLocation(name, def, model),
})
}
}
}
}