Skip to content

Add CodeLenses for BPLs, DTLs, KPIs and Rules #1303

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 3 additions & 32 deletions src/commands/newFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -555,17 +555,7 @@ Method OnProcessInput(pInput As %RegisteredObject, pOutput As %RegisteredObject)
${typeof desc == "string" ? "/// " + desc.replace(/\n/g, "\n/// ") : ""}
Class ${cls} Extends Ens.BusinessProcessBPL [ ClassType = persistent, ProcedureBlock ]
{
${
api
? `
/*
You can edit this class in the Business Process Editor by pasting the following URL into your web browser.
You can also edit this XML block directly.
${api.config.https ? "https" : "http"}://${api.config.host}:${api.config.port}${
api.config.pathPrefix
}/csp/${api.config.ns.toLowerCase()}/EnsPortal.BPLEditor.zen?BP=${cls}.BPL\n*/\n`
: ""
}

/// BPL Definition
XData BPL [ XMLNamespace = "http://www.intersystems.com/bpl" ]
{
Expand Down Expand Up @@ -652,17 +642,7 @@ Class ${cls} Extends Ens.DataTransformDTL [ DependsOn = ${
sourceCls == targetCls ? sourceCls : `(${sourceCls}, ${targetCls})`
} ]
{
${
api
? `
/*
You can edit this class in the Data Transformation Editor by pasting the following URL into your web browser.
You can also edit this XML block directly.
${api.config.https ? "https" : "http"}://${api.config.host}:${api.config.port}${
api.config.pathPrefix
}/csp/${api.config.ns.toLowerCase()}/EnsPortal.DTLEditor.zen?DT=${cls}.DTL\n*/\n`
: ""
}

Parameter IGNOREMISSINGSOURCE = 1;

Parameter REPORTERRORS = 1;
Expand Down Expand Up @@ -816,16 +796,7 @@ XData RuleDefinition [ XMLNamespace = "http://www.intersystems.com/rule" ]
${typeof desc == "string" ? "/// " + desc.replace(/\n/g, "\n/// ") : ""}
Class ${cls} Extends %DeepSee.KPI
{
${
api
? `
/*
You can test this KPI by pasting the following URL into your web browser.
${api.config.https ? "https" : "http"}://${api.config.host}:${api.config.port}${
api.config.pathPrefix
}/csp/${api.config.ns.toLowerCase()}/${cls}.cls\n*/\n`
: ""
}

Parameter DOMAIN = "${kpiDomain}";

Parameter RESOURCE = "${kpiResource == "No Resource" ? "" : kpiResource}";
Expand Down
21 changes: 21 additions & 0 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ import { FileDecorationProvider } from "./providers/FileDecorationProvider";
import { RESTDebugPanel } from "./commands/restDebugPanel";
import { modifyWsFolder } from "./commands/addServerNamespaceToWorkspace";
import { WebSocketTerminalProfileProvider, launchWebSocketTerminal } from "./commands/webSocketTerminal";
import { getCSPToken } from "./utils/getCSPToken";

const packageJson = vscode.extensions.getExtension(extensionId).packageJSON;
const extensionVersion = packageJson.version;
Expand Down Expand Up @@ -1324,6 +1325,26 @@ export async function activate(context: vscode.ExtensionContext): Promise<any> {
vscode.commands.registerCommand("vscode-objectscript.importXMLFiles", importXMLFiles),
vscode.commands.registerCommand("vscode-objectscript.exportToXMLFile", exportDocumentsToXMLFile),
vscode.commands.registerCommand("vscode-objectscript.extractXMLFileContents", extractXMLFileContents),
vscode.commands.registerCommand(
"vscode-objectscript.openPathInBrowser",
async (path: string, docUri: vscode.Uri) => {
if (typeof path == "string" && docUri && docUri instanceof vscode.Uri) {
const api = new AtelierAPI(docUri);
let uri = vscode.Uri.parse(
`${api.config.https ? "https" : "http"}://${api.config.host}:${api.config.port}${
api.config.pathPrefix
}${path}`
);
const token = await getCSPToken(api, path.split("?")[0]).catch(() => "");
if (token.length > 0) {
uri = uri.with({
query: uri.query.length ? `${uri.query}&CSPCHD=${token}` : `CSPCHD=${token}`,
});
}
vscode.env.openExternal(uri);
}
}
),

/* Anything we use from the VS Code proposed API */
...proposed
Expand Down
69 changes: 57 additions & 12 deletions src/providers/ObjectScriptCodeLensProvider.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,36 @@
import * as vscode from "vscode";
import { config } from "../extension";
import { currentFile } from "../utils";
import { AtelierAPI } from "../api";

export class ObjectScriptCodeLensProvider implements vscode.CodeLensProvider {
public provideCodeLenses(
document: vscode.TextDocument,
token: vscode.CancellationToken
): vscode.ProviderResult<vscode.CodeLens[]> {
if (document.languageId == "objectscript-class") {
return this.classMethods(document);
return this.classMembers(document);
}
if (["objectscript", "objectscript-int"].includes(document.languageId)) {
return this.routineLabels(document);
}
return [];
}

private classMethods(document: vscode.TextDocument): vscode.CodeLens[] {
private classMembers(document: vscode.TextDocument): vscode.CodeLens[] {
const file = currentFile(document);
const result = new Array<vscode.CodeLens>();

const className = file.name.split(".").slice(0, -1).join(".");

const className = file.name.slice(0, -4);
const { debugThisMethod, copyToClipboard } = config("debug");
if (!debugThisMethod && !copyToClipboard) {
// Return early if both types are turned off
return result;
}
const methodPattern = /(?:^(ClassMethod|Query)\s)([^(]+)\((.*)/i;
const xdataPattern = /^XData\s([^[{\s]+)/i;
const superPattern = new RegExp(
`^\\s*Class\\s+${className.replace(/\./g, "\\.")}\\s+Extends\\s+(?:(?:\\(([^)]+)\\))|(?:([^\\s]+)))`,

Check failure

Code scanning / CodeQL

Incomplete string escaping or encoding

This does not escape backslash characters in the input.
"i"
);
const api = new AtelierAPI(document.uri);

const pattern = /(?:^(ClassMethod|Query)\s)([^(]+)\((.*)/i;
let superclasses: string[] = [];
let inComment = false;
for (let i = 0; i < document.lineCount; i++) {
const line = document.lineAt(i);
Expand All @@ -45,8 +47,51 @@ export class ObjectScriptCodeLensProvider implements vscode.CodeLensProvider {
continue;
}

const methodMatch = text.match(pattern);
if (methodMatch) {
const methodMatch = text.match(methodPattern);
const xdataMatch = text.match(xdataPattern);
const superMatch = text.match(superPattern);
if (superMatch) {
const [, superclassesList, superclass] = superMatch;
if (superclass) {
superclasses = [superclass];
} else {
superclasses = superclassesList.replace(/\s+/g, "").split(",");
}
} else if (xdataMatch && api.active) {
let [, xdataName] = xdataMatch;
xdataName = xdataName.trim();
let cmd: vscode.Command = undefined;
if (
(xdataName == "BPL" && superclasses.includes("Ens.BusinessProcessBPL")) ||
(xdataName == "DTL" && superclasses.includes("Ens.DataTransformDTL"))
) {
cmd = {
title: "Open Graphical Editor",
command: "vscode-objectscript.openPathInBrowser",
tooltip: "Open graphical editor in an external browser",
arguments: [
`/csp/${api.config.ns.toLowerCase()}/EnsPortal.${
xdataName == "BPL" ? `BPLEditor.zen?BP=${className}.BPL` : `DTLEditor.zen?DT=${className}.DTL`
}`,
document.uri,
],
};
} else if (xdataName == "RuleDefinition" && superclasses.includes("Ens.Rule.Definition")) {
cmd = {
title: "Reopen in Graphical Editor",
command: "workbench.action.toggleEditorType",
tooltip: "Replace text editor with graphical editor",
};
} else if (xdataName == "KPI" && superclasses.includes("%DeepSee.KPI")) {
cmd = {
title: "Test KPI",
command: "vscode-objectscript.openPathInBrowser",
tooltip: "Open testing page in an external browser",
arguments: [`/csp/${api.config.ns.toLowerCase()}/${className}.cls`, document.uri],
};
}
if (cmd) result.push(new vscode.CodeLens(new vscode.Range(i, 0, i, 80), cmd));
} else if (methodMatch && (debugThisMethod || copyToClipboard)) {
const [, kind, name, paramsRaw] = methodMatch;
let params = paramsRaw;
params = params.replace(/"[^"]*"/g, '""');
Expand Down