bifocal/node_modules/gscan/lib/checks/120-no-unknown-globals.js

136 lines
4.7 KiB
JavaScript

const _ = require('lodash');
const spec = require('../specs');
const versions = require('../utils').versions;
const ASTLinter = require('../ast-linter');
function processFileFunction(files, failures, theme, partialsFound) {
const processedFiles = [];
return function processFile(linter, themeFile, parentInlinePartials = []) {
if (processedFiles.includes(themeFile.file)) {
return;
}
processedFiles.push(themeFile.file);
// Reset inline partial variables
linter.inlinePartials = [];
linter.options.inlinePartials = [];
linter.verify({
parsed: themeFile.parsed,
rules: [
require('../ast-linter/rules/mark-declared-inline-partials')
],
source: themeFile.content,
moduleId: themeFile.file
});
// Store the inline partials for the actual partial linting
const inlinePartials = linter.inlinePartials;
linter.options.inlinePartials = [...inlinePartials, ...parentInlinePartials];
const astResults = linter.verify({
parsed: themeFile.parsed,
rules: [
require('../ast-linter/rules/mark-used-partials'),
require('../ast-linter/rules/lint-no-unknown-globals')
],
source: themeFile.content,
moduleId: themeFile.file
});
if (astResults.length) {
astResults.forEach((result) => {
failures.push({
ref: themeFile.file,
message: result.message
});
});
}
theme.helpers = theme.helpers || {};
linter.helpers.forEach((helper) => {
if (!theme.helpers[helper.name]) {
theme.helpers[helper.name] = [];
}
theme.helpers[helper.name].push(themeFile.file);
});
linter.partials.forEach((partial) => {
const partialName = partial.node;
partialsFound[partialName] = true;
const file = files.find(f => f.normalizedFile === `partials/${partial.normalizedName}.hbs`);
if (file) {
// Find all inline partial declaration that were within the partial usage block
const childrenInlinePartials = [...parentInlinePartials];
for (const inline of inlinePartials) {
//Only partials that are in scope
if (inline.parents.some(node => node.type === partial.type &&
node.loc.source === partial.loc.source &&
node.loc.start.line === partial.loc.start.line &&
node.loc.start.column === partial.loc.start.column &&
node.loc.end.line === partial.loc.end.line &&
node.loc.end.column === partial.loc.end.column)) {
// Override the `parents` attribute as the inline partials are in another context than the children file
childrenInlinePartials.push({
...inline,
parents: []
});
}
}
processFile(linter, file, childrenInlinePartials);
}
});
};
}
const checkNoUnknownGlobals = function checkNoUnknownGlobals(theme, options) {
const failures = [];
const checkVersion = _.get(options, 'checkVersion', versions.default);
const ruleSet = spec.get([checkVersion]);
let partialsFound = {};
// Reset theme.helpers to make sure we only get helpers that are used
theme.helpers = {};
// CASE: 001-deprecations checks only needs `rules` that start with `GS001-DEPR-`
const ruleRegex = /GS120-.*/g;
const rulesToCheck = _.pickBy(ruleSet.rules, function (rule, ruleCode) {
if (ruleCode.match(ruleRegex)) {
return rule;
}
});
const processFile = processFileFunction(theme.files, failures, theme, partialsFound);
_.each(rulesToCheck, function (check, ruleCode) {
const linter = new ASTLinter({
partials: theme.partials,
helpers: ruleSet.knownHelpers
});
_.each(theme.files, function (themeFile) {
let templateTest = themeFile.file.match(/(?<!partials\/.+?)\.hbs$/);
if (templateTest) {
processFile(linter, themeFile);
}
});
theme.partials = Object.keys(partialsFound);
if (failures.length > 0) {
theme.results.fail[ruleCode] = {failures: failures};
} else {
theme.results.pass.push(ruleCode);
}
});
return theme;
};
module.exports = checkNoUnknownGlobals;