Skip to content

Commit e3d3baf

Browse files
LeoAndersisc-bsavianogjsjohnmurraybot
authored
Sync with upstream master (InterSystems official) (#21)
* Add command for showing all class members, including inherited (intersystems-community#1656) * Copy Windows filesystem file correctly to isfs filesystem (intersystems-community#1658) * Allow opening low-code editors from read-only file systems (intersystems-community#1655) * Skip compilation of web app files that do not require it (intersystems-community#1660) * Lite Terminal shell integration improvements (intersystems-community#1654) * Enable Terminal Completion via Language Server (intersystems-community#1661) * Prepare 3.2.0 release (intersystems-community#1662) * auto bump version with release --------- Co-authored-by: Brett Saviano <[email protected]> Co-authored-by: John Murray <[email protected]> Co-authored-by: ProjectBot <[email protected]>
1 parent ffc47fe commit e3d3baf

13 files changed

+346
-102
lines changed

CHANGELOG.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,21 @@
11
# Change Log
22

3+
## [3.2.0] 06-Oct-2025
4+
Minimum VS Code version is now 1.104.0.
5+
- Enhancements
6+
- Better error handling when expanding InterSystems and Projects Explorers (#1652)
7+
- Allow opening low-code editors from read-only file systems (#1655)
8+
- Add command for showing all class members, including inherited (#1656)
9+
- Allow commands to be re-run in the Lite Terminal from VS Code shell integration without user confirmation (#1654)
10+
- Allow pasting of multi-line content into Lite Terminal `READ` prompts (#1654)
11+
- Fixes
12+
- Fix stringification of `AggregateError` (#1651)
13+
- Work around VS Code bug to allow re-running of multi-line commands in Lite Terminal from VS Code shell integration (#1654)
14+
- Correctly capture Lite Terminal command output in shell integration (#1654)
15+
- Fix some edge cases where the Lite Terminal cursor and text could get out of sync (#1654)
16+
- Copy Windows filesystem file correctly to `isfs` filesystem (#1658)
17+
- Upgrade dependencies (#1650, #1653)
18+
319
## [3.0.6] 09-Sep-2025
420
- Enhancements
521
- Add `objectscript.unitTest.enabled` setting (#1627)

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ To unlock these features (optional):
5555

5656
1. Download and install a beta version from GitHub. This is necessary because Marketplace does not allow publication of extensions that use proposed APIs.
5757
- Go to https://github.com/intersystems-community/vscode-objectscript/releases
58-
- Locate the beta immediately above the release you installed from Marketplace. For instance, if you installed `3.0.6`, look for `3.0.7-beta.1`. This will be functionally identical to the Marketplace version apart from being able to use proposed APIs.
59-
- Download the VSIX file (for example `vscode-objectscript-3.0.7-beta.1.vsix`) and install it. One way to install a VSIX is to drag it from your download folder and drop it onto the list of extensions in the Extensions view of VS Code.
58+
- Locate the beta immediately above the release you installed from Marketplace. For instance, if you installed `3.2.0`, look for `3.2.1-beta.1`. This will be functionally identical to the Marketplace version apart from being able to use proposed APIs.
59+
- Download the VSIX file (for example `vscode-objectscript-3.2.1-beta.1.vsix`) and install it. One way to install a VSIX is to drag it from your download folder and drop it onto the list of extensions in the Extensions view of VS Code.
6060

6161
2. From [Command Palette](https://code.visualstudio.com/docs/getstarted/tips-and-tricks#_command-palette) choose `Preferences: Configure Runtime Arguments`.
6262
3. In the argv.json file that opens, add this line (required for both Stable and Insiders versions of VS Code):

package-lock.json

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "vscode-objectscript",
33
"displayName": "InterSystems ObjectScript",
44
"description": "InterSystems ObjectScript language support for Visual Studio Code",
5-
"version": "3.0.7-SNAPSHOT",
5+
"version": "3.2.1-SNAPSHOT",
66
"icon": "images/logo.png",
77
"aiKey": "InstrumentationKey=9cd75d51-697c-406c-a929-2bcf46e97c64;IngestionEndpoint=https://eastus2-4.in.applicationinsights.azure.com/;LiveEndpoint=https://eastus2.livediagnostics.monitor.azure.com/;ApplicationId=a431c56f-8ccc-4b99-b5e9-fce3763215b1",
88
"categories": [
@@ -48,7 +48,7 @@
4848
}
4949
],
5050
"engines": {
51-
"vscode": "^1.93.0"
51+
"vscode": "^1.104.0"
5252
},
5353
"enabledApiProposals": [
5454
"fileSearchProvider",
@@ -225,7 +225,11 @@
225225
},
226226
{
227227
"command": "vscode-objectscript.showClassDocumentationPreview",
228-
"when": "editorLangId == objectscript-class && activeCustomEditorId == ''"
228+
"when": "false"
229+
},
230+
{
231+
"command": "vscode-objectscript.showAllClassMembers",
232+
"when": "false"
229233
},
230234
{
231235
"command": "vscode-objectscript.exportCurrentFile",
@@ -535,14 +539,14 @@
535539
"command": "vscode-objectscript.showClassDocumentationPreview",
536540
"group": "navigation@3",
537541
"when": "editorLangId == objectscript-class && activeCustomEditorId == ''"
542+
},
543+
{
544+
"command": "vscode-objectscript.showAllClassMembers",
545+
"group": "[email protected]",
546+
"when": "vscode-objectscript.connectActive && editorLangId == objectscript-class && activeCustomEditorId == ''"
538547
}
539548
],
540549
"editor/title/context": [
541-
{
542-
"command": "vscode-objectscript.showClassDocumentationPreview",
543-
"group": "1_open",
544-
"when": "resourceLangId == objectscript-class && activeCustomEditorId == ''"
545-
},
546550
{
547551
"command": "vscode-objectscript.showRESTDebugWebview",
548552
"group": "1_open",
@@ -1194,6 +1198,12 @@
11941198
"command": "vscode-objectscript.openISCDocument",
11951199
"title": "Open InterSystems Document...",
11961200
"icon": "$(go-to-file)"
1201+
},
1202+
{
1203+
"category": "ObjectScript",
1204+
"command": "vscode-objectscript.showAllClassMembers",
1205+
"title": "Show All Class Members",
1206+
"icon": "$(symbol-class)"
11971207
}
11981208
],
11991209
"keybindings": [
@@ -1805,7 +1815,7 @@
18051815
"test": "node ./out/test/runTest.js",
18061816
"lint": "eslint src/**",
18071817
"lint-fix": "eslint --fix src/**",
1808-
"download-api": "dts dev 1.93.0",
1818+
"download-api": "dts dev 1.104.0",
18091819
"postinstall": "npm run download-api"
18101820
},
18111821
"devDependencies": {
@@ -1816,7 +1826,7 @@
18161826
"@types/mocha": "^7.0.2",
18171827
"@types/node": "20.17.6",
18181828
"@types/semver": "7.5.4",
1819-
"@types/vscode": "1.93.0",
1829+
"@types/vscode": "1.104.0",
18201830
"@types/ws": "8.18.0",
18211831
"@types/xmldom": "^0.1.34",
18221832
"@typescript-eslint/eslint-plugin": "^8.15.0",

src/commands/compile.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import {
2626
handleError,
2727
isClassDeployed,
2828
isClassOrRtn,
29+
isCompilable,
2930
lastUsedLocalUri,
3031
notIsfs,
3132
notNull,
@@ -333,7 +334,7 @@ export async function importAndCompile(
333334
throw error;
334335
})
335336
.then(() => {
336-
if (compileFile) compile([file], flags);
337+
if (compileFile && isCompilable(file.name)) compile([file], flags);
337338
});
338339
}
339340

@@ -369,7 +370,7 @@ export async function compileOnly(askFlags = false, document?: vscode.TextDocume
369370

370371
const defaultFlags = config().compileFlags;
371372
const flags = askFlags ? await compileFlags() : defaultFlags;
372-
if (!file.fileName.startsWith("\\.vscode\\")) {
373+
if (isCompilable(file.name)) {
373374
compile([file], flags);
374375
}
375376
}
@@ -444,7 +445,7 @@ async function importFiles(files: vscode.Uri[], noCompile = false) {
444445
)
445446
.then((curFile) => {
446447
if (curFile) {
447-
if (typeof curFile.content == "string") toCompile.push(curFile); // Only compile text files
448+
if (typeof curFile.content == "string" && isCompilable(curFile.name)) toCompile.push(curFile);
448449
return importFile(curFile).then(() => outputChannel.appendLine("Imported file: " + curFile.fileName));
449450
}
450451
});

src/commands/documaticPreviewPanel.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,10 @@ export class DocumaticPreviewPanel {
3838
*/
3939
public static currentPanel: DocumaticPreviewPanel | undefined;
4040

41-
public static create(): void {
41+
public static create(uri: vscode.Uri): void {
4242
// Get the open document and check that it's an ObjectScript class
43-
const openEditor = vscode.window.activeTextEditor;
43+
const uriString = uri.toString();
44+
const openEditor = vscode.window.visibleTextEditors.find((e) => e.document.uri.toString() == uriString);
4445
if (openEditor === undefined) {
4546
// Need an open document to preview
4647
return;
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
import * as vscode from "vscode";
2+
import { AtelierAPI } from "../api";
3+
import { clsLangId, lsExtensionId } from "../extension";
4+
import { currentFile, handleError, stripClassMemberNameQuotes } from "../utils";
5+
import { DocumentContentProvider } from "../providers/DocumentContentProvider";
6+
7+
export async function showAllClassMembers(uri: vscode.Uri): Promise<void> {
8+
try {
9+
// Determine the name of the class
10+
const uriString = uri.toString();
11+
const textDocument = vscode.workspace.textDocuments.find((td) => td.uri.toString() == uriString);
12+
if (textDocument?.languageId != clsLangId) {
13+
vscode.window.showErrorMessage("The document in the active text editor is not a class definition.", "Dismiss");
14+
return;
15+
}
16+
const file = currentFile(textDocument);
17+
if (!file) {
18+
vscode.window.showErrorMessage("The class definition in the active text editor is malformed.", "Dismiss");
19+
return;
20+
}
21+
const cls = file.name.slice(0, -4);
22+
const api = new AtelierAPI(file.uri);
23+
if (!api.active) {
24+
vscode.window.showErrorMessage("Showing all members of a class requires an active server connection.", "Dismiss");
25+
return;
26+
}
27+
// Get an array of all members
28+
const members: {
29+
Name: string;
30+
Origin: string;
31+
MemberType: "f" | "i" | "m" | "p" | "j" | "a" | "q" | "s" | "t" | "x";
32+
Info: string;
33+
}[] = await api
34+
.actionQuery(
35+
`SELECT Name, Origin, MemberType, Info FROM (
36+
SELECT Name, Origin, 'f' AS MemberType, Parent, Internal, NotInheritable, '('||REPLACE(Properties,',',', ')||') References '||ReferencedClass||(CASE WHEN ReferencedKey IS NOT NULL THEN '('||ReferencedKey||')' ELSE '' END) AS Info FROM %Dictionary.CompiledForeignKey UNION
37+
SELECT Name, Origin, 'i' AS MemberType, Parent, Internal, NotInheritable, (CASE WHEN Properties LIKE '%,%' THEN 'On ('||REPLACE(Properties,',',', ')||') ' WHEN Properties IS NOT NULL THEN 'On '||Properties||' ' ELSE '' END)||(CASE WHEN Type IS NOT NULL THEN '[ Type = '||Type||' ]' ELSE '' END) AS Info FROM %Dictionary.CompiledIndex WHERE NOT (Name %STARTSWITH '$') UNION
38+
SELECT Name, Origin, 'm' AS MemberType, Parent, Internal, NotInheritable, '('||(CASE WHEN FormalSpec IS NULL THEN '' ELSE REPLACE(REPLACE(FormalSpec,',',', '),'=',' = ') END)||')'||(CASE WHEN ReturnType IS NOT NULL THEN ' As '||ReturnType||(CASE WHEN ReturnTypeParams IS NOT NULL THEN '('||REPLACE(ReturnTypeParams,'=',' = ')||')' ELSE '' END) ELSE '' END) AS Info FROM %Dictionary.CompiledMethod WHERE Stub IS NULL UNION
39+
SELECT Name, Origin, 'p' AS MemberType, Parent, Internal, NotInheritable, CASE WHEN Expression IS NOT NULL THEN Expression WHEN _Default IS NOT NULL THEN _Default ELSE Type END AS Info FROM %Dictionary.CompiledParameter UNION
40+
SELECT Name, Origin, 'j' AS MemberType, Parent, Internal, NotInheritable, Type AS Info FROM %Dictionary.CompiledProjection UNION
41+
SELECT Name, Origin, 'a' AS MemberType, Parent, Internal, NotInheritable, CASE WHEN Collection IS NOT NULL THEN Collection||' Of '||Type ELSE Type END AS Info FROM %Dictionary.CompiledProperty UNION
42+
SELECT Name, Origin, 'q' AS MemberType, Parent, Internal, NotInheritable, '('||(CASE WHEN FormalSpec IS NULL THEN '' ELSE REPLACE(REPLACE(FormalSpec,',',', '),'=',' = ') END)||') As '||Type AS Info FROM %Dictionary.CompiledQuery UNION
43+
SELECT Name, Origin, 's' AS MemberType, Parent, Internal, NotInheritable, Type AS Info FROM %Dictionary.CompiledStorage UNION
44+
SELECT Name, Origin, 't' AS MemberType, Parent, Internal, NotInheritable, Event||' '||_Time||' '||Foreach AS Info FROM %Dictionary.CompiledTrigger UNION
45+
SELECT Name, Origin, 'x' AS MemberType, Parent, Internal, 0 AS NotInheritable, MimeType||(CASE WHEN SUBSTR(MimeType,-4) = '/xml' AND XMLNamespace IS NOT NULL THEN ' ('||XMLNamespace||')' ELSE '' END) AS Info FROM %Dictionary.CompiledXData
46+
) WHERE Parent = ? AND ((NotInheritable = 0 AND Internal = 0) OR (Origin = Parent)) ORDER BY Name`.replaceAll(
47+
"\n",
48+
" "
49+
),
50+
[cls]
51+
)
52+
.then((data) => data?.result?.content ?? []);
53+
if (!members.length) {
54+
vscode.window.showWarningMessage(
55+
"The server returned no members for this class. If members are expected, re-compile the class then try again.",
56+
"Dismiss"
57+
);
58+
return;
59+
}
60+
// Prompt the user to pick one
61+
const member = await vscode.window.showQuickPick(
62+
// Convert the query rows into QuickPickItems
63+
members.map((m) => {
64+
const [iconId, memberType] = (() => {
65+
switch (m.MemberType) {
66+
case "m":
67+
return ["method", "Method"];
68+
case "q":
69+
return ["function", "Query"];
70+
case "t":
71+
return ["event", "Trigger"];
72+
case "p":
73+
return ["constant", "Parameter"];
74+
case "i":
75+
return ["array", "Index"];
76+
case "f":
77+
return ["key", "ForeignKey"];
78+
case "x":
79+
return ["struct", "XData"];
80+
case "s":
81+
return ["object", "Storage"];
82+
case "j":
83+
return ["interface", "Projection"];
84+
default:
85+
return ["property", "Property"];
86+
}
87+
})();
88+
let detail = m.Info;
89+
if ("mq".includes(m.MemberType)) {
90+
// Need to beautify the argument list
91+
detail = "";
92+
let inQuotes = false;
93+
let braceDepth = 0;
94+
for (const c of m.Info) {
95+
if (c == '"') {
96+
inQuotes = !inQuotes;
97+
detail += c;
98+
continue;
99+
}
100+
if (!inQuotes) {
101+
if (c == "{") {
102+
braceDepth++;
103+
detail += c;
104+
continue;
105+
} else if (c == "}") {
106+
braceDepth = Math.max(0, braceDepth - 1);
107+
detail += c;
108+
continue;
109+
}
110+
}
111+
if (!inQuotes && braceDepth == 0 && ":&*=".includes(c)) {
112+
detail += c == ":" ? " As " : c == "&" ? "ByRef " : c == "*" ? "Output " : " = ";
113+
} else {
114+
detail += c;
115+
}
116+
}
117+
}
118+
return {
119+
label: m.Name,
120+
description: m.Origin,
121+
detail,
122+
iconPath: new vscode.ThemeIcon(`symbol-${iconId}`),
123+
memberType,
124+
};
125+
}),
126+
{
127+
title: `All members of ${cls}`,
128+
placeHolder: "Pick a member to show it in the editor",
129+
}
130+
);
131+
if (!member) return;
132+
// Show the picked member
133+
const targetUri =
134+
member.description == cls
135+
? uri
136+
: DocumentContentProvider.getUri(
137+
`${member.description}.cls`,
138+
undefined,
139+
undefined,
140+
undefined,
141+
vscode.workspace.getWorkspaceFolder(uri)?.uri
142+
);
143+
const symbols = (
144+
await vscode.commands.executeCommand<vscode.DocumentSymbol[]>("vscode.executeDocumentSymbolProvider", targetUri)
145+
)[0]?.children;
146+
// Find the symbol for this member
147+
const memberType = member.memberType.toLowerCase();
148+
const symbol = symbols?.find(
149+
(s) =>
150+
stripClassMemberNameQuotes(s.name) == member.label &&
151+
(memberType == "method"
152+
? s.detail.toLowerCase().includes(memberType)
153+
: memberType == "property"
154+
? ["property", "relationship"].includes(s.detail.toLowerCase())
155+
: s.detail.toLowerCase() == memberType)
156+
);
157+
if (!symbol) {
158+
vscode.window.showErrorMessage(
159+
`Did not find ${member.memberType} '${member.label}' in class '${member.description}'.`,
160+
"Dismiss"
161+
);
162+
return;
163+
}
164+
// If Language Server is active, selectionRange is the member name.
165+
// Else, range is the first line of the member definition excluding description.
166+
const position = vscode.extensions.getExtension(lsExtensionId)?.isActive
167+
? symbol.selectionRange.start
168+
: symbol.range.start;
169+
await vscode.window.showTextDocument(targetUri, {
170+
selection: new vscode.Range(position, position),
171+
preview: false,
172+
});
173+
} catch (error) {
174+
handleError(error, "Failed to show all class members.");
175+
}
176+
}

0 commit comments

Comments
 (0)