aboutsummaryrefslogtreecommitdiff
path: root/server/src/completion.ts
blob: cde63f5b4ff64c67b2a0b309bda4f33e1a1ef2b4 (plain)
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
import {
    CompletionItem,
    CompletionItemKind,
    TextDocumentPositionParams,
    TextDocuments
} from "vscode-languageserver/node";
import {execFileSync} from "node:child_process";
import {TextDocument} from "vscode-languageserver-textdocument";

export default class WingCompletion {
    public static run(_textDocumentPosition: TextDocumentPositionParams, textDocument: TextDocument): CompletionItem[] {
        let position = _textDocumentPosition.position;

        let currentLine = textDocument.getText().replace(/\r\n/g, "\n").split("\n")[position.line].trim();

        console.log(currentLine);

        let results = JSON.parse(execFileSync("wing", [ "--lint", "--base64", Buffer.from(textDocument.getText()).toString("base64") ]).toString());

        let keywords = ["function", "if", "do", "end"];
        let builtin = ["include", "require", "?!", "??", "?"];
        let replacements = [
            {
                labels: [ "dep", "deprecation", "deprecated", "old" ],
                code:  "?!Deprecated"
            },
            {
                labels: [ "err", "error", "fatal", "critical" ],
                code:  "??Error"
            },
            {
                labels: [ "warn", "warning", "alert", "notice" ],
                code:  "?Warning"
            },
            {
                labels: [ ".func", ".fun", ".fn", ".function" ],
                code:  "function name\n    -- Your code here\nend"
            },
            {
                labels: [ ".if", "cond", "condition" ],
                code:  "if condition do\n    -- Your code here\nend"
            },
            {
                labels: [ ".ifelse", "condelse", "conditionelse" ],
                code:  "if condition do\n    -- Your code here\nelse\n    -- Your code here\nend"
            }
        ];

        let replacementsList = [];

        for (let replacement of replacements) {
            for (let label of replacement.labels) {
                replacementsList.push({
                    label,
                    kind: CompletionItemKind.Snippet,
                    data: "replacement",
                    insertText: replacement.code
                })
            }
        }

        return [
            ...keywords.filter(() => currentLine.trim() === "" || currentLine.startsWith("if ") || currentLine.startsWith("else ") || !currentLine.match(/^(.+) /gm)).map((i: string) => {
                return {
                    label: i,
                    kind: CompletionItemKind.Keyword,
                    data: "keyword",
                    insertText: i,
                    commitCharacters: [" ", "$"]
                }
            }),
            ...results['functions'].filter(() => !currentLine.match(/^([a-zA-Z0-9-_]+) /gm) && !currentLine.startsWith("function ")).map((i: string) => {
                return {
                    label: i,
                    kind: CompletionItemKind.Function,
                    data: "function",
                    insertText: i,
                    commitCharacters: [" ", "$"]
                }
            }),
            ...results['variables'].filter(() => !currentLine.startsWith("function ")).map((i: string) => {
                return {
                    label: "$" + i,
                    kind: CompletionItemKind.Variable,
                    data: "variable",
                    insertText: i,
                    commitCharacters: [" ", "$"]
                }
            }),
            ...results['constants'].filter(() => !currentLine.startsWith("function ")).map((i: string) => {
                return {
                    label: "$" + i,
                    kind: CompletionItemKind.Constant,
                    data: "constant",
                    insertText: i,
                    commitCharacters: [" ", "$"]
                }
            }),
            ...results['operations'].filter(() => !!currentLine.match(/^\$([a-zA-Z0-9-_]+)( +|)</gm)).map((i: string) => {
                return {
                    label: i,
                    kind: CompletionItemKind.Operator,
                    data: "operator",
                    insertText: i,
                    commitCharacters: [" ", "$"]
                }
            }),
            ...results['conditions'].filter(() => currentLine.startsWith("if ") || currentLine.startsWith("else if ")).map((i: string) => {
                return {
                    label: i,
                    kind: CompletionItemKind.Event,
                    data: "condition",
                    commitCharacters: [" ", "$"]
                }
            }),
            ...builtin.filter(() => currentLine.trim() === "" && !currentLine.match(/^(.+) /gm)).map((i: string) => {
                return {
                    label: i,
                    kind: CompletionItemKind.Method,
                    data: "built-in",
                    insertText: (i === "include" || i === "require" ? "#" : "") + i,
                    commitCharacters: [" ", "$"]
                }
            }),
            ...replacementsList.filter(i => currentLine.trim() === "")
        ];
    }

    public static detail(item: CompletionItem) {
        item.detail = item.documentation = item.data;
        return item;
    }
}