lion/packages-node/providence-analytics/test-helpers/templates/analyzer-template.js

107 lines
3 KiB
JavaScript

const { Analyzer } = require('../../src/program/analyzers/helpers/Analyzer.js');
/**
* This file outlines the minimum required functionality for an analyzer.
* Whenever a new analyzer is created, this file can serve as a guideline on how to do this.
* For 'match-analyzers' (having requiresReference: true), please look in the analyzers folder for
* an example
*/
/**
* Everything that is configured via {AnalyzerConfig} [customConfig] in the execute
* function, should be configured here
*/
const options = {
optionA(entryResult) {
// here, we perform a transformation on the entryResult
return entryResult;
},
};
/**
* This file takes the output of one AST (or 'program'), which
* corresponds to one file.
* The contents of this function should be designed in such a way that they
* can be directly pasted and edited in https://astexplorer.net/
* @param {BabelAST} ast
* @returns {TransformedEntry}
*/
// eslint-disable-next-line no-unused-vars
function myAnalyzerPerAstEntry(ast) {
// Visit AST...
const transformedEntryResult = [];
// Do the traverse: https://babeljs.io/docs/en/babel-traverse
// Inside of ypur traverse function, add when there is a match wrt intended analysis
transformedEntryResult.push({ matched: 'entry' });
return transformedEntryResult;
}
class MyAnalyzer extends Analyzer {
constructor() {
super();
/**
* This must match with the name in file-system (will be used for reporting)
*/
this.name = 'my-analyzer';
/**
* The ast format that the execute function expects
* Compatible with formats supported by AstService.getAst()
*/
this.requiredAst = 'babel';
/**
* Not all analyzers require a references. Those that do, (usually 'match analyzers'),
* must explicitly state so with `requiresReference: true`
*/
}
/**
* @param {AstDataProject[]} astDataProjects
* @param {AnalyzerConfig} [customConfig]
* @returns {QueryResult}
*/
async execute(customConfig = {}) {
const cfg = {
targetProjectPaths: null,
optionA: false,
optionB: '',
...customConfig,
};
/**
* Prepare
*/
const analyzerResult = this._prepare(cfg);
if (analyzerResult) {
return analyzerResult;
}
/**
* Traverse
*/
const queryOutput = await this._traverse((ast, astContext) => {
// Run the traversel per entry
let transformedEntryResult = myAnalyzerPerAstEntry(ast);
const meta = {};
// (optional): Post processors on TransformedEntry
if (cfg.optionA) {
// Run entry transformation based on option A
transformedEntryResult = options.optionA(astContext);
}
return { result: transformedEntryResult, meta };
});
// (optional): Post processors on TransformedQueryResult
if (cfg.optionB) {
// Run your QueryResult transformation based on option B
}
/**
* Finalize
*/
return this._finalize(queryOutput, cfg);
}
}
module.exports = MyAnalyzer;