Skip to content

Commit f584bc7

Browse files
Merge branch 'master' into do-1243
2 parents d98e18d + e9dba8c commit f584bc7

File tree

10 files changed

+345
-501
lines changed

10 files changed

+345
-501
lines changed

package-lock.json

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

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1799,7 +1799,7 @@
17991799
"eslint-plugin-promise": "^7.1.0",
18001800
"glob": "^11.0.1",
18011801
"globals": "^15.12.0",
1802-
"mocha": "^9.1.3",
1802+
"mocha": "^11.1.0",
18031803
"path-browserify": "^1.0.1",
18041804
"prettier": "^3.3.1",
18051805
"ts-loader": "^9.5.1",

src/commands/compile.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,16 @@ import {
2323
exportedUris,
2424
handleError,
2525
isClassDeployed,
26+
isClassOrRtn,
2627
notIsfs,
2728
notNull,
2829
outputChannel,
30+
RateLimiter,
2931
routineNameTypeRegex,
30-
throttleRequests,
3132
} from "../utils";
3233
import { StudioActions } from "./studio";
3334
import { NodeBase, PackageNode, RootNode } from "../explorer/nodes";
35+
import { updateIndexForDocument } from "../utils/documentIndex";
3436

3537
async function compileFlags(): Promise<string> {
3638
const defaultFlags = config().compileFlags;
@@ -226,6 +228,10 @@ export async function loadChanges(files: (CurrentTextFile | CurrentBinaryFile)[]
226228
file.uri,
227229
Buffer.isBuffer(content) ? content : new TextEncoder().encode(content.join("\n"))
228230
);
231+
if (isClassOrRtn(file.uri)) {
232+
// Update the document index
233+
updateIndexForDocument(file.uri, undefined, undefined, content);
234+
}
229235
exportedUris.push(file.uri.toString());
230236
} else if (filesystemSchemas.includes(file.uri.scheme)) {
231237
fileSystemProvider.fireFileChanged(file.uri);
@@ -414,9 +420,10 @@ export async function namespaceCompile(askFlags = false): Promise<any> {
414420

415421
async function importFiles(files: vscode.Uri[], noCompile = false) {
416422
const toCompile: CurrentFile[] = [];
423+
const rateLimiter = new RateLimiter(50);
417424
await Promise.allSettled<void>(
418-
files.map(
419-
throttleRequests((uri: vscode.Uri) => {
425+
files.map((uri) =>
426+
rateLimiter.call(async () => {
420427
return vscode.workspace.fs
421428
.readFile(uri)
422429
.then((contentBytes) => {
@@ -661,7 +668,7 @@ export async function importLocalFilesToServerSideFolder(wsFolderUri: vscode.Uri
661668
return;
662669
}
663670
// Filter out non-ISC files
664-
uris = uris.filter((uri) => ["cls", "mac", "int", "inc"].includes(uri.path.split(".").pop().toLowerCase()));
671+
uris = uris.filter(isClassOrRtn);
665672
if (uris.length == 0) {
666673
vscode.window.showErrorMessage("No classes or routines were selected.", "Dismiss");
667674
return;
@@ -711,9 +718,10 @@ export async function importLocalFilesToServerSideFolder(wsFolderUri: vscode.Uri
711718
docs.map((e) => e.name)
712719
);
713720
// Import the files
721+
const rateLimiter = new RateLimiter(50);
714722
return Promise.allSettled<string>(
715-
docs.map(
716-
throttleRequests((doc: { name: string; content: string; uri: vscode.Uri }) => {
723+
docs.map((doc) =>
724+
rateLimiter.call(async () => {
717725
// Allow importing over deployed classes since the XML import
718726
// command and SMP, terminal, and Studio imports allow it
719727
return importFileFromContent(doc.name, doc.content, api, false, true).then(() => {

src/commands/export.ts

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,19 @@ import { AtelierAPI } from "../api";
44
import { config, explorerProvider, OBJECTSCRIPT_FILE_SCHEMA, schemas, workspaceState } from "../extension";
55
import {
66
currentFile,
7-
currentFileFromContent,
87
exportedUris,
98
handleError,
9+
isClassOrRtn,
1010
notNull,
1111
outputChannel,
12+
RateLimiter,
1213
stringifyError,
13-
throttleRequests,
1414
uriOfWorkspaceFolder,
15+
workspaceFolderOfUri,
1516
} from "../utils";
1617
import { pickDocuments } from "../utils/documentPicker";
1718
import { NodeBase } from "../explorer/nodes";
19+
import { updateIndexForDocument } from "../utils/documentIndex";
1820

1921
export function getCategory(fileName: string, addCategory: any | boolean): string {
2022
const fileExt = fileName.split(".").pop().toLowerCase();
@@ -99,28 +101,19 @@ async function exportFile(wsFolderUri: vscode.Uri, namespace: string, name: stri
99101
throw new Error("Received malformed JSON object from server fetching document");
100102
}
101103
const content = data.result.content;
102-
103-
// Local function to update local record of mtime
104-
const recordMtime = async () => {
105-
const contentString = Buffer.isBuffer(content) ? "" : content.join("\n");
106-
const file = currentFileFromContent(fileUri, contentString);
107-
const serverTime = Number(new Date(data.result.ts + "Z"));
108-
await workspaceState.update(`${file.uniqueId}:mtime`, serverTime);
109-
};
110-
if (Buffer.isBuffer(content)) {
111-
// This is a binary file
112-
await vscode.workspace.fs.writeFile(fileUri, content);
113-
exportedUris.push(fileUri.toString());
114-
await recordMtime();
115-
log("Success");
116-
} else {
117-
// This is a text file
118-
const joinedContent = content.join("\n");
119-
await vscode.workspace.fs.writeFile(fileUri, new TextEncoder().encode(joinedContent));
120-
exportedUris.push(fileUri.toString());
121-
await recordMtime();
122-
log("Success");
104+
await vscode.workspace.fs.writeFile(
105+
fileUri,
106+
Buffer.isBuffer(content) ? content : new TextEncoder().encode(content.join("\n"))
107+
);
108+
if (isClassOrRtn(fileUri)) {
109+
// Update the document index
110+
updateIndexForDocument(fileUri, undefined, undefined, content);
123111
}
112+
exportedUris.push(fileUri.toString());
113+
const ws = workspaceFolderOfUri(fileUri);
114+
const mtime = Number(new Date(data.result.ts + "Z"));
115+
if (ws) await workspaceState.update(`${ws}:${name}:mtime`, mtime > 0 ? mtime : undefined);
116+
log("Success");
124117
} catch (error) {
125118
const errorStr = stringifyError(error);
126119
log(errorStr == "" ? "ERROR" : errorStr);
@@ -146,6 +139,7 @@ export async function exportList(files: string[], workspaceFolder: string, names
146139
const { atelier, folder, addCategory, map } = config("export", workspaceFolder);
147140
const root = wsFolderUri.fsPath + (folder.length ? path.sep + folder : "");
148141
outputChannel.show(true);
142+
const rateLimiter = new RateLimiter(50);
149143
return vscode.window.withProgress(
150144
{
151145
title: `Exporting ${files.length == 1 ? files[0] : files.length + " documents"}`,
@@ -154,8 +148,8 @@ export async function exportList(files: string[], workspaceFolder: string, names
154148
},
155149
() =>
156150
Promise.allSettled<void>(
157-
files.map(
158-
throttleRequests((file: string) =>
151+
files.map((file) =>
152+
rateLimiter.call(() =>
159153
exportFile(wsFolderUri, namespace, file, getFileName(root, file, atelier, addCategory, map))
160154
)
161155
)

src/commands/restDebugPanel.ts

Lines changed: 11 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import axios from "axios";
22
import * as httpsModule from "https";
3-
43
import * as vscode from "vscode";
54
import { AtelierAPI } from "../api";
6-
import { cspAppsForUri, handleError } from "../utils";
5+
import { handleError } from "../utils";
76
import { iscIcon } from "../extension";
87

98
interface WebviewMessage {
@@ -83,24 +82,6 @@ export class RESTDebugPanel {
8382
return;
8483
}
8584

86-
// Build the list of all non-CSP web apps
87-
const cspWebApps: string[] = cspAppsForUri(openEditor.document.uri);
88-
const allWebApps: string[] | null = await api
89-
.actionQuery("CALL %CSP.Apps_CSPAppList()", [])
90-
.then((data) => data.result.content.map((obj) => obj.AppUrl))
91-
.catch((error) => {
92-
handleError(error, "Failed to fetch the list of web applications from the server.");
93-
return null;
94-
});
95-
if (allWebApps == null) {
96-
return;
97-
}
98-
const restWebApps = allWebApps.filter((app) => !cspWebApps.includes(app));
99-
if (restWebApps.length == 0) {
100-
vscode.window.showErrorMessage("No REST web applications are configured in the server's namespace.", "Dismiss");
101-
return;
102-
}
103-
10485
if (this.currentPanel !== undefined) {
10586
// Can only have one panel open at once
10687
if (!this.currentPanel._panel.visible) {
@@ -133,10 +114,10 @@ export class RESTDebugPanel {
133114
panel.iconPath = iscIcon;
134115

135116
this._file = openEditor.document.uri;
136-
this.currentPanel = new RESTDebugPanel(panel, webviewFolderUri, api, restWebApps);
117+
this.currentPanel = new RESTDebugPanel(panel, webviewFolderUri, api);
137118
}
138119

139-
private constructor(panel: vscode.WebviewPanel, webviewFolderUri: vscode.Uri, api: AtelierAPI, webApps: string[]) {
120+
private constructor(panel: vscode.WebviewPanel, webviewFolderUri: vscode.Uri, api: AtelierAPI) {
140121
this._panel = panel;
141122
const serverInfo = `${api.config.https ? "https" : "http"}://${api.config.host}:${api.config.port}${
142123
api.config.pathPrefix
@@ -153,12 +134,7 @@ export class RESTDebugPanel {
153134
vscode.Uri.joinPath(webviewFolderUri, "elements-1.6.3.js")
154135
)}"></script>
155136
<title>${RESTDebugPanel._viewTitle}</title>
156-
<style>
157-
.path-grid {
158-
display: grid;
159-
grid-template-columns: 1fr 20fr;
160-
column-gap: 0.5rem;
161-
}
137+
<style>
162138
.component-container > * {
163139
margin: 0.5rem 0;
164140
}
@@ -168,15 +144,6 @@ export class RESTDebugPanel {
168144
vscode-tabs {
169145
display: contents;
170146
}
171-
.path-grid-container {
172-
display: flex;
173-
flex-direction: row;
174-
align-items: flex-start;
175-
justify-content: flex-start;
176-
}
177-
#webApp {
178-
max-width: 45vw;
179-
}
180147
#button {
181148
margin-top: 0.5rem;
182149
}
@@ -198,15 +165,8 @@ export class RESTDebugPanel {
198165
<vscode-tab-header id="bodyTab">BODY</vscode-tab-header>
199166
<vscode-tab-panel id="methodPathView">
200167
<section class="component-container">
201-
<p>
202-
Select a method for this request, then select the web application
203-
to use from the dropdown and enter the rest of the path in the input field
204-
next to the dropdown.
205-
</p>
206-
<p>
207-
The connection information of the server definition
208-
is shown for clarity but it cannot be edited.
209-
</p>
168+
<p>Select a method for this request, then enter the path in the bottom input field.</p>
169+
<p>The connection information of the server definition is shown, but it cannot be edited.</p>
210170
<vscode-radio-group id="method" name="method">
211171
<vscode-radio value="GET" name="method" checked>GET</vscode-radio>
212172
<vscode-radio value="POST" name="method">POST</vscode-radio>
@@ -217,14 +177,7 @@ export class RESTDebugPanel {
217177
<vscode-radio value="OPTIONS" name="method">OPTIONS</vscode-radio>
218178
</vscode-radio-group>
219179
<vscode-textfield readonly id="serverInfo"></vscode-textfield>
220-
<section class="path-grid">
221-
<section class="path-grid-container">
222-
<vscode-single-select id="webApp" name="webApp" position="below"></vscode-single-select>
223-
</section>
224-
<section class="path-grid-container">
225-
<vscode-textfield id="path" name="path" placeholder="/path" pattern="^/.*$" required></vscode-textfield>
226-
</section>
227-
</section>
180+
<vscode-textfield id="path" name="path" placeholder="/path" pattern="^/.*$" required></vscode-textfield>
228181
</section>
229182
</vscode-tab-panel>
230183
<vscode-tab-panel id="headersView">
@@ -271,13 +224,12 @@ export class RESTDebugPanel {
271224
const bodyType = document.getElementById("bodyType");
272225
const bodyContent = document.getElementById("bodyContent");
273226
const button = document.getElementById("button");
274-
const webApp = document.getElementById("webApp");
275-
const formFields = [method, serverInfo, path, headersText, paramsText, bodyType, bodyContent, webApp];
227+
const formFields = [method, serverInfo, path, headersText, paramsText, bodyType, bodyContent];
276228
const sendData = (submitted) => {
277229
const data = Object.fromEntries(new FormData(form));
278230
if (
279231
Object.keys(data).length == (formFields.length - 1) &&
280-
data.webApp != "" && data.method != "" && data.bodyType != "" &&
232+
data.method != "" && data.bodyType != "" &&
281233
(!submitted || (submitted && path.checkValidity()))
282234
) {
283235
vscode.postMessage({
@@ -290,24 +242,7 @@ export class RESTDebugPanel {
290242
window.onmessage = (event) => {
291243
const data = event.data, currentVals = new FormData(form);
292244
formFields.forEach((field) => {
293-
if (field.id == "webApp" && webApp.children.length == 0) {
294-
// Create options and set the initial value
295-
const initIdx = data.webApps.findIndex((e) => e == data.webApp) ?? 0;
296-
data.webApps.forEach((webAppStr, idx) => {
297-
const option = document.createElement("vscode-option");
298-
option.innerText = webAppStr;
299-
option.setAttribute("value",webAppStr);
300-
if (idx == initIdx) {
301-
option.selected = true;
302-
}
303-
webApp.appendChild(option);
304-
});
305-
// Update width of dropdown
306-
const longest = data.webApps.reduce((a,b) => a.length > b.length ? a : b);
307-
const context = document.createElement("canvas").getContext("2d");
308-
context.font = window.getComputedStyle(webApp,null).getPropertyValue("font");
309-
webApp.style.width = Math.ceil(context.measureText(longest).width*(4/3)) + "px";
310-
} else if (data[field.id] != undefined && currentVals.get(field.id) != data[field.id]) {
245+
if (data[field.id] != undefined && currentVals.get(field.id) != data[field.id]) {
311246
if (["method","bodyType"].includes(field.id)) {
312247
// Check the correct radio
313248
for (const c of field.children) {
@@ -341,7 +276,7 @@ export class RESTDebugPanel {
341276
// Bubble change events up to the form
342277
bodyContent.onchange = headersText.onchange =
343278
paramsText.onchange = path.onchange =
344-
webApp.onchange = () => form.dispatchEvent(new Event("change"));
279+
() => form.dispatchEvent(new Event("change"));
345280
</script>
346281
</body>
347282
</html>`;
@@ -460,7 +395,6 @@ export class RESTDebugPanel {
460395
// Restore the content
461396
this._panel.webview.postMessage({
462397
serverInfo,
463-
webApps,
464398
...RESTDebugPanel._cache,
465399
});
466400
}

src/extension.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ import {
101101
cspApps,
102102
otherDocExts,
103103
getWsServerConnection,
104+
isClassOrRtn,
104105
addWsServerRootFolderData,
105106
} from "./utils";
106107
import { ObjectScriptDiagnosticProvider } from "./providers/ObjectScriptDiagnosticProvider";
@@ -1232,7 +1233,7 @@ export async function activate(context: vscode.ExtensionContext): Promise<any> {
12321233
return Promise.all(
12331234
e.files
12341235
.filter(notIsfs)
1235-
.filter((uri) => ["cls", "inc", "int", "mac"].includes(uri.path.split(".").pop().toLowerCase()))
1236+
.filter(isClassOrRtn)
12361237
.map(async (uri) => {
12371238
// Determine the file name
12381239
const workspace = workspaceFolderOfUri(uri);

src/providers/DocumentContentProvider.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { AtelierAPI } from "../api";
55

66
import { getFileName } from "../commands/export";
77
import { config, FILESYSTEM_SCHEMA, FILESYSTEM_READONLY_SCHEMA, OBJECTSCRIPT_FILE_SCHEMA } from "../extension";
8-
import { currentWorkspaceFolder, notIsfs, uriOfWorkspaceFolder } from "../utils";
8+
import { currentWorkspaceFolder, isClassOrRtn, notIsfs, uriOfWorkspaceFolder } from "../utils";
99
import { getUrisForDocument } from "../utils/documentIndex";
1010

1111
export function compareConns(
@@ -52,7 +52,7 @@ export class DocumentContentProvider implements vscode.TextDocumentContentProvid
5252
if (!notIsfs(wsFolder.uri)) return;
5353
const conf = vscode.workspace.getConfiguration("objectscript.export", wsFolder);
5454
const confFolder = conf.get("folder", "");
55-
if (["cls", "mac", "int", "inc"].includes(name.split(".").pop().toLowerCase())) {
55+
if (isClassOrRtn(name)) {
5656
// Use the document index to find the local URI
5757
const uris = getUrisForDocument(name, wsFolder);
5858
switch (uris.length) {

0 commit comments

Comments
 (0)