finish reconstruct manage module

This commit is contained in:
锦恢 2023-04-18 20:03:37 +08:00
parent 6ef036fa78
commit 8b127d5302
11 changed files with 294 additions and 45 deletions

View File

@ -1,6 +1,5 @@
{
"content": {
"error": [],
"modules": [
{
"instances": [
@ -180,7 +179,6 @@
"value": "out"
}
],
"error": [],
"includes": [
{
"path": "child_1.v",

View File

@ -24,12 +24,18 @@
"configuration": {
"title": "Digital-IDE",
"properties": {
"lib.custom.path": {
"prj.lib.custom.path": {
"scope": "window",
"type": "string",
"default": "",
"description": "path of the dictionary of \"custom\" in library"
},
"prj.file.structure.notice": {
"scope": "window",
"type": "boolean",
"default": true,
"description": "notice when change file structure"
},
"function.doc.webview.backgroundImage": {
"type": "string",
"default": "",
@ -168,6 +174,15 @@
"dark": "images/svg/dark/debug.svg"
}
},
{
"command": "digital-ide.pickLibrary",
"title": "import library",
"icon": {
"light": "images/svg/light/library.svg",
"dark": "images/svg/dark/library.svg"
},
"category": "Digital-IDE"
},
{
"command": "digital-ide.treeView.arch.expand",
"category": "tool",
@ -280,7 +295,7 @@
"when": "view == digital-ide-treeView-arch"
},
{
"command": "TOOL.libPick",
"command": "digital-ide.pickLibrary",
"group": "navigation",
"when": "view == digital-ide-treeView-arch"
},

View File

@ -14,8 +14,10 @@ async function launch(context: vscode.ExtensionContext) {
console.time('launch');
prjManage.initOpeParam(context);
console.log(opeParam.prjInfo);
const hdlFiles = prjManage.getPrjHardwareFiles();
await hdlParam.initialize(hdlFiles);
console.timeLog('launch');
await registerCommand(context);

View File

@ -1,6 +1,5 @@
import * as assert from 'assert';
import * as fs from 'fs';
import { hdlFile } from '../hdlFs';
import { Arch, PrjInfo, RawPrjInfo, resolve, toSlash } from './prjInfo';
@ -24,6 +23,16 @@ interface FirstTopModuleDesc {
path: AbsPath
};
function readJSON(path: AbsPath): object {
try {
const context = fs.readFileSync(path, 'utf-8');
return JSON.parse(context);
} catch (err) {
console.log('fail to read JSON: ', err);
}
return {};
}
class OpeParam {
private _os: string = OpeParamDefaults.os;
@ -146,18 +155,32 @@ class OpeParam {
/**
* get User's property.json
*/
public getUserPrjInfo() {
public getUserPrjInfo(): PrjInfo {
const propertyJsonPath = this.propertyJsonPath;
const userPrjInfo = new PrjInfo();
if (fs.existsSync(propertyJsonPath)) {
const rawPrjInfo = hdlFile.readJSON(propertyJsonPath);
const rawPrjInfo = readJSON(propertyJsonPath);
userPrjInfo.merge(rawPrjInfo);
} else {
// use default config instead
const rawPrjInfo = hdlFile.readJSON(this.propertyInitPath);
const rawPrjInfo = readJSON(this.propertyInitPath);
userPrjInfo.merge(rawPrjInfo);
}
return userPrjInfo;
}
public getRawUserPrjInfo(): RawPrjInfo {
const propertyJsonPath = this.propertyJsonPath;
if (fs.existsSync(propertyJsonPath)) {
const rawPrjInfo = readJSON(propertyJsonPath);
return rawPrjInfo;
} else {
// use default config instead
const rawPrjInfo = readJSON(this.propertyInitPath);
return rawPrjInfo;
}
}
};
const opeParam: OpeParam = new OpeParam();

View File

@ -8,6 +8,8 @@ import { ToolChainType, LibraryState, XilinxIP,
validToolChainType, validXilinxIP, validLibraryState } from './enum';
import { PrjInfoSchema } from './propertySchema';
import assert = require('assert');
import * as hdlPath from '../hdlFs/path';
type AbsPath = string;
type RelPath = string;
@ -409,7 +411,7 @@ class PrjInfo implements PrjInfoMeta {
}
}
if (library.hardware) {
// TODO : finish this when you can require root of common and custom
// TODO : finish this when you can acquire root of common and custom
const commonPath = this.libCommonPath;
const customPath = this.libCustomPath;
this.updatePathWisely(this.library.hardware, 'common', library.hardware.common, commonPath);
@ -418,6 +420,30 @@ class PrjInfo implements PrjInfoMeta {
}
}
public appendLibraryCommonPath(relPath: RelPath) {
this._library.hardware.common.push(relPath);
}
public appendLibraryCustomPath(relPath: RelPath) {
this._library.hardware.custom.push(relPath);
}
public getLibraryCommonPaths(absolute: boolean = true): Path[] {
if (absolute) {
const commonFolder = hdlPath.join(this.libCommonPath, 'Empty');
return this._library.hardware.common.map<Path>(relPath => hdlPath.rel2abs(commonFolder, relPath));
}
return this._library.hardware.common;
}
public getLibraryCustomPaths(absolute: boolean = true): Path[] {
if (absolute) {
const configFolder = hdlPath.join(this.libCustomPath, 'Empty');
return this._library.hardware.custom.map<Path>(relPath => hdlPath.rel2abs(configFolder, relPath));
}
return this._library.hardware.custom;
}
/**
* merge the input uncomplete prjInfo into this
* cover the value that exist in rawPrjInfo recursively
@ -450,7 +476,20 @@ class PrjInfo implements PrjInfoMeta {
}
public get libCustomPath(): AbsPath {
return vscode.workspace.getConfiguration().get('lib.custom.path', this._workspacePath);
return vscode.workspace.getConfiguration().get('prj.lib.custom.path', this._workspacePath);
}
public json(): RawPrjInfo {
return {
toolChain: this._toolChain,
prjName: this._prjName,
IP_REPO: this._IP_REPO,
soc: this._soc,
enableShowLog: this._enableShowLog,
device: this._device,
arch: this._arch,
library: this._library,
};
}
};

View File

@ -74,7 +74,7 @@ function isHDLFile(path: AbsPath): boolean {
}
function getHDLFiles(path: AbsPath | AbsPath[] | Set<AbsPath>, ignores?: AbsPath[]) {
function getHDLFiles(path: AbsPath | AbsPath[] | Set<AbsPath>, ignores?: AbsPath[]): AbsPath[] {
return pickFileRecursive(path, ignores,
filePath => isHDLFile(filePath));
}
@ -98,7 +98,7 @@ function pickFileRecursive(path: AbsPath | AbsPath[] | Set<AbsPath>, ignores?: A
for (const file of fs.readdirSync(path)) {
const filePath = hdlPath.join(path, file);
if (isDir(filePath)) {
const subHdlFiles = getHDLFiles(filePath, ignores);
const subHdlFiles = pickFileRecursive(filePath, ignores);
if (subHdlFiles.length > 0) {
hdlFiles.push(...subHdlFiles);
}

View File

@ -1,11 +1,17 @@
import * as vscode from 'vscode';
import { prjManage } from './prj';
import { pickLibrary } from './libPick';
function registerManagerCommands(context: vscode.ExtensionContext) {
vscode.commands.registerCommand('digital-ide.property-json.generate', prjManage.generatePropertyJson);
vscode.commands.registerCommand('digital-ide.property-json.overwrite', prjManage.overwritePropertyJson);
// libpick
vscode.commands.registerCommand('digital-ide.pickLibrary', pickLibrary);
}
export {

View File

@ -1,11 +1,50 @@
import * as vscode from 'vscode';
import * as fs from 'fs';
import { AbsPath, opeParam } from '../global';
import { hdlFile, hdlPath } from '../hdlFs';
import { hdlDir, hdlFile, hdlPath } from '../hdlFs';
import { Library } from '../global/prjInfo';
import { Path } from '../../resources/hdlParser';
interface LibFileChange {
add: AbsPath[],
del: AbsPath[],
}
interface LibStatus {
type?: string,
list: AbsPath[]
}
/**
* a与b的差集
* @param a
* @param b
* @returns
*/
function diffElement<T>(a: T[], b: T[]): T[] {
const bSet = new Set<T>(b);
return a.filter(el => !bSet.has(el));
}
function removeDuplicates<T>(a: T[]): T[] {
const aSet = new Set(a);
return [...aSet];
}
class LibManage {
constructor() {
curr: LibStatus;
next: LibStatus;
constructor() {
this.curr = { list : [] };
this.next = { list : [] };
}
public get customerPath(): AbsPath {
return opeParam.prjInfo.libCustomPath;
}
public get srcPath(): AbsPath {
@ -32,8 +71,118 @@ class LibManage {
return opeParam.prjInfo.libCustomPath;
}
public processLibFiles() {
public processLibFiles(library: Library): LibFileChange {
// 在不设置state属性的时候默认为remote
this.next.list = this.getLibFiles(library);
if (!hdlFile.isHasAttr(library, 'state')) {
this.next.type = 'remote';
} else {
if (library.state !== 'remote' && library.state !== 'local') {
return {
'add' : [],
'del' : [],
};
}
this.next.type = library.state;
}
// 处于初始状态时的情况
if (!this.curr.type) {
if (!hdlFile.isDir(this.localLibPath)) {
this.curr.type = 'local';
} else {
this.curr.type = 'remote';
}
}
const state = `${this.curr.type}-${this.next.type}`;
let add: AbsPath[] = [];
let del: AbsPath[] = [];
switch (state) {
case 'remote-remote':
add = diffElement(this.next.list, this.curr.list);
del = diffElement(this.curr.list, this.next.list);
break;
case 'remote-local':
// 删除的内容全是remote的将curr的交出去即可
del = this.curr.list;
// 将新增的全部复制到本地交给monitor进行处理
this.remote2Local(this.next.list, (src, dist) => {
hdlFile.copyFile(src, dist);
});
break;
case 'local-remote':
// 本地的lib全部删除交给monitor进行处理
const fn = async () => {
if (fs.existsSync(this.localLibPath)) {
const needNotice = vscode.workspace.getConfiguration('prj.file.structure.notice');
if (needNotice) {
let select = await vscode.window.showWarningMessage("local lib will be removed.", 'Yes', 'Cancel');
if (select === "Yes") {
hdlDir.rmdir(this.localLibPath);
}
} else {
hdlDir.rmdir(this.localLibPath);
}
}
};
fn();
// 增加的内容全是remote的将next的交出去即可
add = this.next.list;
break;
case 'local-local':
// 只管理library里面的内容如果自己再localPath里加减代码则不去管理
add = diffElement(this.next.list, this.curr.list);
del = diffElement(this.curr.list, this.next.list);
this.remote2Local(add, (src, dist) => {
hdlFile.copyFile(src, dist);
});
this.remote2Local(del, (src, dist) => {
hdlFile.removeFile(dist);
});
add = []; del = [];
break;
default: break;
}
return { add, del };
}
getLibFiles(library: Library) {
const libFileList: AbsPath[] = [];
const prjInfo = opeParam.prjInfo;
// collect common libs
prjInfo.getLibraryCommonPaths().forEach(absPath => libFileList.push(...hdlFile.getHDLFiles(absPath)));
// collect custom libs
prjInfo.getLibraryCustomPaths().forEach(absPath => libFileList.push(...hdlFile.getHDLFiles(absPath)));
// Remove duplicate HDL files
return removeDuplicates(libFileList);
}
remote2Local(remotes: Path[], callback: (src: AbsPath, dist: AbsPath) => void) {
for (const src of remotes) {
let dist;
if (src.includes(this.customerPath)) {
dist = src.replace(this.customerPath, this.localLibPath);
} else {
dist = src.replace(this.sourceLibPath, this.localLibPath);
}
callback(src, dist);
}
}
};
const libManage = new LibManage();
export {
libManage,
LibManage
};

View File

@ -3,8 +3,9 @@ import * as fspath from 'path';
import * as fs from 'fs';
import { AbsPath, opeParam } from '../global';
import { PrjInfo, RawPrjInfo } from '../global/prjInfo';
import { HdlLangID } from '../global/enum';
import { hdlDir, hdlFile, hdlPath } from '../hdlFs';
import { hdlFile, hdlPath } from '../hdlFs';
import { getIconConfig } from '../hdlFs/icons';
type MissPathType = { path?: string };
@ -144,30 +145,35 @@ class LibPick {
const selectedPath = event.item.path;
if (selectedPath && hdlPath.exist(selectedPath)) {
const ppyPath = hdlPath.join(opeParam.workspacePath, '.vscode', 'property.json');
// 抽象这块
let prjInfo = null;
// 如果存在,则读取用户的配置文件,否则使用默认的
if (!hdlPath.exist(ppyPath)) {
prjInfo = hdlFile.readJSON(opeParam.propertyInitPath);
} else {
prjInfo = hdlFile.readJSON(ppyPath);
}
const userPrjInfo = opeParam.getUserPrjInfo();
if (selectedPath.includes(this.commonQuickPickItem.path!)) {
// this is a module import from common, use relative path
const relPath = selectedPath.replace(this.commonQuickPickItem.path + '/', '');
appendLibraryCommonPath(relPath, prjInfo);
userPrjInfo.appendLibraryCommonPath(relPath);
} else {
// this is a module import from custom, use absolute path
const relPath = selectedPath.replace(this.customQuickPickItem.path + '/', '');
appendLibraryCustomPath(relPath, prjInfo);
userPrjInfo.appendLibraryCustomPath(relPath);
}
hdlFile.writeJSON(ppyPath, prjInfo);
// acquire raw and replace it
const rawUserPrjInfo = opeParam.getRawUserPrjInfo();
rawUserPrjInfo.library = userPrjInfo.library;
hdlFile.writeJSON(opeParam.propertyJsonPath, rawUserPrjInfo);
}
});
pickWidget.show();
}
}
function pickLibrary() {
const picker = new LibPick();
picker.pickItems();
}
export {
LibPick,
LibPickItem,
pickLibrary
};

View File

@ -6,6 +6,7 @@ import { AbsPath, opeParam } from '../global';
import { PathSet } from '../global/util';
import { RawPrjInfo } from '../global/prjInfo';
import { hdlFile, hdlPath } from '../hdlFs';
import { libManage } from './lib';
class PrjManage {
// generate property template and write it to .vscode/property.json
@ -66,21 +67,30 @@ class PrjManage {
}
}
public getIgnoreFiles(): AbsPath[] {
return [];
}
public getPrjHardwareFiles(): AbsPath[] {
const searchPathSet = new PathSet();
const hardwareInfo = opeParam.prjInfo.arch.hardware;
const prjInfo = opeParam.prjInfo;
const hardwareInfo = prjInfo.arch.hardware;
// handle library first
libManage.processLibFiles(prjInfo.library);
// add possible folder to search
searchPathSet.checkAdd(hardwareInfo.src);
searchPathSet.checkAdd(hardwareInfo.sim);
searchPathSet.checkAdd(prjInfo.getLibraryCommonPaths());
searchPathSet.checkAdd(prjInfo.getLibraryCustomPaths());
// TODO : make something like .gitignore
const ignores = this.getIgnoreFiles();
// search src
searchPathSet.checkAdd(hardwareInfo.src);
// search sim
searchPathSet.checkAdd(hardwareInfo.sim);
// do search
const searchPaths = searchPathSet.files;
return hdlFile.getHDLFiles(searchPaths, []);
return hdlFile.getHDLFiles(searchPaths, ignores);
}
public initialise() {
@ -91,5 +101,6 @@ class PrjManage {
const prjManage = new PrjManage();
export {
prjManage
prjManage,
PrjManage
};