Skip to content

Commit 5c624a9

Browse files
committed
Merge remote-tracking branch 'upstream/master' into ws-folder-servers
2 parents 824c003 + 56e5d8c commit 5c624a9

File tree

12 files changed

+499
-294
lines changed

12 files changed

+499
-294
lines changed

package.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,10 @@
287287
"command": "vscode-objectscript.newFile.kpi",
288288
"when": "false"
289289
},
290+
{
291+
"command": "vscode-objectscript.newFile.message",
292+
"when": "false"
293+
},
290294
{
291295
"command": "vscode-objectscript.importLocalFilesServerSide",
292296
"when": "false"
@@ -654,6 +658,11 @@
654658
"command": "vscode-objectscript.newFile.dtl",
655659
"when": "workspaceFolderCount != 0",
656660
"group": "file"
661+
},
662+
{
663+
"command": "vscode-objectscript.newFile.message",
664+
"when": "workspaceFolderCount != 0",
665+
"group": "file"
657666
}
658667
]
659668
},
@@ -1120,6 +1129,11 @@
11201129
"command": "vscode-objectscript.newFile.dtl",
11211130
"title": "Data Transformation"
11221131
},
1132+
{
1133+
"category": "ObjectScript",
1134+
"command": "vscode-objectscript.newFile.message",
1135+
"title": "Interoperability Message"
1136+
},
11231137
{
11241138
"category": "ObjectScript",
11251139
"command": "vscode-objectscript.importLocalFilesServerSide",

src/api/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ export class AtelierAPI {
111111
if (
112112
parts.length === 2 &&
113113
(config("intersystems.servers").has(parts[0].toLowerCase()) ||
114-
vscode.workspace.workspaceFolders.find(
114+
vscode.workspace.workspaceFolders?.find(
115115
(ws) => ws.uri.scheme === "file" && ws.name.toLowerCase() === parts[0].toLowerCase()
116116
))
117117
) {

src/commands/compile.ts

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ export async function importFile(
9292
ignoreConflict?: boolean,
9393
skipDeplCheck = false
9494
): Promise<any> {
95+
if (!file) return;
9596
const api = new AtelierAPI(file.uri);
9697
if (!api.active) return;
9798
if (file.name.split(".").pop().toLowerCase() === "cls" && !skipDeplCheck) {
@@ -261,6 +262,8 @@ export async function loadChanges(files: (CurrentTextFile | CurrentBinaryFile)[]
261262
}
262263

263264
export async function compile(docs: (CurrentTextFile | CurrentBinaryFile)[], flags?: string): Promise<any> {
265+
docs = docs.filter(notNull);
266+
if (!docs.length) return;
264267
const wsFolder = vscode.workspace.getWorkspaceFolder(docs[0].uri);
265268
const conf = vscode.workspace.getConfiguration("objectscript", wsFolder || docs[0].uri);
266269
flags = flags || conf.get("compileFlags");
@@ -379,9 +382,7 @@ export async function compileOnly(askFlags = false, document?: vscode.TextDocume
379382
export async function namespaceCompile(askFlags = false): Promise<any> {
380383
const api = new AtelierAPI();
381384
const fileTypes = ["*.CLS", "*.MAC", "*.INC", "*.BAS"];
382-
if (!config("conn").active) {
383-
throw new Error(`No Active Connection`);
384-
}
385+
if (!api.active) return;
385386
const confirm = await vscode.window.showWarningMessage(
386387
`Compiling all files in namespace ${api.ns} might be expensive. Are you sure you want to proceed?`,
387388
"Cancel",
@@ -437,18 +438,20 @@ async function importFiles(files: vscode.Uri[], noCompile = false) {
437438
rateLimiter.call(async () => {
438439
return vscode.workspace.fs
439440
.readFile(uri)
440-
.then((contentBytes) => {
441-
if (isText(uri.path.split("/").pop(), Buffer.from(contentBytes))) {
442-
const textFile = currentFileFromContent(uri, new TextDecoder().decode(contentBytes));
443-
toCompile.push(textFile);
444-
return textFile;
445-
} else {
446-
return currentFileFromContent(uri, Buffer.from(contentBytes));
441+
.then((contentBytes) =>
442+
currentFileFromContent(
443+
uri,
444+
isText(uri.path.split("/").pop(), Buffer.from(contentBytes))
445+
? new TextDecoder().decode(contentBytes)
446+
: Buffer.from(contentBytes)
447+
)
448+
)
449+
.then((curFile) => {
450+
if (curFile) {
451+
if (typeof curFile.content == "string") toCompile.push(curFile); // Only compile text files
452+
return importFile(curFile).then(() => outputChannel.appendLine("Imported file: " + curFile.fileName));
447453
}
448-
})
449-
.then((curFile) =>
450-
importFile(curFile).then(() => outputChannel.appendLine("Imported file: " + curFile.fileName))
451-
);
454+
});
452455
})
453456
)
454457
);
@@ -460,6 +463,7 @@ async function importFiles(files: vscode.Uri[], noCompile = false) {
460463
}
461464

462465
export async function importFolder(uri: vscode.Uri, noCompile = false): Promise<any> {
466+
if (!(uri instanceof vscode.Uri)) return;
463467
if (filesystemSchemas.includes(uri.scheme)) return; // Not for server-side URIs
464468
if ((await vscode.workspace.fs.stat(uri)).type != vscode.FileType.Directory) {
465469
return importFiles([uri], noCompile);

src/commands/connectFolderToServerNamespace.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ export async function connectFolderToServerNamespace(): Promise<void> {
5050
items.length == 1 && !items[0].detail.startsWith("Currently")
5151
? items[0]
5252
: await vscode.window.showQuickPick(items, { title: "Pick a folder" });
53+
if (!pick) return;
5354
const folder = vscode.workspace.workspaceFolders.find((el) => el.name === pick.label);
5455
// Get user's choice of server
5556
const options: vscode.QuickPickOptions = {};

src/commands/newFile.ts

Lines changed: 107 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ export enum NewFileType {
228228
DTL = "Data Transformation",
229229
Rule = "Business Rule",
230230
KPI = "Business Intelligence KPI",
231+
Message = "Interoperability Message",
231232
}
232233

233234
interface RuleAssistClasses {
@@ -716,7 +717,10 @@ ClassMethod Transform(source As ${sourceCls}, ByRef target As ${targetCls}) As %
716717
// Prompt for the production, if required
717718
let production: string;
718719
if (Object.keys(ruleAssists).length && assistCls in ruleAssists && ruleAssists[assistCls].hasProduction) {
719-
const productions: string[] = await api.getEnsClassList(11).then((data) => data.result.content);
720+
const productions: string[] = await api
721+
.getEnsClassList(11)
722+
.then((data) => data.result.content)
723+
.catch(() => []);
720724
if (productions.length) {
721725
production = await vscode.window.showQuickPick(productions, {
722726
ignoreFocusOut: true,
@@ -827,6 +831,108 @@ ClassMethod %OnDashboardAction(pAction As %String, pContext As %ZEN.proxyObject)
827831
Return $$$OK
828832
}
829833
834+
}
835+
`;
836+
} else if (type == NewFileType.Message) {
837+
// Create the prompt for message type
838+
inputSteps.push({
839+
type: "quickPick",
840+
title: "Pick the message type",
841+
items: [
842+
{
843+
label: "Request",
844+
value: "Request",
845+
},
846+
{
847+
label: "Response",
848+
value: "Response",
849+
},
850+
],
851+
});
852+
853+
// Prompt the user
854+
const results = await multiStepInput(inputSteps);
855+
if (!results) {
856+
return;
857+
}
858+
cls = results[0];
859+
const [, desc, msgType] = results;
860+
861+
let respClass: string;
862+
if (msgType == "Request") {
863+
// Prompt the user for the response type
864+
const respClasses: vscode.QuickPickItem[] = api
865+
? await api
866+
.getEnsClassList(4)
867+
.then((data) =>
868+
data.result.content.map((label: string) => {
869+
return { label };
870+
})
871+
)
872+
.catch(() => [])
873+
: [];
874+
if (respClasses.length) {
875+
// Use a QuickPick
876+
respClass = await new Promise((resolve) => {
877+
const quickPick = vscode.window.createQuickPick();
878+
quickPick.items = respClasses;
879+
quickPick.title =
880+
"Pick an optional response class for this request. You may also enter a class name that is not in the list and press 'Enter' to use it. Press 'Escape' to skip.";
881+
quickPick.ignoreFocusOut = true;
882+
quickPick.onDidAccept(() => {
883+
const pickedClass = quickPick.selectedItems[0]?.label ?? quickPick.value.trim();
884+
if (!quickPick.selectedItems.length) {
885+
// The class name came from the value text, so validate it first
886+
const validationMsg = validateClassName(pickedClass);
887+
if (validationMsg) {
888+
// The class name is invalid
889+
vscode.window.showErrorMessage(
890+
`${validationMsg}. Please pick a class or enter a valid class name.`,
891+
"Dismiss"
892+
);
893+
} else {
894+
// The class name is valid
895+
resolve(pickedClass);
896+
quickPick.hide();
897+
}
898+
} else {
899+
// The class name came from an item so no validation is required
900+
resolve(pickedClass);
901+
quickPick.hide();
902+
}
903+
});
904+
quickPick.onDidHide(() => {
905+
resolve(undefined);
906+
quickPick.dispose();
907+
});
908+
quickPick.show();
909+
});
910+
} else {
911+
// Fall back to using an InputBox
912+
respClass = await vscode.window.showInputBox({
913+
title: "Enter an optional response class for this request. Press 'Escape' to skip.",
914+
ignoreFocusOut: true,
915+
validateInput: validateClassName,
916+
});
917+
}
918+
}
919+
920+
// Generate the file's content
921+
clsContent = `
922+
${typeof desc == "string" ? "/// " + desc.replace(/\n/g, "\n/// ") : ""}
923+
Class ${cls} Extends (%Persistent, Ens.${msgType})
924+
{
925+
${
926+
respClass
927+
? `
928+
/// The corresponding response class for this request
929+
Parameter RESPONSECLASSNAME As CLASSNAME = "${respClass}";`
930+
: ""
931+
}
932+
933+
/// InterSystems IRIS purges message bodies based on the class when the option to purge message bodies is enabled
934+
Parameter ENSPURGE As BOOLEAN = 1;
935+
830936
}
831937
`;
832938
}

0 commit comments

Comments
 (0)