Skip to content

Commit

Permalink
[OneExplorer] Parse .cfg and display on tree (#553)
Browse files Browse the repository at this point in the history
* [OneExplorer] Parse .cfg and display on tree

This commit parses config and link all specified model nodes.

ONE-vscode-DCO-1.0-Signed-off-by: Dayoung Lee <[email protected]>

* Update src/OneExplorer.ts

Co-authored-by: Jiyoung Giuliana Yun <[email protected]>

* Fix to include output_path

ONE-vscode-DCO-1.0-Signed-off-by: Dayoung Lee <[email protected]>

* Rename grepTarget to grepAll

ONE-vscode-DCO-1.0-Signed-off-by: Dayoung Lee <[email protected]>

* style changes by feedback

ONE-vscode-DCO-1.0-Signed-off-by: Dayoung Lee <[email protected]>

* Formad and add comments

ONE-vscode-DCO-1.0-Signed-off-by: Dayoung Lee <[email protected]>

Co-authored-by: Dayoung Lee <[email protected]>
Co-authored-by: Jiyoung Giuliana Yun <[email protected]>
  • Loading branch information
3 people authored May 4, 2022
1 parent 8daaabc commit f388f22
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 18 deletions.
13 changes: 13 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@
"devDependencies": {
"@types/chai": "^4.3.0",
"@types/glob": "^7.1.3",
"@types/ini": "^1.3.31",
"@types/mocha": "^9.1.0",
"@types/node": "^12.11.7",
"@types/vscode": "^1.46.0",
Expand Down
154 changes: 136 additions & 18 deletions src/OneExplorer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/

import * as fs from 'fs';
import * as ini from 'ini';
import * as path from 'path';
import * as vscode from 'vscode';
import {CfgEditorPanel} from './CfgEditor/CfgEditorPanel';
Expand All @@ -23,12 +24,32 @@ import {ToolArgs} from './Project/ToolArgs';
import {ToolRunner} from './Project/ToolRunner';
import {Logger} from './Utils/Logger';

const which = require('which');
/**
* Read an ini file
* @param filePath
* @returns `object` if file read is successful, or `null` if file open has failed
*
*/
function readIni(filePath: string): object|null {
let configRaw: string;
try {
configRaw = fs.readFileSync(filePath, 'utf-8');
} catch (e) {
console.error(e);
return null;
}

// TODO check if toString() is required
return ini.parse(configRaw.toString());
}


// TODO find better name for `model`
enum NodeType {
directory,
model,
config
model, // models generated by config
config,
baseModel, // base model given by input_path of one-import-${ext}
}

function nodeTypeToStr(t: NodeType): string {
Expand Down Expand Up @@ -78,6 +99,8 @@ export class OneNode extends vscode.TreeItem {
this.iconPath = new vscode.ThemeIcon('gear');
} else if (node.type === NodeType.directory) {
this.iconPath = vscode.ThemeIcon.Folder;
} else if (node.type === NodeType.baseModel) {
this.iconPath = vscode.ThemeIcon.File;
} else if (node.type === NodeType.model) {
this.iconPath = vscode.ThemeIcon.File;
}
Expand Down Expand Up @@ -127,9 +150,11 @@ export class OneTreeDataProvider implements vscode.TreeDataProvider<OneNode> {
if (node.type === NodeType.directory) {
return new OneNode(node.name, vscode.TreeItemCollapsibleState.Expanded, node);
} else if (node.type === NodeType.model) {
return new OneNode(node.name, vscode.TreeItemCollapsibleState.None, node);
} else if (node.type === NodeType.baseModel) {
return new OneNode(node.name, vscode.TreeItemCollapsibleState.Collapsed, node);
} else { // (node.type == NodeType.config)
let oneNode = new OneNode(node.name, vscode.TreeItemCollapsibleState.None, node);
let oneNode = new OneNode(node.name, vscode.TreeItemCollapsibleState.Expanded, node);
oneNode.command = {
command: 'onevscode.open-cfg',
title: 'Open File',
Expand Down Expand Up @@ -170,7 +195,7 @@ export class OneTreeDataProvider implements vscode.TreeDataProvider<OneNode> {
} else if (
fstat.isFile() &&
(fname.endsWith('.pb') || fname.endsWith('.tflite') || fname.endsWith('.onnx'))) {
const childNode = new Node(NodeType.model, [], vscode.Uri.file(fpath));
const childNode = new Node(NodeType.baseModel, [], vscode.Uri.file(fpath));

this.searchPairConfig(childNode);

Expand All @@ -179,29 +204,122 @@ export class OneTreeDataProvider implements vscode.TreeDataProvider<OneNode> {
}
}

// TODO(dayo) extract file-relative functions as another module
private parseInputPath = (configPath: string, modelPath: string): string|undefined => {
const config = readIni(configPath);
const ext = path.extname(modelPath).slice(1);

if (ext === undefined || config === null) {
return undefined;
}

return config[`one-import-${ext}` as keyof typeof config] ?.['input_path'];
};

// TODO(dayo) extract file-relative functions as another module
private grepTargetInCommand = (str: string): string[] => {
return str.split(' ').filter(e => path.extname(e) === '.tvn' || path.extname(e) === '.circle');
};

// TODO(dayo) extract file-relative functions as another module
private grepAll = (str: string): string[] => {
return [str];
};

// TODO(dayo) extract file-relative functions as another module
private parseIntermediates = (configPath: string): string[] => {
const config = readIni(configPath);

if (config === null) {
return [];
}

const targetLocator = [
{section: 'one-optimize', key: 'input_path', grepper: this.grepAll},
{section: 'one-optimize', key: 'output_path', grepper: this.grepAll},
{section: 'one-quantize', key: 'input_path', grepper: this.grepAll},
{section: 'one-quantize', key: 'output_path', grepper: this.grepAll},
{section: 'one-codegen', key: 'command', grepper: this.grepTargetInCommand},
];

let intermediates: string[] = [];
for (let loc of targetLocator) {
let confSection = config[loc.section as keyof typeof config];
let confKey = confSection ?.[loc.key as keyof typeof config];
if (confKey) {
const targets = loc.grepper(confKey);
for (let target of targets) {
if (intermediates.includes(target) === false) {
intermediates.push(target);
}
}
}
}

return intermediates;
};

/**
* compare paths by normalization
* NOTE that '~'(home) is not supported
* TODO(dayo) support '~'
* TODO(dayo) extract file-relative functions as another module
*/
private comparePath(path0: string, path1: string): boolean {
const absPath0 = path.resolve(path.normalize(path0));
const absPath1 = path.resolve(path.normalize(path1));
return absPath0 === absPath1;
}

/**
* Search .cfg files in the same directory of the node
*
* NOTE It assumes 1-1 relation for model and config
*
* TODO(dayo) Support N-N relation
* TODO(dayo) Search by parsing config file's model entry (Currently model name and cfg name must
* match)
* Search .cfg files in the same directory
*/
private searchPairConfig(node: Node) {
console.assert(node.type === NodeType.baseModel);

const files = fs.readdirSync(node.parent);

const extSlicer = (fileName: string) => {
return fileName.slice(0, fileName.lastIndexOf('.'));
};
for (const fname of files) {
const fpath = path.join(node.parent, fname);
const fstat = fs.statSync(fpath);

if (fstat.isFile() && fname.endsWith('.cfg')) {
const parsedInputPath = this.parseInputPath(fpath, node.path);
if (parsedInputPath) {
const fullInputPath = path.join(node.parent, parsedInputPath);
if (this.comparePath(fullInputPath, node.path)) {
const pairNode = new Node(NodeType.config, [], vscode.Uri.file(fpath));
this.searchChildModels(pairNode);
node.childNodes.push(pairNode);
}
}
}
}
}

/**
* Search specified intermediate model files in the same directory
*/
private searchChildModels(node: Node) {
console.assert(node.type === NodeType.config);
console.log('searchChildModels');
const files = fs.readdirSync(node.parent);

for (const fname of files) {
const fpath = path.join(node.parent, fname);
const fstat = fs.statSync(fpath);

if (fstat.isFile() && fname.endsWith('.cfg') && (extSlicer(fname) === extSlicer(node.name))) {
const pairNode = new Node(NodeType.config, [], vscode.Uri.file(fpath));
node.childNodes.push(pairNode);
// TODO(dayo) Get .tvn file extension from backend
if (fstat.isFile() && (fname.endsWith('.circle') || fname.endsWith('.tvn'))) {
const intermediates = this.parseIntermediates(node.path);
for (let intermediate of intermediates) {
const parsedPath = path.join(node.parent, intermediate);
if (this.comparePath(parsedPath, fpath)) {
const child = new Node(NodeType.model, [], vscode.Uri.file(fpath));
node.childNodes.push(child);
break;
}
}
}
}
}
Expand Down

0 comments on commit f388f22

Please sign in to comment.