Commit 92f4d055 authored by George Wang's avatar George Wang
Browse files

Added initial support of component connections visualization

parent 1c4ed43b
# Change Log
All notable changes to the "lisa-lang" extension will be documented in this file.
## 0.0.6 - 2019-12-23
Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file.
* Added initial support for component connections visualization
## [Unreleased]
## 0.0.5
- Initial release
* Added support of "Go To Definition" for LISA+ components
## 0.0.4
* Further enhancements on the IntelliSense for ports with extra information
## 0.0.3
* Added auto-completion of ports, protocols, compositions and components
* Added "LISA+: Scan Workspace" command
* Added support for sgrepo files
* Added support for sgproj files
* Minor bug fixes
## 0.0.2
* Enhancement on the auto-completion
* Minor bug fixes
## 0.0.1
Initial release of LISA+ Language Support
......@@ -13,35 +13,14 @@ N/A
The extension provides command "LISA+: Scan Workspace" to scan the workspace which offers better IntelliSense results.
It runs automatically when the extension is activated. You can also trigger the command by pressing <kbd>shift</kbd> + <kbd>command</kbd> + <kbd>P</kbd>, then type "LISA+: Scan Workspace"
You can also visualize the current component by using command
* LISA+: Visualize Current Component
## Known Issues
N/A
## Release Notes
### 0.0.5
* Added support of "Go To Definition" for LISA+ components
### 0.0.4
* Further enhancements on the IntelliSense for ports with extra information
### 0.0.3
* Added auto-completion of ports, protocols, compositions and components
* Added "LISA+: Scan Workspace" command
* Added support for sgrepo files
* Added support for sgproj files
* Minor bug fixes
### 0.0.2
* Enhancement on the auto-completion
* Minor bug fixes
### 0.0.1
Initial release of LISA+ Language Support
-----------------------------------------------------------------------------------------------------------
Please see Change Log
{
"name": "lisa-lang",
"version": "0.0.5",
"version": "0.0.6",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
......
......@@ -2,7 +2,7 @@
"name": "lisa-lang",
"displayName": "LISA+",
"description": "LISA+ Language Support for VSCode",
"version": "0.0.5",
"version": "0.0.6",
"publisher": "GeorgeWang0402",
"repository": {
"type": "git",
......@@ -21,7 +21,8 @@
"onLanguage:lisa",
"onLanguage:sgproj",
"onLanguage:sgrepo",
"onCommand:lisa.scan"
"onCommand:lisa.scan",
"onCommand:lisa.visualize"
],
"contributes": {
"languages": [
......@@ -82,6 +83,10 @@
{
"command": "lisa.scan",
"title": "LISA+: Scan Workspace"
},
{
"command": "lisa.visualize",
"title": "LISA+: Visualize Current Component"
}
]
},
......@@ -100,5 +105,6 @@
},
"dependencies": {
"vsce": "^1.71.0"
}
},
"extensionDependencies": ["tintinweb.graphviz-interactive-preview"]
}
import * as vscode from 'vscode';
import * as fs from 'fs';
import { start } from 'repl';
import * as path from 'path';
class LISADocumentHighlightProvider implements vscode.DocumentHighlightProvider {
......@@ -27,6 +27,8 @@ class LISADocumentHighlightProvider implements vscode.DocumentHighlightProvider
let lisa_files: vscode.Uri[] = []
let component_ports = new Map();
let component_definitions = new Map();
let component_connections = new Map();
class LISADefinitionProvider implements vscode.DefinitionProvider {
public provideDefinition(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken)
......@@ -52,6 +54,7 @@ class LISADefinitionProvider implements vscode.DefinitionProvider {
export function activate(context: vscode.ExtensionContext): void {
let instances_map = new Map();
let current_component = "";
let provider_variables = vscode.languages.registerCompletionItemProvider('lisa', {
provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, context: vscode.CompletionContext) {
let first_line = document.lineAt(0);
......@@ -61,6 +64,14 @@ export function activate(context: vscode.ExtensionContext): void {
let composition_regexp = new RegExp("composition\\s*{(.*?)}", "gms");
let composition = composition_regexp.exec(text);
let component_regexp = new RegExp('([\\w\\d]+)\\s*:\\s*([\\w\\d]+)\\(.*?\\);', 'gms');
let current_component_regexp = new RegExp("component\\s+([\\w\\d]+)\\s*\\{(.*?)^\\}", "gms");
let matches = text.matchAll(current_component_regexp); // This is not a very reliable way of extracting the contents with {}
for (let match of matches) // Extracting components in the lisa files
{
current_component = match[1];
break;
}
instances_map.clear();
let instances: string[] = [];
let components: string[] = []
......@@ -285,8 +296,10 @@ export function activate(context: vscode.ExtensionContext): void {
let content = fs.readFileSync(file.path, 'utf-8');
let component_regexp = new RegExp("component\\s+([\\w\\d]+)\\s*\\{(.*?)^\\}", "gms");
let port_regexp = new RegExp("^\\s*(internal)?\\s*(master|slave)\\s*(addressable)?\\s*port\\s*<(.*?)>\\s*([\\w\\d]+)", "gms");
let matches = content.matchAll(component_regexp);
for (let match of matches)
let connection_regexp = new RegExp("connection\\s*\\{(.*?)\\}", "gms");
let conn_regexp = new RegExp("(\\w+)\.(\\w+)([\\w\\.\\[\\]]+)?\\s*=>\\s*(\\w+)\\.(\\w+)", "gms");
let matches = content.matchAll(component_regexp); // This is not a very reliable way of extracting the contents with {}
for (let match of matches) // Extracting components in the lisa files
{
let name = match[1];
// Gather component definitions
......@@ -316,7 +329,7 @@ export function activate(context: vscode.ExtensionContext): void {
// console.log("Component: " + name)
// fs.appendFileSync("/Users/zhewan02/Work/lisa-lang/src/log.txt", "\nComponent: " + name);
let text = match[2];
let text = match[2]; // The content of the component
let ports = text.matchAll(port_regexp);
let ports_instances = [];
for (let port of ports)
......@@ -332,12 +345,125 @@ export function activate(context: vscode.ExtensionContext): void {
// fs.appendFileSync("/Users/zhewan02/Work/lisa-lang/src/log.txt", "\n => \n" + documentation,);
}
component_ports.set(name, Array.from(ports_instances));
// Extracting connection information
let connections = text.matchAll(conn_regexp);
for (let conn of connections)
{
let from = conn[1];
let from_p = conn[2];
let to = conn[4];
let to_p = conn[5];
if(!component_connections.has(name))
{
component_connections.set(name, [conn]);
}
else
{
let conns = component_connections.get(name);
conns.push(conn);
component_connections.set(name, conns);
}
}
}
}
console.log("INFO: Workspace scan accomplished")
};
context.subscriptions.push(vscode.commands.registerCommand(command_scan, scan_handler));
const command_visualize = "lisa.visualize";
const visualize_handler = async () => {
let instances_graphviz = new Map();
// console.log("DEBUG: visualize_handler triggered");
let gv_file_content = 'digraph G {\n'
+ 'graph [labelloc="t" label="' + current_component + '" layout="dot" splines=true overlap=false rankdir="LR"];\n'
+ 'ratio = auto;\n'
+ '\n"self" [ shape=record ];';
instances_map.forEach((value: string, key: string) => {
// console.log("Key: " + key);
// console.log("Value: " + value);
if (component_ports.has(value))
{
let ports = component_ports.get(value);
let code_block = '"' + key + '" '
+ '[ style = "filled, solid" penwidth = 1 fillcolor = "white" fontname = "Arial" fontsize = 9 shape = none margin = 0 label =\n'
+ '\t<<table border="1" cellborder="0" cellpadding="1" bgcolor="white">\n'
+ '\t\t<tr><td bgcolor="#ADD8E6" align="center" colspan="2">' + key + '(' + value + ')</td></tr>\n';
let masters = [];
let slaves = [];
for(let port of ports)
{
if(port[1] != "internal")
{
if(port[2] == "master") // on the right side
{
masters.push(port[5]);
}
else
{
slaves.push(port[5])
}
}
}
for(let i=0; i < Math.max(masters.length, slaves.length); i++)
{
let left = '';
let left_pin = "&gt;";
if(i < slaves.length)
left = slaves[i];
else
left_pin = '';
let right = '';
let right_pin = "&gt;";
if(i < masters.length)
right = masters[i];
else
right_pin = '';
code_block += '\t\t<tr><td align="left" port="' + left + '">'+ left_pin + left + '</td><td align="right" port="' + right + '">' + right + right_pin + '</td></tr>\n'
}
code_block += "\t</table>> ];\n"
// console.log(code_block)
gv_file_content += code_block;
instances_graphviz.set(key, code_block);
}
});
let connections = component_connections.get(current_component)
let connection_str = "";
for(let conn of connections)
{
let from = conn[1];
let from_p = conn[2];
let to = conn[4];
let to_p = conn[5];
connection_str += from + ":" + from_p + " -> " + to + ":" + to_p + "[style=solid,color=blue];\n";
}
// console.log(connection_str);
gv_file_content += connection_str + '}';
// console.log(gv_file_content);
let current_dir = vscode.window.activeTextEditor?.document.uri.fsPath;
if(current_dir == undefined)
current_dir = "."
else
current_dir = path.dirname(current_dir);
fs.writeFileSync(path.join(current_dir, current_component+'.gv'), gv_file_content);
function callbackFunc(webpanel: any) : void
{
webpanel.onClick = function(message: any) {
// console.log("Received message - " + message.value);
}
};
let args = {
document: vscode.window.activeTextEditor?.document,
content: gv_file_content,
callback: callbackFunc
}
vscode.commands.executeCommand("interactive-graphviz.preview.beside", args);
};
context.subscriptions.push(vscode.commands.registerCommand(command_visualize, visualize_handler));
// support for sgrepo files
let provider_sgrepo = vscode.languages.registerCompletionItemProvider(
'sgrepo',
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment