Skip to content

Commit c6087e8

Browse files
committed
go to macros definition
1 parent 9a89504 commit c6087e8

5 files changed

+106
-30
lines changed

Diff for: api/index.ts

+27-17
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export class AtelierAPI {
3737
this._config = conn;
3838
}
3939

40-
request(method: string, path?: string, params?: any, headers?: any, body?: any): Promise<any> {
40+
async request(method: string, path?: string, body?: any, params?: any, headers?: any): Promise<any> {
4141
if (!this._config.active) {
4242
return Promise.reject();
4343
}
@@ -146,7 +146,7 @@ export class AtelierAPI {
146146
type?: string;
147147
filter?: string;
148148
}): Promise<any> {
149-
return this.request('GET', `v3/${this.ns}/docnames/${category}/${type}`, {
149+
return this.request('GET', `v3/${this.ns}/docnames/${category}/${type}`, null, {
150150
filter,
151151
generated
152152
});
@@ -164,35 +164,45 @@ export class AtelierAPI {
164164

165165
putDoc(name: string, data: { enc: boolean; content: string[] }, ignoreConflict?: boolean): Promise<any> {
166166
let params = { ignoreConflict };
167-
return this.request('PUT', `v3/${this.ns}/doc/${name}`, params, {}, data);
167+
return this.request('PUT', `v3/${this.ns}/doc/${name}`, data, params);
168168
}
169169

170170
actionIndex(docs: string[]): Promise<any> {
171-
return this.request('POST', `v3/${this.ns}/action/index`, {}, {}, docs);
171+
return this.request('POST', `v3/${this.ns}/action/index`, docs);
172172
}
173173

174174
actionSearch(params: { query: string; files?: string; sys?: boolean; gen?: boolean; max?: number }): Promise<any> {
175-
return this.request('GET', `v3/${this.ns}/action/search`, params, {});
175+
return this.request('GET', `v3/${this.ns}/action/search`, null, params);
176176
}
177177

178178
actionQuery(query: string, parameters: string[]): Promise<any> {
179-
return this.request(
180-
'POST',
181-
`v3/${this.ns}/action/query`,
182-
{},
183-
{},
184-
{
185-
query,
186-
parameters
187-
}
188-
);
179+
return this.request('POST', `v3/${this.ns}/action/query`, {
180+
query,
181+
parameters
182+
});
189183
}
190184

191185
actionCompile(docs: string[], flags?: string, source = false): Promise<any> {
192-
return this.request('POST', `v3/${this.ns}/action/compile`, { flags, source }, {}, docs);
186+
return this.request('POST', `v3/${this.ns}/action/compile`, docs, { flags, source });
193187
}
194188

195189
cvtXmlUdl(source: string): Promise<any> {
196-
return this.request('POST', `v3/${this.ns}/cvt/xml/doc`, {}, { 'Content-Type': 'application/xml' }, source);
190+
return this.request('POST', `v3/${this.ns}/cvt/xml/doc`, source, {}, { 'Content-Type': 'application/xml' });
191+
}
192+
193+
getmacrodefinition(docname: string, macroname: string, includes: string[]) {
194+
return this.request('POST', `v3/${this.ns}/action/getmacrodefinition`, {
195+
docname,
196+
macroname,
197+
includes
198+
});
199+
}
200+
201+
getmacrolocation(docname: string, macroname: string, includes: string[]) {
202+
return this.request('POST', `v3/${this.ns}/action/getmacrolocation`, {
203+
docname,
204+
macroname,
205+
includes
206+
});
197207
}
198208
}

Diff for: providers/ObjectScriptDefinitionProvider.ts

+23
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import * as vscode from 'vscode';
22
import { DocumentContentProvider } from './DocumentContentProvider';
3+
import { AtelierAPI } from '../api';
4+
import { ClassDefinition } from '../utils/classDefinition';
5+
import { currentFile } from '../utils';
36

47
export class ObjectScriptDefinitionProvider implements vscode.DefinitionProvider {
58
provideDefinition(
@@ -9,6 +12,16 @@ export class ObjectScriptDefinitionProvider implements vscode.DefinitionProvider
912
): vscode.ProviderResult<vscode.Location | vscode.Location[] | vscode.DefinitionLink[]> {
1013
let lineText = document.lineAt(position.line).text;
1114

15+
let macroRange = document.getWordRangeAtPosition(position, /\${3}\b\w+\b/);
16+
let macroText = macroRange ? document.getText(macroRange) : '';
17+
let macroMatch = macroText.match(/^\${3}(\b\w+\b)$/);
18+
if (macroMatch) {
19+
let fileName = currentFile().name;
20+
let [, macro] = macroMatch;
21+
return this.macro(fileName, macro).then(
22+
data => new vscode.Location(DocumentContentProvider.getUri(data.document), new vscode.Position(data.line, 0))
23+
);
24+
}
1225
let asClass = /(\b(?:Of|As|Extends)\b %?\b[a-zA-Z][a-zA-Z0-9]+(?:\.[a-zA-Z][a-zA-Z0-9]+)*\b(?! of))/i;
1326
let parts = lineText.split(asClass);
1427
let pos = 0;
@@ -149,4 +162,14 @@ export class ObjectScriptDefinitionProvider implements vscode.DefinitionProvider
149162
targetUri: DocumentContentProvider.getUri(name)
150163
};
151164
}
165+
166+
async macro(fileName: string, macro: string): Promise<{ document: string; line: number }> {
167+
const api = new AtelierAPI();
168+
let includes = [];
169+
if (fileName.toLowerCase().endsWith('cls')) {
170+
let classDefinition = new ClassDefinition(fileName);
171+
includes = await classDefinition.includeCode();
172+
}
173+
return api.getmacrolocation(fileName, macro, includes).then(data => data.result.content);
174+
}
152175
}

Diff for: providers/ObjectScriptHoverProvider.ts

+28-6
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ import commands = require('./completion/commands.json');
44
import systemFunctions = require('./completion/systemFunctions.json');
55
import systemVariables = require('./completion/systemVariables.json');
66
import structuredSystemVariables = require('./completion/structuredSystemVariables.json');
7+
import { currentFile } from '../utils/index.js';
8+
import { AtelierAPI } from '../api/index.js';
9+
import { ClassDefinition } from '../utils/classDefinition.js';
710

811
export class ObjectScriptHoverProvider implements vscode.HoverProvider {
912
provideHover(
@@ -19,21 +22,25 @@ export class ObjectScriptHoverProvider implements vscode.HoverProvider {
1922
let text = document.getText(
2023
new vscode.Range(new vscode.Position(position.line, 0), new vscode.Position(position.line, word.end.character))
2124
);
25+
let file = currentFile();
2226

2327
let dollarsMatch = text.match(/(\^?\$+)(\b\w+\b)$/);
2428
if (dollarsMatch) {
25-
let [search, dollars] = dollarsMatch;
29+
let range = document.getWordRangeAtPosition(position, /\^?\$+\b\w+\b$/);
30+
let [search, dollars, value] = dollarsMatch;
2631
search = search.toUpperCase();
27-
if (dollars === '$' || dollars === '^$') {
32+
if (dollars === '$$$') {
33+
return this.macro(file.name, value).then(contents => ({
34+
range,
35+
contents: [contents.join('')]
36+
}));
37+
} else if (dollars === '$' || dollars === '^$') {
2838
let found = systemFunctions.find(el => el.label === search || el.alias.includes(search));
2939
found = found || systemVariables.find(el => el.label === search || el.alias.includes(search));
3040
found = found || structuredSystemVariables.find(el => el.label === search || el.alias.includes(search));
3141
if (found) {
3242
return {
33-
range: new vscode.Range(
34-
new vscode.Position(word.start.line, word.start.character - dollars.length),
35-
new vscode.Position(word.end.line, word.end.character)
36-
),
43+
range,
3744
contents: [found.documentation.join(''), this.documentationLink(found.link)]
3845
};
3946
}
@@ -43,6 +50,21 @@ export class ObjectScriptHoverProvider implements vscode.HoverProvider {
4350
return null;
4451
}
4552

53+
async macro(fileName: string, macro: string): Promise<string[]> {
54+
const api = new AtelierAPI();
55+
let includes = [];
56+
if (fileName.toLowerCase().endsWith('cls')) {
57+
let classDefinition = new ClassDefinition(fileName);
58+
includes = await classDefinition.includeCode();
59+
}
60+
return api
61+
.getmacrodefinition(fileName, macro, includes)
62+
.then(data =>
63+
data.result.content.definition.map((line: string) => (line.match(/^\s*#def/) ? line : `#define ${line}`))
64+
)
65+
.then(data => ['```objectscript\n', ...data, '\n```']);
66+
}
67+
4668
commands(document: vscode.TextDocument, position: vscode.Position): vscode.ProviderResult<vscode.Hover> {
4769
let word = document.getWordRangeAtPosition(position);
4870
let text = document.getText(

Diff for: providers/WorkspaceSymbolProvider.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export class WorkspaceSymbolProvider implements vscode.WorkspaceSymbolProvider {
2525
return result.map(el => {
2626
let item;
2727
let [className, method] = el.ID.split('||');
28-
let uri = DocumentContentProvider.getUri(ClassDefinition.normalizeClassName(className));
28+
let uri = DocumentContentProvider.getUri(ClassDefinition.normalizeClassName(className, true));
2929
if (method) {
3030
item = {
3131
name: method,

Diff for: utils/classDefinition.ts

+27-6
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
import { AtelierAPI } from '../api';
22

33
export class ClassDefinition {
4-
public static normalizeClassName(className): string {
5-
return className.replace(/^%(\b\w+\b)$/, '%Library.$1') + '.cls';
4+
private _className: string;
5+
private _classFileName: string;
6+
public static normalizeClassName(className, withExtension = false): string {
7+
return className.replace(/^%(\b\w+\b)$/, '%Library.$1') + (withExtension ? '.cls' : '');
68
}
79

8-
constructor(private _className: string) {
9-
this._className = ClassDefinition.normalizeClassName(_className);
10+
constructor(className: string) {
11+
if (className.endsWith('.cls')) {
12+
className = className.replace(/\.cls$/i, '');
13+
}
14+
this._className = ClassDefinition.normalizeClassName(className, false);
15+
this._classFileName = ClassDefinition.normalizeClassName(className, true);
1016
}
1117

1218
async methods(scope: 'any' | 'class' | 'instance'): Promise<any[]> {
@@ -17,13 +23,28 @@ export class ClassDefinition {
1723
let extend = [];
1824
content.forEach(el => {
1925
methods.push(...el.content.methods);
20-
extend.push(...el.content.super.map(extendName => ClassDefinition.normalizeClassName(extendName)));
26+
extend.push(...el.content.super.map(extendName => ClassDefinition.normalizeClassName(extendName, true)));
2127
});
2228
if (extend.length) {
2329
return api.actionIndex(extend).then(data => getMethods(data.result.content));
2430
}
2531
return methods.filter(filterScope);
2632
};
27-
return api.actionIndex([this._className]).then(data => getMethods(data.result.content));
33+
return api.actionIndex([this._classFileName]).then(data => getMethods(data.result.content));
34+
}
35+
36+
async includeCode(): Promise<string[]> {
37+
const api = new AtelierAPI();
38+
let sql = `SELECT LIST(IncludeCode) List FROM %Dictionary.CompiledClass WHERE Name %INLIST (
39+
SELECT $LISTFROMSTRING(PrimarySuper, '~') FROM %Dictionary.CompiledClass WHERE Name = ?)`;
40+
let defaultIncludes = ['%occInclude', '%occErrors'];
41+
return api
42+
.actionQuery(sql, [this._className])
43+
.then(data =>
44+
data.result.content.reduce(
45+
(list: string[], el: { List: string }) => list.concat(el.List.split(',')),
46+
defaultIncludes
47+
)
48+
);
2849
}
2950
}

0 commit comments

Comments
 (0)