├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── VBScript-vscode.code-workspace
├── client
├── .gitignore
├── .vscode
│ ├── launch.json
│ ├── settings.json
│ └── tasks.json
├── .vscodeignore
├── buildVSIX.bat
├── package-lock.json
├── package.json
├── resources
│ ├── vbs.png
│ └── vbs.svg
├── src
│ └── extension.ts
└── tsconfig.json
└── server
├── .gitignore
├── .vscode
├── launch.json
├── settings.json
└── tasks.json
├── package-lock.json
├── package.json
├── src
├── VBSSymbols
│ ├── VBSClassSymbol.ts
│ ├── VBSConstantSymbol.ts
│ ├── VBSMemberSymbol.ts
│ ├── VBSMethodSymbol.ts
│ ├── VBSPropertySymbol.ts
│ ├── VBSSymbol.ts
│ └── VBSVariableSymbol.ts
└── server.ts
└── tsconfig.json
/.gitignore:
--------------------------------------------------------------------------------
1 | /client/*.vsix
2 | /client/README.md
3 | /client/CHANGELOG.md
4 | Thumbs.db
5 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # CHANGELOG
2 |
3 | # Version 1.0.2
4 |
5 | - corrected error message for (end property expected)
6 | - added filename to 'refreshed symbols' log message
7 | - added start character to error messages
8 | - added support for array arguments
9 |
10 | # Version 1.0.1
11 |
12 | - fixed issue: Default property #10
13 |
14 | # Version 1.0.0
15 |
16 | - performance tweaks
17 | - method end were not recognized if they were written in a different case (Sub vs. sub)
18 |
19 | # Version 0.0.7
20 |
21 | - fixed issue: Parameters as symbols
22 | - added language contribution
23 | - fixed issue: Underline seperation
24 |
25 | # Version 0.0.6
26 |
27 | - fixed issue: Multi-Dim support
28 |
29 | # Version 0.0.5
30 |
31 | - support for code completion of symbols based on scope
32 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Andreas Lenzen
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # VBScript symbols extension
2 |
3 | This extension provides symbols for VBScript.
4 |
5 | Pressing Ctrl + Shift + O lists all symbols of the current file.
6 |
7 | You can display symbols by using extensions like "Code Outline" by Patryk Zawadzki as well.
8 |
9 | ## Supported Symbols
10 |
11 | - __Class__
12 | - __Function__
13 | - __Sub__
14 | - __Property__
15 | - __Field__
16 | - global and class wide __Const__
17 | - __Dim__
18 | - Parameters
19 |
20 | ## Version 1.0.0
21 |
22 | This version is the first version which contains a valuable feature set to make VBScript development more productive.
23 | This version supports the recognition of all important symbols of a file and provides IntelliSense support according the scope.
24 |
25 | ## (Maybe) Upcoming Features
26 |
27 | ### VBScript debugging
28 |
29 | I would like to see a VBScript debugger built in into this extension. This will most likely be only available for windows but it would make the VSCode - VBScript experience somwhat complete.
30 |
31 | ### Lexer (ANTLR?)
32 |
33 | I would appreciate if the regular expressions of mine will be superseded someday by a formal grammar. A popular possibility would be ANTLR. I hope that this would make it a bit faster, more reliable and much easier to read.
34 |
35 |
36 | [GitHub](https://github.com/Luncher91/VBScript-vscode)
37 |
--------------------------------------------------------------------------------
/VBScript-vscode.code-workspace:
--------------------------------------------------------------------------------
1 | {
2 | "folders": [
3 | {
4 | "path": "server"
5 | },
6 | {
7 | "path": "client"
8 | }
9 | ],
10 | "settings": {
11 | "typescript.tsdk": "./node_modules/typescript/lib"
12 | }
13 | }
--------------------------------------------------------------------------------
/client/.gitignore:
--------------------------------------------------------------------------------
1 | out
2 | server
3 | node_modules
--------------------------------------------------------------------------------
/client/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | // A launch configuration that compiles the extension and then opens it inside a new window
2 | {
3 | "version": "0.2.0",
4 | "configurations": [
5 | {
6 | "name": "Launch Extension",
7 | "type": "extensionHost",
8 | "request": "launch",
9 | "runtimeExecutable": "${execPath}",
10 | "args": ["--extensionDevelopmentPath=${workspaceRoot}" ],
11 | "stopOnEntry": false,
12 | "sourceMaps": true,
13 | "outFiles": [ "${workspaceRoot}/out/src/**/*.js" ]
14 | },
15 | {
16 | "name": "Launch Tests",
17 | "type": "extensionHost",
18 | "request": "launch",
19 | "runtimeExecutable": "${execPath}",
20 | "args": ["--extensionDevelopmentPath=${workspaceRoot}", "--extensionTestsPath=${workspaceRoot}/out/test" ],
21 | "stopOnEntry": false,
22 | "sourceMaps": true,
23 | "outFiles": [ "${workspaceRoot}/out/test/**/*.js" ],
24 | "preLaunchTask": {
25 | "type": "npm",
26 | "script": "watch"
27 | }
28 | }
29 | ]
30 | }
--------------------------------------------------------------------------------
/client/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | // Place your settings in this file to overwrite default and user settings.
2 | {
3 | "files.exclude": {
4 | "out": false // set this to true to hide the "out" folder with the compiled JS files
5 | },
6 | "search.exclude": {
7 | "out": true // set this to false to include "out" folder in search results
8 | },
9 | "typescript.tsdk": "./node_modules/typescript/lib" // we want to use the TS server from our node_modules folder to control its version
10 | }
--------------------------------------------------------------------------------
/client/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | // Available variables which can be used inside of strings.
2 | // ${workspaceRoot}: the root folder of the team
3 | // ${file}: the current opened file
4 | // ${fileBasename}: the current opened file's basename
5 | // ${fileDirname}: the current opened file's dirname
6 | // ${fileExtname}: the current opened file's extension
7 | // ${cwd}: the current working directory of the spawned process
8 |
9 | // A task runner that calls a custom npm script that compiles the extension.
10 | {
11 | "version": "2.0.0",
12 | "tasks": [
13 | {
14 | "label": "compile watch",
15 | "type": "shell",
16 | "command": "npm",
17 | "args": ["run", "compile", "--loglevel", "silent"],
18 | "problemMatcher": ["$tsc-watch"],
19 | }
20 | ],
21 | }
--------------------------------------------------------------------------------
/client/.vscodeignore:
--------------------------------------------------------------------------------
1 | .vscode/**
2 | typings/**
3 | out/test/**
4 | test/**
5 | src/**
6 | **/*.map
7 | .gitignore
8 | tsconfig.json
9 | vsc-extension-quickstart.md
10 | buildVSIX.bat
11 |
--------------------------------------------------------------------------------
/client/buildVSIX.bat:
--------------------------------------------------------------------------------
1 | xcopy /y ..\README.md .
2 | xcopy /y ..\CHANGELOG.md .
3 | vsce package
--------------------------------------------------------------------------------
/client/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vbscript-language-server-client",
3 | "version": "1.1.0",
4 | "lockfileVersion": 1,
5 | "requires": true,
6 | "dependencies": {
7 | "@tootallnate/once": {
8 | "version": "1.1.2",
9 | "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
10 | "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==",
11 | "dev": true
12 | },
13 | "@types/node": {
14 | "version": "8.10.60",
15 | "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.60.tgz",
16 | "integrity": "sha512-YjPbypHFuiOV0bTgeF07HpEEqhmHaZqYNSdCKeBJa+yFoQ/7BC+FpJcwmi34xUIIRVFktnUyP1dPU8U0612GOg==",
17 | "dev": true
18 | },
19 | "agent-base": {
20 | "version": "6.0.0",
21 | "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.0.tgz",
22 | "integrity": "sha512-j1Q7cSCqN+AwrmDd+pzgqc0/NpC655x2bUf5ZjRIO77DcNBFmh+OgRNzF6OKdCC9RSCb19fGd99+bhXFdkRNqw==",
23 | "dev": true,
24 | "requires": {
25 | "debug": "4"
26 | }
27 | },
28 | "balanced-match": {
29 | "version": "1.0.0",
30 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
31 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
32 | "dev": true
33 | },
34 | "brace-expansion": {
35 | "version": "1.1.11",
36 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
37 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
38 | "dev": true,
39 | "requires": {
40 | "balanced-match": "^1.0.0",
41 | "concat-map": "0.0.1"
42 | }
43 | },
44 | "browser-stdout": {
45 | "version": "1.3.1",
46 | "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
47 | "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
48 | "dev": true
49 | },
50 | "buffer-from": {
51 | "version": "1.1.1",
52 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
53 | "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
54 | "dev": true
55 | },
56 | "commander": {
57 | "version": "2.15.1",
58 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
59 | "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==",
60 | "dev": true
61 | },
62 | "concat-map": {
63 | "version": "0.0.1",
64 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
65 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
66 | "dev": true
67 | },
68 | "debug": {
69 | "version": "4.1.1",
70 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
71 | "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
72 | "dev": true,
73 | "requires": {
74 | "ms": "^2.1.1"
75 | }
76 | },
77 | "diff": {
78 | "version": "3.5.0",
79 | "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
80 | "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
81 | "dev": true
82 | },
83 | "es6-promise": {
84 | "version": "4.2.8",
85 | "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
86 | "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==",
87 | "dev": true
88 | },
89 | "es6-promisify": {
90 | "version": "5.0.0",
91 | "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz",
92 | "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=",
93 | "dev": true,
94 | "requires": {
95 | "es6-promise": "^4.0.3"
96 | }
97 | },
98 | "escape-string-regexp": {
99 | "version": "1.0.5",
100 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
101 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
102 | "dev": true
103 | },
104 | "fs.realpath": {
105 | "version": "1.0.0",
106 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
107 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
108 | "dev": true
109 | },
110 | "glob": {
111 | "version": "7.1.6",
112 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
113 | "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
114 | "dev": true,
115 | "requires": {
116 | "fs.realpath": "^1.0.0",
117 | "inflight": "^1.0.4",
118 | "inherits": "2",
119 | "minimatch": "^3.0.4",
120 | "once": "^1.3.0",
121 | "path-is-absolute": "^1.0.0"
122 | }
123 | },
124 | "growl": {
125 | "version": "1.10.5",
126 | "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz",
127 | "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==",
128 | "dev": true
129 | },
130 | "has-flag": {
131 | "version": "3.0.0",
132 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
133 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
134 | "dev": true
135 | },
136 | "he": {
137 | "version": "1.1.1",
138 | "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz",
139 | "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=",
140 | "dev": true
141 | },
142 | "http-proxy-agent": {
143 | "version": "4.0.1",
144 | "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz",
145 | "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==",
146 | "dev": true,
147 | "requires": {
148 | "@tootallnate/once": "1",
149 | "agent-base": "6",
150 | "debug": "4"
151 | }
152 | },
153 | "https-proxy-agent": {
154 | "version": "5.0.0",
155 | "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz",
156 | "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==",
157 | "dev": true,
158 | "requires": {
159 | "agent-base": "6",
160 | "debug": "4"
161 | }
162 | },
163 | "inflight": {
164 | "version": "1.0.6",
165 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
166 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
167 | "dev": true,
168 | "requires": {
169 | "once": "^1.3.0",
170 | "wrappy": "1"
171 | }
172 | },
173 | "inherits": {
174 | "version": "2.0.4",
175 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
176 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
177 | "dev": true
178 | },
179 | "minimatch": {
180 | "version": "3.0.4",
181 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
182 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
183 | "dev": true,
184 | "requires": {
185 | "brace-expansion": "^1.1.7"
186 | }
187 | },
188 | "minimist": {
189 | "version": "0.0.8",
190 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
191 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
192 | "dev": true
193 | },
194 | "mkdirp": {
195 | "version": "0.5.1",
196 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
197 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
198 | "dev": true,
199 | "requires": {
200 | "minimist": "0.0.8"
201 | }
202 | },
203 | "mocha": {
204 | "version": "5.2.0",
205 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz",
206 | "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==",
207 | "dev": true,
208 | "requires": {
209 | "browser-stdout": "1.3.1",
210 | "commander": "2.15.1",
211 | "debug": "3.1.0",
212 | "diff": "3.5.0",
213 | "escape-string-regexp": "1.0.5",
214 | "glob": "7.1.2",
215 | "growl": "1.10.5",
216 | "he": "1.1.1",
217 | "minimatch": "3.0.4",
218 | "mkdirp": "0.5.1",
219 | "supports-color": "5.4.0"
220 | },
221 | "dependencies": {
222 | "debug": {
223 | "version": "3.1.0",
224 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
225 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
226 | "dev": true,
227 | "requires": {
228 | "ms": "2.0.0"
229 | }
230 | },
231 | "glob": {
232 | "version": "7.1.2",
233 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
234 | "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
235 | "dev": true,
236 | "requires": {
237 | "fs.realpath": "^1.0.0",
238 | "inflight": "^1.0.4",
239 | "inherits": "2",
240 | "minimatch": "^3.0.4",
241 | "once": "^1.3.0",
242 | "path-is-absolute": "^1.0.0"
243 | }
244 | },
245 | "ms": {
246 | "version": "2.0.0",
247 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
248 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
249 | "dev": true
250 | }
251 | }
252 | },
253 | "ms": {
254 | "version": "2.1.2",
255 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
256 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
257 | "dev": true
258 | },
259 | "once": {
260 | "version": "1.4.0",
261 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
262 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
263 | "dev": true,
264 | "requires": {
265 | "wrappy": "1"
266 | }
267 | },
268 | "path-is-absolute": {
269 | "version": "1.0.1",
270 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
271 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
272 | "dev": true
273 | },
274 | "semver": {
275 | "version": "5.7.1",
276 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
277 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
278 | "dev": true
279 | },
280 | "source-map": {
281 | "version": "0.6.1",
282 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
283 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
284 | "dev": true
285 | },
286 | "source-map-support": {
287 | "version": "0.5.18",
288 | "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.18.tgz",
289 | "integrity": "sha512-9luZr/BZ2QeU6tO2uG8N2aZpVSli4TSAOAqFOyTO51AJcD9P99c0K1h6dD6r6qo5dyT44BR5exweOaLLeldTkQ==",
290 | "dev": true,
291 | "requires": {
292 | "buffer-from": "^1.0.0",
293 | "source-map": "^0.6.0"
294 | }
295 | },
296 | "supports-color": {
297 | "version": "5.4.0",
298 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz",
299 | "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==",
300 | "dev": true,
301 | "requires": {
302 | "has-flag": "^3.0.0"
303 | }
304 | },
305 | "typescript": {
306 | "version": "2.9.2",
307 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz",
308 | "integrity": "sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==",
309 | "dev": true
310 | },
311 | "vscode": {
312 | "version": "1.1.37",
313 | "resolved": "https://registry.npmjs.org/vscode/-/vscode-1.1.37.tgz",
314 | "integrity": "sha512-vJNj6IlN7IJPdMavlQa1KoFB3Ihn06q1AiN3ZFI/HfzPNzbKZWPPuiU+XkpNOfGU5k15m4r80nxNPlM7wcc0wg==",
315 | "dev": true,
316 | "requires": {
317 | "glob": "^7.1.2",
318 | "http-proxy-agent": "^4.0.1",
319 | "https-proxy-agent": "^5.0.0",
320 | "mocha": "^5.2.0",
321 | "semver": "^5.4.1",
322 | "source-map-support": "^0.5.0",
323 | "vscode-test": "^0.4.1"
324 | }
325 | },
326 | "vscode-jsonrpc": {
327 | "version": "3.5.0",
328 | "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-3.5.0.tgz",
329 | "integrity": "sha1-hyOdnhZrLXNSJFuKgTWXgEwdY6o="
330 | },
331 | "vscode-languageclient": {
332 | "version": "3.5.1",
333 | "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-3.5.1.tgz",
334 | "integrity": "sha512-GTQ+hSq/o4c/y6GYmyP9XNrVoIu0NFZ67KltSkqN+tO0eUNDIlrVNX+3DJzzyLhSsrctuGzuYWm3t87mNAcBmQ==",
335 | "requires": {
336 | "vscode-languageserver-protocol": "3.5.1"
337 | }
338 | },
339 | "vscode-languageserver-protocol": {
340 | "version": "3.5.1",
341 | "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.5.1.tgz",
342 | "integrity": "sha512-1fPDIwsAv1difCV+8daOrJEGunClNJWqnUHq/ncWrjhitKWXgGmRCjlwZ3gDUTt54yRcvXz1PXJDaRNvNH6pYA==",
343 | "requires": {
344 | "vscode-jsonrpc": "3.5.0",
345 | "vscode-languageserver-types": "3.5.0"
346 | }
347 | },
348 | "vscode-languageserver-types": {
349 | "version": "3.5.0",
350 | "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.5.0.tgz",
351 | "integrity": "sha1-5I15li8LjgLelV4/UkkI4rGcA3Q="
352 | },
353 | "vscode-test": {
354 | "version": "0.4.3",
355 | "resolved": "https://registry.npmjs.org/vscode-test/-/vscode-test-0.4.3.tgz",
356 | "integrity": "sha512-EkMGqBSefZH2MgW65nY05rdRSko15uvzq4VAPM5jVmwYuFQKE7eikKXNJDRxL+OITXHB6pI+a3XqqD32Y3KC5w==",
357 | "dev": true,
358 | "requires": {
359 | "http-proxy-agent": "^2.1.0",
360 | "https-proxy-agent": "^2.2.1"
361 | },
362 | "dependencies": {
363 | "agent-base": {
364 | "version": "4.3.0",
365 | "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz",
366 | "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==",
367 | "dev": true,
368 | "requires": {
369 | "es6-promisify": "^5.0.0"
370 | }
371 | },
372 | "debug": {
373 | "version": "3.1.0",
374 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
375 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
376 | "dev": true,
377 | "requires": {
378 | "ms": "2.0.0"
379 | }
380 | },
381 | "http-proxy-agent": {
382 | "version": "2.1.0",
383 | "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz",
384 | "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==",
385 | "dev": true,
386 | "requires": {
387 | "agent-base": "4",
388 | "debug": "3.1.0"
389 | }
390 | },
391 | "https-proxy-agent": {
392 | "version": "2.2.4",
393 | "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz",
394 | "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==",
395 | "dev": true,
396 | "requires": {
397 | "agent-base": "^4.3.0",
398 | "debug": "^3.1.0"
399 | }
400 | },
401 | "ms": {
402 | "version": "2.0.0",
403 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
404 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
405 | "dev": true
406 | }
407 | }
408 | },
409 | "wrappy": {
410 | "version": "1.0.2",
411 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
412 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
413 | "dev": true
414 | }
415 | }
416 | }
417 |
--------------------------------------------------------------------------------
/client/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vbscript-language-server-client",
3 | "displayName": "VBScript symbols",
4 | "description": "VBScript symbol support",
5 | "author": "Andreas Lenzen",
6 | "license": "MIT",
7 | "version": "1.1.0",
8 | "publisher": "andreaslenzen",
9 | "repository": {
10 | "type": "git",
11 | "url": "https://github.com/Luncher91/VBScript-vscode"
12 | },
13 | "bugs": {
14 | "url": "https://github.com/Luncher91/VBScript-vscode/issues"
15 | },
16 | "homepage": "https://github.com/Luncher91/VBScript-vscode/blob/master/README.md",
17 | "galleryBanner": {
18 | "color": "#888888",
19 | "theme": "dark"
20 | },
21 | "icon": "resources/vbs.png",
22 | "engines": {
23 | "vscode": "^1.18.0"
24 | },
25 | "categories": [
26 | "Language Packs"
27 | ],
28 | "keywords": [
29 | "VBS",
30 | "VBScript",
31 | "Language",
32 | "Symbol",
33 | "Functionlist",
34 | "ASP"
35 | ],
36 | "activationEvents": [
37 | "onLanguage:vb",
38 | "onLanguage:vba",
39 | "onLanguage:vbs",
40 | "onLanguage:vbscript",
41 | "onLanguage:asp"
42 | ],
43 | "main": "./out/extension",
44 | "contributes": {
45 | "languages": [
46 | {
47 | "id": "vbs",
48 | "aliases": [
49 | "VBScript",
50 | "vbscript",
51 | "VBS"
52 | ]
53 | }
54 | ],
55 | "configuration": {
56 | "type": "object",
57 | "title": "VBScript language configuration",
58 | "properties": {
59 | "vbsLanguageServer.trace.server": {
60 | "type": "string",
61 | "enum": [
62 | "off",
63 | "messages",
64 | "verbose"
65 | ],
66 | "default": "off",
67 | "description": "Traces the communication between VSCode and the VBScriptLanguageServer service."
68 | }
69 | }
70 | }
71 | },
72 | "scripts": {
73 | "vscode:prepublish": "tsc -p ./",
74 | "compile": "tsc -watch -p ./",
75 | "update-vscode": "node ./node_modules/vscode/bin/install",
76 | "postinstall": "node ./node_modules/vscode/bin/install"
77 | },
78 | "devDependencies": {
79 | "@types/node": "^8.0.26",
80 | "typescript": "^2.1.5",
81 | "vscode": "^1.0.3"
82 | },
83 | "dependencies": {
84 | "vscode-languageclient": "^3.1.0"
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/client/resources/vbs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Luncher91/VBScript-vscode/074c8b9c3c59fbae26f1e0a0ce9187a9db58ead6/client/resources/vbs.png
--------------------------------------------------------------------------------
/client/resources/vbs.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/client/src/extension.ts:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import * as path from 'path';
4 |
5 | import { workspace, Disposable, ExtensionContext } from 'vscode';
6 | import { LanguageClient, LanguageClientOptions, SettingMonitor, ServerOptions, TransportKind } from 'vscode-languageclient';
7 |
8 | export function activate(context: ExtensionContext) {
9 | let serverModule = context.asAbsolutePath(path.join('server', 'server.js'));
10 | let debugOptions = { execArgv: ["--nolazy", "--inspect=6009"] };
11 | let serverOptions: ServerOptions = {
12 | run : { module: serverModule, transport: TransportKind.ipc },
13 | debug: { module: serverModule, transport: TransportKind.ipc, options: debugOptions }
14 | }
15 |
16 | let clientOptions: LanguageClientOptions = {
17 | documentSelector: ['asp','vbs', 'vb', 'vbscript', 'vba'],
18 | synchronize: {
19 | configurationSection: 'vbsLanguageServer',
20 | fileEvents: workspace.createFileSystemWatcher('**/.clientrc')
21 | }
22 | }
23 |
24 | let disposable = new LanguageClient('vbsLanguageServer', 'VBScript Language Server', serverOptions, clientOptions).start();
25 | context.subscriptions.push(disposable);
26 | }
27 |
--------------------------------------------------------------------------------
/client/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es6",
4 | "module": "commonjs",
5 | "moduleResolution": "node",
6 | "outDir": "out",
7 | "lib": [ "es2016" ],
8 | "sourceMap": true
9 | },
10 | "exclude": [
11 | "node_modules",
12 | "server"
13 | ]
14 | }
--------------------------------------------------------------------------------
/server/.gitignore:
--------------------------------------------------------------------------------
1 | out
2 | node_modules
--------------------------------------------------------------------------------
/server/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.2.0",
3 | // List of configurations. Add new configurations or edit existing ones.
4 | "configurations": [
5 | {
6 | "name": "Attach",
7 | "type": "node",
8 | "request": "attach",
9 | "port": 6009,
10 | "sourceMaps": true,
11 | "outFiles": [ "${workspaceRoot}/../client/server/**/*.js" ]
12 | }
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/server/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "typescript.tsdk": "./node_modules/typescript/lib"
3 | }
--------------------------------------------------------------------------------
/server/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "2.0.0",
3 | "tasks": [
4 | {
5 | "label": "Run watch",
6 | "type": "shell",
7 | "command": "npm",
8 | "args": [
9 | "run", "watch"
10 | ],
11 | "problemMatcher": ["$tsc-watch"]
12 | }
13 | ]
14 | }
--------------------------------------------------------------------------------
/server/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vbscript-language-server",
3 | "version": "1.0.3",
4 | "lockfileVersion": 1,
5 | "requires": true,
6 | "dependencies": {
7 | "@types/node": {
8 | "version": "8.10.60",
9 | "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.60.tgz",
10 | "integrity": "sha512-YjPbypHFuiOV0bTgeF07HpEEqhmHaZqYNSdCKeBJa+yFoQ/7BC+FpJcwmi34xUIIRVFktnUyP1dPU8U0612GOg=="
11 | },
12 | "typescript": {
13 | "version": "2.9.2",
14 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz",
15 | "integrity": "sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==",
16 | "dev": true
17 | },
18 | "vscode-jsonrpc": {
19 | "version": "3.5.0",
20 | "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-3.5.0.tgz",
21 | "integrity": "sha1-hyOdnhZrLXNSJFuKgTWXgEwdY6o="
22 | },
23 | "vscode-languageserver": {
24 | "version": "3.5.1",
25 | "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-3.5.1.tgz",
26 | "integrity": "sha512-RYUKn0DgHTFcS8kS4VaNCjNMaQXYqiXdN9bKrFjXzu5RPKfjIYcoh47oVWwZj4L3R/DPB0Se7HPaDatvYY2XgQ==",
27 | "requires": {
28 | "vscode-languageserver-protocol": "3.5.1",
29 | "vscode-uri": "^1.0.1"
30 | }
31 | },
32 | "vscode-languageserver-protocol": {
33 | "version": "3.5.1",
34 | "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.5.1.tgz",
35 | "integrity": "sha512-1fPDIwsAv1difCV+8daOrJEGunClNJWqnUHq/ncWrjhitKWXgGmRCjlwZ3gDUTt54yRcvXz1PXJDaRNvNH6pYA==",
36 | "requires": {
37 | "vscode-jsonrpc": "3.5.0",
38 | "vscode-languageserver-types": "3.5.0"
39 | }
40 | },
41 | "vscode-languageserver-types": {
42 | "version": "3.5.0",
43 | "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.5.0.tgz",
44 | "integrity": "sha1-5I15li8LjgLelV4/UkkI4rGcA3Q="
45 | },
46 | "vscode-uri": {
47 | "version": "1.0.8",
48 | "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-1.0.8.tgz",
49 | "integrity": "sha512-obtSWTlbJ+a+TFRYGaUumtVwb+InIUVI0Lu0VBUAPmj2cU5JutEXg3xUE0c2J5Tcy7h2DEKVJBFi+Y9ZSFzzPQ=="
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/server/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vbscript-language-server",
3 | "description": "Implementation of a VBScript language server in node.",
4 | "version": "1.0.3",
5 | "author": "Andreas Lenzen",
6 | "license": "MIT",
7 | "engines": {
8 | "vscode": "^1.43.0"
9 | },
10 | "dependencies": {
11 | "vscode-languageserver": "^3.1.0",
12 | "@types/node": "^8.0.26"
13 | },
14 | "devDependencies": {
15 | "typescript": "^2.1.5"
16 | },
17 | "scripts": {
18 | "compile": "installServerIntoExtension ../client ./package.json ./tsconfig.json && tsc -p .",
19 | "watch": "installServerIntoExtension ../client ./package.json ./tsconfig.json && tsc --watch -p ."
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/server/src/VBSSymbols/VBSClassSymbol.ts:
--------------------------------------------------------------------------------
1 | import * as ls from 'vscode-languageserver';
2 | import { VBSSymbol } from "./VBSSymbol";
3 |
4 | export class VBSClassSymbol extends VBSSymbol {
5 | public GetLsSymbolKind(): ls.SymbolKind {
6 | return ls.SymbolKind.Class;
7 | }
8 |
9 | public GetLsCompletionItem(): ls.CompletionItem {
10 | let item = ls.CompletionItem.create(this.name);
11 | item.filterText = this.name;
12 | item.insertText = this.name;
13 | item.kind = ls.CompletionItemKind.Class;
14 | return item;
15 | }
16 | }
--------------------------------------------------------------------------------
/server/src/VBSSymbols/VBSConstantSymbol.ts:
--------------------------------------------------------------------------------
1 | import * as ls from 'vscode-languageserver';
2 | import { VBSSymbol } from "./VBSSymbol";
3 |
4 | export class VBSConstantSymbol extends VBSSymbol {
5 | public GetLsSymbolKind(): ls.SymbolKind {
6 | return ls.SymbolKind.Constant;
7 | }
8 |
9 | public GetLsCompletionItem(): ls.CompletionItem {
10 | let item = ls.CompletionItem.create(this.name);
11 | item.filterText = this.name;
12 | item.insertText = this.name;
13 | item.kind = ls.CompletionItemKind.Variable;
14 | return item;
15 | }
16 | }
--------------------------------------------------------------------------------
/server/src/VBSSymbols/VBSMemberSymbol.ts:
--------------------------------------------------------------------------------
1 | import * as ls from 'vscode-languageserver';
2 | import { VBSSymbol } from "./VBSSymbol";
3 |
4 | export class VBSMemberSymbol extends VBSSymbol {
5 | public GetLsSymbolKind(): ls.SymbolKind {
6 | return ls.SymbolKind.Field;
7 | }
8 |
9 | public GetLsCompletionItem(): ls.CompletionItem {
10 | let item = ls.CompletionItem.create(this.name);
11 | item.filterText = this.name;
12 | item.insertText = this.name;
13 | item.kind = ls.CompletionItemKind.Field;
14 | return item;
15 | }
16 | }
--------------------------------------------------------------------------------
/server/src/VBSSymbols/VBSMethodSymbol.ts:
--------------------------------------------------------------------------------
1 | import * as ls from 'vscode-languageserver';
2 | import { VBSSymbol } from "./VBSSymbol";
3 |
4 | export class VBSMethodSymbol extends VBSSymbol {
5 | public GetLsName(): string {
6 | return this.name + " (" + this.args + ")";
7 | }
8 |
9 | public GetLsSymbolKind(): ls.SymbolKind {
10 | return ls.SymbolKind.Method;
11 | }
12 |
13 | public GetLsCompletionItem(): ls.CompletionItem {
14 | let item = ls.CompletionItem.create(this.name);
15 | item.documentation = this.visibility + " " + this.type + " " + this.name + "(" + this.args + ")"
16 | item.filterText = this.name;
17 | item.insertText = this.name + "(" + this.args + ")";
18 | item.kind = ls.CompletionItemKind.Method;
19 | return item;
20 | }
21 | }
--------------------------------------------------------------------------------
/server/src/VBSSymbols/VBSPropertySymbol.ts:
--------------------------------------------------------------------------------
1 | import * as ls from 'vscode-languageserver';
2 | import { VBSSymbol } from "./VBSSymbol";
3 |
4 | export class VBSPropertySymbol extends VBSSymbol {
5 | public GetLsName(): string {
6 | if(this.args != "")
7 | return this.type + " " + this.name + " (" + this.args + ")";
8 | else
9 | return this.type + " " + this.name;
10 | }
11 |
12 | public GetLsSymbolKind(): ls.SymbolKind {
13 | return ls.SymbolKind.Property;
14 | }
15 |
16 | public GetLsCompletionItem(): ls.CompletionItem {
17 | let item = ls.CompletionItem.create(this.name);
18 |
19 | item.documentation = this.GetDocu();
20 | item.filterText = this.name;
21 | item.insertText = this.name;
22 | item.kind = ls.CompletionItemKind.Property;
23 | return item;
24 | }
25 |
26 | private GetDocu(): string {
27 | let docu = "";
28 |
29 | if(this.visibility != null)
30 | docu += this.visibility.trim();
31 |
32 | if(this.type != null)
33 | docu += this.type.trim();
34 |
35 | if(this.name != null)
36 | docu += this.name.trim();
37 |
38 | if(this.args != null)
39 | docu += "(" + this.args + ")";
40 |
41 | return docu.trim();
42 | }
43 | }
--------------------------------------------------------------------------------
/server/src/VBSSymbols/VBSSymbol.ts:
--------------------------------------------------------------------------------
1 | import * as ls from 'vscode-languageserver';
2 |
3 | export class VBSSymbol {
4 | public visibility: string = "";
5 | public name: string = "";
6 | public type: string = "";
7 | public args: string = "";
8 | public symbolRange: ls.Range = null;
9 | public nameLocation: ls.Location = null;
10 |
11 | public parentName: string = "";
12 |
13 | public GetLsName(): string {
14 | return this.name;
15 | }
16 |
17 | public GetLsSymbolKind(): ls.SymbolKind {
18 | // I do not know any better value to return here - I liked to have something like ls.SymbolKind.UNKNOWN
19 | return ls.SymbolKind.File;
20 | }
21 |
22 | public GetLsCompletionItem(): ls.CompletionItem {
23 | let item = ls.CompletionItem.create(this.name);
24 | item.filterText = this.name;
25 | item.insertText = this.name;
26 | item.kind = ls.CompletionItemKind.Text;
27 | return item;
28 | }
29 |
30 | public static GetLanguageServerSymbols(symbols: VBSSymbol[]): ls.SymbolInformation[] {
31 | let lsSymbols: ls.SymbolInformation[] = [];
32 |
33 | symbols.forEach(symbol => {
34 | let lsSymbol: ls.SymbolInformation = ls.SymbolInformation.create(
35 | symbol.GetLsName(),
36 | symbol.GetLsSymbolKind(),
37 | symbol.symbolRange,
38 | symbol.nameLocation.uri,
39 | symbol.parentName
40 | );
41 | lsSymbols.push(lsSymbol);
42 | });
43 |
44 | return lsSymbols;
45 | }
46 |
47 | public static GetLanguageServerCompletionItems(symbols: VBSSymbol[]): ls.CompletionItem[] {
48 | let completionItems: ls.CompletionItem[] = [];
49 |
50 | symbols.forEach(symbol => {
51 | let lsItem = symbol.GetLsCompletionItem();
52 | completionItems.push(lsItem);
53 | });
54 |
55 | return completionItems;
56 | }
57 | }
--------------------------------------------------------------------------------
/server/src/VBSSymbols/VBSVariableSymbol.ts:
--------------------------------------------------------------------------------
1 | import * as ls from 'vscode-languageserver';
2 | import { VBSSymbol } from "./VBSSymbol";
3 |
4 | export class VBSVariableSymbol extends VBSSymbol {
5 | public GetLsSymbolKind(): ls.SymbolKind {
6 | return ls.SymbolKind.Variable;
7 | }
8 |
9 | public GetLsCompletionItem(): ls.CompletionItem {
10 | let item = ls.CompletionItem.create(this.name);
11 | item.filterText = this.name;
12 | item.insertText = this.name;
13 | item.kind = ls.CompletionItemKind.Variable;
14 | return item;
15 | }
16 | }
--------------------------------------------------------------------------------
/server/src/server.ts:
--------------------------------------------------------------------------------
1 | /* --------------------------------------------------------------------------------------------
2 | * Copyright (c) Andreas Lenzen. All rights reserved.
3 | * Licensed under the MIT License. See License.txt in the project root for license information.
4 | * ------------------------------------------------------------------------------------------ */
5 | 'use strict';
6 |
7 | import * as ls from 'vscode-languageserver';
8 | import { VBSSymbol } from "./VBSSymbols/VBSSymbol";
9 | import { VBSMethodSymbol } from './VBSSymbols/VBSMethodSymbol';
10 | import { VBSPropertySymbol } from './VBSSymbols/VBSPropertySymbol';
11 | import { VBSClassSymbol } from './VBSSymbols/VBSClassSymbol';
12 | import { VBSMemberSymbol } from './VBSSymbols/VBSMemberSymbol';
13 | import { VBSVariableSymbol } from './VBSSymbols/VBSVariableSymbol';
14 | import { VBSConstantSymbol } from './VBSSymbols/VBSConstantSymbol';
15 |
16 | // Create a connection for the server. The connection uses Node's IPC as a transport
17 | let connection: ls.IConnection = ls.createConnection(new ls.IPCMessageReader(process), new ls.IPCMessageWriter(process));
18 |
19 | // Create a simple text document manager. The text document manager
20 | // supports full document sync only
21 | let documents: ls.TextDocuments = new ls.TextDocuments();
22 | // Make the text document manager listen on the connection
23 | // for open, change and close text document events
24 | documents.listen(connection);
25 |
26 | // After the server has started the client sends an initialize request. The server receives
27 | // in the passed params the rootPath of the workspace plus the client capabilities.
28 | let workspaceRoot: string;
29 | connection.onInitialize((params): ls.InitializeResult => {
30 | workspaceRoot = params.rootPath;
31 | return {
32 | capabilities: {
33 | // Tell the client that the server works in FULL text document sync mode
34 | textDocumentSync: documents.syncKind,
35 | documentSymbolProvider: true,
36 | // Tell the client that the server support code complete
37 | completionProvider: {
38 | resolveProvider: true
39 | }
40 | }
41 | }
42 | });
43 |
44 | // The content of a text document has changed. This event is emitted
45 | // when the text document first opened or when its content has changed.
46 | documents.onDidChangeContent((change: ls.TextDocumentChangeEvent) => {
47 | });
48 |
49 | connection.onDidChangeWatchedFiles((changeParams: ls.DidChangeWatchedFilesParams) => {
50 | for (let i = 0; i < changeParams.changes.length; i++) {
51 | let event = changeParams.changes[i];
52 |
53 | switch(event.type) {
54 | case ls.FileChangeType.Changed:
55 | case ls.FileChangeType.Created:
56 | RefreshDocumentsSymbols(event.uri);
57 | break;
58 | case ls.FileChangeType.Deleted:
59 | symbolCache[event.uri] = null;
60 | break;
61 | }
62 | }
63 | });
64 |
65 | // This handler provides the initial list of the completion items.
66 | connection.onCompletion((_textDocumentPosition: ls.TextDocumentPositionParams): ls.CompletionItem[] => {
67 | return SelectCompletionItems(_textDocumentPosition);
68 | });
69 |
70 | connection.onCompletionResolve((complItem: ls.CompletionItem): ls.CompletionItem => {
71 | return complItem;
72 | });
73 |
74 | function GetSymbolsOfDocument(uri: string) : ls.SymbolInformation[] {
75 | RefreshDocumentsSymbols(uri);
76 | return VBSSymbol.GetLanguageServerSymbols(symbolCache[uri]);
77 | }
78 |
79 | function SelectCompletionItems(textDocumentPosition: ls.TextDocumentPositionParams): ls.CompletionItem[] {
80 | let symbols = symbolCache[textDocumentPosition.textDocument.uri];
81 |
82 | if(symbols == null) {
83 | RefreshDocumentsSymbols(textDocumentPosition.textDocument.uri);
84 | symbols = symbolCache[textDocumentPosition.textDocument.uri];
85 | }
86 |
87 | let scopeSymbols = GetSymbolsOfScope(symbols, textDocumentPosition.position);
88 | return VBSSymbol.GetLanguageServerCompletionItems(scopeSymbols);
89 | }
90 |
91 | function GetVBSSymbolTree(symbols: VBSSymbol[]) {
92 | // sort by start positition
93 | let sortedSymbols: VBSSymbol[] = symbols.sort(function(a: VBSSymbol, b: VBSSymbol){
94 | let diff = a.symbolRange.start.line - b.symbolRange.start.line;
95 |
96 | if(diff != 0)
97 | return diff;
98 |
99 | return a.symbolRange.start.character - b.symbolRange.start.character;
100 | });
101 |
102 | let root = new VBSSymbolTree();
103 |
104 | for (var i = 0; i < sortedSymbols.length; i++) {
105 | var symbol = sortedSymbols[i];
106 | root.InsertIntoTree(symbol);
107 | }
108 |
109 | return root;
110 | }
111 |
112 | function GetSymbolsOfScope(symbols: VBSSymbol[], position: ls.Position): VBSSymbol[] {
113 | let symbolTree = GetVBSSymbolTree(symbols);
114 | // bacause of hoisting we will have just a few possible scopes:
115 | // - file wide
116 | // - method of file wide
117 | // - class scope
118 | // - method or property of class scope
119 | // get all symbols which are accessable from here (ignore visibility in the first step)
120 |
121 | return symbolTree.FindDirectParent(position).GetAllParentsAndTheirDirectChildren();
122 | }
123 |
124 | class VBSSymbolTree {
125 | parent: VBSSymbolTree = null;
126 | children: VBSSymbolTree[] = [];
127 | data: VBSSymbol = null;
128 |
129 | public InsertIntoTree(symbol: VBSSymbol): boolean {
130 | if(this.data != null && !PositionInRange(this.data.symbolRange, symbol.symbolRange.start))
131 | return false;
132 |
133 | for (var i = 0; i < this.children.length; i++) {
134 | var symbolTree = this.children[i];
135 | if(symbolTree.InsertIntoTree(symbol))
136 | return true;
137 | }
138 |
139 | let newTreeNode = new VBSSymbolTree();
140 | newTreeNode.data = symbol;
141 | newTreeNode.parent = this;
142 |
143 | this.children.push(newTreeNode);
144 |
145 | return true;
146 | }
147 |
148 | public FindDirectParent(position: ls.Position): VBSSymbolTree {
149 | if(this.data != null && !PositionInRange(this.data.symbolRange, position))
150 | return null;
151 |
152 | for (var i = 0; i < this.children.length; i++) {
153 | let symbolTree = this.children[i];
154 | let found = symbolTree.FindDirectParent(position);
155 | if(found != null)
156 | return found;
157 | }
158 |
159 | return this;
160 | }
161 |
162 | public GetAllParentsAndTheirDirectChildren(): VBSSymbol[] {
163 | let symbols: VBSSymbol[];
164 |
165 | if(this.parent != null)
166 | symbols = this.parent.GetAllParentsAndTheirDirectChildren();
167 | else
168 | symbols = [];
169 |
170 | let childSymbols = this.children.map(function(symbolTree) {
171 | return symbolTree.data;
172 | });
173 |
174 | return symbols.concat(childSymbols);
175 | }
176 | }
177 |
178 | function PositionInRange(range: ls.Range, position: ls.Position): boolean {
179 | if(range.start.line > position.line)
180 | return false;
181 |
182 | if(range.end.line < position.line)
183 | return false;
184 |
185 | if(range.start.line == position.line && range.start.character >= position.character)
186 | return false;
187 |
188 | if(range.end.line == position.line && range.end.character <= position.character)
189 | return false;
190 |
191 | return true;
192 | }
193 |
194 | let symbolCache: { [id: string] : VBSSymbol[]; } = {};
195 | function RefreshDocumentsSymbols(uri: string) {
196 | let startTime: number = Date.now();
197 | let symbolsList: VBSSymbol[] = CollectSymbols(documents.get(uri));
198 | symbolCache[uri] = symbolsList;
199 | console.info("Found " + symbolsList.length + " symbols in '" + uri + "': " + (Date.now() - startTime) + " ms");
200 | }
201 |
202 | connection.onDocumentSymbol((docParams: ls.DocumentSymbolParams): ls.SymbolInformation[] => {
203 | return GetSymbolsOfDocument(docParams.textDocument.uri);
204 | });
205 |
206 | function CollectSymbols(document: ls.TextDocument): VBSSymbol[] {
207 | let symbols: Set = new Set();
208 | let lines = document.getText().split(/\r?\n/g);
209 |
210 | let startMultiLine: number = -1;
211 | let multiLines: string[] = [];
212 |
213 | for (var i = 0; i < lines.length; i++) {
214 | let line = lines[i];
215 |
216 | let containsComment = line.indexOf("'");
217 | if(containsComment > -1)
218 | line = line.substring(0, containsComment);
219 |
220 | if(startMultiLine == -1)
221 | startMultiLine = i;
222 |
223 | if(line.trim().endsWith("_")) {
224 | multiLines.push(line.slice(0, -1));
225 | continue;
226 | } else {
227 | multiLines.push(line);
228 | }
229 |
230 | multiLines = ReplaceStringLiterals(multiLines);
231 | let statements = SplitStatements(multiLines, startMultiLine);
232 |
233 | statements.forEach(statement => {
234 | FindSymbol(statement, document.uri, symbols);
235 | });
236 |
237 | startMultiLine =-1;
238 | multiLines = [];
239 | }
240 |
241 | return Array.from(symbols);
242 | }
243 |
244 | class MultiLineStatement {
245 | startCharacter: number = 0;
246 | startLine: number = -1;
247 | lines: string[] = [];
248 |
249 | public GetFullStatement(): string {
250 | return " ".repeat(this.startCharacter) + this.lines.join("");
251 | }
252 |
253 | public GetPostitionByCharacter(charIndex: number) : ls.Position {
254 | let internalIndex = charIndex - this.startCharacter;
255 |
256 | for (let i = 0; i < this.lines.length; i++) {
257 | let line = this.lines[i];
258 |
259 | if(internalIndex <= line.length) {
260 | if(i == 0)
261 | return ls.Position.create(this.startLine + i, internalIndex + this.startCharacter);
262 | else
263 | return ls.Position.create(this.startLine + i, internalIndex);
264 |
265 | }
266 |
267 | internalIndex = internalIndex - line.length;
268 |
269 | if(internalIndex < 0)
270 | break;
271 | }
272 |
273 | console.warn("WARNING: cannot resolve " + charIndex + " in me: " + JSON.stringify(this));
274 | return null;
275 | }
276 | }
277 |
278 | function SplitStatements(lines: string[], startLineIndex: number): MultiLineStatement[] {
279 | let statement: MultiLineStatement = new MultiLineStatement();
280 | let statements: MultiLineStatement[] = [];
281 | let charOffset: number = 0;
282 |
283 | for (var i = 0; i < lines.length; i++) {
284 | var line = lines[i];
285 | charOffset = 0;
286 | let sts: string[] = line.split(":");
287 |
288 | if(sts.length == 1) {
289 | statement.lines.push(sts[0]);
290 | if(statement.startLine == -1) {
291 | statement.startLine = startLineIndex + i;
292 | }
293 | } else {
294 | for (var j = 0; j < sts.length; j++) {
295 | var st = sts[j];
296 |
297 | if(statement.startLine == -1)
298 | statement.startLine = startLineIndex + i;
299 |
300 | statement.lines.push(st);
301 |
302 | if(j == sts.length-1) {
303 | break;
304 | }
305 |
306 | statement.startCharacter = charOffset;
307 | statements.push(statement);
308 | statement = new MultiLineStatement();
309 |
310 | charOffset += st.length
311 | + 1; // ":"
312 | }
313 | }
314 | }
315 |
316 | if(statement.startLine != -1) {
317 | statement.startCharacter = charOffset;
318 | statements.push(statement);
319 | }
320 |
321 | return statements;
322 | }
323 |
324 | function ReplaceStringLiterals(lines:string[]) : string[] {
325 | let newLines: string[] = [];
326 |
327 | for (var i = 0; i < lines.length; i++) {
328 | var line = lines[i];
329 | let stringLiterals = /\"(([^\"]|\"\")*)\"/gi;
330 | newLines.push(line.replace(stringLiterals, ReplaceBySpaces));
331 | }
332 |
333 | return newLines;
334 | }
335 |
336 | function ReplaceBySpaces(match: string) : string {
337 | return " ".repeat(match.length);
338 | }
339 |
340 | function AddArrayToSet(s: Set, a: any[]) {
341 | a.forEach(element => {
342 | s.add(element);
343 | });
344 | }
345 |
346 | function FindSymbol(statement: MultiLineStatement, uri: string, symbols: Set) : void {
347 | let newSym: VBSSymbol;
348 | let newSyms: VBSVariableSymbol[] = null;
349 |
350 | if(GetMethodStart(statement, uri)) {
351 | return;
352 | }
353 |
354 | newSyms = GetMethodSymbol(statement, uri);
355 | if(newSyms != null && newSyms.length != 0) {
356 | AddArrayToSet(symbols, newSyms);
357 | return;
358 | }
359 |
360 | if(GetPropertyStart(statement, uri))
361 | return;
362 |
363 | newSyms = GetPropertySymbol(statement, uri);;
364 | if(newSyms != null && newSyms.length != 0) {
365 | AddArrayToSet(symbols, newSyms);
366 | return;
367 | }
368 |
369 | if(GetClassStart(statement, uri))
370 | return;
371 |
372 | newSym = GetClassSymbol(statement, uri);
373 | if(newSym != null) {
374 | symbols.add(newSym);
375 | return;
376 | }
377 |
378 | newSym = GetMemberSymbol(statement, uri);
379 | if(newSym != null) {
380 | symbols.add(newSym);
381 | return;
382 | }
383 |
384 | newSyms = GetVariableSymbol(statement, uri);
385 | if(newSyms != null && newSyms.length != 0) {
386 | AddArrayToSet(symbols, newSyms);
387 | return;
388 | }
389 |
390 | newSym = GetConstantSymbol(statement, uri);
391 | if(newSym != null) {
392 | symbols.add(newSym);
393 | return;
394 | }
395 | }
396 |
397 | let openClassName : string = null;
398 | let openClassStart : ls.Position = ls.Position.create(-1, -1);
399 |
400 | class OpenMethod {
401 | visibility: string;
402 | type: string;
403 | name: string;
404 | argsIndex: number;
405 | args: string;
406 | startPosition: ls.Position;
407 | nameLocation: ls.Location;
408 | statement: MultiLineStatement;
409 | }
410 |
411 | let openMethod: OpenMethod = null;
412 |
413 | function GetMethodStart(statement: MultiLineStatement, uri: string): boolean {
414 | let line = statement.GetFullStatement();
415 |
416 | let rex:RegExp = /^\s*(?public\s+|private\s+)?(?function|sub)(\s+)(?[a-zA-Z0-9\-\_]+)(\s*)(?\(.*\))?\s*$/gi;
417 | let regexResult = rex.exec(line);
418 |
419 | if(regexResult == null || regexResult.length < 6)
420 | return;
421 |
422 | if(openMethod == null) {
423 | let leadingSpaces = GetNumberOfFrontSpaces(line);
424 | let preLength = leadingSpaces + regexResult.index;
425 |
426 | for (var i = 1; i < 6; i++) {
427 | var resElement = regexResult[i];
428 | if(resElement != null)
429 | preLength += resElement.length;
430 | }
431 |
432 | openMethod = {
433 | visibility: regexResult.groups.visibility,
434 | type: regexResult.groups.type,
435 | name: regexResult.groups.name,
436 | argsIndex: preLength + 1, // opening bracket
437 | args: regexResult.groups.args,
438 | startPosition: statement.GetPostitionByCharacter(leadingSpaces),
439 | nameLocation: ls.Location.create(uri, ls.Range.create(
440 | statement.GetPostitionByCharacter(line.indexOf(regexResult.groups.name)),
441 | statement.GetPostitionByCharacter(line.indexOf(regexResult.groups.name) + regexResult.groups.name.length))
442 | ),
443 | statement: statement
444 | };
445 |
446 | if(openMethod.args == null)
447 | openMethod.args = "";
448 |
449 | return true;
450 | } else {
451 | // ERROR!!! I expected "end function|sub"!
452 | console.error("ERROR - line " + statement.startLine + " at " + statement.startCharacter + ": 'end " + openMethod.type + "' expected!");
453 | }
454 |
455 | return false;
456 | }
457 |
458 | function GetMethodSymbol(statement: MultiLineStatement, uri: string) : VBSSymbol[] {
459 | let line: string = statement.GetFullStatement();
460 |
461 | let classEndRegex:RegExp = /^[ \t]*end[ \t]+(function|sub)[ \t]*$/gi;
462 |
463 | let regexResult = classEndRegex.exec(line);
464 |
465 | if(regexResult == null || regexResult.length < 2)
466 | return null;
467 |
468 | let type = regexResult[1];
469 |
470 | if(openMethod == null) {
471 | // ERROR!!! I cannot close any method!
472 | console.error("ERROR - line " + statement.startLine + " at " + statement.startCharacter + ": There is no " + type + " to end!");
473 | return null;
474 | }
475 |
476 | if(type.toLowerCase() != openMethod.type.toLowerCase()) {
477 | // ERROR!!! I expected end function|sub and not sub|function!
478 | // show the user the error and then go on like it was the right type!
479 | console.error("ERROR - line " + statement.startLine + " at " + statement.startCharacter + ": 'end " + openMethod.type + "' expected!");
480 | }
481 |
482 | let range: ls.Range = ls.Range.create(openMethod.startPosition, statement.GetPostitionByCharacter(GetNumberOfFrontSpaces(line) + regexResult[0].trim().length))
483 |
484 | let symbol: VBSMethodSymbol = new VBSMethodSymbol();
485 | symbol.visibility = openMethod.visibility;
486 | symbol.type = openMethod.type;
487 | symbol.name = openMethod.name;
488 | symbol.args = openMethod.args;
489 | symbol.nameLocation = openMethod.nameLocation;
490 | symbol.parentName = openClassName;
491 | symbol.symbolRange = range;
492 |
493 | let parametersSymbol = GetParameterSymbols(openMethod.args, openMethod.argsIndex, openMethod.statement, uri);
494 |
495 | openMethod = null;
496 |
497 | //return [symbol];
498 | return parametersSymbol.concat(symbol);
499 | }
500 |
501 | function ReplaceAll(target: string, search: string, replacement: string): string {
502 | return target.replace(new RegExp(search, 'g'), replacement);
503 | };
504 |
505 | function GetParameterSymbols(args: string, argsIndex: number, statement: MultiLineStatement, uri: string): VBSVariableSymbol[] {
506 | let symbols: VBSVariableSymbol[] = [];
507 |
508 | if(args == null || args == "")
509 | return symbols;
510 |
511 | let argsSplitted: string[] = args.split(',');
512 |
513 | for (let i = 0; i < argsSplitted.length; i++) {
514 | let arg = argsSplitted[i];
515 |
516 | let splittedByValByRefName = ReplaceAll(ReplaceAll(arg, "\t", " "), " ", " ").trim().split(" ");
517 |
518 | let varSymbol:VBSVariableSymbol = new VBSVariableSymbol();
519 | varSymbol.args = "";
520 | varSymbol.type = "";
521 | varSymbol.visibility = "";
522 |
523 | if(splittedByValByRefName.length == 1)
524 | varSymbol.name = splittedByValByRefName[0].trim();
525 | else if(splittedByValByRefName.length > 1)
526 | {
527 | // ByVal or ByRef
528 | varSymbol.type = splittedByValByRefName[0].trim();
529 | varSymbol.name = splittedByValByRefName[1].trim();
530 | }
531 |
532 | let range = ls.Range.create(
533 | statement.GetPostitionByCharacter(argsIndex + arg.indexOf(varSymbol.name)),
534 | statement.GetPostitionByCharacter(argsIndex + arg.indexOf(varSymbol.name) + varSymbol.name.length)
535 | );
536 | varSymbol.nameLocation = ls.Location.create(uri, range);
537 | varSymbol.symbolRange = range;
538 |
539 | symbols.push(varSymbol);
540 | argsIndex += arg.length + 1; // comma
541 | }
542 |
543 | return symbols;
544 | }
545 |
546 | function GetNumberOfFrontSpaces(line: string): number {
547 | let counter: number = 0;
548 |
549 | for (var i = 0; i < line.length; i++) {
550 | var char = line[i];
551 | if(char == " " || char == "\t")
552 | counter++;
553 | else
554 | break;
555 | }
556 |
557 | return counter;
558 | }
559 |
560 | class OpenProperty {
561 | visibility: string;
562 | type: string;
563 | name: string;
564 | argsIndex: number;
565 | args: string;
566 | startPosition: ls.Position;
567 | nameLocation: ls.Location;
568 | statement: MultiLineStatement;
569 | }
570 |
571 | let openProperty: OpenProperty = null;
572 |
573 | function GetPropertyStart(statement: MultiLineStatement, uri: string) : boolean {
574 | let line: string = statement.GetFullStatement();
575 |
576 | let propertyStartRegex:RegExp = /^[ \t]*(public[ \t]+|private[ \t]+)?(default[ \t]+)?(property[ \t]+)(let[ \t]+|set[ \t]+|get[ \t]+)([a-zA-Z0-9\-\_]+)([ \t]*)(\(([a-zA-Z0-9\_\-, \t(\(\))]*)\))?[ \t]*$/gi;
577 | let regexResult = propertyStartRegex.exec(line);
578 |
579 | if(regexResult == null || regexResult.length < 6)
580 | return null;
581 |
582 | let leadingSpaces = GetNumberOfFrontSpaces(line);
583 | let preLength = leadingSpaces + regexResult.index;
584 |
585 | for (var i = 1; i < 7; i++) {
586 | var resElement = regexResult[i];
587 | if(resElement != null)
588 | preLength += resElement.length;
589 | }
590 |
591 | if(openProperty == null) {
592 | openProperty = {
593 | visibility: regexResult[1],
594 | type: regexResult[4],
595 | name: regexResult[5],
596 | argsIndex: preLength + 1,
597 | args: regexResult[8],
598 | startPosition: statement.GetPostitionByCharacter(leadingSpaces),
599 | nameLocation: ls.Location.create(uri, ls.Range.create(
600 | statement.GetPostitionByCharacter(line.indexOf(regexResult[5])),
601 | statement.GetPostitionByCharacter(line.indexOf(regexResult[5]) + regexResult[5].length))
602 | ),
603 | statement: statement
604 | };
605 |
606 | if(openProperty.args == null)
607 | openProperty.args = "";
608 |
609 | return true;
610 | } else {
611 | // ERROR!!! I expected "end function|sub"!
612 | console.error("ERROR - line " + statement.startLine + " at " + statement.startCharacter + ": 'end property' expected!");
613 | }
614 |
615 | return false;
616 | }
617 |
618 | function GetPropertySymbol(statement: MultiLineStatement, uri: string) : VBSSymbol[] {
619 | let line: string = statement.GetFullStatement();
620 |
621 | let classEndRegex:RegExp = /^[ \t]*end[ \t]+property[ \t]*$/gi;
622 |
623 | let regexResult = classEndRegex.exec(line);
624 |
625 | if(regexResult == null || regexResult.length < 1)
626 | return null;
627 |
628 | if(openProperty == null) {
629 | // ERROR!!! I cannot close any property!
630 | console.error("ERROR - line " + statement.startLine + " at " + statement.startCharacter + ": There is no property to end!");
631 | return null;
632 | }
633 |
634 | // range of the whole definition
635 | let range: ls.Range = ls.Range.create(
636 | openProperty.startPosition,
637 | statement.GetPostitionByCharacter(GetNumberOfFrontSpaces(line) + regexResult[0].trim().length)
638 | );
639 |
640 | let symbol = new VBSPropertySymbol();
641 | symbol.visibility = "";
642 | symbol.type = openProperty.type;
643 | symbol.name = openProperty.name;
644 | symbol.args = openProperty.args;
645 | symbol.symbolRange = range;
646 | symbol.nameLocation = openProperty.nameLocation;
647 | symbol.parentName = openClassName;
648 | symbol.symbolRange = range;
649 |
650 | let parametersSymbol = GetParameterSymbols(openProperty.args, openProperty.argsIndex, openProperty.statement, uri);
651 |
652 | openProperty = null;
653 |
654 | return parametersSymbol.concat(symbol);
655 | }
656 |
657 | function GetMemberSymbol(statement: MultiLineStatement, uri: string) : VBSMemberSymbol {
658 | let line: string = statement.GetFullStatement();
659 |
660 | let memberStartRegex:RegExp = /^[ \t]*(public[ \t]+|private[ \t]+)([a-zA-Z0-9\-\_]+)[ \t]*$/gi;
661 | let regexResult = memberStartRegex.exec(line);
662 |
663 | if(regexResult == null || regexResult.length < 3)
664 | return null;
665 |
666 | let visibility = regexResult[1];
667 | let name = regexResult[2];
668 | let intendention = GetNumberOfFrontSpaces(line);
669 | let nameStartIndex = line.indexOf(line);
670 |
671 | let range: ls.Range = ls.Range.create(
672 | statement.GetPostitionByCharacter(intendention),
673 | statement.GetPostitionByCharacter(intendention + regexResult[0].trim().length)
674 | );
675 |
676 | let symbol: VBSMemberSymbol = new VBSMemberSymbol();
677 | symbol.visibility = visibility;
678 | symbol.type = "";
679 | symbol.name = name;
680 | symbol.args = "";
681 | symbol.symbolRange = range;
682 | symbol.nameLocation = ls.Location.create(uri,
683 | ls.Range.create(
684 | statement.GetPostitionByCharacter(nameStartIndex),
685 | statement.GetPostitionByCharacter(nameStartIndex + name.length)
686 | )
687 | );
688 | symbol.parentName = openClassName;
689 |
690 | return symbol;
691 | }
692 |
693 | function GetVariableNamesFromList(vars: string): string[] {
694 | return vars.split(',').map(function(s) { return s.trim(); });
695 | }
696 |
697 | function GetVariableSymbol(statement: MultiLineStatement, uri: string) : VBSVariableSymbol[] {
698 | let line: string = statement.GetFullStatement();
699 |
700 | let variableSymbols: VBSVariableSymbol[] = [];
701 | let memberStartRegex:RegExp = /^[ \t]*(dim[ \t]+)(([a-zA-Z0-9\-\_]+[ \t]*\,[ \t]*)*)([a-zA-Z0-9\-\_]+)[ \t]*$/gi;
702 | let regexResult = memberStartRegex.exec(line);
703 |
704 | if(regexResult == null || regexResult.length < 3)
705 | return null;
706 |
707 | // (dim[ \t]+)
708 | let visibility = regexResult[1];
709 | let variables = GetVariableNamesFromList(regexResult[2] + regexResult[4]);
710 | let intendention = GetNumberOfFrontSpaces(line);
711 | let nameStartIndex = line.indexOf(line);
712 | let firstElementOffset = visibility.length;
713 | let parentName: string = "";
714 |
715 | if(openClassName != null)
716 | parentName = openClassName;
717 |
718 | if(openMethod != null)
719 | parentName = openMethod.name;
720 |
721 | if(openProperty != null)
722 | parentName = openProperty.name;
723 |
724 | for (let i = 0; i < variables.length; i++) {
725 | let varName = variables[i];
726 | let symbol: VBSVariableSymbol = new VBSVariableSymbol();
727 | symbol.visibility = "";
728 | symbol.type = "";
729 | symbol.name = varName;
730 | symbol.args = "";
731 | symbol.nameLocation = ls.Location.create(uri,
732 | GetNameRange(statement, varName )
733 | );
734 |
735 | symbol.symbolRange = ls.Range.create(
736 | ls.Position.create(symbol.nameLocation.range.start.line, symbol.nameLocation.range.start.character - firstElementOffset),
737 | ls.Position.create(symbol.nameLocation.range.end.line, symbol.nameLocation.range.end.character)
738 | );
739 |
740 | firstElementOffset = 0;
741 | symbol.parentName = parentName;
742 |
743 | variableSymbols.push(symbol);
744 | }
745 |
746 | return variableSymbols;
747 | }
748 |
749 | function GetNameRange(statement: MultiLineStatement, name: string): ls.Range {
750 | let line: string = statement.GetFullStatement();
751 |
752 | let findVariableName = new RegExp("(" + name.trim() + "[ \t]*)(\,|$)","gi");
753 | let matches = findVariableName.exec(line);
754 |
755 | let rng = ls.Range.create(
756 | statement.GetPostitionByCharacter(matches.index),
757 | statement.GetPostitionByCharacter(matches.index + name.trim().length)
758 | );
759 |
760 | return rng;
761 | }
762 |
763 | function GetConstantSymbol(statement: MultiLineStatement, uri: string) : VBSConstantSymbol {
764 | if(openMethod != null || openProperty != null)
765 | return null;
766 |
767 | let line: string = statement.GetFullStatement();
768 |
769 | let memberStartRegex:RegExp = /^[ \t]*(public[ \t]+|private[ \t]+)?const[ \t]+([a-zA-Z0-9\-\_]+)[ \t]*\=.*$/gi;
770 | let regexResult = memberStartRegex.exec(line);
771 |
772 | if(regexResult == null || regexResult.length < 3)
773 | return null;
774 |
775 | let visibility = regexResult[1];
776 | if(visibility != null)
777 | visibility = visibility.trim();
778 |
779 | let name = regexResult[2].trim();
780 | let intendention = GetNumberOfFrontSpaces(line);
781 | let nameStartIndex = line.indexOf(line);
782 |
783 | let range: ls.Range = ls.Range.create(
784 | statement.GetPostitionByCharacter(intendention),
785 | statement.GetPostitionByCharacter(intendention + regexResult[0].trim().length)
786 | );
787 |
788 | let parentName: string = "";
789 |
790 | if(openClassName != null)
791 | parentName = openClassName;
792 |
793 | if(openMethod != null)
794 | parentName = openMethod.name;
795 |
796 | if(openProperty != null)
797 | parentName = openProperty.name;
798 |
799 | let symbol: VBSConstantSymbol = new VBSConstantSymbol();
800 | symbol.visibility = visibility;
801 | symbol.type = "";
802 | symbol.name = name;
803 | symbol.args = "";
804 | symbol.symbolRange = range;
805 | symbol.nameLocation = ls.Location.create(uri,
806 | ls.Range.create(
807 | statement.GetPostitionByCharacter(nameStartIndex),
808 | statement.GetPostitionByCharacter(nameStartIndex + name.length)
809 | )
810 | );
811 | symbol.parentName = parentName;
812 |
813 | return symbol;
814 | }
815 |
816 | function GetClassStart(statement: MultiLineStatement, uri: string) : boolean {
817 | let line: string = statement.GetFullStatement();
818 |
819 | let classStartRegex:RegExp = /^[ \t]*class[ \t]+([a-zA-Z0-9\-\_]+)[ \t]*$/gi;
820 | let regexResult = classStartRegex.exec(line);
821 |
822 | if(regexResult == null || regexResult.length < 2)
823 | return false;
824 |
825 | let name = regexResult[1];
826 | openClassName = name;
827 | openClassStart = statement.GetPostitionByCharacter(GetNumberOfFrontSpaces(line));
828 |
829 | return true;
830 | }
831 |
832 | function GetClassSymbol(statement: MultiLineStatement, uri: string) : VBSClassSymbol {
833 | let line: string = statement.GetFullStatement();
834 |
835 | let classEndRegex:RegExp = /^[ \t]*end[ \t]+class[ \t]*$/gi;
836 |
837 | if(openClassName == null)
838 | return null;
839 |
840 | let regexResult = classEndRegex.exec(line);
841 |
842 | if(regexResult == null || regexResult.length < 1)
843 | return null;
844 |
845 | if(openMethod != null) {
846 | // ERROR! expected to close method before!
847 | console.error("ERROR - line " + statement.startLine + " at " + statement.startCharacter + ": 'end " + openMethod.type + "' expected!");
848 | }
849 |
850 | if(openProperty != null) {
851 | // ERROR! expected to close property before!
852 | console.error("ERROR - line " + statement.startLine + " at " + statement.startCharacter + ": 'end property' expected!");
853 | }
854 |
855 | let range: ls.Range = ls.Range.create(openClassStart, statement.GetPostitionByCharacter(regexResult[0].length))
856 | let symbol: VBSClassSymbol = new VBSClassSymbol();
857 | symbol.name = openClassName;
858 | symbol.nameLocation = ls.Location.create(uri,
859 | ls.Range.create(openClassStart,
860 | ls.Position.create(openClassStart.line, openClassStart.character + openClassName.length)
861 | )
862 | );
863 | symbol.symbolRange = range;
864 | //let symbol: ls.SymbolInformation = ls.SymbolInformation.create(openClassName, ls.SymbolKind.Class, range, uri);
865 |
866 | openClassName = null;
867 | openClassStart = ls.Position.create(-1, -1);
868 |
869 | return symbol;
870 | }
871 |
872 | // Listen on the connection
873 | connection.listen();
--------------------------------------------------------------------------------
/server/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es6",
4 | "module": "commonjs",
5 | "moduleResolution": "node",
6 | "sourceMap": true,
7 | "lib" : [ "es2018" ],
8 | "outDir": "../client/server",
9 | "noImplicitAny": true,
10 | "removeComments": true
11 | },
12 | "exclude": [
13 | "node_modules"
14 | ],
15 | "types": [
16 | "node"
17 | ]
18 | }
--------------------------------------------------------------------------------