Skip to content

Commit f07928c

Browse files
committed
go to defintion for self object
1 parent 4216eb7 commit f07928c

File tree

5 files changed

+119
-17
lines changed

5 files changed

+119
-17
lines changed

Diff for: CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
- some small fixes in the highlighting, and selecting words/variables
1919
- Intellisense. Show list of methods for ##class(SomeClass)
2020
- Go to macros definition
21+
- Go to definition for methods and properties for self object like `..Name`, `..SomeMethod()`
2122

2223
## [0.7.7]
2324

Diff for: providers/ObjectScriptCompletionItemProvider.ts

+29-11
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import systemFunctions = require('./completion/systemFunctions.json');
55
import systemVariables = require('./completion/systemVariables.json');
66
import structuredSystemVariables = require('./completion/structuredSystemVariables.json');
77
import { ClassDefinition } from '../utils/classDefinition.js';
8+
import { currentFile } from '../utils/index.js';
89

910
export class ObjectScriptCompletionItemProvider implements vscode.CompletionItemProvider {
1011
provideCompletionItems(
@@ -193,23 +194,40 @@ export class ObjectScriptCompletionItemProvider implements vscode.CompletionItem
193194
): vscode.ProviderResult<vscode.CompletionItem[] | vscode.CompletionList> {
194195
let range = document.getWordRangeAtPosition(position, /%?\b\w+[\w\d]*\b/) || new vscode.Range(position, position);
195196
let textBefore = document.getText(new vscode.Range(new vscode.Position(position.line, 0), range.start));
197+
let curFile = currentFile();
198+
199+
const method = el => ({
200+
label: el.name,
201+
documentation: el.desc.length ? new vscode.MarkdownString(el.desc.join('')) : null,
202+
kind: vscode.CompletionItemKind.Method,
203+
insertText: new vscode.SnippetString(`${el.name}($0)`)
204+
});
205+
206+
const property = el => ({
207+
label: el.name,
208+
documentation: el.desc.length ? new vscode.MarkdownString(el.desc.join('')) : null,
209+
kind: vscode.CompletionItemKind.Property,
210+
insertText: new vscode.SnippetString(`${el.name}`)
211+
});
196212

197213
let classRef = textBefore.match(/##class\(([^)]+)\)\.$/i);
198214
if (classRef) {
199215
let [, className] = classRef;
200216
let classDef = new ClassDefinition(className);
201-
return classDef.methods('class').then(methods => {
202-
let completion = [
203-
...methods.map(el => ({
204-
label: el.name,
205-
documentation: el.desc.length ? new vscode.MarkdownString(el.desc.join('')) : null,
206-
kind: vscode.CompletionItemKind.Method,
207-
insertText: new vscode.SnippetString(`${el.name}($0)`)
208-
}))
209-
];
210-
return completion;
211-
});
217+
return classDef.methods('class').then(data => data.map(method));
212218
}
219+
220+
if (curFile.fileName.endsWith('cls')) {
221+
let selfRef = textBefore.match(/(?<!\.)\.\.$/i);
222+
if (selfRef) {
223+
let classDef = new ClassDefinition(curFile.name);
224+
return Promise.all([classDef.methods(), classDef.properties()]).then(data => {
225+
let [methods, properties] = data;
226+
return [...methods.map(method), ...properties.map(property)];
227+
});
228+
}
229+
}
230+
213231
return null;
214232
}
215233
}

Diff for: providers/ObjectScriptDefinitionProvider.ts

+8
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@ export class ObjectScriptDefinitionProvider implements vscode.DefinitionProvider
1111
token: vscode.CancellationToken
1212
): vscode.ProviderResult<vscode.Location | vscode.Location[] | vscode.DefinitionLink[]> {
1313
let lineText = document.lineAt(position.line).text;
14+
let file = currentFile();
15+
16+
let selfRef = document.getWordRangeAtPosition(position, /\.\.%?[a-zA-Z][a-zA-Z0-9]+(?:\.[a-zA-Z][a-zA-Z0-9]+)*/);
17+
if (selfRef) {
18+
let selfEntity = document.getText(selfRef).substr(2);
19+
let classDefinition = new ClassDefinition(file.name);
20+
return classDefinition.getPosition(selfEntity, document);
21+
}
1422

1523
let macroRange = document.getWordRangeAtPosition(position);
1624
let macroText = macroRange ? document.getText(macroRange) : '';

Diff for: utils/classDefinition.ts

+74-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
import * as vscode from 'vscode';
12
import { AtelierAPI } from '../api';
3+
import { onlyUnique } from '.';
4+
import { DocumentContentProvider } from '../providers/DocumentContentProvider';
25

36
export class ClassDefinition {
47
private _className: string;
@@ -15,7 +18,7 @@ export class ClassDefinition {
1518
this._classFileName = ClassDefinition.normalizeClassName(className, true);
1619
}
1720

18-
async methods(scope: 'any' | 'class' | 'instance'): Promise<any[]> {
21+
async methods(scope: 'any' | 'class' | 'instance' = 'any'): Promise<any[]> {
1922
let methods = [];
2023
let filterScope = method => scope === 'any' || method.scope === scope;
2124
const api = new AtelierAPI();
@@ -28,23 +31,43 @@ export class ClassDefinition {
2831
if (extend.length) {
2932
return api.actionIndex(extend).then(data => getMethods(data.result.content));
3033
}
31-
return methods.filter(filterScope);
34+
return methods
35+
.filter(filterScope)
36+
.filter(onlyUnique)
37+
.sort();
3238
};
3339
return api.actionIndex([this._classFileName]).then(data => getMethods(data.result.content));
3440
}
3541

42+
async properties(): Promise<any[]> {
43+
let properties = [];
44+
const api = new AtelierAPI();
45+
const getProperties = content => {
46+
let extend = [];
47+
content.forEach(el => {
48+
properties.push(...el.content.properties);
49+
extend.push(...el.content.super.map(extendName => ClassDefinition.normalizeClassName(extendName, true)));
50+
});
51+
if (extend.length) {
52+
return api.actionIndex(extend).then(data => getProperties(data.result.content));
53+
}
54+
return properties.filter(onlyUnique).sort();
55+
};
56+
return api.actionIndex([this._classFileName]).then(data => getProperties(data.result.content));
57+
}
58+
3659
async super(): Promise<string[]> {
3760
const api = new AtelierAPI();
3861
let sql = `SELECT PrimarySuper FROM %Dictionary.CompiledClass WHERE Name = ?`;
39-
return api
40-
.actionQuery(sql, [this._className])
41-
.then(data =>
62+
return api.actionQuery(sql, [this._className]).then(
63+
data =>
4264
data.result.content.reduce(
4365
(list: string[], el: { PrimarySuper: string }) =>
4466
list.concat(el.PrimarySuper.split('~').filter(el => el.length)),
4567
[]
4668
)
47-
);
69+
// .filter(name => !['%Library.Base', '%Library.SystemBase'].includes(name))
70+
);
4871
}
4972

5073
async includeCode(): Promise<string[]> {
@@ -61,4 +84,49 @@ export class ClassDefinition {
6184
)
6285
);
6386
}
87+
88+
async getPosition(name: string, document: vscode.TextDocument): Promise<vscode.Location[]> {
89+
let pattern = `((Class)?Method|Property|RelationShip) ${name}(?!\w)`;
90+
let foundLine;
91+
if (document) {
92+
for (let i = 0; i < document.lineCount; i++) {
93+
let line = document.lineAt(i);
94+
if (line.text.match(pattern)) {
95+
foundLine = i;
96+
break;
97+
}
98+
}
99+
}
100+
let result: vscode.Location[] = [];
101+
if (foundLine) {
102+
result.push({
103+
uri: DocumentContentProvider.getUri(this._classFileName),
104+
range: new vscode.Range(foundLine, 0, foundLine, 0)
105+
});
106+
}
107+
let extendList = await this.super();
108+
let api = new AtelierAPI();
109+
let docs = [];
110+
extendList.forEach(async docName => {
111+
docName = ClassDefinition.normalizeClassName(docName, true);
112+
docs.push(api.getDoc(docName));
113+
});
114+
return Promise.all(docs).then((docs: any[]) => {
115+
for (let doc of docs) {
116+
if (doc && doc.result.content) {
117+
let docName = doc.result.name;
118+
let content = doc.result.content;
119+
for (let line of content.keys()) {
120+
if (content[line].match(pattern)) {
121+
result.push({
122+
uri: DocumentContentProvider.getUri(docName),
123+
range: new vscode.Range(line, 0, line, 0)
124+
});
125+
}
126+
}
127+
}
128+
}
129+
return result;
130+
});
131+
}
64132
}

Diff for: utils/index.ts

+7
Original file line numberDiff line numberDiff line change
@@ -87,3 +87,10 @@ export function currentWorkspaceFolder(): string {
8787
export function workspaceFolderUri(workspaceFolder: string): vscode.Uri {
8888
return vscode.workspace.workspaceFolders.find(el => el.name.toLowerCase() === workspaceFolder.toLowerCase()).uri;
8989
}
90+
91+
export function onlyUnique(value: any, index: number, self: any) {
92+
if (value && value.name) {
93+
return self.findIndex(el => el.name === value.name) === index;
94+
}
95+
return self.indexOf(value) === index;
96+
}

0 commit comments

Comments
 (0)