major updates to Mocha/ZQL support for VSCode

This commit is contained in:
Michael Becker 2025-04-01 15:18:32 -04:00
parent 431fa59a71
commit a6e608e1fc
23 changed files with 1561 additions and 100 deletions

View File

@ -28,12 +28,23 @@
"name": "text.bracketed"
},
{
"match": "\\b(?i)(class||static|stub|function)\\b",
"name": "keyword.other.sql"
"match": "^\\s*(public|private|root|protected)\\s?+(static\\s*)?+(class|function)\\b",
"name": "storage.modifier.zql"
},
{
"match": "\\b(?i)(class|static|stub|published|function|extends|if|then|else|let|optional|token|update|create|yield|set|override|this)\\b",
"name": "keyword.basic.zql"
},
{
"match": "\\b(test|case|assert)\\b",
"name": "keyword.testing.zql"
},
{
"include": "#comments"
},
{
"include": "#type-operators"
},
{
"captures": {
"1": {
@ -92,58 +103,12 @@
"name": "meta.alter.sql"
},
{
"captures": {
"1": {
"name": "storage.type.sql"
},
"2": {
"name": "storage.type.sql"
},
"3": {
"name": "constant.numeric.sql"
},
"4": {
"name": "storage.type.sql"
},
"5": {
"name": "constant.numeric.sql"
},
"6": {
"name": "storage.type.sql"
},
"7": {
"name": "constant.numeric.sql"
},
"8": {
"name": "constant.numeric.sql"
},
"9": {
"name": "storage.type.sql"
},
"10": {
"name": "constant.numeric.sql"
},
"11": {
"name": "storage.type.sql"
},
"12": {
"name": "storage.type.sql"
},
"13": {
"name": "storage.type.sql"
},
"14": {
"name": "constant.numeric.sql"
},
"15": {
"name": "storage.type.sql"
}
},
"match": "(?xi)\n\n\t\t\t\t# normal stuff, capture 1\n\t\t\t\t \\b(bigint|bigserial|bit|boolean|box|bytea|cidr|circle|date|double\\sprecision|inet|int|integer|line|lseg|macaddr|money|oid|path|point|polygon|real|serial|smallint|numeric|text)\\b\n\n\t\t\t\t# numeric suffix, capture 2 + 3i\n\t\t\t\t|\\b(bit\\svarying|character\\s(?:varying)?|tinyint|var\\schar|float|interval)\\((\\d+)\\)\n\n\t\t\t\t# optional numeric suffix, capture 4 + 5i\n\t\t\t\t|\\b(char|number|varchar\\d?)\\b(?:\\((\\d+)\\))?\n\n\t\t\t\t# special case, capture 6 + 7i + 8i\n\t\t\t\t|\\b(numeric|decimal)\\b(?:\\((\\d+),(\\d+)\\))?\n\n\t\t\t\t# special case, captures 9, 10i, 11\n\t\t\t\t|\\b(times?)\\b(?:\\((\\d+)\\))?(\\swith(?:out)?\\stime\\szone\\b)?\n\n\t\t\t\t# special case, captures 12, 13, 14i, 15\n\t\t\t\t|\\b(timestamp)(?:(s|tz))?\\b(?:\\((\\d+)\\))?(\\s(with|without)\\stime\\szone\\b)?\n\n\t\t\t"
"match": "(boolean|date|numeric|text|xml|file)",
"name": "support.class"
},
{
"match": "(?i:\\b((?:primary|foreign)\\s+key|references|on\\sdelete(\\s+cascade)?|check|constraint)\\b)",
"name": "storage.modifier.sql"
"match": "functions:",
"name": "markup.bold"
},
{
"match": "\\b\\d+\\b",
@ -295,6 +260,108 @@
"repository": {
"comments": {
"patterns": [
{
"name": "meta.return.type.colon.zql",
"begin": ":\\s*(\\w*)",
"beginCaptures": {
"1": {
"name": "support.class"
}
},
"end": "\\s"
},
{
"name": "meta.return.value.equals.zql",
"begin": "=\\s*(\\w*)",
"beginCaptures": {
"1": {
"name": "support.variable"
}
},
"end": "\\n"
},
{
"name": "section.instances",
"begin": "instances:\\s*",
"end": "\\n",
"beginCaptures": {
"0": {
"name": "markup.bold"
}
},
"patterns": [
{
"match": "\\s*(\\w*)\\s*,\\s*(\\d*\\$\\d*)\\s*",
"captures": {
"1": {
"name": "support.variable"
},
"2": {
"name": "markup.italic"
}
}
}
]
},
{
"name": "section.attributes",
"begin": "attributes:\\s*",
"end": "\\n",
"beginCaptures": {
"0": {
"name": "markup.bold"
}
},
"patterns": [
{
"match": "\\s*(\\w*)\\s*,\\s*(\\d*\\$\\d*)\\s*:\\s*(\\w*)\\s*",
"captures": {
"1": {
"name": "support.variable"
},
"2": {
"name": "markup.italic"
},
"3": {
"name": "support.class"
}
}
}
]
},
{
"name": "section.relationships",
"begin": "relationships:\\s*",
"end": "\\n",
"beginCaptures": {
"0": {
"name": "markup.bold"
}
},
"patterns": [
{
"match": "\\s*(\\w*)\\s*,\\s*(\\d*\\$\\d*)\\s*",
"captures": {
"1": {
"name": "support.variable"
},
"2": {
"name": "markup.italic"
}
}
}
]
},
{
"begin": "//",
"beginCaptures": {
"0": {
"name": "punctuation.definition.comment.zql"
}
},
"end": "\\n",
"name": "comment.line.double-slash.zql"
},
{
"begin": "(^[ \\t]+)?(?=--)",
"beginCaptures": {
@ -334,7 +401,7 @@
}
},
"end": "\\*/",
"name": "comment.block.c"
"name": "comment.block.zql"
}
]
},

BIN
icons/decorations/class.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 524 B

106
icons/decorations/class.svg Executable file
View File

@ -0,0 +1,106 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="16"
height="16"
viewBox="0 0 16 16"
version="1.1"
id="svg5"
sodipodi:docname="class.svg"
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
inkscape:export-filename="class.png"
inkscape:export-xdpi="64"
inkscape:export-ydpi="64"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview7"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:document-units="mm"
showgrid="true"
width="24px"
units="px"
showguides="true"
inkscape:zoom="11.317365"
inkscape:cx="-7.8640214"
inkscape:cy="16.214022"
inkscape:window-width="1840"
inkscape:window-height="1011"
inkscape:window-x="80"
inkscape:window-y="32"
inkscape:window-maximized="1"
inkscape:current-layer="layer1"
inkscape:showpageshadow="2"
inkscape:deskcolor="#d1d1d1">
<inkscape:grid
type="xygrid"
id="grid11646"
enabled="true"
dotted="false"
originx="11.999994"
originy="11.999994" />
</sodipodi:namedview>
<defs
id="defs2">
<linearGradient
id="linearGradient7883"
inkscape:swatch="solid">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop7881" />
</linearGradient>
<linearGradient
id="linearGradient5790"
inkscape:swatch="solid">
<stop
style="stop-color:#ffb100;stop-opacity:1;"
offset="0"
id="stop5788" />
</linearGradient>
<linearGradient
id="linearGradient5784"
inkscape:swatch="solid">
<stop
style="stop-color:#ffb100;stop-opacity:1;"
offset="0"
id="stop5782" />
</linearGradient>
<linearGradient
id="linearGradient1808"
inkscape:swatch="solid">
<stop
style="stop-color:#008317;stop-opacity:1;"
offset="0"
id="stop1806" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient1808"
id="linearGradient1810"
x1="0.1886691"
y1="3.3783665"
x2="6.2098794"
y2="3.3783665"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(2.0701729,0,0,2.0701729,1.4268834,1.1474537)" />
</defs>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<path
id="path282"
style="fill:url(#linearGradient1810);fill-opacity:1;stroke:none;stroke-width:0.548596;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 7.9868451,2.2546882 C 5.2611116,2.259315 2.5395496,2.8075045 2.5223502,3.8861203 2.4879514,6.0433516 6.6149666,13.760848 7.9996827,13.745318 9.3843986,13.729792 13.546055,6.080367 13.477015,3.8861203 13.442495,2.7889967 10.712579,2.2500611 7.9868451,2.2546882 Z m 0.00642,1.6153851 a 3.286408,3.3022391 0 0 1 3.2928189,3.2949579 l -3.2863989,0.00749 H 11.286082 A 3.286408,3.3022391 0 0 1 8.0018222,10.474966 3.286408,3.3022391 0 0 1 4.7132832,7.1767989 3.286408,3.3022391 0 0 1 7.9932627,3.8700733 Z" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -3,6 +3,7 @@
"displayName": "Mocha for VSCode",
"description": "Tools for working with the Mocha Advanced Database Infrastructure platform",
"version": "0.0.1",
"publisher": "mochapowered",
"engines": {
"vscode": "^1.92.0"
},
@ -18,6 +19,11 @@
"title": "",
"category": "Mocha"
},
{
"command": "mocha.suvmanager.suv_select",
"title": "Select Preferred SUV",
"category": "Mocha"
},
{
"command": "mocha.suvmanager.suv_manager",
"title": "Manage SUVs",
@ -70,17 +76,17 @@
"category": "Mocha"
},
{
"command": "mocha.publish_zq_stub_with_implementation",
"command": "mocha.zq_publish_stub_with_implementation",
"title": "Publish as ZQ stub and upload implementation",
"category": "Mocha"
},
{
"command": "mocha.publish_zq_stub",
"command": "mocha.zq_publish_stub",
"title": "Publish as ZQ stub method",
"category": "Mocha"
},
{
"command": "mocha.import_function_implementation_from_zq",
"command": "mocha.zq_import_function_implementation",
"title": "Import Function Implementation from ZQ",
"category": "Mocha"
},
@ -97,13 +103,33 @@
{
"command": "mocha.zq_open_document",
"title": "Open ZQ Document",
"enablement": "never",
"category": "Mocha"
},
{
"command": "mocha.zq_import_function_signature",
"title": "Import ZQ Function Signature",
"category": "Mocha"
},
{
"command": "mocha.moduleExplorer.module_import_zq_implementation",
"title": "Import ZQ Implementation",
"category": "Mocha"
},
{
"command": "mocha.moduleExplorer.module_show_in_web",
"title": "Show in Web Browser",
"category": "Mocha"
},
{
"command": "mocha.moduleExplorer.module_copy_text",
"title": "Copy Text",
"category": "Mocha"
},
{
"command": "mocha.moduleExplorer.module_copy_instance_id",
"title": "Copy Instance ID",
"category": "Mocha"
}
],
"keybindings": [
@ -180,8 +206,35 @@
],
"view/item/context": [
{
"command": "mocha.suvmanager.suv_show",
"command": "mocha.moduleExplorer.module_import_zq_implementation",
"group": "0_view@1",
"when": "view == mocha.moduleExplorer"
},
{
"command": "mocha.moduleExplorer.module_show_in_web",
"group": "0_view@2",
"when": "view == mocha.moduleExplorer"
},
{
"command": "mocha.moduleExplorer.module_copy_text",
"group": "1_copy@1",
"when": "view == mocha.moduleExplorer"
},
{
"command": "mocha.moduleExplorer.module_copy_instance_id",
"group": "1_copy@2",
"when": "view == mocha.moduleExplorer"
},
{
"command": "mocha.suvmanager.suv_select",
"group": "0_view@1",
"when": "view == mocha.suvManager"
},
{
"command": "mocha.suvmanager.suv_show",
"group": "0_view@2",
"when": "view == mocha.suvManager"
},
{

71
src/StringExtensions.ts Normal file
View File

@ -0,0 +1,71 @@
// Copyright (C) 2025 Michael Becker <alcexhim@gmail.com>
//
// This file is part of mocha-vscode.
//
// mocha-vscode is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// mocha-vscode is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with mocha-vscode. If not, see <https://www.gnu.org/licenses/>.
export class IndexOfAnyResult {
private _Index : number;
public get Index() : number {
return this._Index;
}
public set Index(v : number) {
this._Index = v;
}
private _Needle : string;
public get Needle() : string {
return this._Needle;
}
public set Needle(v : string) {
this._Needle = v;
}
constructor(index: number, needle: string) {
this._Index = index;
this._Needle = needle;
}
}
export class StringExtensions {
static indexOfAny(line: string, needle: string[], position?: number): number {
let idx: number = -1;
for (var i = 0; i < needle.length; i++) {
let idx2: number = line.indexOf(needle[i], position);
if (idx2 > -1 && (idx2 < idx || idx === -1)) {
idx = idx2;
}
}
return idx;
}
static indexOfAnyEx(line: string, needle: string[], position?: number): IndexOfAnyResult {
let idx: number = -1;
let realNeedle: string = "";
for (var i = 0; i < needle.length; i++) {
let idx2: number = line.indexOf(needle[i], position);
if (idx2 > -1 && (idx2 < idx || idx === -1)) {
idx = idx2;
realNeedle = needle[i];
}
}
return new IndexOfAnyResult(idx, realNeedle);
}
}

View File

@ -4,7 +4,7 @@ import * as vscode from 'vscode';
import { GenericTreeDataProvider } from './tdp/GenericTreeDataProvider';
import { GenericTreeDataItem } from './tdp/GenericTreeDataItem';
import { ModuleExplorerTreeDataProvider } from './ModuleExplorerTreeDataProvider';
import { ModuleExplorerTreeDataProvider } from './moduleExplorer/ModuleExplorerTreeDataProvider';
import { userInfo } from 'os';
import { Machine } from './Machine';
@ -14,11 +14,38 @@ import { SuvManagerTreeDataProvider } from './suvManager/SuvManagerTreeDataProvi
import * as path from 'path';
import https from 'node:https';
import { stat } from 'node:fs';
import { ZqGenerator } from './zq/ZqGenerator';
import { ZqFunctionDefinition } from './zq/ZqFunctionDefinition';
import { ZqClass } from './zq/ZqClass';
import { InstanceKey } from './mocha/core/InstanceKey';
import { ZqAttribute } from './zq/ZqAttribute';
import { ZqRelationship } from './zq/ZqRelationship';
import { ZqInstance } from './zq/ZqInstance';
import { ZqInstanceReference } from './zq/ZqInstanceReference';
import { ZqObject } from './zq/ZqObject';
import { ZqParser } from './zq/parser/ZqParser';
const cp = require('child_process');
const extension = vscode.extensions.getExtension('mochapowered.mocha-vscode');
let dpModuleExplorer = new ModuleExplorerTreeDataProvider();
let treeSuvManager: vscode.TreeView<Machine> | undefined = undefined;
let currentSuvId: string | null = null;
let statusBarItem : vscode.StatusBarItem | undefined = undefined;
const updateStatusBarText = () => {
if (statusBarItem !== undefined) { statusBarItem.text = `$(server-environment) ${currentSuvId || "(none)"}`; }
}
const updateStatusBarItemVisibility = () => {
let showStatusbar: boolean = true;
if (statusBarItem !== undefined) { showStatusbar ? statusBarItem.show() : statusBarItem.hide(); }
}
export function getCurrentSuvId() {
return currentSuvId;
}
// register the decoration provider
vscode.window.registerFileDecorationProvider(new SuvManagerTreeDecorationProvider());
@ -31,6 +58,7 @@ export function mkotsuri(suvId : string, tenantName : string, command : string,
function updateModuleExplorerTreeView() {
/*
dpModuleExplorer.items.push(new GenericTreeDataItem("tools", "tools", [
new GenericTreeDataItem("tools:xpresso", "xpressO", [
new GenericTreeDataItem("tools:xpressO:method", "method", [
@ -53,28 +81,28 @@ function updateModuleExplorerTreeView() {
}
));
return;
*/
let suvId : string = "i-0c0398f84acecb702";
let tenantName : string = "super";
let otsuri = mkotsuri(suvId, tenantName, "module/list");
let suvId: string | null = getCurrentSuvId();
if (suvId !== null) {
let tenantName: string = "super";
let otsuri = mkotsuri(suvId, tenantName, "module/list");
cp.exec("curl " + otsuri.toString(), (err: string, stdout: string, stderr: string) =>
{
if (err != "")
{
vscode.window.showErrorMessage(err);
}
let json = JSON.parse(stdout);
for (var i = 0; i < json.items.length; i++)
{
recursiveAddItemToTreeView(dpModuleExplorer, json.items[i], null);
}
cp.exec("curl " + otsuri.toString(), (err: string, stdout: string, stderr: string) => {
if (err !== "") {
vscode.window.showErrorMessage(err);
}
let json = JSON.parse(stdout);
for (var i = 0; i < json.items.length; i++) {
recursiveAddItemToTreeView(dpModuleExplorer, json.items[i], null);
}
dpModuleExplorer.refresh();
dpModuleExplorer.refresh();
//let treeModuleExplorer = vscode.window.createTreeView("mocha.moduleExplorer", { "canSelectMany": true, "showCollapseAll": true, "treeDataProvider": dpModuleExplorer });
//console.log(stdout);
});
//let treeModuleExplorer = vscode.window.createTreeView("mocha.moduleExplorer", { "canSelectMany": true, "showCollapseAll": true, "treeDataProvider": dpModuleExplorer });
//console.log(stdout);
});
}
}
function recursiveAddItemToTreeView(dp : GenericTreeDataProvider, item : any, parent : GenericTreeDataItem | null)
@ -88,6 +116,7 @@ function recursiveAddItemToTreeView(dp : GenericTreeDataProvider, item : any, pa
{
p = new GenericTreeDataItem(item.name, item.title, undefined, { "type": item.type });
}
p.description = item.instanceId;
if (item.items)
{
for (var i = 0; i < item.items.length; i++)
@ -117,6 +146,79 @@ function launchSuv(name : string)
let outputChannel: vscode.OutputChannel | undefined = undefined;
const options = {
borderWidth: '1px',
borderStyle: 'solid',
overviewRulerColor: 'blue',
overviewRulerLane: vscode.OverviewRulerLane.Right,
light: {
// this color will be used in light color themes
borderColor: 'darkblue',
contentIconPath: extension?.extensionPath + '/icons/light/explorer/class.svg'
},
dark: {
// this color will be used in dark color themes
borderColor: 'lightblue',
contentIconPath: extension?.extensionPath + '/icons/dark/explorer/class.svg'
}
}
const classDecorationType = vscode.window.createTextEditorDecorationType({
before:
{
contentIconPath: extension?.extensionPath + '/icons/decorations/class.svg',
margin: "2px 2px 0px 2px"
}
});
function openEditorForInstance(filename: string, instanceId: string)
{
let tdi = vscode.workspace.openTextDocument(vscode.Uri.file(path.join(userInfo().homedir, filename + ".zql") ).with({ scheme: "untitled" })).then( (doc) =>
{
vscode.window.showTextDocument(doc).then((editor) =>
{
editor.edit(edit => {
// let zq = new ZqGenerator();
let clz = new ZqClass();
clz.name = filename.replaceAll(' ', '').replaceAll('-', '_');
clz.instanceKey = InstanceKey.parse(instanceId);
clz.attributes = [
new ZqAttribute("name", InstanceKey.parse("4$1"), "text"),
new ZqAttribute("order", InstanceKey.parse("4$1"), "text")
];
clz.relationships = [
new ZqRelationship("snapshotsSystemName", InstanceKey.parse("3$61051"))
];
clz.functions = [
new ZqFunctionDefinition(),
new ZqFunctionDefinition()
];
clz.functions[0].name = "getMethodAccessPublicInstance";
clz.functions[0].isStatic = true;
clz.functions[0].returnDataType = "AccessModifier";
clz.functions[0].returnValue = "Public";
clz.functions[1].name = "getMostRestrictiveFromSet";
clz.functions[1].isStatic = true;
clz.functions[1].isStub = true;
clz.functions[1].returnDataType = "AccessModifier";
clz.functions[1].returnValue = "Public";
clz.instances = [
new ZqInstanceReference("Public", InstanceKey.parse("934$102"))
];
edit.delete(new vscode.Range(new vscode.Position(0, 0), new vscode.Position(editor.document.lineCount - 1, editor.document.lineAt(editor.document.lineCount - 1).range.end.character)));
edit.insert(new vscode.Position(0, 0), clz.toString());
}).then(success => {
updateZqEditor(editor);
});
});
});
}
export function openWebBrowser(url: vscode.Uri) {
cp.exec("xdg-open " + url.toString(), (err: string, stdout: string, stderr: string) => {
@ -134,7 +236,6 @@ export function activate(context: vscode.ExtensionContext) {
treeSuvManager = vscode.window.createTreeView("mocha.suvManager", { "canSelectMany": true, "showCollapseAll": true, "treeDataProvider": treeDataProvider });
treeDataProvider.treeview = treeSuvManager;
treeSuvManager.badge = { "value": 1, "tooltip": "1 SUV(s) running" };
let treeModuleExplorer = vscode.window.createTreeView("mocha.moduleExplorer", { "canSelectMany": true, "showCollapseAll": true, "treeDataProvider": dpModuleExplorer });
@ -153,7 +254,36 @@ export function activate(context: vscode.ExtensionContext) {
let list = stdout.trim().split('\n');
console.log(list[0]);
});
});
});
vscode.commands.registerCommand("mocha.suvmanager.suv_copy_id", (item: Machine) => {
if (item.name !== undefined) {
vscode.env.clipboard.writeText(item.name);
}
});
vscode.commands.registerCommand("mocha.zq_import_function_implementation", () => {
let ed = vscode.window.activeTextEditor;
if (ed !== undefined) {
if (ed.document.languageId === 'zql') {
// thanks https://stackoverflow.com/questions/68342626
const selection = ed.selection;
const currentLineRange = ed.document.lineAt(selection.active.line).range;
const line: string = ed.document.getText(currentLineRange).trim();
let c = ZqParser.parse("class Relationship, 1$3 {\n\nattributes:\n name, 4$1 : text\n order, 4$8 : text\n\nrelationships:\n snapshotsBySystemTarget, 3$418926\n\ninstances:\n testRel, 3$112842\n}");
let decl = ZqParser.parse(line);
if (decl !== null) {
(decl as ZqFunctionDefinition).isStub = false;
ed.edit(edit => edit.replace(currentLineRange, decl.toString()));
}
}
}
});
let cmd_zq_import_function_signature = vscode.commands.registerCommand("mocha.zq_import_function_signature", () => {
/*s
@ -206,7 +336,14 @@ export function activate(context: vscode.ExtensionContext) {
var qqq = ppp[1].replaceAll(" ", "").replaceAll(".", "");
var xxx = qqq.substring(0, qqq.indexOf('('));
edit.insert(ed.selection.active, "static stub function " + xxx + "() : AccessModifier");
let spct: number = ed.selection.start.character;
edit.insert(ed.selection.active, "/**\n" + indentLines(spct, [
" formerly known as: " + choice,
"",
" @return the Public access modifier",
" */",
"static stub function " + xxx + "() : AccessModifier = Public"
]));
}
}
@ -217,25 +354,16 @@ export function activate(context: vscode.ExtensionContext) {
});
let cmd_mocha_open_doc = vscode.commands.registerCommand("mocha.zq_open_document", (item : GenericTreeDataItem) => {
console.log(item.name);
if (item.customAttributes["instanceId"])
{
let tdi = vscode.workspace.openTextDocument(vscode.Uri.file(path.join(userInfo().homedir, item.title + ".zql") ).with({ scheme: "untitled" })).then( (doc) =>
{
vscode.window.showTextDocument(doc).then((editor) =>
{
editor.edit(edit => {
edit.delete(new vscode.Range(new vscode.Position(0, 0), new vscode.Position(editor.document.lineCount - 1, editor.document.lineAt(editor.document.lineCount-1).range.end.character)))
edit.insert(new vscode.Position(0, 0), "class " + item.title + ", " + item.customAttributes["instanceId"] + " {\n\nattributes:\n name: 4$1 : text\n order, 4$7 : text\n\nrelationships:\n forMetadataWithAccessModifier, 3$11854\n\nfunctions:\n\ninstances:\n Public, 4170$1\n}");
});
});
});
vscode.commands.registerCommand("mocha.moduleExplorer.module_import_zq_implementation", (item: GenericTreeDataItem) => {
if (item.customAttributes["instanceId"]) {
openEditorForInstance(item.title, item.customAttributes["instanceId"]);
}
});
let cmd_mocha_open_doc = vscode.commands.registerCommand("mocha.zq_open_document", (item : GenericTreeDataItem) => {
if (item.customAttributes["instanceId"]) {
openEditorForInstance(item.title, item.customAttributes["instanceId"]);
}
});
// The command has been defined in the package.json file
@ -306,6 +434,46 @@ export function activate(context: vscode.ExtensionContext) {
launchSuv(machine.name);
}
});
statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 10);
statusBarItem.name = "Mocha SUV Manager";
statusBarItem.tooltip = "Choose preferred SUV";
statusBarItem.command = "mocha.suvmanager.suv_select";
// statusBarItem.setText = text => statusBarItem.text = `$(currentSuvId) ${currentSuvId || "(none)"}`;
// statusBarItem.setText();
updateStatusBarText();
updateStatusBarItemVisibility();
let cmd_suv_select = vscode.commands.registerCommand('mocha.suvmanager.suv_select', (...args) => {
if (args.length === 0) {
cp.exec('mocha suv list', (err: string, stdout: string, stderr: string) => {
vscode.window.showInformationMessage(stdout);
let list = stdout.split('\n');
let list2 = new Array<string>();
list.forEach((element) => {
if (element.trim() === "") {
return;
}
list2.push(element.trim());
});
var w = vscode.window.showQuickPick(list2, { "title": "Select Preferred SUV", "placeHolder": "Choose your preferred SUV" }).then((value) => {
if (value !== undefined) {
selectPreferredSuv(value);
}
});
});
}
else
{
let machine : Machine = args[0] as Machine;
selectPreferredSuv(machine.name);
}
});
let cmd_suv_new = vscode.commands.registerCommand('mocha.suvmanager.suv_new', () => {
outputChannel?.appendLine("Provisioning a new persistent SUV...");
@ -330,11 +498,70 @@ export function activate(context: vscode.ExtensionContext) {
});
});
context.subscriptions.push(cmd_suv_up);
context.subscriptions.push(vscode.window.onDidChangeTextEditorSelection((e) => {
if (e.textEditor.document.languageId === "zql") {
let clz = ZqParser.parse(e.textEditor.document.getText()) as ZqClass;
if (clz !== null)
{
clz.relationships.forEach(rel => {
});
}
}
}));
context.subscriptions.push(vscode.window.onDidChangeActiveTextEditor((editor) => {
if (editor?.document !== undefined) {
updateZqEditor(editor);
}
}));
}
function updateZqEditor(editor: vscode.TextEditor) {
if (editor?.document.languageId !== 'zql') {
return;
}
if (editor?.document.getText().startsWith("class ")) {
addClassDecoration(editor);
}
}
function addClassDecoration(editor : vscode.TextEditor) {
const decorations: vscode.DecorationOptions[] = [];
const myContent = new vscode.MarkdownString(editor?.document.fileName + '\n[Open in Mocha](command:myCommand?arg1)');
myContent.isTrusted = true;
const decoration = { range: new vscode.Range(new vscode.Position(0, 0), new vscode.Position(0, 0)), hoverMessage: myContent };
decorations.push(decoration);
editor.setDecorations(classDecorationType, decorations);
}
// This method is called when your extension is deactivated
export function deactivate() {}
export function selectPreferredSuv(value: string) {
currentSuvId = value;
updateStatusBarText();
updateModuleExplorerTreeView();
}
function indentLines(count: number, lines: string[]): string {
let indent: string = " ".repeat(count);
let retval: string = "";
lines.forEach(line => {
retval += indent + line + "\n";
});
retval += indent;
return retval;
}
/*
// This method is called when your extension is activated

View File

@ -0,0 +1,53 @@
// Copyright (C) 2025 Michael Becker <alcexhim@gmail.com>
//
// This file is part of mocha-vscode.
//
// mocha-vscode is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// mocha-vscode is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with mocha-vscode. If not, see <https://www.gnu.org/licenses/>.
export class InstanceKey {
static parse(value : string): InstanceKey | null {
let p = value.split('$', 2);
if (p.length === 2) {
let ik = new InstanceKey(parseInt(p[0]), parseInt(p[1]));
return ik;
}
return null;
}
private _ClassIndex : number;
public get ClassIndex() : number {
return this._ClassIndex;
}
public set ClassIndex(v : number) {
this._ClassIndex = v;
}
private _InstanceIndex : number;
public get InstanceIndex() : number {
return this._InstanceIndex;
}
public set InstanceIndex(v : number) {
this._InstanceIndex = v;
}
toString(): string {
return this.ClassIndex + "$" + this.InstanceIndex;
}
constructor(classIndex: number, instanceIndex: number) {
this._ClassIndex = classIndex;
this._InstanceIndex = instanceIndex;
}
}

View File

@ -2,9 +2,9 @@ import * as vscode from 'vscode';
import * as fs from 'fs';
import * as path from 'path';
import { GenericTreeDataItem } from './tdp/GenericTreeDataItem';
import { GenericTreeDataItem } from '../tdp/GenericTreeDataItem';
import { Uri } from 'vscode';
import { GenericTreeDataProvider } from './tdp/GenericTreeDataProvider';
import { GenericTreeDataProvider } from '../tdp/GenericTreeDataProvider';
export class ModuleExplorerTreeDataProvider extends GenericTreeDataProvider {

View File

@ -34,6 +34,14 @@ export class GenericTreeDataItem
public set title(v : string) {
this._title = v;
}
private _description : string = "";
public get description() : string {
return this._description;
}
public set description(v : string) {
this._description = v;
}
private _customAttributes? : Dictionary;
public get customAttributes() : Dictionary {

View File

@ -44,8 +44,9 @@ export class GenericTreeDataProvider implements vscode.TreeDataProvider<GenericT
item.command = {
command: "mocha.zq_open_document",
arguments: [ element ],
title: "OpenFile"
title: "OpenFile",
};
item.description = element.description;
item.iconPath = this.getIconPath(element);
/*

53
src/zq/ZqAttribute.ts Normal file
View File

@ -0,0 +1,53 @@
// Copyright (C) 2025 Michael Becker <alcexhim@gmail.com>
//
// This file is part of mocha-vscode.
//
// mocha-vscode is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// mocha-vscode is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with mocha-vscode. If not, see <https://www.gnu.org/licenses/>.
import { InstanceKey } from "../mocha/core/InstanceKey";
import { ZqInstance } from "./ZqInstance";
export class ZqAttribute extends ZqInstance {
private _dataType : string | null;
public get dataType() : string | null {
return this._dataType;
}
public set dataType(v : string | null) {
this._dataType = v;
}
constructor(name: string, instanceKey: InstanceKey | null, dataType: string | null) {
super();
this.name = name;
this.instanceKey = instanceKey;
this._dataType = dataType;
}
toString(): string {
let s: string = "";
s += this.name;
if (this.instanceKey !== null) {
s += ", " + this.instanceKey.toString();
}
if (this.dataType !== null) {
s += ": " + this.dataType;
}
return s;
}
}

84
src/zq/ZqClass.ts Normal file
View File

@ -0,0 +1,84 @@
// Copyright (C) 2025 Michael Becker <alcexhim@gmail.com>
//
// This file is part of mocha-vscode.
//
// mocha-vscode is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// mocha-vscode is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with mocha-vscode. If not, see <https://www.gnu.org/licenses/>.
import { ZqInstance } from "./ZqInstance";
export class ZqClass extends ZqInstance {
toString(): string {
let r = "";
r += "class " + this.name;
if (this.instanceKey !== null) {
r += ", " + this.instanceKey.toString();
}
r += " {\n";
r += "\n";
r += "attributes:\n";
if (this.attributes.length > 0) {
this.attributes.forEach(attr => {
r += " " + attr.name;
if (attr.instanceKey !== null) {
r += ", " + attr.instanceKey.toString();
}
if (attr.dataType !== null) {
r += ": " + attr.dataType;
}
r += "\n";
});
}
r += "\n";
r += "relationships:\n";
if (this.relationships.length > 0) {
this.relationships.forEach(rel => {
r += " " + rel.name;
if (rel.instanceKey !== null) {
r += ", " + rel.instanceKey.toString();
}
r += "\n";
});
}
r += "\n";
r += "functions:\n";
if (this.functions.length > 0) {
this.functions.forEach(func => {
r += func.toString();
r += "\n";
});
}
r += "\n";
r += "instances:\n";
if (this.instances.length > 0) {
this.instances.forEach(inst => {
r += " " + inst.name;
if (inst.instanceKey !== null) {
r += ", " + inst.instanceKey.toString();
}
r += "\n";
});
}
r += "\n";
r += "}\n";
return r;
}
}

View File

@ -0,0 +1,21 @@
// Copyright (C) 2025 Michael Becker <alcexhim@gmail.com>
//
// This file is part of mocha-vscode.
//
// mocha-vscode is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// mocha-vscode is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with mocha-vscode. If not, see <https://www.gnu.org/licenses/>.
class ZqDocumentLinkProvider
{
}

View File

@ -0,0 +1,88 @@
// Copyright (C) 2025 Michael Becker <alcexhim@gmail.com>
//
// This file is part of mocha-vscode.
//
// mocha-vscode is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// mocha-vscode is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with mocha-vscode. If not, see <https://www.gnu.org/licenses/>.
import { ZqObject } from "./ZqObject";
export class ZqFunctionDefinition extends ZqObject {
private _isPublished : boolean = false;
public get isPublished() : boolean {
return this._isPublished;
}
public set isPublished(v : boolean) {
this._isPublished = v;
}
private _isStatic : boolean = false;
public get isStatic() : boolean {
return this._isStatic;
}
public set isStatic(v : boolean) {
this._isStatic = v;
}
private _isStub: boolean = false;
public get isStub() : boolean {
return this._isStub;
}
public set isStub(v : boolean) {
this._isStub = v;
}
private _returnValue : string | undefined;
public get returnValue() : string | undefined {
return this._returnValue;
}
public set returnValue(v : string | undefined) {
this._returnValue = v;
}
private _returnDataType : string | undefined;
public get returnDataType() : string | undefined {
return this._returnDataType;
}
public set returnDataType(v : string | undefined) {
this._returnDataType = v;
}
toString(): string {
let r = "";
if (this.isPublished) {
r += "published ";
}
if (this.isStatic) {
r += "static ";
}
if (this.isStub) {
r += "stub ";
}
r += "function " + this.name + "(";
r += ")";
if (this.returnDataType !== undefined) {
r += " : " + this.returnDataType;
}
if (this.returnValue !== undefined) {
r += " = " + this.returnValue;
}
return r;
}
}

30
src/zq/ZqGenerator.ts Normal file
View File

@ -0,0 +1,30 @@
// Copyright (C) 2025 Michael Becker <alcexhim@gmail.com>
//
// This file is part of mocha-vscode.
//
// mocha-vscode is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// mocha-vscode is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with mocha-vscode. If not, see <https://www.gnu.org/licenses/>.
export class ZqGenerator
{
generateClass(title : string, instanceId : string, attributes : string[]) : string
{
let retval: string = "class " + title.replaceAll(' ', '').replaceAll('-', '_') + ", " + instanceId + " {\n\n";
retval += "attributes: \n name, 4$1: text\n order, 4$7: text\n\nrelationships: \n forMetadataWithAccessModifier, 3$11854\n\n" +
"functions: \n static function getMethodAccessPublicInstance() : AccessModifier = Public\n" +
" static stub function getMostRestrictiveFromSet(accessModifier_Nonsingular_ : AccessModifier*) : AccessModifier = Public\n" +
"\ninstances: \n Public, 4170$1\n" +
"\n}";
return retval;
}
}

71
src/zq/ZqInstance.ts Normal file
View File

@ -0,0 +1,71 @@
// Copyright (C) 2025 Michael Becker <alcexhim@gmail.com>
//
// This file is part of mocha-vscode.
//
// mocha-vscode is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// mocha-vscode is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with mocha-vscode. If not, see <https://www.gnu.org/licenses/>.
import { InstanceKey } from "../mocha/core/InstanceKey";
import { ZqFunctionDefinition } from "./ZqFunctionDefinition";
import { ZqAttribute } from "./ZqAttribute";
import { ZqInstanceReference } from "./ZqInstanceReference";
import { ZqObject } from "./ZqObject";
import { ZqRelationship } from "./ZqRelationship";
export class ZqInstance extends ZqObject {
private _instanceKey: InstanceKey | null = null;
public get instanceKey() : InstanceKey | null {
return this._instanceKey;
}
public set instanceKey(v : InstanceKey | null) {
this._instanceKey = v;
}
private _attributes : ZqAttribute[] = [ ];
public get attributes() : ZqAttribute[] {
return this._attributes;
}
public set attributes(v : ZqAttribute[]) {
this._attributes = v;
}
private _relationships : ZqRelationship[] = [ ];
public get relationships() : ZqRelationship[] {
return this._relationships;
}
public set relationships(v : ZqRelationship[]) {
this._relationships = v;
}
private _functions : ZqFunctionDefinition[] = [ ];
public get functions() : ZqFunctionDefinition[] {
return this._functions;
}
public set functions(v : ZqFunctionDefinition[]) {
this._functions = v;
}
private _instances : ZqInstanceReference[] = [ ];
public get instances() : ZqInstanceReference[] {
return this._instances;
}
public set instances(v : ZqInstanceReference[]) {
this._instances = v;
}
}

View File

@ -0,0 +1,46 @@
// Copyright (C) 2025 Michael Becker <alcexhim@gmail.com>
//
// This file is part of mocha-vscode.
//
// mocha-vscode is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// mocha-vscode is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with mocha-vscode. If not, see <https://www.gnu.org/licenses/>.
import { InstanceKey } from "../mocha/core/InstanceKey";
import { ZqObject } from "./ZqObject";
export class ZqInstanceReference extends ZqObject {
private _instanceKey : InstanceKey | null;
public get instanceKey() : InstanceKey | null {
return this._instanceKey;
}
public set instanceKey(v : InstanceKey | null) {
this._instanceKey = v;
}
constructor(name: string, instanceKey: InstanceKey | null) {
super();
this.name = name;
this._instanceKey = instanceKey;
}
toString(): string {
let r = "";
r += this.name;
if (this.instanceKey !== null) {
r += ", " + this.instanceKey.toString();
}
return r;
}
}

40
src/zq/ZqObject.ts Normal file
View File

@ -0,0 +1,40 @@
// Copyright (C) 2025 Michael Becker <alcexhim@gmail.com>
//
// This file is part of mocha-vscode.
//
// mocha-vscode is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// mocha-vscode is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with mocha-vscode. If not, see <https://www.gnu.org/licenses/>.
import { ZqObjectDefinition } from "./ZqObjectDefinition";
export class ZqObject {
private _name : string = "";
public get name() : string {
return this._name;
}
public set name(v : string) {
this._name = v;
}
private _definition : ZqObjectDefinition = new ZqObjectDefinition(0, 0);
public get definition() : ZqObjectDefinition {
return this._definition;
}
public set definition(v : ZqObjectDefinition) {
this._definition = v;
}
}

View File

@ -0,0 +1,42 @@
// Copyright (C) 2025 Michael Becker <alcexhim@gmail.com>
//
// This file is part of mocha-vscode.
//
// mocha-vscode is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// mocha-vscode is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with mocha-vscode. If not, see <https://www.gnu.org/licenses/>.
export class ZqObjectDefinition {
private _lineIndex : number = 0;
public get lineIndex() : number {
return this._lineIndex;
}
public set lineIndex(v : number) {
this._lineIndex = v;
}
private _columnIndex : number = 0;
public get columnIndex() : number {
return this._columnIndex;
}
public set columnIndex(v : number) {
this._columnIndex = v;
}
constructor(lineIndex: number, columnIndex: number) {
this.lineIndex = lineIndex;
this.columnIndex = columnIndex;
}
}

38
src/zq/ZqRelationship.ts Normal file
View File

@ -0,0 +1,38 @@
// Copyright (C) 2025 Michael Becker <alcexhim@gmail.com>
//
// This file is part of mocha-vscode.
//
// mocha-vscode is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// mocha-vscode is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with mocha-vscode. If not, see <https://www.gnu.org/licenses/>.
import { InstanceKey } from "../mocha/core/InstanceKey";
import { ZqInstanceReference } from "./ZqInstanceReference";
export class ZqRelationship extends ZqInstanceReference {
constructor(name: string, instanceKey: InstanceKey | null) {
super(name, instanceKey);
}
toString(): string {
let s: string = "";
s += this.name;
if (this.instanceKey !== null) {
s += ", " + this.instanceKey.toString();
}
return s;
}
}

186
src/zq/parser/ZqParser.ts Normal file
View File

@ -0,0 +1,186 @@
// Copyright (C) 2025 Michael Becker <alcexhim@gmail.com>
//
// This file is part of mocha-vscode.
//
// mocha-vscode is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// mocha-vscode is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with mocha-vscode. If not, see <https://www.gnu.org/licenses/>.
import { InstanceKey } from "../../mocha/core/InstanceKey";
import { StringExtensions } from "../../StringExtensions";
import { ZqAttribute } from "../ZqAttribute";
import { ZqClass } from "../ZqClass";
import { ZqFunctionDefinition } from "../ZqFunctionDefinition";
import { ZqInstanceReference } from "../ZqInstanceReference";
import { ZqObject } from "../ZqObject";
import { ZqRelationship } from "../ZqRelationship";
import { ZqParserContext } from "./ZqParserContext";
import { ZqTokenInfo } from "./ZqTokenInfo";
export class ZqParser {
static parse(line: string): ZqObject {
let idx: number = 0;
let insideBlock: boolean = false;
let nextStatic: boolean = false;
let nextStub: boolean = false;
let retval: any = null;
let ctx: ZqParserContext = new ZqParserContext(line);
while (!ctx.endOfStream) {
let token: ZqTokenInfo | null = ctx.readToken();
if (token !== null) {
if (token.value === "{") {
insideBlock = true;
}
else if (token.value === "static") {
nextStatic = true;
}
else if (token.value === "stub") {
nextStub = true;
}
else if (token.value === "class") {
let obj = parseClass(line, token.nextStart);
return obj;
}
else if (token.value === "function") {
let obj = new ZqFunctionDefinition();
let re = new RegExp("(public|private|protected)?\\s*(static)?\\s*(stub)?\\s*(function)\\s*(\\w*)\\s*\\(((\\s*\\w*\\s*\\:\\s*\\w*\\*?\\,?)*)\\)\\s*\\:\\s*(\\w*\\*?)\\s*(?:=\\s*(\\w*))?");
let result = re.exec(line);
let returnDataType = result?.at(8);
if (returnDataType !== undefined) {
obj.returnDataType = returnDataType;
}
let returnValue = result?.at(9);
if (returnValue !== undefined) {
obj.returnValue = returnValue;
}
obj.isStatic = nextStatic;
obj.isStub = nextStub;
obj.name = line.substring(token.nextStart, line.indexOf('(', token.nextStart)).trim();
token.nextStart = token.nextStart + obj.name.length + 1;
retval = obj;
}
line = line.substring(token.nextStart).trim();
// idx = token.NextStart;
idx = 0;
}
}
return retval;
}
}
function parseClass(line: string, NextStart: number) {
let obj = new ZqClass();
let re = new RegExp("class\\s*(\\w*)(?:\\s*,\\s*(\\d*\\$\\d*))?");
let result = re.exec(line);
if (result !== null) {
let r = result.at(0);
if (r !== undefined) {
let name: string | undefined = result.at(1);
let instanceKey: string | undefined = result.at(2);
if (name !== undefined) {
obj.name = name;
}
if (instanceKey !== undefined) {
obj.instanceKey = InstanceKey.parse(instanceKey);
}
line = line.substring(r.length).trim();
}
}
if (line.startsWith("{") && line.endsWith("}"))
{
let i: number = 0;
let section: string = "";
let ctx: ZqParserContext = new ZqParserContext(line.substring(1, line.length - 2).trim());
while (!ctx.endOfStream) {
if (section === "attributes") {
let line = ctx.readLine();
if (line === '') {
section = "";
continue;
}
let re = new RegExp("\\s*(\\w*)\\s*(?:,\\s*(\\d*\\$\\d*))\\s*:\\s*(\\w*)\\s*");
let result = re.exec(line);
let name = result?.at(1);
let instanceKey = result?.at(2);
let dataType = result?.at(3);
if (name !== undefined && instanceKey !== undefined && dataType !== undefined) {
obj.attributes.push(new ZqAttribute(name, InstanceKey.parse(instanceKey), dataType));
}
}
else if (section === "relationships" || section === "instances") {
let line = ctx.readLine();
if (line === '') {
section = "";
continue;
}
let re = new RegExp("\\s*(\\w*)\\s*,\\s*(\\d*\\$\\d*)");
let result = re.exec(line);
let name = result?.at(1);
let instanceKey = result?.at(2);
if (name !== undefined) {
let instanceKeyObj: InstanceKey | null = null;
if (instanceKey !== undefined) {
instanceKeyObj = InstanceKey.parse(instanceKey);
}
if (section === "relationships") {
let rel = new ZqRelationship(name, instanceKeyObj);
rel.definition.columnIndex = ctx.columnIndex;
rel.definition.lineIndex = ctx.lineIndex;
obj.relationships.push(rel);
}
else if (section === "instances") {
obj.instances.push(new ZqInstanceReference(name, instanceKeyObj));
}
}
}
else if (section === "") {
let tok = ctx.readToken();
if (tok !== null) {
if (tok.token === ":") {
section = tok.value;
ctx.readLine();
}
}
}
else {
// unknown section, let's just skip over it
section = "";
while (true) {
let line = ctx.readLine();
if (line === "") {
break;
}
}
}
}
let t = null;
}
return obj;
}

View File

@ -0,0 +1,123 @@
// Copyright (C) 2025 Michael Becker <alcexhim@gmail.com>
//
// This file is part of mocha-vscode.
//
// mocha-vscode is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// mocha-vscode is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with mocha-vscode. If not, see <https://www.gnu.org/licenses/>.
import { StringExtensions } from "../../StringExtensions";
import { ZqTokenInfo } from "./ZqTokenInfo";
export class ZqParserContext {
private _value: string = "";
public get value(): string {
return this._value;
}
private _currentIndex: number = 0;
public get currentIndex(): number {
return this._currentIndex;
}
public get currentValue(): string {
return this.value.substring(this.currentIndex);
}
public get endOfStream(): boolean {
return this.currentIndex >= this.value.length;
}
private _lineIndex : number = 0;
public get lineIndex() : number {
return this._lineIndex;
}
public set lineIndex(v : number) {
this._lineIndex = v;
}
private _columnIndex : number = 0;
public get columnIndex() : number {
return this._columnIndex;
}
public set columnIndex(v : number) {
this._columnIndex = v;
}
constructor(value: string) {
this._value = value;
}
readLine() : string {
let idxNewline = this._value.indexOf("\n", this._currentIndex);
let retval = this._value.substring(this._currentIndex);
if (idxNewline > -1) {
retval = this._value.substring(this._currentIndex, idxNewline);
this._currentIndex += retval.length + 1;
this._lineIndex++;
this._columnIndex = 0;
}
else {
this._currentIndex += retval.length;
this._lineIndex++;
this._columnIndex = 0;
}
return retval;
}
readChars(count: number) {
let before: string = this._value.substring(this._currentIndex, this._currentIndex + count);
this._currentIndex += count;
return before;
}
readToken(): ZqTokenInfo | null {
let end = this._value.length;
let token = "";
let index = StringExtensions.indexOfAnyEx(this._value, [' ', '(', '{', ':'], this._currentIndex);
if (index.Index > -1) {
token = index.Needle;
end = index.Index;
}
let tok : ZqTokenInfo | null = null;
let val = this._value.substring(this._currentIndex, end);
if (val === '' && this._value.length > 0) {
tok = new ZqTokenInfo(this._value.substring(this._currentIndex, end + 1), end + 1);
} else {
tok = new ZqTokenInfo(val, end);
}
this._currentIndex += val.length + token.length;
tok.token = token;
return tok;
/*
const id = line.indexOf('function');
const id2 = line.indexOf('(', id);
let name: string = "";
if (id > -1) {
name = line.substring(id + 'function'.length, id2).trim();
}
return null;
*/
}
}

View File

@ -0,0 +1,53 @@
// Copyright (C) 2025 Michael Becker <alcexhim@gmail.com>
//
// This file is part of mocha-vscode.
//
// mocha-vscode is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// mocha-vscode is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with mocha-vscode. If not, see <https://www.gnu.org/licenses/>.
export class ZqTokenInfo {
private _value : string;
public get value() : string {
return this._value;
}
public set value(v : string) {
this._value = v;
}
private _token : string = "";
public get token() : string {
return this._token;
}
public set token(v : string) {
this._token = v;
}
private _nextStart : number;
public get nextStart() : number {
return this._nextStart;
}
public set nextStart(v : number) {
this._nextStart = v;
}
constructor(value: string, nextStart: number) {
this._value = value;
this._nextStart = nextStart;
}
}