Skip to content

Commit 7f71dfe

Browse files
committed
completion for parameters
1 parent eaecbb0 commit 7f71dfe

File tree

6 files changed

+199
-79
lines changed

6 files changed

+199
-79
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
- Intellisense. Show list of methods for ##class(SomeClass)
2020
- Go to macros definition
2121
- Go to definition for methods and properties for self object like `..Name`, `..SomeMethod()`
22+
- Added completion for class parameters
2223

2324
## [0.7.7]
2425

package-lock.json

Lines changed: 45 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,7 @@
456456
"tslint": "^5.11.0",
457457
"tslint-microsoft-contrib": "^5.2.1",
458458
"typescript": "^3.2.2",
459-
"vsce": "^1.53.2",
459+
"vsce": "^1.57.0",
460460
"vscode": "^1.1.26"
461461
},
462462
"dependencies": {

providers/ObjectScriptCompletionItemProvider.ts

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,14 @@ export class ObjectScriptCompletionItemProvider implements vscode.CompletionItem
1515
context: vscode.CompletionContext
1616
): vscode.ProviderResult<vscode.CompletionItem[] | vscode.CompletionList> {
1717
if (context.triggerKind === vscode.CompletionTriggerKind.TriggerCharacter) {
18-
if (context.triggerCharacter === '#') return this.macro(document, position, token, context);
18+
if (context.triggerCharacter === '#')
19+
return this.macro(document, position, token, context) || this.entities(document, position, token, context);
1920
if (context.triggerCharacter === '.') return this.entities(document, position, token, context);
2021
}
2122
return (
2223
this.dollarsComplete(document, position) ||
2324
this.commands(document, position) ||
25+
this.entities(document, position, token, context) ||
2426
this.macro(document, position, token, context) ||
2527
this.constants(document, position, token, context)
2628
);
@@ -195,6 +197,7 @@ export class ObjectScriptCompletionItemProvider implements vscode.CompletionItem
195197
let range = document.getWordRangeAtPosition(position, /%?\b\w+[\w\d]*\b/) || new vscode.Range(position, position);
196198
let textBefore = document.getText(new vscode.Range(new vscode.Position(position.line, 0), range.start));
197199
let curFile = currentFile();
200+
let searchText = document.getText(range);
198201

199202
const method = el => ({
200203
label: el.name,
@@ -203,27 +206,43 @@ export class ObjectScriptCompletionItemProvider implements vscode.CompletionItem
203206
insertText: new vscode.SnippetString(`${el.name}($0)`)
204207
});
205208

209+
const parameter = el => ({
210+
label: `${el.name}`,
211+
documentation: el.desc.length ? new vscode.MarkdownString(el.desc.join('')) : null,
212+
kind: vscode.CompletionItemKind.Constant,
213+
range,
214+
insertText: new vscode.SnippetString(`${el.name}`)
215+
});
216+
206217
const property = el => ({
207218
label: el.name,
208219
documentation: el.desc.length ? new vscode.MarkdownString(el.desc.join('')) : null,
209220
kind: vscode.CompletionItemKind.Property,
210221
insertText: new vscode.SnippetString(`${el.name}`)
211222
});
212223

213-
let classRef = textBefore.match(/##class\(([^)]+)\)\.$/i);
224+
const search = el => el.name.startsWith(searchText);
225+
226+
let classRef = textBefore.match(/##class\(([^)]+)\)\.#?$/i);
214227
if (classRef) {
215228
let [, className] = classRef;
216229
let classDef = new ClassDefinition(className);
217-
return classDef.methods('class').then(data => data.map(method));
230+
if (textBefore.endsWith('#')) {
231+
return classDef.parameters().then(data => data.filter(search).map(parameter));
232+
}
233+
return classDef.methods('class').then(data => data.filter(search).map(method));
218234
}
219235

220236
if (curFile.fileName.endsWith('cls')) {
221-
let selfRef = textBefore.match(/(?<!\.)\.\.$/i);
237+
let selfRef = textBefore.match(/(?<!\.)\.\.#?$/i);
222238
if (selfRef) {
223239
let classDef = new ClassDefinition(curFile.name);
240+
if (textBefore.endsWith('#')) {
241+
return classDef.parameters().then(data => data.filter(search).map(parameter));
242+
}
224243
return Promise.all([classDef.methods(), classDef.properties()]).then(data => {
225244
let [methods, properties] = data;
226-
return [...methods.map(method), ...properties.map(property)];
245+
return [...methods.filter(search).map(method), ...properties.filter(search).map(property)];
227246
});
228247
}
229248
}

providers/ObjectScriptDefinitionProvider.ts

Lines changed: 53 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ export class ObjectScriptDefinitionProvider implements vscode.DefinitionProvider
1313
let lineText = document.lineAt(position.line).text;
1414
let file = currentFile();
1515

16+
let fromClassRef = this.classRef(document, position);
17+
if (fromClassRef) {
18+
return fromClassRef;
19+
}
20+
1621
let selfRef = document.getWordRangeAtPosition(position, /\.\.%?[a-zA-Z][a-zA-Z0-9]+(?:\.[a-zA-Z][a-zA-Z0-9]+)*/);
1722
if (selfRef) {
1823
let selfEntity = document.getText(selfRef).substr(2);
@@ -39,24 +44,8 @@ export class ObjectScriptDefinitionProvider implements vscode.DefinitionProvider
3944
if (part.match(asClass)) {
4045
let [keyword, name] = part.split(' ');
4146
let start = pos + keyword.length + 1;
42-
let end = pos + part.length;
43-
if (this.isValid(position, start, end)) {
44-
return [this.makeClassDefinition(position, start, end, this.normalizeClassName(document, name))];
45-
}
46-
}
47-
pos += part.length;
48-
}
49-
50-
let classRef = /(##class\([^)]+\))/i;
51-
parts = lineText.split(classRef);
52-
pos = 0;
53-
for (let part of parts) {
54-
if (part.match(classRef)) {
55-
let [, name] = /##class\(([^)]+)\)/i.exec(part);
56-
let start = pos + 8;
57-
let end = pos + part.length - 1;
58-
if (this.isValid(position, start, end)) {
59-
return [this.makeClassDefinition(position, start, end, this.normalizeClassName(document, name))];
47+
if (this.isValid(position, start, name.length)) {
48+
return [this.makeClassDefinition(position, start, name.length, this.normalizeClassName(document, name))];
6049
}
6150
}
6251
pos += part.length;
@@ -67,25 +56,27 @@ export class ObjectScriptDefinitionProvider implements vscode.DefinitionProvider
6756
pos = 0;
6857
for (let part of parts) {
6958
if (part.match(asClassList)) {
70-
let listClasses = /\(([^)]+)\)/.exec(part)[1].split(',');
71-
for (let name of listClasses) {
72-
name = name.trim();
73-
let start = pos + part.indexOf(name);
74-
let end = start + name.length;
75-
if (this.isValid(position, start, end)) {
76-
return [this.makeClassDefinition(position, start, end, this.normalizeClassName(document, name))];
77-
}
78-
}
59+
let listClasses = /\(([^)]+)\)/.exec(part)[1].split(/\s*,\s*/);
60+
return listClasses
61+
.map(name => {
62+
name = name.trim();
63+
let start = pos + part.indexOf(name);
64+
if (this.isValid(position, start, name.length)) {
65+
return this.makeClassDefinition(position, start, name.length, this.normalizeClassName(document, name));
66+
}
67+
})
68+
.filter(el => el != null);
7969
}
8070
pos += part.length;
8171
}
8272

8373
if (lineText.match(/^#?(?:Include|IncludeGenerator) %?\b[a-zA-Z][a-zA-Z0-9]+(?:\.[a-zA-Z][a-zA-Z0-9]+)*\b/i)) {
8474
let [, name] = lineText.split(' ');
8575
let start = lineText.indexOf(' ') + 1;
86-
let end = start + name.length;
87-
if (this.isValid(position, start, end)) {
88-
return [this.makeRoutineDefinition(position, start, end, this.normalizeRoutineName(document, name, 'inc'))];
76+
if (this.isValid(position, start, name.length)) {
77+
return [
78+
this.makeRoutineDefinition(position, start, name.length, this.normalizeRoutineName(document, name, 'inc'))
79+
];
8980
}
9081
}
9182

@@ -98,9 +89,10 @@ export class ObjectScriptDefinitionProvider implements vscode.DefinitionProvider
9889
for (let name of listRoutines) {
9990
name = name.trim();
10091
let start = pos + part.indexOf(name);
101-
let end = start + name.length;
102-
if (this.isValid(position, start, end)) {
103-
return [this.makeRoutineDefinition(position, start, end, this.normalizeRoutineName(document, name, 'inc'))];
92+
if (this.isValid(position, start, name.length)) {
93+
return [
94+
this.makeRoutineDefinition(position, start, name.length, this.normalizeRoutineName(document, name, 'inc'))
95+
];
10496
}
10597
}
10698
}
@@ -110,8 +102,30 @@ export class ObjectScriptDefinitionProvider implements vscode.DefinitionProvider
110102
return [];
111103
}
112104

113-
isValid(position: vscode.Position, start: number, end: number): boolean {
114-
return position.character >= start && position.character <= end;
105+
classRef(
106+
document: vscode.TextDocument,
107+
position: vscode.Position
108+
): vscode.ProviderResult<vscode.Location | vscode.Location[] | vscode.DefinitionLink[]> {
109+
let classRef = /##class\(([^)]+)\)(?:\\$this)?\.(#?%?[a-zA-Z][a-zA-Z0-9]*)/i;
110+
let classRefRange = document.getWordRangeAtPosition(position, classRef);
111+
if (classRefRange) {
112+
let [, className, entity] = document.getText(classRefRange).match(classRef);
113+
let start = classRefRange.start.character + 8;
114+
if (this.isValid(position, start, className.length)) {
115+
return [
116+
this.makeClassDefinition(position, start, className.length, this.normalizeClassName(document, className))
117+
];
118+
} else {
119+
let classDefinition = new ClassDefinition(className);
120+
return classDefinition.getPosition(entity);
121+
}
122+
}
123+
124+
return null;
125+
}
126+
127+
isValid(position: vscode.Position, start: number, length: number): boolean {
128+
return position.character >= start && position.character <= start + length;
115129
}
116130

117131
normalizeClassName(document: vscode.TextDocument, name: string): string {
@@ -149,24 +163,24 @@ export class ObjectScriptDefinitionProvider implements vscode.DefinitionProvider
149163
return '';
150164
}
151165

152-
makeClassDefinition(position: vscode.Position, start: number, end: number, name: string): vscode.DefinitionLink {
166+
makeClassDefinition(position: vscode.Position, start: number, length: number, name: string): vscode.DefinitionLink {
153167
let firstLinePos = new vscode.Position(0, 0);
154168
return {
155169
originSelectionRange: new vscode.Range(
156170
new vscode.Position(position.line, start),
157-
new vscode.Position(position.line, end)
171+
new vscode.Position(position.line, start + length)
158172
),
159173
targetRange: new vscode.Range(firstLinePos, firstLinePos),
160174
targetUri: DocumentContentProvider.getUri(name)
161175
};
162176
}
163177

164-
makeRoutineDefinition(position: vscode.Position, start: number, end: number, name: string): vscode.DefinitionLink {
178+
makeRoutineDefinition(position: vscode.Position, start: number, length: number, name: string): vscode.DefinitionLink {
165179
let firstLinePos = new vscode.Position(0, 0);
166180
return {
167181
originSelectionRange: new vscode.Range(
168182
new vscode.Position(position.line, start),
169-
new vscode.Position(position.line, end)
183+
new vscode.Position(position.line, start + length)
170184
),
171185
targetRange: new vscode.Range(firstLinePos, firstLinePos),
172186
targetUri: DocumentContentProvider.getUri(name)

0 commit comments

Comments
 (0)