Skip to content

Commit a965cdf

Browse files
authored
Merge branch 'master' into fix-595
2 parents 5cf8319 + 2fcd0b8 commit a965cdf

File tree

6 files changed

+171
-25
lines changed

6 files changed

+171
-25
lines changed

package.json

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,7 @@
402402
]
403403
},
404404
{
405-
"id": "objectscript-output",
405+
"id": "vscode-objectscript-output",
406406
"mimetypes": [
407407
"text/x-code-output"
408408
]
@@ -936,6 +936,16 @@
936936
"description": "Automatically show terminal when connected to docker-compose.",
937937
"type": "boolean",
938938
"default": false
939+
},
940+
"objectscript.compileOnSave": {
941+
"description": "Automatically compile an InterSystems file when saved in the editor.",
942+
"type": "boolean",
943+
"default": true
944+
},
945+
"objectscript.multilineMethodArgs": {
946+
"markdownDescription": "List method arguments on multiple lines, if the server supports it. **NOTE:** Only supported on IRIS 2019.1.2, 2020.1.1+, 2021.1.0+ and subsequent versions! On all other versions, this setting will have no effect.",
947+
"type": "boolean",
948+
"default": false
939949
}
940950
}
941951
},

src/api/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -426,13 +426,16 @@ export class AtelierAPI {
426426
// api v1+
427427
public getDoc(name: string, format?: string): Promise<Atelier.Response<Atelier.Document>> {
428428
let params = {};
429+
if (!format && config("multilineMethodArgs") && this._config.apiVersion >= 4) {
430+
format = "udl-multiline";
431+
}
429432
if (format) {
430433
params = {
431434
format,
432435
};
433436
}
434437
name = this.transformNameIfCsp(name);
435-
return this.request(1, "GET", `${this.ns}/doc/${name}`, params);
438+
return this.request(1, "GET", `${this.ns}/doc/${name}`, null, params);
436439
}
437440

438441
// api v1+

src/commands/compile.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,11 @@ async function compile(docs: CurrentFile[], flags?: string): Promise<any> {
240240
.then(loadChanges);
241241
}
242242

243-
export async function importAndCompile(askFlags = false, document?: vscode.TextDocument): Promise<any> {
243+
export async function importAndCompile(
244+
askFlags = false,
245+
document?: vscode.TextDocument,
246+
compileFile = true
247+
): Promise<any> {
244248
const file = currentFile(document);
245249
if (!file) {
246250
return;
@@ -260,7 +264,15 @@ export async function importAndCompile(askFlags = false, document?: vscode.TextD
260264
})
261265
.then(() => {
262266
if (!file.fileName.startsWith("\\.vscode\\")) {
263-
compile([file], flags);
267+
if (compileFile) {
268+
compile([file], flags);
269+
} else {
270+
if (file.uri.scheme === FILESYSTEM_SCHEMA || file.uri.scheme === FILESYSTEM_READONLY_SCHEMA) {
271+
// Fire the file changed event to avoid VSCode alerting the user on the next save that
272+
// "The content of the file is newer."
273+
fileSystemProvider.fireFileChanged(file.uri);
274+
}
275+
}
264276
}
265277
});
266278
}

src/commands/jumpToTagAndOffset.ts

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,20 @@ export async function jumpToTagAndOffset(): Promise<void> {
1616
return;
1717
}
1818

19-
// Build map of labels in routine
20-
const map = new Map();
21-
const options = [];
22-
for (let i = 0; i < document.lineCount; i++) {
23-
const labelMatch = document.lineAt(i).text.match(/^(%?\w+).*/);
24-
if (labelMatch) {
25-
map.set(labelMatch[1], i);
26-
options.push(labelMatch[1]);
27-
}
28-
}
29-
30-
const items: vscode.QuickPickItem[] = options.map((option) => {
31-
return { label: option };
32-
});
19+
// Get the labels from the document symbol provider
20+
const map = new Map<string, number>();
21+
const symbols: vscode.DocumentSymbol[] = await vscode.commands.executeCommand(
22+
"vscode.executeDocumentSymbolProvider",
23+
document.uri
24+
);
25+
const items: vscode.QuickPickItem[] = symbols
26+
.filter((symbol) => symbol.kind === vscode.SymbolKind.Method)
27+
.map((symbol) => {
28+
map.set(symbol.name, symbol.range.start.line);
29+
return {
30+
label: symbol.name,
31+
};
32+
});
3333
const quickPick = vscode.window.createQuickPick();
3434
quickPick.title = "Jump to Tag + Offset";
3535
quickPick.items = items;
@@ -50,7 +50,7 @@ export async function jumpToTagAndOffset(): Promise<void> {
5050
return;
5151
}
5252
} else {
53-
offset += parseInt(map.get(parts[0]), 10);
53+
offset += map.get(parts[0]);
5454
}
5555
if (parts.length > 1) {
5656
offset += parseInt(parts[1], 10);

src/commands/viewOthers.ts

Lines changed: 122 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,135 @@ export async function viewOthers(): Promise<void> {
1313
return;
1414
}
1515

16-
const open = (item) => {
17-
const uri = DocumentContentProvider.getUri(item);
18-
vscode.window.showTextDocument(uri);
16+
const open = async (item: string) => {
17+
const colonidx: number = item.indexOf(":");
18+
if (colonidx !== -1) {
19+
// A location is appened to the name of the other document
20+
const options: vscode.TextDocumentShowOptions = {};
21+
22+
// Split the document name form the location
23+
let loc = item.slice(colonidx + 1);
24+
item = item.slice(0, colonidx);
25+
const uri = DocumentContentProvider.getUri(item);
26+
27+
if (item.endsWith(".cls")) {
28+
// Locations in classes are of the format method+offset+namespace
29+
loc = loc.slice(0, loc.lastIndexOf("+"));
30+
let method = loc.slice(0, loc.lastIndexOf("+"));
31+
32+
// Properly delimit method name if it contains invalid characters
33+
if (method.match(/(^([A-Za-z]|%)$)|(^([A-Za-z]|%)([A-Za-z]|\d|[^\x20-\x7F])+$)/g) === null) {
34+
method = '"' + method.replace(/"/g, '""') + '"';
35+
}
36+
37+
// Find the location of the given method in the class
38+
const symbols: vscode.DocumentSymbol[] = await vscode.commands.executeCommand(
39+
"vscode.executeDocumentSymbolProvider",
40+
uri
41+
);
42+
if (symbols !== undefined) {
43+
for (const symbol of symbols[0].children) {
44+
if (symbol.name === method) {
45+
// This is symbol that the location is in
46+
const doc = await vscode.workspace.openTextDocument(uri);
47+
48+
// Need to find the actual start of the method
49+
for (
50+
let methodlinenum = symbol.selectionRange.start.line;
51+
methodlinenum <= symbol.range.end.line;
52+
methodlinenum++
53+
) {
54+
const methodlinetext: string = doc.lineAt(methodlinenum).text.trim();
55+
if (methodlinetext.endsWith("{")) {
56+
// This is the last line of the method definition, so count from here
57+
const selectionline: number = methodlinenum + +loc.slice(loc.lastIndexOf("+") + 1);
58+
options.selection = new vscode.Range(selectionline, 0, selectionline, 0);
59+
break;
60+
}
61+
}
62+
break;
63+
}
64+
}
65+
}
66+
} else {
67+
if (item.endsWith(".mac")) {
68+
// Locations in MAC routines are of the format +offset+namespace
69+
loc = loc.slice(0, loc.lastIndexOf("+"));
70+
}
71+
// Locations in INT routines are of the format +offset
72+
const linenum: number = +loc.slice(1);
73+
options.selection = new vscode.Range(linenum, 0, linenum, 0);
74+
}
75+
vscode.window.showTextDocument(uri, options);
76+
} else {
77+
const uri = DocumentContentProvider.getUri(item);
78+
vscode.window.showTextDocument(uri);
79+
}
1980
};
2081

2182
const getOthers = (info) => {
2283
return info.result.content[0].others;
2384
};
85+
2486
const api = new AtelierAPI(file.uri);
87+
let indexarg: string = file.name;
88+
const cursorpos: vscode.Position = vscode.window.activeTextEditor.selection.active;
89+
const fileExt: string = file.name.split(".").pop().toLowerCase();
90+
91+
if (api.config.apiVersion >= 4 && (fileExt === "cls" || fileExt === "mac" || fileExt === "int")) {
92+
// Send the server the current position in the document appended to the name if it supports it
93+
let symbols: vscode.DocumentSymbol[] = await vscode.commands.executeCommand(
94+
"vscode.executeDocumentSymbolProvider",
95+
file.uri
96+
);
97+
if (symbols !== undefined) {
98+
if (fileExt === "cls") {
99+
symbols = symbols[0].children;
100+
}
101+
102+
let currentSymbol: vscode.DocumentSymbol;
103+
for (const symbol of symbols) {
104+
if (symbol.range.contains(cursorpos)) {
105+
currentSymbol = symbol;
106+
break;
107+
}
108+
}
109+
110+
if (
111+
currentSymbol !== undefined &&
112+
currentSymbol.kind === vscode.SymbolKind.Method &&
113+
currentSymbol.detail.toLowerCase() !== "query" &&
114+
currentSymbol.name.charAt(0) !== '"' &&
115+
currentSymbol.name.charAt(currentSymbol.name.length - 1) !== '"'
116+
) {
117+
// The current position is in a symbol that we can convert into a label+offset that the server understands
118+
let offset: number = cursorpos.line - currentSymbol.selectionRange.start.line;
119+
120+
if (fileExt === "cls") {
121+
// Need to find the actual start of the method
122+
const currentdoc: vscode.TextDocument = vscode.window.activeTextEditor.document;
123+
for (
124+
let methodlinenum = currentSymbol.selectionRange.start.line;
125+
methodlinenum <= currentSymbol.range.end.line;
126+
methodlinenum++
127+
) {
128+
const methodlinetext: string = currentdoc.lineAt(methodlinenum).text.trim();
129+
if (methodlinetext.endsWith("{")) {
130+
// This is the last line of the method definition, so count from here
131+
offset = cursorpos.line - methodlinenum;
132+
break;
133+
}
134+
}
135+
}
136+
137+
offset = offset < 0 ? 0 : offset;
138+
indexarg = indexarg + ":" + currentSymbol.name + "+" + offset;
139+
}
140+
}
141+
}
142+
25143
return api
26-
.actionIndex([file.name])
144+
.actionIndex([indexarg])
27145
.then((info) => {
28146
const listOthers = getOthers(info) || [];
29147
if (!listOthers.length) {

src/extension.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,7 @@ export async function activate(context: vscode.ExtensionContext): Promise<any> {
535535
workspace.onDidSaveTextDocument((file) => {
536536
if (schemas.includes(file.uri.scheme) || languages.includes(file.languageId)) {
537537
if (documentBeingProcessed !== file) {
538-
return importAndCompile(false, file);
538+
return importAndCompile(false, file, config("compileOnSave"));
539539
}
540540
}
541541
});
@@ -864,9 +864,12 @@ export async function activate(context: vscode.ExtensionContext): Promise<any> {
864864
documentSelector("objectscript-class"),
865865
new ObjectScriptClassCodeLensProvider()
866866
),
867-
vscode.languages.registerDocumentLinkProvider({ language: "objectscript-output" }, new DocumentLinkProvider()),
868867
vscode.commands.registerCommand("vscode-objectscript.compileOnly", () => compileOnly(false)),
869868
vscode.commands.registerCommand("vscode-objectscript.compileOnlyWithFlags", () => compileOnly(true)),
869+
vscode.languages.registerDocumentLinkProvider(
870+
{ language: "vscode-objectscript-output" },
871+
new DocumentLinkProvider()
872+
),
870873

871874
/* Anything we use from the VS Code proposed API */
872875
...proposed

0 commit comments

Comments
 (0)