Skip to content

Commit

Permalink
Load state from files and create apply/revert/copy commands
Browse files Browse the repository at this point in the history
Key points:
1. make the data folder(.vscode/konveyor) the main permanent storage.
   This replaces the current usages of vscode.workspaceState.
2. store analysis results and received solutions directly in the
   extension state. Both values are frequently read from the command
   layer. Retrieval from the DB adds unnecessary delay.
3. load initial data asynchronously on extension start
4. implement commands: applyAll,applyFile, revertAll, revertFile,
   copyPath, copyDiff
5. create loadResultsFromDataFolder command ("Reload results" in the
   command palette)for initial data load and development.

Signed-off-by: Radoslaw Szwajkowski <[email protected]>
  • Loading branch information
rszwajko committed Nov 12, 2024
1 parent d2faf02 commit f06e9eb
Show file tree
Hide file tree
Showing 16 changed files with 237 additions and 75 deletions.
52 changes: 33 additions & 19 deletions vscode/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@
"title": "Load results from files",
"category": "Konveyor"
},
{
"command": "konveyor.loadResultsFromDataFolder",
"title": "Reload results",
"category": "Konveyor"
},
{
"command": "konveyor.cleanRuleSets",
"title": "Reset analysis results",
Expand All @@ -96,9 +101,9 @@
"category": "Konveyor"
},
{
"command": "konveyor.diffView.applyAll",
"command": "konveyor.applyAll",
"title": "Apply All",
"category": "Resolutions",
"category": "Konveyor",
"icon": {
"light": "resources/icons/light/check.svg",
"dark": "resources/icons/dark/check.svg"
Expand All @@ -107,15 +112,16 @@
{
"command": "konveyor.diffView.revertAll",
"title": "Discard local changes to Resolutions",
"category": "Resolutions",
"category": "Konveyor",
"icon": {
"light": "resources/icons/light/discard.svg",
"dark": "resources/icons/dark/discard.svg"
}
},
{
"command": "konveyor.diffView.applyFile",
"command": "konveyor.applyFile",
"title": "Apply",
"category": "Konveyor",
"icon": {
"light": "resources/icons/light/check.svg",
"dark": "resources/icons/dark/check.svg"
Expand All @@ -124,26 +130,36 @@
{
"command": "konveyor.diffView.revertFile",
"title": "Discard local changes to Resolutions",
"category": "Konveyor",
"icon": {
"light": "resources/icons/light/discard.svg",
"dark": "resources/icons/dark/discard.svg"
}
},
{
"command": "konveyor.diffView.copyDiff",
"command": "konveyor.copyDiff",
"category": "Konveyor",
"title": "Copy Diff"
},
{
"command": "konveyor.diffView.copyPath",
"command": "konveyor.copyPath",
"category": "Konveyor",
"title": "Copy Path"
},
{
"command": "konveyor.diffView.next",
"category": "Konveyor",
"title": "Go to Next File"
},
{
"command": "konveyor.diffView.prev",
"category": "Konveyor",
"title": "Go to Previous File"
},
{
"command": "konveyor.diffView.viewFix",
"category": "Konveyor",
"title": "View suggested fix"
}
],
"submenus": [
Expand Down Expand Up @@ -183,7 +199,7 @@
"when": "view == konveyor.konveyorGUIView"
},
{
"command": "konveyor.diffView.applyAll",
"command": "konveyor.applyAll",
"group": "navigation@1",
"when": "view == konveyor.diffView"
},
Expand All @@ -195,7 +211,7 @@
],
"view/item/context": [
{
"command": "konveyor.diffView.applyFile",
"command": "konveyor.applyFile",
"group": "inline",
"when": "view == konveyor.diffView && viewItem == file-item"
},
Expand All @@ -205,7 +221,7 @@
"when": "view == konveyor.diffView && viewItem == file-item"
},
{
"command": "konveyor.diffView.applyFile",
"command": "konveyor.applyFile",
"group": "1@1",
"when": "view == konveyor.diffView && viewItem == file-item"
},
Expand All @@ -215,12 +231,12 @@
"when": "view == konveyor.diffView && viewItem == file-item"
},
{
"command": "konveyor.diffView.copyDiff",
"command": "konveyor.copyDiff",
"group": "2@1",
"when": "view == konveyor.diffView && viewItem == file-item"
},
{
"command": "konveyor.diffView.copyPath",
"command": "konveyor.copyPath",
"group": "2@2",
"when": "view == konveyor.diffView && viewItem == file-item"
}
Expand Down Expand Up @@ -249,19 +265,19 @@
"when": "never"
},
{
"command": "konveyor.diffView.applyFile",
"command": "konveyor.applyFile",
"when": "never"
},
{
"command": "konveyor.diffView.revertFile",
"when": "never"
},
{
"command": "konveyor.diffView.copyDiff",
"command": "konveyor.copyDiff",
"when": "never"
},
{
"command": "konveyor.diffView.copyPath",
"command": "konveyor.copyPath",
"when": "never"
},
{
Expand All @@ -273,10 +289,8 @@
"when": "never"
},
{
"command": "konveyor.diffView.applyAll"
},
{
"command": "konveyor.diffView.revertAll"
"command": "konveyor.diffView.viewFix",
"when": "never"
}
]
},
Expand Down Expand Up @@ -463,4 +477,4 @@
"babel-loader": "^9.2.1",
"diff": "^7.0.0"
}
}
}
2 changes: 1 addition & 1 deletion vscode/src/KonveyorGUIWebviewViewProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ export class KonveyorGUIWebviewViewProvider implements WebviewViewProvider {

private _loadInitialContent() {
if (this._isWebviewReady && this._view) {
const data = this._extensionState.extensionContext.workspaceState.get("storedRuleSets");
const data = this._extensionState.ruleSets;
this._view.webview.postMessage({
type: "loadStoredAnalysis",
data,
Expand Down
26 changes: 21 additions & 5 deletions vscode/src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,24 @@ import {
ViewColumn,
workspace,
} from "vscode";
import { cleanRuleSets, loadRuleSets, loadSolution, loadStaticResults } from "./data";
import {
cleanRuleSets,
loadResultsFromDataFolder,
loadRuleSets,
loadSolution,
loadStaticResults,
} from "./data";
import { GetSolutionResult, RuleSet } from "@shared/types";
import { applyAll, revertAll, copyDiff, copyPath, FileItem, viewFix } from "./diffView";
import {
applyAll,
revertAll,
copyDiff,
copyPath,
FileItem,
viewFix,
applyFile,
revertFile,
} from "./diffView";

let fullScreenPanel: WebviewPanel | undefined;

Expand Down Expand Up @@ -321,14 +336,15 @@ const commandsMap: (state: ExtensionState) => {
"konveyor.loadRuleSets": (ruleSets: RuleSet[]): void => loadRuleSets(state, ruleSets),
"konveyor.cleanRuleSets": () => cleanRuleSets(state),
"konveyor.loadStaticResults": loadStaticResults,
"konveyor.loadResultsFromDataFolder": loadResultsFromDataFolder,
"konveyor.loadSolution": async (solution: GetSolutionResult) => loadSolution(state, solution),
"konveyor.applyAll": () => applyAll(state),
"konveyor.applyFile": (item: FileItem) => item.apply(),
"konveyor.copyDiff": copyDiff,
"konveyor.applyFile": (item: FileItem | Uri) => applyFile(item, state),
"konveyor.copyDiff": (item: FileItem | Uri) => copyDiff(item, state),
"konveyor.copyPath": copyPath,
"konveyor.diffView.viewFix": viewFix,
"konveyor.diffView.revertAll": () => revertAll(state),
"konveyor.diffView.revertFile": (item: FileItem) => item.revert(),
"konveyor.diffView.revertFile": (item: FileItem | Uri) => revertFile(item, state),
};
};

Expand Down
1 change: 1 addition & 0 deletions vscode/src/data/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from "./loadStaticResults";
export * from "./loadResults";
export * from "./fileSystemProvider";
export * from "./storage";
21 changes: 14 additions & 7 deletions vscode/src/data/loadResults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,25 @@ import { GetSolutionResult, RuleSet } from "@shared/types";
import { processIncidents } from "./analyzerResults";
import { ExtensionState } from "src/extensionState";
import { writeDataFile } from "./storage";
import { writeSolutionsToMemFs } from "./virtualStorage";
import { toLocalChanges, writeSolutionsToMemFs } from "./virtualStorage";
import { Location, Position } from "vscode";
import {
KONVEYOR_SCHEME,
RULE_SET_DATA_FILE_PREFIX,
SOLUTION_DATA_FILE_PREFIX,
} from "../utilities";

export const loadRuleSets = (state: ExtensionState, ruleSets: RuleSet[]): void => {
writeDataFile(ruleSets, "analysis");
state.extensionContext.workspaceState.update("storedRuleSets", ruleSets);
writeDataFile(ruleSets, RULE_SET_DATA_FILE_PREFIX);
state.ruleSets = ruleSets;
state.diagnosticCollection.set(processIncidents(ruleSets));
state.sidebarProvider?.webview?.postMessage({
type: "loadStoredAnalysis",
data: ruleSets,
});
};
export const cleanRuleSets = (state: ExtensionState) => {
state.extensionContext.workspaceState.update("storedRuleSets", undefined);
state.ruleSets = [];
state.diagnosticCollection.clear();
state.sidebarProvider?.webview?.postMessage({
type: "loadStoredAnalysis",
Expand All @@ -24,9 +29,11 @@ export const cleanRuleSets = (state: ExtensionState) => {
};

export const loadSolution = async (state: ExtensionState, solution: GetSolutionResult) => {
writeDataFile(solution, "solution");
state.extensionContext.workspaceState.update("storedSolution", solution);
const localChanges = await writeSolutionsToMemFs(solution, state);
writeDataFile(solution, SOLUTION_DATA_FILE_PREFIX);
const localChanges = toLocalChanges(solution);
state.memFs.removeAll(KONVEYOR_SCHEME);
await writeSolutionsToMemFs(localChanges, state);
state.localChanges = localChanges;
const locations = localChanges.map(
({ originalUri: uri }) => new Location(uri, new Position(0, 0)),
);
Expand Down
28 changes: 12 additions & 16 deletions vscode/src/data/loadStaticResults.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import * as vscode from "vscode";
import fs from "fs/promises";
import { RuleSet } from "@shared/types";
import { isAnalysis, isSolution } from "./typeGuards";
import { loadStateFromDataFolder, readDataFiles } from "./storage";

export const loadStaticResults = async () => {
const options: vscode.OpenDialogOptions = {
Expand All @@ -17,20 +16,7 @@ export const loadStaticResults = async () => {
return;
}

let analysisResults = undefined;
let solution = undefined;
for (const uri of uris) {
if (!uri || (analysisResults && solution)) {
break;
}
const fileContent = await fs.readFile(uri.fsPath, { encoding: "utf8" });
const parsed = JSON.parse(fileContent);
solution = !solution && isSolution(parsed) ? parsed : solution;
analysisResults =
!analysisResults && Array.isArray(parsed) && parsed.every((item) => isAnalysis(item))
? parsed
: analysisResults;
}
const [analysisResults, solution] = await readDataFiles(uris);

if (!analysisResults && !solution) {
vscode.window.showErrorMessage("Konveyor: failed to load data from selected file(s).");
Expand Down Expand Up @@ -61,3 +47,13 @@ const filePathsCorrect = (ruleSets: RuleSet[]) =>
(incident) =>
!incident.uri || vscode.workspace.getWorkspaceFolder(vscode.Uri.parse(incident.uri)),
);

export const loadResultsFromDataFolder = async () => {
const [analysisResults, solution] = await loadStateFromDataFolder();
if (analysisResults) {
vscode.commands.executeCommand("konveyor.loadRuleSets", analysisResults);
}
if (solution) {
vscode.commands.executeCommand("konveyor.loadSolution", solution);
}
};
48 changes: 48 additions & 0 deletions vscode/src/data/storage.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import path from "path";
import * as vscode from "vscode";
import fs from "fs";

import { RuleSet, GetSolutionResult } from "@shared/types";
import {
isAnalysis,
isSolution,
RULE_SET_DATA_FILE_PREFIX,
SOLUTION_DATA_FILE_PREFIX,
} from "../utilities";

const MAX_FILES = 5;

Expand Down Expand Up @@ -82,3 +89,44 @@ export async function writeDataFile(

deleteOldestDataFiles(prefix, MAX_FILES);
}

export const loadStateFromDataFolder = async (): Promise<
[RuleSet[] | undefined, GetSolutionResult | undefined]
> => {
const dataFolder = getDataFolder();
if (!dataFolder) {
return [undefined, undefined];
}

const [analysisFiles, solutionFiles] = await Promise.all([
getDataFilesByPrefix(RULE_SET_DATA_FILE_PREFIX),
getDataFilesByPrefix(SOLUTION_DATA_FILE_PREFIX),
]);

const [newestAnalysis] = analysisFiles.reverse();
const [newestSolution] = solutionFiles.reverse();
const uris = [newestAnalysis, newestSolution]
.filter(Boolean)
.map(([name]) => vscode.Uri.file(path.join(dataFolder, name)));
return readDataFiles(uris);
};

export const readDataFiles = async (
uris: vscode.Uri[],
): Promise<[RuleSet[] | undefined, GetSolutionResult | undefined]> => {
let analysisResults = undefined;
let solution = undefined;
for (const uri of uris) {
if (!uri || (analysisResults && solution)) {
break;
}
const fileContent = await fs.promises.readFile(uri.fsPath, { encoding: "utf8" });
const parsed = JSON.parse(fileContent);
solution = !solution && isSolution(parsed) ? parsed : solution;
analysisResults =
!analysisResults && Array.isArray(parsed) && parsed.every((item) => isAnalysis(item))
? parsed
: analysisResults;
}
return [analysisResults, solution];
};
Loading

0 comments on commit f06e9eb

Please sign in to comment.