finish reconstruct manage module
This commit is contained in:
parent
6ef036fa78
commit
8b127d5302
@ -1,6 +1,5 @@
|
||||
{
|
||||
"content": {
|
||||
"error": [],
|
||||
"modules": [
|
||||
{
|
||||
"instances": [
|
||||
@ -180,7 +179,6 @@
|
||||
"value": "out"
|
||||
}
|
||||
],
|
||||
"error": [],
|
||||
"includes": [
|
||||
{
|
||||
"path": "child_1.v",
|
19
package.json
19
package.json
@ -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"
|
||||
},
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
@ -417,7 +419,31 @@ 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,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -11,7 +11,7 @@ class PathSet {
|
||||
if (path instanceof Array) {
|
||||
path.forEach(p => this.checkAdd(p));
|
||||
} else if (fs.existsSync(path)) {
|
||||
this.files.add(path);
|
||||
this.files.add(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
};
|
@ -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);
|
||||
const relPath = selectedPath.replace(this.commonQuickPickItem.path + '/', '');
|
||||
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
|
||||
};
|
@ -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
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user