Skip to content

Commit 2307c06

Browse files
authored
Merge pull request #632 from isc-bsaviano/fix-363
Jump to corresponding location in "other" document if server api version is 4 or greater
2 parents d9bdf3b + 7107f25 commit 2307c06

File tree

1 file changed

+122
-4
lines changed

1 file changed

+122
-4
lines changed

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) {

0 commit comments

Comments
 (0)