From 06798a680f3d73b2a4472ef686154c71d3b2b82f Mon Sep 17 00:00:00 2001 From: Dayoung Lee Date: Tue, 17 Oct 2023 15:19:40 +0900 Subject: [PATCH] [OneExplorer] Targetted refresh on Change/Delete This commit refreshs only the required nodes on change and delete file. ONE-vscode-DCO-1.0-Signed-off-by: Dayoung Lee --- src/OneExplorer/ConfigObject.ts | 36 ++++++++++ src/OneExplorer/OneExplorer.ts | 121 ++++++++++++++++++++++++++------ src/OneExplorer/OneStorage.ts | 7 ++ 3 files changed, 144 insertions(+), 20 deletions(-) diff --git a/src/OneExplorer/ConfigObject.ts b/src/OneExplorer/ConfigObject.ts index 638f4a0e..a4c8a32d 100644 --- a/src/OneExplorer/ConfigObject.ts +++ b/src/OneExplorer/ConfigObject.ts @@ -121,6 +121,42 @@ export class ConfigObj { }; } + static diffBaseModels( + newCfgObj?: ConfigObj, + oldCfgObj?: ConfigObj + ): [addedBaseModels: string[], removedBaseModels: string[]] { + const newBaseModels = + newCfgObj?.getBaseModelsExists.map((artifact) => artifact.path) ?? []; + const oldBaseModels = + oldCfgObj?.getBaseModelsExists.map((artifact) => artifact.path) ?? []; + + const addedBaseModels = + newBaseModels.filter((path) => !oldBaseModels.includes(path)) ?? []; + + const removedBaseModels = + oldBaseModels.filter((path) => !newBaseModels.includes(path)) ?? []; + + return [addedBaseModels, removedBaseModels]; + } + + static diffProducts( + newCfgObj?: ConfigObj, + oldCfgObj?: ConfigObj + ): [addedProducts: string[], removedProducts: string[]] { + const newProducts = + newCfgObj?.getProductsExists.map((artifact) => artifact.path) ?? []; + const oldProducts = + oldCfgObj?.getProductsExists.map((artifact) => artifact.path) ?? []; + + const addedProducts = + newProducts.filter((path) => !oldProducts.includes(path)) ?? []; + + const removedProducts = + oldProducts.filter((path) => !newProducts.includes(path)) ?? []; + + return [addedProducts, removedProducts]; + } + public updateBaseModelField( oldpath: string, newpath: string diff --git a/src/OneExplorer/OneExplorer.ts b/src/OneExplorer/OneExplorer.ts index 8a39b0f6..e6b19a1c 100644 --- a/src/OneExplorer/OneExplorer.ts +++ b/src/OneExplorer/OneExplorer.ts @@ -23,6 +23,7 @@ import { CfgEditorPanel } from "../CfgEditor/CfgEditorPanel"; import { obtainWorkspaceRoots } from "../Utils/Helpers"; import { Logger } from "../Utils/Logger"; +import { ConfigObj } from "./ConfigObject"; import { ArtifactAttr } from "./ArtifactLocator"; import { OneStorage } from "./OneStorage"; @@ -157,6 +158,21 @@ export abstract class Node { // Return a NodeType as a string value return NodeType[this.type]; } + + /** + * Match possible node types from the given uri + */ + static matchType(uri: vscode.Uri): NodeType { + if (BaseModelNode.extList.some((ext) => uri.fsPath.endsWith(ext))) { + return NodeType.baseModel; + } else if (ConfigNode.extList.some((ext) => uri.fsPath.endsWith(ext))) { + return NodeType.config; + } else if (ProductNode.extList.some((ext) => uri.fsPath.endsWith(ext))) { + return NodeType.product; + } + + return NodeType.directory; + } } class NodeFactory { @@ -516,6 +532,16 @@ export class OneTreeDataProvider implements vscode.TreeDataProvider { readonly onDidChangeTreeData: vscode.Event = this._onDidChangeTreeData.event; + private _onDidChangeConfig: vscode.EventEmitter = + new vscode.EventEmitter(); + readonly onDidChangeConfig: vscode.Event = + this._onDidChangeConfig.event; + + private _onDidDeleteProduct: vscode.EventEmitter = + new vscode.EventEmitter(); + readonly onDidDeleteProduct: vscode.Event = + this._onDidDeleteProduct.event; + private fileWatcher = vscode.workspace.createFileSystemWatcher(`**/*`); private _tree: Node[] | undefined; @@ -543,30 +569,85 @@ export class OneTreeDataProvider implements vscode.TreeDataProvider { provider.refresh(); }), provider.fileWatcher.onDidChange((uri: vscode.Uri) => { - if ( - [ - ...BaseModelNode.extList, - ...ConfigNode.extList, - ...ProductNode.extList, - ].includes(path.parse(uri.path).ext) - ) { - Logger.info( - "OneExploer", - `Refresh explorer view on a file change in '${uri.path}'` - ); - // TODO Handle by each node types - provider.refresh(); + switch (Node.matchType(uri)) { + case NodeType.config: + provider._onDidChangeConfig.fire(uri); + break; + case NodeType.baseModel: + case NodeType.product: + default: + // Do nothing + break; } }), + provider.onDidChangeConfig((uri: vscode.Uri) => { + let nodesChanged: Node[] = []; + + const oldCfgObj = OneStorage.getCfgObj(uri.fsPath); + const newCfgObj = ConfigObj.createConfigObj(uri)!; + + const [adopters, droppers] = ConfigObj.diffBaseModels( + newCfgObj, + oldCfgObj + ); + + // Create new config node + adopters + .map((adopter) => OneStorage.getBaseModelNode(adopter)) + .forEach((adopterNode) => { + OneStorage.insert( + NodeFactory.create(NodeType.config, uri.fsPath, adopterNode) + ); + adopterNode.resetChildren(); + adopterNode.getChildren(); + nodesChanged.push(adopterNode); + }); + + // Remove old config node + OneStorage.getNodes(uri.fsPath).forEach((node) => { + if (droppers.some((dropper) => dropper === node?.parent?.path)) { + OneStorage.delete(node, true); + } + }); + + droppers + .map((dropper) => OneStorage.getBaseModelNode(dropper)) + .forEach((dropperNode) => { + dropperNode.resetChildren(); + dropperNode.getChildren(); + nodesChanged.push(dropperNode); + }); + + nodesChanged.forEach((node) => { + provider._onDidChangeTreeData.fire(node); + }); + }), provider.fileWatcher.onDidDelete((uri: vscode.Uri) => { - const nodes = OneStorage.getNodes(uri.fsPath); - if (nodes.length === 0) { - return; + switch (Node.matchType(uri)) { + case NodeType.product: + provider._onDidDeleteProduct.fire(uri); + break; + case NodeType.directory: + case NodeType.config: + case NodeType.baseModel: + OneStorage.getNodes(uri.fsPath).forEach((node) => { + OneStorage.delete(node, true); + provider._onDidChangeTreeData.fire(node.parent); + }); + break; + default: + // Do nothing + break; } - - nodes.forEach((node) => { - OneStorage.delete(node, true); - provider.refresh(node.parent); + }), + provider.onDidDeleteProduct((uri: vscode.Uri) => { + OneStorage.getNodes(uri.fsPath).forEach((node) => { + OneStorage.delete(node); + + const dropper = node.parent; + dropper!.resetChildren(); + dropper!.getChildren(); + provider._onDidChangeTreeData.fire(dropper); }); }), vscode.workspace.onDidChangeWorkspaceFolders(() => { diff --git a/src/OneExplorer/OneStorage.ts b/src/OneExplorer/OneStorage.ts index 3572cb3d..9be8ccb8 100644 --- a/src/OneExplorer/OneStorage.ts +++ b/src/OneExplorer/OneStorage.ts @@ -280,6 +280,13 @@ export class OneStorage { return OneStorage.get()._nodeMap.get(fsPath); } + public static getBaseModelNode(fsPath: string): Node { + const nodes = OneStorage.get()._nodeMap.get(fsPath); + assert.ok(nodes.length === 1); + assert.ok(nodes[0].type === NodeType.baseModel); + return nodes[0]; + } + public static insert(node: Node) { const inst = OneStorage.get();