UNPKG

@sap/eslint-plugin-cds

Version:

ESLint plugin including recommended SAP Cloud Application Programming model and environment rules

121 lines (110 loc) 3.5 kB
'use strict' const SEP = '[,;\t]' const EOL = '\\r?\\n' const findFuzzy = require('./findFuzzy') module.exports = { findFuzzy, /** * @param {object} definition CSN definition object. * @param {string} [name] The definition's name. Inferred for "linked CSN". */ splitDefName(definition, name = definition.name) { if (!name) return null // Entity names from CSN are of the form: // <namespace>.<service>.<def>.<'texts'|'localized'>|<composition value> let prefix = '' let suffix = '' const names = name.split('.') let defName = names[names.length - 1] if (defName) { // Managed composition get compiler tag `_up` let isManagedComposition = false if (definition.elements) { isManagedComposition = Object.keys(definition.elements).some(k => k === 'up_') } // Check for compiler tags const compilerTagsToExclude = ['texts', 'localized'] const isCompilerTag = compilerTagsToExclude.includes(defName) if (isManagedComposition || isCompilerTag) { suffix = names[names.length - 1] defName = names[names.length - 2] } prefix = name.split(`.${defName}`)[0] } return { prefix, name: defName, suffix } }, _findInCode: function (miss, code) { // middle let match = new RegExp(SEP + miss + SEP).exec(code) if (match) return match.index + 1 // end of line match = new RegExp(SEP + miss + EOL).exec(code) if (match) return match.index + 1 // start of doc match = new RegExp('^' + miss + SEP).exec(code) if (match) return match.index // somewhere (fallback) return code.indexOf(miss) }, /** * Returns true if the given string is non-empty. The string is trimmed, i.e. leading/trailing * whitespace is removed prior to checking. * * @param {string} value * @returns {boolean} */ isEmptyString(value) { return value?.trim() === '' }, isEmptyObject: function (value) { function isEmpty (object) { if (Object.keys(object).length) { return false } return true } if (!value || typeof value !== 'object' || (typeof value === 'object' && !isEmpty(value)) || (typeof value === 'object' && value && value.length > 0)) { return false } return true }, isStringInArray (str, arr, caps = false) { const notIncluded = !arr.includes(str) if (!caps && notIncluded) { return false } if (caps && notIncluded && !arr.includes(str.toLowerCase()) && !arr.includes(str.toUpperCase())) { return false } return true }, getReplacementsSuggestions: function (context, value, loc) { let invalid const lineToReplace = context.sourcecode.lines[loc.line] const regExp = /\[([^)]+)\]/ const matches = regExp.exec(lineToReplace) if (matches && matches[0]) { invalid = matches[0] } const startIndex = lineToReplace.indexOf(invalid) const candidates = `['${value}']` const suggest = { messageId: 'ReplaceItemWith', data: { invalid, candidates }, fix: fixer => fixer.replaceTextRange([startIndex, startIndex + invalid.length] + 1, candidates) } return ({ messageId: 'InvalidItem', data: { invalid, candidates }, loc: { start: { line: loc.line + 1, column: startIndex }, end: { line: loc.line + 1, column: startIndex + invalid.length } }, file: loc.file, suggest, severity: 'warn' }) } }