Skip to content

Commit

Permalink
Merge pull request #141 from Lightning-Flow-Scanner/feat/update-core-…
Browse files Browse the repository at this point in the history
…with-new-rules

chore(log): add log manager for tracing purposes
  • Loading branch information
junners authored Nov 16, 2024
2 parents 5c05da3 + a9e96cd commit 10ae849
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 61 deletions.
12 changes: 12 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,18 @@
{
"version": "0.2.0",
"configurations": [
{
"args": [
"--extensionDevelopmentPath=${workspaceFolder}"
],
"name": "Launch Extension VSCE",
"outFiles": [
"${workspaceFolder}/out/**/*.js"
],
"preLaunchTask": "npm: compile",
"request": "launch",
"type": "extensionHost"
},
{
"args": [
"--extensionDevelopmentPath=${workspaceFolder}"
Expand Down
8 changes: 8 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@
"npm: watch-tests"
],
"problemMatcher": []
},
{
"type": "npm",
"script": "compile",
"group": "build",
"problemMatcher": [],
"label": "npm: compile",
"detail": "webpack --config ./build/node-extension.webpack.config.js"
}
]
}
124 changes: 77 additions & 47 deletions src/commands/handlers.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
import * as vscode from "vscode";
import { RuleOverview } from "../panels/RuleOverviewPanel";
import { SelectFlows } from "../libs/SelectFlows";
import { SaveFlow } from "../libs/SaveFlow";
import { ScanOverview } from "../panels/ScanOverviewPanel";
import * as core from "lightning-flow-scanner-core";
import { findFlowCoverage } from "../libs/FindFlowCoverage";
import { CacheProvider } from "../providers/cache-provider";
import { testdata } from "../store/testdata";
import * as vscode from 'vscode';
import { RuleOverview } from '../panels/RuleOverviewPanel';
import { SelectFlows } from '../libs/SelectFlows';
import { SaveFlow } from '../libs/SaveFlow';
import { ScanOverview } from '../panels/ScanOverviewPanel';
import * as core from 'lightning-flow-scanner-core';
import { findFlowCoverage } from '../libs/FindFlowCoverage';
import { CacheProvider } from '../providers/cache-provider';
import { testdata } from '../store/testdata';
import { OutputChannel } from '../providers/outputChannel';

export default class Commands {
constructor(private context: vscode.ExtensionContext) {}

get handlers() {
/* eslint-disable @typescript-eslint/naming-convention */
return Object.entries({
"lightningflowscanner.viewDefaulFlowRules": () =>
'lightningflowscanner.viewDefaulFlowRules': () =>
this.viewDefaulFlowRules(),
"lightningflowscanner.configRules": () => this.configRules(),
"lightningflowscanner.debugView": () => this.debugView(),
"lightningflowscanner.scanFlows": () => this.scanFlows(),
"lightningflowscanner.fixFlows": () => this.fixFlows(),
"lightningflowscanner.calculateFlowTestCoverage": () =>
'lightningflowscanner.configRules': () => this.configRules(),
'lightningflowscanner.debugView': () => this.debugView(),
'lightningflowscanner.scanFlows': () => this.scanFlows(),
'lightningflowscanner.fixFlows': () => this.fixFlows(),
'lightningflowscanner.calculateFlowTestCoverage': () =>
this.calculateFlowTestCoverage(),
});
}
Expand All @@ -37,7 +38,7 @@ export default class Commands {
return { label: rule.label, value: rule.name };
});
items.forEach((item) => {
item["picked"] = true;
item['picked'] = true;
});

const selectedRules = await vscode.window.showQuickPick(items, {
Expand All @@ -46,76 +47,76 @@ export default class Commands {

for (const rule of allRules) {
if (selectedRules.map((r) => r.value).includes(rule.name)) {
ruleConfig.rules[rule.name] = { severity: "error" };
ruleConfig.rules[rule.name] = { severity: 'error' };
}
}
if (selectedRules.map((r) => r.value).includes("FlowName")) {
if (selectedRules.map((r) => r.value).includes('FlowName')) {
const namingConventionString = await vscode.window.showInputBox({
prompt:
"Readability of a flow is very important. Setting a naming convention for the Flow Name will improve the findability/searchability and overall consistency. You can define your default naming convention using REGEX.",
placeHolder: "[A-Za-z0-9]+_[A-Za-z0-9]+",
value: "[A-Za-z0-9]+_[A-Za-z0-9]+",
'Readability of a flow is very important. Setting a naming convention for the Flow Name will improve the findability/searchability and overall consistency. You can define your default naming convention using REGEX.',
placeHolder: '[A-Za-z0-9]+_[A-Za-z0-9]+',
value: '[A-Za-z0-9]+_[A-Za-z0-9]+',
});
ruleConfig.rules["FlowName"] = {
severity: "error",
ruleConfig.rules['FlowName'] = {
severity: 'error',
expression: namingConventionString,
};
await vscode.workspace
.getConfiguration()
.update(
"lightningFlowScanner.NamingConvention",
'lightningFlowScanner.NamingConvention',
namingConventionString,
true
);
}
if (selectedRules.map((r) => r.value).includes("APIVersion")) {
if (selectedRules.map((r) => r.value).includes('APIVersion')) {
const apiVersionEvalExpressionString = await vscode.window.showInputBox({
prompt:
" The Api Version has been available as an attribute on the Flow since API v50.0 and it is recommended to limit variation and to update them on a regular basis. Set an expression to set a valid range of API versions(Minimum 50).",
placeHolder: ">50",
value: ">50",
' The Api Version has been available as an attribute on the Flow since API v50.0 and it is recommended to limit variation and to update them on a regular basis. Set an expression to set a valid range of API versions(Minimum 50).',
placeHolder: '>50',
value: '>50',
});
ruleConfig.rules["APIVersion"] = {
severity: "error",
ruleConfig.rules['APIVersion'] = {
severity: 'error',
expression: apiVersionEvalExpressionString,
};
await vscode.workspace
.getConfiguration()
.update(
"lightningFlowScanner.APIVersion",
'lightningFlowScanner.APIVersion',
apiVersionEvalExpressionString,
true
);
}
await CacheProvider.instance.set("ruleconfig", ruleConfig);
await CacheProvider.instance.set('ruleconfig', ruleConfig);
}

private async debugView() {
let results = testdata as unknown as core.ScanResult[];
await CacheProvider.instance.set("results", results);
await CacheProvider.instance.set('results', results);
ScanOverview.createOrShow(this.context.extensionUri, results);
await vscode.commands.executeCommand(
"workbench.action.webview.openDeveloperTools"
'workbench.action.webview.openDeveloperTools'
);
}

private async calculateFlowTestCoverage() {
const results = CacheProvider.instance.get("results");
const results = CacheProvider.instance.get('results');
ScanOverview.createOrShow(this.context.extensionUri, []);
if (results && results.length > 0) {
const coverageMap = await findFlowCoverage(results);
const newResults = [];
for (let result of results) {
let flowName = result.flow.name;
const coverage = coverageMap.get(flowName);
result["coverage"] = coverage;
result['coverage'] = coverage;
newResults.push(result);
await CacheProvider.instance.set("results", newResults);
await CacheProvider.instance.set('results', newResults);
ScanOverview.createOrShow(this.context.extensionUri, newResults);
}
} else {
vscode.window.showInformationMessage(
"No results found. Please make sure to complete a scan before calculating coverage."
'No results found. Please make sure to complete a scan before calculating coverage.'
);
}
}
Expand All @@ -124,49 +125,78 @@ export default class Commands {
const rootPath = vscode.workspace.workspaceFolders?.[0]?.uri;
const selectedUris = await new SelectFlows(
rootPath,
"Select a root folder:"
'Select a root folder:'
).execute(rootPath);
OutputChannel.getInstance().logChannel.debug(
'Selected uris',
...selectedUris
);
if (selectedUris.length > 0) {
let results: core.ScanResult[] = [];
const panel = ScanOverview.createOrShow(
this.context.extensionUri,
results
);
OutputChannel.getInstance().logChannel.trace('create panel');
let configReset: vscode.WorkspaceConfiguration =
vscode.workspace
.getConfiguration("lightningFlowScanner")
.get("Reset") ?? undefined;
.getConfiguration('lightningFlowScanner')
.get('Reset') ?? undefined;
OutputChannel.getInstance().logChannel.trace(
'load vscode stored configurations'
);
if (configReset) {
OutputChannel.getInstance().logChannel.trace('reset configurations');
await this.configRules();
}
const ruleConfig = CacheProvider.instance.get("ruleconfig");
const ruleConfig = CacheProvider.instance.get('ruleconfig');
results = core.scan(await core.parse(selectedUris), ruleConfig);
await CacheProvider.instance.set("results", results);
OutputChannel.getInstance().logChannel.debug('Scan Results', ...results);
await CacheProvider.instance.set('results', results);
ScanOverview.createOrShow(this.context.extensionUri, results);
} else {
vscode.window.showInformationMessage("No flow files found.");
vscode.window.showInformationMessage('No flow files found.');
}
}

private async fixFlows() {
const storedResults = CacheProvider.instance.get("results");
const storedResults = CacheProvider.instance.get('results');
OutputChannel.getInstance().logChannel.trace(
'has scan results?',
storedResults.length
);
if (storedResults && storedResults.length > 0) {
OutputChannel.getInstance().logChannel.debug(
'contains scan results',
...storedResults
);
ScanOverview.createOrShow(this.context.extensionUri, []);
const newResults: core.ScanResult[] = core.fix(storedResults);
OutputChannel.getInstance().logChannel.debug(
'invoked scanned results in total: ',
newResults.length
);
for (const newResult of newResults) {
OutputChannel.getInstance().logChannel.trace('Fixed File', newResult);
const uri = vscode.Uri.file(newResult.flow.fsPath);
await new SaveFlow().execute(newResult.flow, uri);
}
if (newResults && newResults.length > 0) {
await CacheProvider.instance.set("results", newResults);
OutputChannel.getInstance().logChannel.trace(
'Has fixed results, storing inside cache'
);
await CacheProvider.instance.set('results', newResults);
await ScanOverview.createOrShow(this.context.extensionUri, newResults);
} else {
OutputChannel.getInstance().logChannel.trace(
'Nothing fixed, showing warning message'
);
await ScanOverview.createOrShow(
this.context.extensionUri,
storedResults
);
await vscode.window.showWarningMessage(
"Fix Flows: UnusedVariable and UnconnectedElement rules are currently supported, stay tuned for more rules."
'Fix Flows: UnusedVariable and UnconnectedElement rules are currently supported, stay tuned for more rules.'
);
}
}
Expand Down
26 changes: 12 additions & 14 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,22 @@ import * as vscode from 'vscode';
import { Sidebar } from './panels/SidebarPanel';
import Commands from './commands/handlers';
import { CacheProvider } from './providers/cache-provider';
import { OutputChannel } from './providers/outputChannel';

export async function activate(context: vscode.ExtensionContext) {
OutputChannel.getInstance().logChannel.debug('initialize');

CacheProvider.init(context, {'results' : [], 'ruleconfig': {}});
CacheProvider.init(context, { results: [], ruleconfig: {} });

const sidebarPanel = new Sidebar(context.extensionUri);
const commands = new Commands(context);
context.subscriptions.push(
vscode.window.registerWebviewViewProvider(
'lfs-sb',
sidebarPanel
)
);

commands.handlers.forEach(([cmd, fn]) =>
context.subscriptions.push(vscode.commands.registerCommand(cmd, fn))
);
const sidebarPanel = new Sidebar(context.extensionUri);
const commands = new Commands(context);
context.subscriptions.push(
vscode.window.registerWebviewViewProvider('lfs-sb', sidebarPanel)
);

commands.handlers.forEach(([cmd, fn]) =>
context.subscriptions.push(vscode.commands.registerCommand(cmd, fn))
);
}

export function deactivate() { }
export function deactivate() {}
19 changes: 19 additions & 0 deletions src/providers/outputChannel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import * as vscode from 'vscode';

// Usage in the OutputChannel class
export class OutputChannel {
private static instance: OutputChannel;

private constructor(public logChannel: vscode.LogOutputChannel) {}

public static getInstance(): OutputChannel {
if (!this.instance) {
this.instance = new OutputChannel(
vscode.window.createOutputChannel('Lightning Flow Scanner', {
log: true,
})
);
}
return this.instance;
}
}

0 comments on commit 10ae849

Please sign in to comment.