-
Notifications
You must be signed in to change notification settings - Fork 0
/
extension.ts
168 lines (144 loc) · 5.59 KB
/
extension.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
"use strict";
import * as vscode from 'vscode';
const LUA_MODE: vscode.DocumentFilter = { language: 'lua', scheme: 'file' };
const EXT_TAG = "APICO-API-VSCode";
// api method list
const api = {
"functions": [
{
"description": "Toggle devmode.",
"name": "api_set_devmode",
"variants": [{
"arguments": [{
"description": "Whether to set devmode to true or false.",
"name": "bool",
"type": "boolean"
}]
}]
}
]
}
// handle suggestions
function getSuggestions(line: string, currentWord: string) {
var results: vscode.CompletionItem[] = [];
// check as long as not blank
if (currentWord == "") {
// find all functions
let funcs = api.functions;
for (let i = 0; i < funcs.length; i++) {
let newItem = new vscode.CompletionItem(funcs[i].name, vscode.CompletionItemKind.Function);
newItem.detail = EXT_TAG;
newItem.documentation = funcs[i].description;
results.push(newItem);
}
return results;
} else {
results = [];
return results;
}
}
// handle signatures
class APISignatureHelpProvider implements vscode.SignatureHelpProvider {
public provideSignatureHelp(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): Promise<vscode.SignatureHelp | null> {
let theCall = this.walkBackwardsToBeginningOfCall(document, position);
if (theCall == null) {
return Promise.resolve(null);
}
// Find the name of the function that's being called
let functionNameRange = this.previousTokenPosition(document, theCall.openParen);
let functionName = document.getText(functionNameRange!);
// Find the full method call
let currentLine = document.lineAt(position.line).text.substring(0, position.character);
let fullMethodCall = currentLine.trim().split('(')[0];
let result = new vscode.SignatureHelp();
let si: vscode.SignatureInformation;
result.activeParameter = theCall.commas.length;
let functionData = this.getFunctionData(functionName, api.functions);
si = new vscode.SignatureInformation(functionName);
si.documentation = functionData.description;
let params: vscode.ParameterInformation[] = [];
si.parameters = params;
console.log("Result:", result);
result.signatures.push(si);
result.activeSignature = 0;
result.activeParameter = Math.min(theCall.commas.length, si.parameters.length - 1);
result.activeSignature = 0;
return Promise.resolve(result);
}
// return the matching function from the api
private getFunctionData(targetFunction: string, functions: any) {
for (let i = 0; i < functions.length; i++) {
if (targetFunction == functions[i].name) {
return functions[i];
}
}
}
// helper to get token position
private previousTokenPosition(document: vscode.TextDocument, position: vscode.Position): Range|null {
while (position.character > 0) {
let word = document.getWordRangeAtPosition(position);
if (word) {
return word;
}
position = position.translate(0, -1);
}
return null;
}
// helper to get start of suggestion
private walkBackwardsToBeginningOfCall(document: vscode.TextDocument, position: vscode.Position): { openParen: vscode.Position, commas: vscode.Position[] }|null {
let currentLine = document.lineAt(position.line).text.substring(0, position.character);
let parenBalance = 0;
let commas = [];
for (let char = position.character; char >= 0; char--) {
switch (currentLine[char]) {
case '(':
parenBalance--;
if (parenBalance < 0) {
return {
openParen: new vscode.Position(position.line, char),
commas: commas
};
}
break;
case ')':
parenBalance++;
break;
case ',':
if (parenBalance === 0) {
commas.push(new vscode.Position(position.line, char));
}
}
}
return null;
}
}
// handle completion suggestions
const completionProvider = vscode.languages.registerCompletionItemProvider(LUA_MODE, {
provideCompletionItems(document: vscode.TextDocument, position: vscode.Position): vscode.CompletionItem[] {
// let filename = document.fileName;
let lineText = document.lineAt(position.line).text;
// let lineTillCurrentPosition = lineText.substr(0, position.character);
let wordAtPosition = document.getWordRangeAtPosition(position);
let currentWord = '';
if (wordAtPosition && wordAtPosition.start.character < position.character) {
let word = document.getText(wordAtPosition);
currentWord = word.substr(0, position.character - wordAtPosition.start.character);
}
// Check through the list of functions that are included in this file and see if any match
// the starting letter of the word we have so far
let suggestions: vscode.CompletionItem[] = getSuggestions(lineText, currentWord);
return suggestions;
}
}, '.')
// handle function suggestions
const signatureProvider = vscode.languages.registerSignatureHelpProvider(LUA_MODE,
new APISignatureHelpProvider(vscode.workspace.getConfiguration('lua')['docsTool']),
'(', ',');
// this method is called when your extension is activated
// your extension is activated the very first time the command is executed
export function activate(context: vscode.ExtensionContext) {
// register stuff
context.subscriptions.push(signatureProvider, completionProvider)
}
// this method is called when your extension is deactivated
export function deactivate() {}