@sasjs/lint
Version:
Linting and formatting for SAS code
125 lines • 5.76 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.strictMacroDefinition = void 0;
const types_1 = require("../../types");
const LintRuleType_1 = require("../../types/LintRuleType");
const parseMacros_1 = require("../../utils/parseMacros");
const name = 'strictMacroDefinition';
const description = 'Enforce strictly rules of macro definition syntax.';
const message = 'Incorrent Macro Definition Syntax';
const validOptions = [
'CMD',
'DES',
'MINDELIMITER',
'MINOPERATOR',
'NOMINOPERATOR',
'PARMBUFF',
'SECURE',
'NOSECURE',
'STMT',
'SOURCE',
'SRC',
'STORE'
];
const processParams = (content, macro, diagnostics, config) => {
const declaration = macro.declaration;
const severity = (config === null || config === void 0 ? void 0 : config.severityLevel[name]) || types_1.Severity.Warning;
const regExpParams = new RegExp(/(?<=\().*(?=\))/);
const regExpParamsResult = regExpParams.exec(declaration);
let _declaration = declaration;
if (regExpParamsResult) {
const paramsPresent = regExpParamsResult[0];
const params = paramsPresent.trim().split(',');
params.forEach((param) => {
const trimedParam = param.split('=')[0].trim();
let paramLineNumber = 1, paramStartIndex = 1, paramEndIndex = content.length;
if (macro.declarationLines.findIndex((dl) => dl.indexOf(trimedParam) !== -1) === -1) {
const comment = '/\\*(.*?)\\*/';
for (let i = 1; i < trimedParam.length; i++) {
const paramWithComment = trimedParam.slice(0, i) + comment + trimedParam.slice(i);
const regEx = new RegExp(paramWithComment);
const declarationLineIndex = macro.declarationLines.findIndex((dl) => !!regEx.exec(dl));
if (declarationLineIndex !== -1) {
const declarationLine = macro.declarationLines[declarationLineIndex];
const partFound = regEx.exec(declarationLine)[0];
paramLineNumber = macro.startLineNumbers[declarationLineIndex];
paramStartIndex = declarationLine.indexOf(partFound);
paramEndIndex =
declarationLine.indexOf(partFound) + partFound.length;
break;
}
}
}
else {
const declarationLineIndex = macro.declarationLines.findIndex((dl) => dl.indexOf(trimedParam) !== -1);
const declarationLine = macro.declarationLines[declarationLineIndex];
paramLineNumber = macro.startLineNumbers[declarationLineIndex];
paramStartIndex = declarationLine.indexOf(trimedParam);
paramEndIndex =
declarationLine.indexOf(trimedParam) + trimedParam.length;
}
if (trimedParam.includes(' ')) {
diagnostics.push({
message: `Param '${trimedParam}' cannot have space`,
lineNumber: paramLineNumber,
startColumnNumber: paramStartIndex + 1,
endColumnNumber: paramEndIndex,
severity
});
}
});
_declaration = declaration.split(`(${paramsPresent})`)[1];
}
return _declaration;
};
const processOptions = (_declaration, macro, diagnostics, config) => {
var _a, _b, _c;
let optionsPresent = (_b = (_a = _declaration.split('/')) === null || _a === void 0 ? void 0 : _a[1]) === null || _b === void 0 ? void 0 : _b.trim();
const severity = (config === null || config === void 0 ? void 0 : config.severityLevel[name]) || types_1.Severity.Warning;
if (optionsPresent) {
const regex = new RegExp(/=["|'](.*?)["|']/, 'g');
let result = regex.exec(optionsPresent);
// removing Option's `="..."` part, e.g. des="..."
while (result) {
optionsPresent =
optionsPresent.slice(0, result.index) +
optionsPresent.slice(result.index + result[0].length);
result = regex.exec(optionsPresent);
}
(_c = optionsPresent
.split(' ')) === null || _c === void 0 ? void 0 : _c.filter((o) => !!o).forEach((option) => {
const trimmedOption = option.trim();
if (!validOptions.includes(trimmedOption.toUpperCase())) {
const declarationLineIndex = macro.declarationLines.findIndex((dl) => dl.indexOf(trimmedOption) !== -1);
const declarationLine = macro.declarationLines[declarationLineIndex];
diagnostics.push({
message: `Option '${trimmedOption}' is not valid`,
lineNumber: macro.startLineNumbers[declarationLineIndex],
startColumnNumber: declarationLine.indexOf(trimmedOption) + 1,
endColumnNumber: declarationLine.indexOf(trimmedOption) + trimmedOption.length,
severity
});
}
});
}
};
const test = (value, config) => {
const diagnostics = [];
const macros = (0, parseMacros_1.parseMacros)(value, config);
macros.forEach((macro) => {
const _declaration = processParams(value, macro, diagnostics, config);
processOptions(_declaration, macro, diagnostics, config);
});
return diagnostics;
};
/**
* Lint rule that checks if a line has followed syntax for macro definition
*/
exports.strictMacroDefinition = {
type: LintRuleType_1.LintRuleType.File,
name,
description,
message,
test
};
//# sourceMappingURL=strictMacroDefinition.js.map