Skip to content

Commit

Permalink
Merge pull request #19 from EDAcation/add-yosys-stat-viewer
Browse files Browse the repository at this point in the history
Add module statistics viewer
  • Loading branch information
DanielleHuisman authored Nov 26, 2023
2 parents 054b8a9 + 5b62488 commit 9d5b1bc
Show file tree
Hide file tree
Showing 50 changed files with 1,938 additions and 319 deletions.
8 changes: 6 additions & 2 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
{
"root": true,
"extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
"extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended-type-checked"],
"parser": "@typescript-eslint/parser",
"plugins": ["@typescript-eslint"],
"parserOptions": {
"project": true
},
"rules": {
"@typescript-eslint/consistent-type-imports": [
"warn",
Expand All @@ -11,6 +14,7 @@
"fixStyle": "inline-type-imports"
}
],
"@typescript-eslint/no-unused-vars": ["warn", {"argsIgnorePattern": "^_"}]
"@typescript-eslint/no-unused-vars": ["warn", {"argsIgnorePattern": "^_"}],
"@typescript-eslint/require-await": "off"
}
}
3 changes: 0 additions & 3 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
dist/

# TODO: un-ignore this file once we find a solution to the jquery import reordering situation
views/digitaljs/src/main.ts
8 changes: 4 additions & 4 deletions package-lock.json

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

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@
"compile-web": "npm run build-views && tsc && webpack",
"package-web": "npm run build-views && tsc && webpack --mode production --devtool hidden-source-map",
"vscode:prepublish": "npm run package-web",
"lint": "eslint ./src ./workers/src --ext ts",
"lint": "eslint ./src --ext ts",
"test": "vscode-test-web --browserType=chromium --extensionDevelopmentPath=. --extensionTestsPath=dist/extension/test/suite/index.js",
"pretest": "npm run compile-web"
},
Expand All @@ -301,7 +301,7 @@
"process": "^0.11.10",
"ts-loader": "^9.5.1",
"ts-node": "^10.9.1",
"typescript": "^5.3.2",
"typescript": "5.2.2",
"webpack": "^5.89.0",
"webpack-cli": "^5.1.4"
},
Expand Down
56 changes: 29 additions & 27 deletions scripts/run-each-view.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,40 @@
import {spawnSync} from 'child_process';
import {readdir} from 'fs/promises';
import path from 'path';
import {fileURLToPath} from 'url';

const command = process.argv.slice(2);
const commandName = ['npm'].concat(command).join(' ');
// eslint-disable-next-line @typescript-eslint/no-floating-promises
(async () => {
const command = process.argv.slice(2);
const commandName = ['npm'].concat(command).join(' ');

const currentDirectory = path.dirname(fileURLToPath(import.meta.url));
const viewsDirectory = path.resolve(currentDirectory, '..', 'views');
const failedDirectories: string[] = [];
const currentDirectory = path.dirname(__filename);
const viewsDirectory = path.resolve(currentDirectory, '..', 'views');
const failedDirectories: string[] = [];

console.log(`Executing command "${commandName}" for all views.`);
console.log();
console.log(`Executing command "${commandName}" for all views.`);
console.log();

for (const directory of await readdir(viewsDirectory)) {
const directoryName = `./views/${directory}`;
for (const directory of await readdir(viewsDirectory)) {
const directoryName = `./views/${directory}`;

console.log(`Executing command "${commandName}" in views "${directoryName}"`);
console.log(`Executing command "${commandName}" in views "${directoryName}"`);

const {status} = spawnSync('npm', command, {
cwd: path.resolve(viewsDirectory, directory),
stdio: ['inherit', 'inherit', 'inherit']
});
console.log();
const {status} = spawnSync('npm', command, {
cwd: path.resolve(viewsDirectory, directory),
stdio: ['inherit', 'inherit', 'inherit']
});
console.log();

if (status !== 0) {
failedDirectories.push(directoryName);
}
}

if (status !== 0) {
failedDirectories.push(directoryName);
if (failedDirectories.length === 0) {
console.log(`Executing command "${commandName}" was successful for all views.`);
} else {
console.log(`Executing command "${commandName}" failed for these views:`);
console.log(failedDirectories.map((directory) => ` - ${directory}`).join('\n'));
console.log('See the logs above for more details.');
}
}

if (failedDirectories.length === 0) {
console.log(`Executing command "${commandName}" was successful for all views.`);
} else {
console.log(`Executing command "${commandName}" failed for these views:`);
console.log(failedDirectories.map((directory) => ` - ${directory}`).join('\n'));
console.log('See the logs above for more details.');
}
})();
4 changes: 4 additions & 0 deletions src/common/universal-worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ type WorkerThreadsModule = typeof import('worker_threads');
type WorkerThreadsWorker = import('worker_threads').Worker;
/* eslint-enable @typescript-eslint/consistent-type-imports */

/* eslint-disable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call */
const module: WorkerThreadsModule | undefined =
typeof Worker === 'undefined' ? __non_webpack_require__('worker_threads') : undefined;
/* eslint-enable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call */

type InternalNodeWorker = {
type: 'node';
Expand Down Expand Up @@ -40,6 +42,7 @@ export const onEvent = <E extends keyof EventCallbacks>(event: E, callback: Even
if (module) {
module.parentPort?.on(event, callback);
} else {
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
addEventListener(event, (event) => callback(extractData(event)));
}
};
Expand Down Expand Up @@ -77,6 +80,7 @@ export class UniversalWorker {

public onEvent<E extends keyof EventCallbacks>(event: E, callback: EventCallbacks[E]): void {
if (this.worker.type === 'web') {
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
this.worker.worker.addEventListener(event, (event) => callback(extractData(event)));
} else {
this.worker.worker.on(event, callback);
Expand Down
8 changes: 4 additions & 4 deletions src/extension/commands/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export class OpenProjectConfigurationCommand extends CurrentProjectCommand {

async executeForCurrentProject(project: Project) {
// Open project file
vscode.commands.executeCommand('vscode.openWith', project.getUri(), ProjectEditor.getViewType());
await vscode.commands.executeCommand('vscode.openWith', project.getUri(), ProjectEditor.getViewType());
}
}

Expand All @@ -31,14 +31,14 @@ abstract class RunTaskCommand extends CurrentProjectCommand {
return false;
}

const uri = vscode.Uri.joinPath(task.scope.uri, task.definition.project);
const uri = vscode.Uri.joinPath(task.scope.uri, task.definition.project as string);
return uri.toString() === project.getUri().toString();
});

if (task) {
vscode.tasks.executeTask(task);
await vscode.tasks.executeTask(task);
} else {
vscode.window.showErrorMessage('No task could be found for the current EDA project.');
await vscode.window.showErrorMessage('No task could be found for the current EDA project.');
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/extension/commands/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export abstract class CurrentProjectCommand extends BaseCommand {
async execute(...args: unknown[]) {
const project = this.projects.getCurrent();
if (!project) {
vscode.window.showWarningMessage('No EDA project selected.');
await vscode.window.showWarningMessage('No EDA project selected.');
return;
}

Expand Down
28 changes: 17 additions & 11 deletions src/extension/commands/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,13 @@ export class NewProjectCommand extends BaseCommand {
// Check if the project is within the workspace folder
const [workspaceRelativePath] = getWorkspaceRelativePath(projectWorkspace, projectUri);
if (!workspaceRelativePath) {
vscode.window.showErrorMessage('Selected project location must be within the selected workspace folder.', {
detail: `File "${projectUri.path}" is not in folder "${projectWorkspace.path}".`,
modal: true
});
await vscode.window.showErrorMessage(
'Selected project location must be within the selected workspace folder.',
{
detail: `File "${projectUri.path}" is not in folder "${projectWorkspace.path}".`,
modal: true
}
);
return;
}

Expand All @@ -126,7 +129,7 @@ export class NewProjectCommand extends BaseCommand {
await this.projects.add(projectUri, true, true);

// Open project file
vscode.commands.executeCommand('vscode.openWith', projectUri, ProjectEditor.getViewType());
await vscode.commands.executeCommand('vscode.openWith', projectUri, ProjectEditor.getViewType());
}
}

Expand Down Expand Up @@ -187,18 +190,21 @@ export class OpenProjectCommand extends BaseCommand {
// Check if the project is within the workspace folder
const [workspaceRelativePath] = getWorkspaceRelativePath(projectWorkspace, projectUri);
if (!workspaceRelativePath) {
vscode.window.showErrorMessage('Selected project location must be within the selected workspace folder.', {
detail: `File "${projectUri.path}" is not in folder "${projectWorkspace.path}".`,
modal: true
});
await vscode.window.showErrorMessage(
'Selected project location must be within the selected workspace folder.',
{
detail: `File "${projectUri.path}" is not in folder "${projectWorkspace.path}".`,
modal: true
}
);
return;
}

// Add project
await this.projects.add(projectUri, true, false);

// Open project file
vscode.commands.executeCommand('vscode.openWith', projectUri, ProjectEditor.getViewType());
await vscode.commands.executeCommand('vscode.openWith', projectUri, ProjectEditor.getViewType());
}
}

Expand All @@ -218,6 +224,6 @@ export class SelectProject extends BaseCommand {
}

async execute(project: Project) {
await this.projects.setCurrent(project);
this.projects.setCurrent(project);
}
}
60 changes: 46 additions & 14 deletions src/extension/editors/base.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as vscode from 'vscode';

import type {Projects} from '../projects/index.js';
import {type ViewMessage} from '../types.js';
import type {GlobalStoreMessage, ViewMessage} from '../types.js';
import {BaseWebview} from '../webview.js';

export interface EditorWebviewArgs {
Expand All @@ -26,57 +26,89 @@ export abstract class BaseEditor extends BaseWebview<EditorWebviewArgs> implemen
_token: vscode.CancellationToken
): void | Thenable<void> {
const disposables: vscode.Disposable[] = [];
const webview = webviewPanel.webview;

// Render webview
webviewPanel.webview.options = {
webview.options = {
enableScripts: true
};
webviewPanel.webview.html = this.getHtmlForWebview(webviewPanel.webview, {document});
webview.html = this.getHtmlForWebview(webview, {document});

// Add message listener
webviewPanel.webview.onDidReceiveMessage(this.onDidReceiveMessage.bind(this, document, webviewPanel.webview));
webview.onDidReceiveMessage(this.onDidReceiveMessage.bind(this, document, webview));

// Add text document listener
disposables.push(
vscode.workspace.onDidChangeTextDocument((event) => {
if (event.document.uri.toString() === document.uri.toString()) {
this.update(document, webviewPanel.webview, true);
this.update(document, webview, true);
}
})
);
disposables.push(
vscode.workspace.onDidSaveTextDocument((event) => {
if (event.uri.toString() === document.uri.toString()) {
this.onSave(document, webviewPanel.webview);
this.onSave(document, webview);
}
})
);

// Create file system watcher
const watcher = vscode.workspace.createFileSystemWatcher(document.uri.fsPath);
watcher.onDidCreate(() => this.update(document, webviewPanel.webview, true));
watcher.onDidChange(() => this.update(document, webviewPanel.webview, true));
watcher.onDidDelete(() => this.update(document, webviewPanel.webview, true));
watcher.onDidCreate(() => this.update(document, webview, true));
watcher.onDidChange(() => this.update(document, webview, true));
watcher.onDidDelete(() => this.update(document, webview, true));
disposables.push(watcher);

// Add dispose listener
webviewPanel.onDidDispose(() => {
this.onClose(document, webview);

for (const disposable of disposables) {
disposable.dispose();
}
});

// Update document
this.update(document, webviewPanel.webview, false);
this.update(document, webview, false);
}

protected abstract onDidReceiveMessage(
document: vscode.TextDocument,
protected async onDidReceiveMessage(
_document: vscode.TextDocument,
webview: vscode.Webview,
message: ViewMessage
): void;
message: ViewMessage | GlobalStoreMessage
): Promise<boolean> {
if (message.type === 'globalStore') {
if (message.action === 'set') {
await this.context.globalState.update(message.name, message.value);
const response: GlobalStoreMessage = {
type: 'globalStore',
action: 'result',
transaction: message.transaction
};
await webview.postMessage(response);

return true;
} else if (message.action === 'get') {
const value = this.context.globalState.get(message.name) || ({} as object);
const response: GlobalStoreMessage = {
type: 'globalStore',
action: 'result',
transaction: message.transaction,
result: value
};
await webview.postMessage(response);

return true;
}
}

return false;
}

protected abstract onSave(document: vscode.TextDocument, webview: vscode.Webview): void;

protected abstract onClose(document: vscode.TextDocument, webview: vscode.Webview): void;

protected abstract update(document: vscode.TextDocument, webview: vscode.Webview, isDocumentChange: boolean): void;
}
2 changes: 1 addition & 1 deletion src/extension/editors/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export * from './digitaljs.js';
export * from './yosys.js';
export * from './nextpnr.js';
export * from './project.js';
Loading

0 comments on commit 9d5b1bc

Please sign in to comment.