Skip to content

Commit

Permalink
feat: Implement SourceCode#traverse()
Browse files Browse the repository at this point in the history
Refs #16999
  • Loading branch information
nzakas committed Aug 3, 2023
1 parent a1635d6 commit 2b31aa1
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 17 deletions.
24 changes: 7 additions & 17 deletions lib/linter/linter.js
Original file line number Diff line number Diff line change
Expand Up @@ -923,22 +923,12 @@ const BASE_TRAVERSAL_CONTEXT = Object.freeze(
* @param {string | undefined} cwd cwd of the cli
* @param {string} physicalFilename The full path of the file on disk without any code block information
* @returns {LintMessage[]} An array of reported problems
* @throws {Error} If traversal into a node fails.
*/
function runRules(sourceCode, configuredRules, ruleMapper, parserName, languageOptions, settings, filename, disableFixes, cwd, physicalFilename) {
const emitter = createEmitter();
const nodeQueue = [];
let currentNode = sourceCode.ast;

Traverser.traverse(sourceCode.ast, {
enter(node, parent) {
node.parent = parent;
nodeQueue.push({ isEntering: true, node });
},
leave(node) {
nodeQueue.push({ isEntering: false, node });
},
visitorKeys: sourceCode.visitorKeys
});
const nodeQueue = sourceCode.traverse();

/*
* Create a frozen object with the ruleContext properties and methods that are shared by all rules.
Expand Down Expand Up @@ -1073,15 +1063,15 @@ function runRules(sourceCode, configuredRules, ruleMapper, parserName, languageO
});

// only run code path analyzer if the top level node is "Program", skip otherwise
const eventGenerator = nodeQueue[0].node.type === "Program"
const eventGenerator = sourceCode.ast.type === "Program"
? new CodePathAnalyzer(new NodeEventGenerator(emitter, { visitorKeys: sourceCode.visitorKeys, fallback: Traverser.getKeys }))
: new NodeEventGenerator(emitter, { visitorKeys: sourceCode.visitorKeys, fallback: Traverser.getKeys });

nodeQueue.forEach(traversalInfo => {
currentNode = traversalInfo.node;
for (const { isEntering, target } of nodeQueue) {
currentNode = target;

try {
if (traversalInfo.isEntering) {
if (isEntering) {
eventGenerator.enterNode(currentNode);
} else {
eventGenerator.leaveNode(currentNode);
Expand All @@ -1090,7 +1080,7 @@ function runRules(sourceCode, configuredRules, ruleMapper, parserName, languageO
err.currentNode = currentNode;
throw err;
}
});
}

return lintingProblems;
}
Expand Down
30 changes: 30 additions & 0 deletions lib/source-code/source-code.js
Original file line number Diff line number Diff line change
Expand Up @@ -724,6 +724,36 @@ class SourceCode extends TokenStore {
}


traverse() {

const steps = [];

Traverser.traverse(this.ast, {
enter(node, parent) {

// save the parent node on a property for backwards compatibility
node.parent = parent;

steps.push({
type: "visit",
target: node,
isEntering: true,
args: [node, parent]
});
},
leave(node, parent) {
steps.push({
type: "visit",
target: node,
isEntering: false,
args: [node, parent]
});
},
visitorKeys: this.visitorKeys
});

return steps;
}
}

module.exports = SourceCode;

0 comments on commit 2b31aa1

Please sign in to comment.