Creating a Custom Plugin
If you wish to extract information from your code that is not available with a built-in plugin, you can create a custom one.
Plugin Model
A plugin is a class that implements the BaseAnalyzerPluginModel
interface. This interface defines the following properties:
Property | Type | Description |
---|---|---|
onFinishProcessing | () => PluginAnalyzedEntity[] | Callback function called when processing of all files finishes. |
onAllFinishProcessing | (items: AnalyzeResults, plugin: BasePlugin) => any | Callback function called when processing of all plugins finishes. Used for post-processor plugins |
fileExtensions | RegExp[] | Which files CodeInsights should scan |
analyzeFile | (analyzeInfo: T, pluginOptions: PluginOptions) => any | Called on each file, this is where the logic of extracing the insights from the code exists |
name | string | Name of the plugin. |
Keep in mind that all of these properties are optional, so you can use only the ones you need.
Plugin Types
Start by creating a class with your plugin name. The plugin needs to extends one of the following classes:
- BaseAnalyzerPlugin - use this if you don't intend to parse any files with the plugin, but only do post-processing, or if you want to parse files that are not supported by CodeInsights.
- TypeScriptPlugin - use this if you intend to parse JS/TS files.
- HTMLPlugin - use this if you intend to parse HTML files.
- JSONPlugin - use this if you intend to parse JSON files.
These type of plugins will dictate which parser that CodeInsights will use to analyze the files, and the type of information that will be provided to the plugin in the analyzeFile
function.
Example
For this example, we'll choose the TypeScriptPlugin:
class ImportsPlugin extends TypeScriptPlugin {
fileExtensions = ["ts", "js"] // optional, this is the default with TypeScriptPlugin
analyzeFile({ labels, visit }: TypeScriptAnalyzeInfo) {
}
onFinishProcessing() {
}
// Useful for post-processor plugins
onAllFinishProcessing() {
}
}
The analyzeFile
method will be called for each file in the codebase, an ast as well as visit utils is provided, in addition to the file information.
From here, you can use the AST to extract specific information, and save it somewhere in the class.
The onFinishProcessing
method will be called after all files have been analyzed. This is where you can do any post-processing requires by the plugin, and return the final result.
Make sure that this function returns the results, otherwise processor plugins won't be able to use them.
Full plugin:
interface ImportDefinition {
type: "import";
path: string;
metrics: AnalyzedEntityMetrics;
labels: {
name: string;
importedFrom: string;
};
}
class ImportsPlugin extends TypeScriptPlugin {
allFilesImports: ImportDefinition[] = [];
analyzeFile({ labels, visit }: TypeScriptAnalyzeInfo) {
const { filePath } = labels;
const allFilesImports: ImportDefinition[] = [];
visit({
visitImportDeclaration(path) {
const importPath = path.node.source.value as string;
const importItems = path.node.specifiers;
if (importItems?.length) {
for (const item of importItems) {
const getName = () => {
if (
item.type === "ImportDefaultSpecifier" ||
item.type === "ImportNamespaceSpecifier"
) {
return item.local?.name;
}
return item.imported.name;
};
const importDefinition: ImportDefinition = {
type: "import",
metrics: {},
path: filePath,
labels: {
name: getName() as string,
importedFrom: importPath,
},
};
allFilesImports.push(importDefinition);
}
}
this.traverse(path);
},
});
this.allFilesImports.push(...allFilesImports);
}
onFinishProcessing() {
return this.allFilesImports;
}
}
export default ImportsPlugin;
Summary
Creating a plugin is simple once you understand the structure of it.
Even if you want to parse a file that is not yet supported, you can do this as the file contents is one of the metadata that is provided to the analyzeFile
function.
Contributing a Plugin
We welcome the contributions of new plugins to the project. If you have created a plugin that you think would be useful to others, please consider submitting it to the project. If you'd like to maintain the plugin on your own, we are happy to feature it here.