Commit f9236ddf authored by George Wang's avatar George Wang
Browse files

0.0.9 release with minor bug fixes and code refactoring

parent 25d6ecb1
\.vscode/*
node_modules/*
out/*
*.vsix
# Change Log
## 0.0.9 - 2020-02-20
* Minor bug fixes and code refactoring
## 0.0.8 - 2019-12-31
* Added extra scan in resources section for IntelliSense
......
# LISA+ README
# Language support for LISA+ for Visual Studio Code
## Features
## Introduction
[LISA](https://en.wikipedia.org/wiki/LISA_(Language_for_Instruction_Set_Architecture)) stands for Language for Instruction Set Architecture, originated from RWTH Aachen University, in Germany. LISA+ is an enhanced version of LISA with capability of describing components and systems. The extesion is based on the published "LISA+ Language for Fast Models Reference Manual", which you can download from [here](https://static.docs.arm.com/dui0839/k/DUI0839K_lisa_rm.pdf).
The extension provides the essential LISA+ language support, such as syntax highlighting, IntelliSense. Also, the basic support for sgrepo and sgproj files are implemented to facilitate the Fast Models development
The extension provides the essential LISA+ language support, such as syntax highlighting, IntelliSense. Also, the basic support for sgrepo and sgproj files are implemented to facilitate the LISA+ based models development.
## Requirements
## Quick Start
N/A
1. Install the extension from marketplace or vsix file.
2. Open the workspace. Or open the working directory and create a new workspace.
3. If .lisa/.sgrepo/.sgproj files are opened, *LISA+: Scan Workspace* will be triggered. The command can also be triggered at any time manually.
4. Once the scan is finished, enjoy the coding!
## Usage
## Features
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"
* Scan Workspace
You can also visualize the current component by using command
The extension provides the command "LISA+: Scan Workspace" to scan the workspace and build database to offer 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"
* LISA+: Visualize Current Component
You can also visualize the current component by using the command. It analyzes the active LISA+ file, generates DOT (.gv) file and visualizes the system in Visual Studio Code.
You can also trigger the command by pressing <kbd>shift</kbd> + <kbd>command</kbd> + <kbd>P</kbd>, then type "LISA+: Visualize Current Component"
* Syntax highlighting
The extension supports syntax highlighting for .lisa, .sgproj and .sgrepo files.
* IntelliSence
The extension provide IntelliSense support for .lisa, .sgproj and .sgrepo files. The list of supported IntelliSense features, but not limited to, is shown below:
1. Code snippets for resources, ports, sections etc.
1. Intelligent code completion for compositions, ports, keywords etc.
1. Support of "Go to Definition" for components and protocols
## Known Issues
N/A
* The visualisation consumes large amount of memory for large and complex system models.
## License
TBD
## Release Notes
......
{
"name": "lisa-lang",
"version": "0.0.8",
"version": "0.0.9",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
......
......@@ -2,8 +2,9 @@
"name": "lisa-lang",
"displayName": "LISA+",
"description": "LISA+ Language Support for VSCode",
"version": "0.0.8",
"version": "0.0.9",
"publisher": "GeorgeWang0402",
"icon": "res/LISA.png",
"repository": {
"type": "git",
"url": "https://test.com"
......
......@@ -3,37 +3,15 @@ import * as fs from 'fs';
import * as path from 'path';
class LISADocumentHighlightProvider implements vscode.DocumentHighlightProvider {
public provideDocumentHighlights(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken)
{
let editor = vscode.window.activeTextEditor;
if (editor)
{
let cursor = editor.selection.start;
let word_range = document.getWordRangeAtPosition(cursor);
let highlights = []
if (word_range)
{
highlights.push(new vscode.DocumentHighlight(word_range, vscode.DocumentHighlightKind.Text));
return highlights;
}
}
return null;
}
}
let lisa_files: vscode.Uri[] = []
let lisa_files: vscode.Uri[] = [];
let component_ports = new Map();
let component_definitions = new Map();
let component_connections = new Map();
let protocol_definitions = new Map();
let protocol_behaviors = new Map();
let instances_map = new Map();
class LISADefinitionProvider implements vscode.DefinitionProvider {
public provideDefinition(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken)
public provideDefinition(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken)
{
let editor = vscode.window.activeTextEditor;
if (editor)
......@@ -55,10 +33,10 @@ class LISADefinitionProvider implements vscode.DefinitionProvider {
}
return null;
}
}
}
function extract_bracket(text: string, pos: number, bracket: string): string
function extractBracket(text: string, pos: number, bracket: string): string
{
let content: string = "";
let brackets = null;
......@@ -77,14 +55,14 @@ function extract_bracket(text: string, pos: number, bracket: string): string
{
if(text.charAt(i) == brackets[0])
{
if(bracket_counter == 0)
{
recording = true;
bracket_counter++;
continue;
}
bracket_counter++;
content += text.charAt(i);
if(bracket_counter == 0)
{
recording = true;
bracket_counter++;
continue;
}
bracket_counter++;
content += text.charAt(i);
}
else if(text.charAt(i) == brackets[1])
{
......@@ -93,19 +71,19 @@ function extract_bracket(text: string, pos: number, bracket: string): string
{
recording = false;
break;
}
content += text.charAt(i);
}
content += text.charAt(i);
}
else if(recording)
{
content += text.charAt(i)
content += text.charAt(i);
}
}
return content;
}
function strip_comments(text: string): string
function stripComments(text: string): string
{
let text_processed = "";
let lines = text.split('\n');
......@@ -134,7 +112,7 @@ function getDocumentText(document: vscode.TextDocument)
function getCurrentComponent(text: string) : string
{
let current_component = ""
let current_component = "";
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
......@@ -165,12 +143,12 @@ function extractResources(text: string)
{
let resources_regexp = new RegExp("resources\\s*{", "gms");
let pos = text.search(resources_regexp);
let resources_text = extract_bracket(text, pos, "curly");
let resources_text = extractBracket(text, pos, "curly");
let register_regexp = new RegExp('REGISTER\\s*\\{.*?\\}\\s*(\\w+);', 'gms');
let parameter_regexp = new RegExp('PARAMETER\\s*\\{.*?\\}\\s*(\\w+);', 'gms');
let resourcesCompletion = []
let resourcesCompletion = [];
if (resources_text)
{
let matches = resources_text.matchAll(register_regexp);
......@@ -189,8 +167,6 @@ function extractResources(text: string)
}
export function activate(context: vscode.ExtensionContext): void {
let provider_variables = vscode.languages.registerCompletionItemProvider('lisa', {
provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, context: vscode.CompletionContext) {
let text = getDocumentText(document);
......@@ -212,19 +188,19 @@ export function activate(context: vscode.ExtensionContext): void {
}
return simpleCompletion_compositions;
}
}
});
let provider_ports = vscode.languages.registerCompletionItemProvider('lisa', {
provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, context: vscode.CompletionContext) {
let text = getDocumentText(document);
let port_regexp = new RegExp("^\\s*(internal)?\\s*(master|slave)\\s*(addressable)?\\s*port\\s*<(.*?)>\\s*([\\w\\d]+)", "gms")
let protocols: string[] = []
let self_ports = []
let port_regexp = new RegExp("^\\s*(internal)?\\s*(master|slave)\\s*(addressable)?\\s*port\\s*<(.*?)>\\s*([\\w\\d]+)", "gms");
let protocols: string[] = [];
let self_ports = [];
let matches = text.matchAll(port_regexp);
for (let match of matches)
{
self_ports.push(Array.from(match))
self_ports.push(Array.from(match));
if (!protocols.includes(match[4]))
{
protocols.push(match[4]);
......@@ -245,7 +221,7 @@ export function activate(context: vscode.ExtensionContext): void {
for (let port of self_ports)
{
let item = new vscode.CompletionItem(port[5], vscode.CompletionItemKind.Field);
item.documentation = new vscode.MarkdownString();
item.documentation.appendMarkdown("* **Internal:** " + ((port[1] == "internal")? "True":"False") + "\n");
item.documentation.appendMarkdown("* **Type:** " + port[2] + "\n");
......@@ -315,15 +291,15 @@ export function activate(context: vscode.ExtensionContext): void {
for(let port of ports)
{
let item = new vscode.CompletionItem(port[5], vscode.CompletionItemKind.Field);
item.documentation = new vscode.MarkdownString();
item.documentation.appendMarkdown("* **Internal:** " + ((port[1] == "internal")? "True":"False") + "\n");
item.documentation.appendMarkdown("* **Type:** " + port[2] + "\n");
item.documentation.appendMarkdown("* **Addressable:** " + ((port[3] == "addressable")? "True":"False") + "\n");
item.documentation.appendMarkdown("* **Type:** " + port[2] + "\n");
item.documentation.appendMarkdown("* **Addressable:** " + ((port[3] == "addressable")? "True":"False") + "\n");
item.documentation.appendMarkdown("* **Protocol:** " + port[4] + "\n");
// console.log("DEBUG: port - " + port[5]);
// console.log("DEBUG: " + item.documentation);
simpleCompletion_ports.push(item);
simpleCompletion_ports.push(item);
}
return simpleCompletion_ports;
}
......@@ -331,7 +307,7 @@ export function activate(context: vscode.ExtensionContext): void {
}
return simpleCompletion_protocols;
}
}
}, '.'
);
......@@ -339,7 +315,7 @@ export function activate(context: vscode.ExtensionContext): void {
provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, context: vscode.CompletionContext) {
// Simple completion items for section keywords
let sections = ["component", "includes", "properties", "resources", "composition", "connection", "behavior"];
let simpleCompletion_sections = []
let simpleCompletion_sections = [];
for (let section of sections) {
simpleCompletion_sections.push(new vscode.CompletionItem(section));
}
......@@ -351,7 +327,7 @@ export function activate(context: vscode.ExtensionContext): void {
provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, context: vscode.CompletionContext) {
// Simple completion items for type keywords
let types = ["master", "slave", "internal", "extern", "enum", "union", "class", "struct", "port", "self"];
let simpleCompletion_types = []
let simpleCompletion_types = [];
for (let type of types) {
simpleCompletion_types.push(new vscode.CompletionItem(type, vscode.CompletionItemKind.Class));
}
......@@ -364,7 +340,7 @@ export function activate(context: vscode.ExtensionContext): void {
provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, context: vscode.CompletionContext) {
// Simple completion items for type keywords
let types = ["int8_t", "int16_t", "int32_t", "int64_t", "uint8_t", "uint16_t", "uint32_t", "uint64_t", "int", "long", "short", "bool", "char", "signed", "unsigned", "float", "double"];
let simpleCompletion_types = []
let simpleCompletion_types = [];
for (let type of types) {
simpleCompletion_types.push(new vscode.CompletionItem(type, vscode.CompletionItemKind.Unit));
}
......@@ -404,23 +380,23 @@ export function activate(context: vscode.ExtensionContext): void {
commandCompletion_slave.kind = vscode.CompletionItemKind.Keyword;
commandCompletion_slave.insertText = 'slave port<> port_name;';
// commandCompletion_slave.command = { command: 'editor.action.triggerSuggest', title: 'Re-trigger completions...' };
// Command completion for port
const commandCompletion_port = new vscode.CompletionItem('port');
commandCompletion_port.kind = vscode.CompletionItemKind.Keyword;
commandCompletion_port.insertText = 'port<> port_name;';
let autocompletions = [
commandCompletion_params,
commandCompletion_params,
commandCompletion_register,
commandCompletion_memory,
commandCompletion_master,
commandCompletion_memory,
commandCompletion_master,
commandCompletion_slave,
commandCompletion_port
];
let content = getDocumentText(document);
content = strip_comments(content);
content = stripComments(content);
autocompletions = autocompletions.concat(extractResources(content));
return autocompletions;
}
......@@ -428,15 +404,14 @@ export function activate(context: vscode.ExtensionContext): void {
context.subscriptions.push(provider_sections, provider_types, provider_native_types, provider_resources, provider_variables, provider_ports);
//context.subscriptions.push(vscode.languages.registerDocumentHighlightProvider('lisa', new LISADocumentHighlightProvider()));
const command_scan = "lisa.scan";
const scan_handler = async () => {
vscode.window.showInformationMessage("LISA+ Extension: Scanning workspace for IntelliSense ...");
lisa_files = await vscode.workspace.findFiles('**/*.lisa')
lisa_files = await vscode.workspace.findFiles('**/*.lisa');
for (let file of lisa_files)
{
let content = fs.readFileSync(file.path, 'utf-8');
content = strip_comments(content);
content = stripComments(content);
let protocol_regexp = new RegExp("protocol\\s+([\\w\\d]+)\\s*\\{(.*?)^\\s?\\}", "gms");
let component_regexp = new RegExp("component\\s+([\\w\\d]+)\\s*\\{", "gms");
......@@ -474,9 +449,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 = extract_bracket(content, found.index, "curly")
let text = extractBracket(content, found.index, "curly");
let ports = text.matchAll(port_regexp);
let ports_instances = [];
for (let port of ports)
......@@ -486,10 +459,9 @@ export function activate(context: vscode.ExtensionContext): void {
// documentation += " * Type: " + port[2] + "\n";
// documentation += " * Addressable: " + ((port[3] == "addressable")? "True":"False") + "\n";
// documentation += " * Protocol: " + port[4] + "\n";
// group 1: internal, group 2: master/slave, group 3: addressable, group 4: protocol, group 5: port name
ports_instances.push(Array.from(port));
// fs.appendFileSync("/Users/zhewan02/Work/lisa-lang/src/log.txt", "\n => \n" + documentation,);
ports_instances.push(Array.from(port));
}
component_ports.set(name, Array.from(ports_instances));
}
......@@ -526,7 +498,7 @@ export function activate(context: vscode.ExtensionContext): void {
break;
}
}
let body = extract_bracket(content, found.index, "curly");
let body = extractBracket(content, found.index, "curly");
let behavior_regex = new RegExp("(optional)?\\s*(behavior|behaviour)\\s*(\\w+)\\s*\\((.*?)\\)\\s*:?\\s*(.*?)[;\\{]+", "gms");
let behaviors = body.matchAll(behavior_regex);
for (let behavior of behaviors)
......@@ -553,7 +525,7 @@ export function activate(context: vscode.ExtensionContext): void {
}
}
vscode.window.showInformationMessage("LISA+ Extension: Scanning workspace for IntelliSense ... done");
console.log("INFO: Workspace scan accomplished")
console.log("INFO: Workspace scan accomplished");
};
context.subscriptions.push(vscode.commands.registerCommand(command_scan, scan_handler));
......@@ -565,18 +537,15 @@ export function activate(context: vscode.ExtensionContext): void {
if (current_document != undefined)
{
text = getDocumentText(current_document.document);
text = strip_comments(text);
text = stripComments(text);
}
constructInstancesMap(text);
let current_component = getCurrentComponent(text);
// 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 ranksep=1 nodesep=0.5 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);
......@@ -596,7 +565,7 @@ export function activate(context: vscode.ExtensionContext): void {
}
else
{
slaves.push(port[5])
slaves.push(port[5]);
}
}
}
......@@ -615,9 +584,9 @@ export function activate(context: vscode.ExtensionContext): void {
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\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"
code_block += "\t</table>> ];\n";
// console.log(code_block)
gv_file_content += code_block;
instances_graphviz.set(key, code_block);
......@@ -640,10 +609,9 @@ export function activate(context: vscode.ExtensionContext): void {
}
gv_file_content += connection_str + '}';
// console.log(gv_file_content);
let current_dir = vscode.window.activeTextEditor?.document.uri.fsPath;
if(!current_dir)
current_dir = "."
current_dir = ".";
else
current_dir = path.dirname(current_dir);
fs.writeFileSync(path.join(current_dir, current_component+'.gv'), gv_file_content);
......@@ -651,25 +619,25 @@ export function activate(context: vscode.ExtensionContext): 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',
'sgrepo',
{
provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, context: vscode.CompletionContext) {
provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken, context: vscode.CompletionContext) {
// Simple completion items for keywords
let keywords = ["component", "path", "files"];
let simpleCompletion_sgrepo = []
let simpleCompletion_sgrepo = [];
for (let keyword of keywords) {
simpleCompletion_sgrepo.push(new vscode.CompletionItem(keyword));
}
......@@ -686,7 +654,7 @@ export function activate(context: vscode.ExtensionContext): void {
let linePrefix = document.lineAt(position).text.substr(0, position.character);
if (linePrefix.endsWith('path = \"')) {
let file_paths = []
let file_paths = [];
for(let lisa of lisa_files)
{
file_paths.push(new vscode.CompletionItem(lisa.path, vscode.CompletionItemKind.File));
......
Markdown is supported
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